summaryrefslogtreecommitdiff
path: root/chromium/content
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2018-10-24 11:30:15 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2018-10-30 12:56:19 +0000
commit6036726eb981b6c4b42047513b9d3f4ac865daac (patch)
tree673593e70678e7789766d1f732eb51f613a2703b /chromium/content
parent466052c4e7c052268fd931888cd58961da94c586 (diff)
downloadqtwebengine-chromium-6036726eb981b6c4b42047513b9d3f4ac865daac.tar.gz
BASELINE: Update Chromium to 70.0.3538.78
Change-Id: Ie634710bf039e26c1957f4ae45e101bd4c434ae7 Reviewed-by: Michael Brüning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/content')
-rw-r--r--chromium/content/app/android/content_child_process_service_delegate.cc8
-rw-r--r--chromium/content/app/content_main_runner_impl.cc91
-rw-r--r--chromium/content/app/strings/content_strings.grd8
-rw-r--r--chromium/content/app/strings/translations/content_strings_am.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_ar.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_bg.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_bn.xtb4
-rw-r--r--chromium/content/app/strings/translations/content_strings_ca.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_cs.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_da.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_de.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_el.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_en-GB.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_es-419.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_es.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_et.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_fa.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_fi.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_fil.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_fr.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_gu.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_hi.xtb4
-rw-r--r--chromium/content/app/strings/translations/content_strings_hr.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_hu.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_id.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_it.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_iw.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_ja.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_kn.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_ko.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_lt.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_lv.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_ml.xtb4
-rw-r--r--chromium/content/app/strings/translations/content_strings_mr.xtb12
-rw-r--r--chromium/content/app/strings/translations/content_strings_ms.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_nl.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_no.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_pl.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_pt-BR.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_pt-PT.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_ro.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_ru.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_sk.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_sl.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_sr.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_sv.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_sw.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_ta.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_te.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_th.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_tr.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_uk.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_vi.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_zh-CN.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_zh-TW.xtb2
-rw-r--r--chromium/content/browser/BUILD.gn139
-rw-r--r--chromium/content/browser/DEPS10
-rw-r--r--chromium/content/browser/OWNERS4
-rw-r--r--chromium/content/browser/accessibility/accessibility_event_recorder.cc11
-rw-r--r--chromium/content/browser/accessibility/accessibility_event_recorder.h25
-rw-r--r--chromium/content/browser/accessibility/accessibility_event_recorder_mac.mm20
-rw-r--r--chromium/content/browser/accessibility/accessibility_event_recorder_win.cc74
-rw-r--r--chromium/content/browser/accessibility/accessibility_ipc_error_browsertest.cc11
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter.cc18
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter.h4
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc51
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_win.cc6
-rw-r--r--chromium/content/browser/accessibility/accessibility_ui.cc416
-rw-r--r--chromium/content/browser/accessibility/accessibility_ui.h43
-rw-r--r--chromium/content/browser/accessibility/accessibility_win_browsertest.cc38
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility.cc56
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility.h15
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_android.cc3
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_auralinux.cc4
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_auralinux.h6
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_auralinux_unittest.cc121
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_cocoa.mm14
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_com_win.cc259
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_com_win.h208
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager.cc101
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager.h7
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_auralinux.cc20
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_auralinux.h9
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm22
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_win.cc18
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_state_impl.cc17
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_state_impl.h14
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_win.cc2
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_win.h4
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc24
-rw-r--r--chromium/content/browser/accessibility/cross_platform_accessibility_browsertest.cc3
-rw-r--r--chromium/content/browser/accessibility/dump_accessibility_browsertest_base.cc2
-rw-r--r--chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc21
-rw-r--r--chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc39
-rw-r--r--chromium/content/browser/accessibility/web_contents_accessibility_android.cc14
-rw-r--r--chromium/content/browser/accessibility/web_contents_accessibility_android.h2
-rw-r--r--chromium/content/browser/android/dialog_overlay_impl.h2
-rw-r--r--chromium/content/browser/android/java/gin_java_bridge_dispatcher_host.h2
-rw-r--r--chromium/content/browser/android/java/gin_java_bridge_message_filter.cc13
-rw-r--r--chromium/content/browser/android/java/gin_java_bridge_message_filter.h8
-rw-r--r--chromium/content/browser/android/javascript_injector.cc2
-rw-r--r--chromium/content/browser/android/launcher_thread.cc5
-rw-r--r--chromium/content/browser/android/overscroll_controller_android_unittest.cc1
-rw-r--r--chromium/content/browser/android/scoped_surface_request_manager.cc6
-rw-r--r--chromium/content/browser/android/scoped_surface_request_manager.h4
-rw-r--r--chromium/content/browser/android/scoped_surface_request_manager_unittest.cc18
-rw-r--r--chromium/content/browser/android/select_popup.cc33
-rw-r--r--chromium/content/browser/android/select_popup.h7
-rw-r--r--chromium/content/browser/android/synchronous_compositor_host.cc22
-rw-r--r--chromium/content/browser/android/synchronous_compositor_host.h11
-rw-r--r--chromium/content/browser/android/tap_disambiguator.cc109
-rw-r--r--chromium/content/browser/android/tap_disambiguator.h57
-rw-r--r--chromium/content/browser/appcache/appcache.cc11
-rw-r--r--chromium/content/browser/appcache/appcache.h12
-rw-r--r--chromium/content/browser/appcache/appcache_database.cc8
-rw-r--r--chromium/content/browser/appcache/appcache_database.h6
-rw-r--r--chromium/content/browser/appcache/appcache_database_unittest.cc8
-rw-r--r--chromium/content/browser/appcache/appcache_disk_cache.cc109
-rw-r--r--chromium/content/browser/appcache/appcache_disk_cache.h31
-rw-r--r--chromium/content/browser/appcache/appcache_disk_cache_unittest.cc8
-rw-r--r--chromium/content/browser/appcache/appcache_dispatcher_host.cc4
-rw-r--r--chromium/content/browser/appcache/appcache_group.cc4
-rw-r--r--chromium/content/browser/appcache/appcache_group.h6
-rw-r--r--chromium/content/browser/appcache/appcache_histograms.cc15
-rw-r--r--chromium/content/browser/appcache/appcache_histograms.h3
-rw-r--r--chromium/content/browser/appcache/appcache_host.cc42
-rw-r--r--chromium/content/browser/appcache/appcache_host.h2
-rw-r--r--chromium/content/browser/appcache/appcache_host_unittest.cc76
-rw-r--r--chromium/content/browser/appcache/appcache_internals_ui.cc39
-rw-r--r--chromium/content/browser/appcache/appcache_internals_ui.h3
-rw-r--r--chromium/content/browser/appcache/appcache_job.cc4
-rw-r--r--chromium/content/browser/appcache/appcache_manifest_parser.h6
-rw-r--r--chromium/content/browser/appcache/appcache_manifest_parser_unittest.cc19
-rw-r--r--chromium/content/browser/appcache/appcache_quota_client.cc16
-rw-r--r--chromium/content/browser/appcache/appcache_quota_client.h7
-rw-r--r--chromium/content/browser/appcache/appcache_request_handler.cc41
-rw-r--r--chromium/content/browser/appcache/appcache_request_handler.h13
-rw-r--r--chromium/content/browser/appcache/appcache_response.cc208
-rw-r--r--chromium/content/browser/appcache/appcache_response.h83
-rw-r--r--chromium/content/browser/appcache/appcache_response_unittest.cc71
-rw-r--r--chromium/content/browser/appcache/appcache_service_impl.cc69
-rw-r--r--chromium/content/browser/appcache/appcache_service_impl.h27
-rw-r--r--chromium/content/browser/appcache/appcache_service_unittest.cc23
-rw-r--r--chromium/content/browser/appcache/appcache_storage.cc7
-rw-r--r--chromium/content/browser/appcache/appcache_storage.h1
-rw-r--r--chromium/content/browser/appcache/appcache_storage_impl.cc35
-rw-r--r--chromium/content/browser/appcache/appcache_storage_unittest.cc26
-rw-r--r--chromium/content/browser/appcache/appcache_subresource_url_factory.cc2
-rw-r--r--chromium/content/browser/appcache/appcache_unittest.cc4
-rw-r--r--chromium/content/browser/appcache/appcache_update_job.cc14
-rw-r--r--chromium/content/browser/appcache/appcache_update_job.h1
-rw-r--r--chromium/content/browser/appcache/appcache_update_job_unittest.cc98
-rw-r--r--chromium/content/browser/appcache/appcache_update_url_fetcher.cc7
-rw-r--r--chromium/content/browser/appcache/appcache_url_loader_job.cc77
-rw-r--r--chromium/content/browser/appcache/appcache_url_loader_job.h8
-rw-r--r--chromium/content/browser/appcache/appcache_url_loader_request.cc1
-rw-r--r--chromium/content/browser/appcache/appcache_url_request_job.cc8
-rw-r--r--chromium/content/browser/appcache/appcache_url_request_job_unittest.cc55
-rw-r--r--chromium/content/browser/appcache/mock_appcache_service.cc11
-rw-r--r--chromium/content/browser/appcache/mock_appcache_service.h5
-rw-r--r--chromium/content/browser/appcache/mock_appcache_storage.h3
-rw-r--r--chromium/content/browser/background_fetch/OWNERS3
-rw-r--r--chromium/content/browser/background_fetch/background_fetch.proto35
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_context.cc283
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_context.h105
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_data_manager.cc92
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_data_manager.h69
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_data_manager_observer.h27
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_data_manager_unittest.cc842
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_delegate_proxy.cc80
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_delegate_proxy.h28
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_delegate_proxy_unittest.cc32
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_embedded_worker_test_helper.cc36
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_embedded_worker_test_helper.h46
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_event_dispatcher.cc72
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_event_dispatcher.h35
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_event_dispatcher_unittest.cc172
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_job_controller.cc112
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_job_controller.h54
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_job_controller_unittest.cc169
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_request_manager.h41
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_request_match_params.cc22
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_request_match_params.h58
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_scheduler.cc136
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_scheduler.h63
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_scheduler_unittest.cc66
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_service_impl.cc83
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_service_impl.h30
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_service_unittest.cc179
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_test_base.cc12
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_test_base.h8
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_test_data_manager.cc20
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_test_data_manager.h3
-rw-r--r--chromium/content/browser/background_fetch/mock_background_fetch_delegate.cc16
-rw-r--r--chromium/content/browser/background_fetch/mock_background_fetch_delegate.h9
-rw-r--r--chromium/content/browser/background_fetch/storage/README.md4
-rw-r--r--chromium/content/browser/background_fetch/storage/cleanup_task.cc8
-rw-r--r--chromium/content/browser/background_fetch/storage/cleanup_task.h2
-rw-r--r--chromium/content/browser/background_fetch/storage/create_metadata_task.cc143
-rw-r--r--chromium/content/browser/background_fetch/storage/create_metadata_task.h14
-rw-r--r--chromium/content/browser/background_fetch/storage/database_helpers.cc78
-rw-r--r--chromium/content/browser/background_fetch/storage/database_helpers.h22
-rw-r--r--chromium/content/browser/background_fetch/storage/database_task.cc73
-rw-r--r--chromium/content/browser/background_fetch/storage/database_task.h45
-rw-r--r--chromium/content/browser/background_fetch/storage/delete_registration_task.cc24
-rw-r--r--chromium/content/browser/background_fetch/storage/delete_registration_task.h6
-rw-r--r--chromium/content/browser/background_fetch/storage/get_developer_ids_task.cc8
-rw-r--r--chromium/content/browser/background_fetch/storage/get_developer_ids_task.h2
-rw-r--r--chromium/content/browser/background_fetch/storage/get_initialization_data_task.cc143
-rw-r--r--chromium/content/browser/background_fetch/storage/get_initialization_data_task.h7
-rw-r--r--chromium/content/browser/background_fetch/storage/get_registration_task.cc74
-rw-r--r--chromium/content/browser/background_fetch/storage/get_registration_task.h68
-rw-r--r--chromium/content/browser/background_fetch/storage/get_settled_fetches_task.cc145
-rw-r--r--chromium/content/browser/background_fetch/storage/get_settled_fetches_task.h26
-rw-r--r--chromium/content/browser/background_fetch/storage/image_helpers.cc72
-rw-r--r--chromium/content/browser/background_fetch/storage/image_helpers.h41
-rw-r--r--chromium/content/browser/background_fetch/storage/image_helpers_unittest.cc92
-rw-r--r--chromium/content/browser/background_fetch/storage/mark_registration_for_deletion_task.cc14
-rw-r--r--chromium/content/browser/background_fetch/storage/mark_registration_for_deletion_task.h2
-rw-r--r--chromium/content/browser/background_fetch/storage/mark_request_complete_task.cc81
-rw-r--r--chromium/content/browser/background_fetch/storage/mark_request_complete_task.h18
-rw-r--r--chromium/content/browser/background_fetch/storage/start_next_pending_request_task.cc56
-rw-r--r--chromium/content/browser/background_fetch/storage/start_next_pending_request_task.h11
-rw-r--r--chromium/content/browser/background_fetch/storage/update_registration_ui_task.cc86
-rw-r--r--chromium/content/browser/background_fetch/storage/update_registration_ui_task.h20
-rw-r--r--chromium/content/browser/bad_message.h2
-rw-r--r--chromium/content/browser/blob_storage/OWNERS4
-rw-r--r--chromium/content/browser/blob_storage/chrome_blob_storage_context.cc4
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_metrics.cc3
-rw-r--r--chromium/content/browser/browser_child_process_host_impl.cc38
-rw-r--r--chromium/content/browser/browser_context.cc26
-rw-r--r--chromium/content/browser/browser_main_loop.cc69
-rw-r--r--chromium/content/browser/browser_main_loop.h5
-rw-r--r--chromium/content/browser/browser_main_loop_unittest.cc2
-rw-r--r--chromium/content/browser/browser_main_runner_impl.cc10
-rw-r--r--chromium/content/browser/browser_plugin/browser_plugin_guest.cc23
-rw-r--r--chromium/content/browser/browser_process_sub_thread.cc14
-rw-r--r--chromium/content/browser/browser_side_navigation_browsertest.cc2
-rw-r--r--chromium/content/browser/browser_thread_browsertest.cc51
-rw-r--r--chromium/content/browser/browser_thread_impl.cc81
-rw-r--r--chromium/content/browser/browser_thread_impl.h7
-rw-r--r--chromium/content/browser/browser_thread_unittest.cc91
-rw-r--r--chromium/content/browser/browsing_data/browsing_data_filter_builder_impl.cc2
-rw-r--r--chromium/content/browser/browsing_data/browsing_data_remover_impl.cc46
-rw-r--r--chromium/content/browser/browsing_data/browsing_data_remover_impl.h3
-rw-r--r--chromium/content/browser/browsing_data/browsing_data_remover_impl_unittest.cc2
-rw-r--r--chromium/content/browser/browsing_data/clear_site_data_handler.cc449
-rw-r--r--chromium/content/browser/browsing_data/clear_site_data_handler.h162
-rw-r--r--chromium/content/browser/browsing_data/clear_site_data_handler_browsertest.cc (renamed from chromium/content/browser/browsing_data/clear_site_data_throttle_browsertest.cc)240
-rw-r--r--chromium/content/browser/browsing_data/clear_site_data_handler_unittest.cc485
-rw-r--r--chromium/content/browser/browsing_data/clear_site_data_throttle.cc63
-rw-r--r--chromium/content/browser/browsing_data/clear_site_data_throttle.h3
-rw-r--r--chromium/content/browser/browsing_data/conditional_cache_deletion_helper.cc4
-rw-r--r--chromium/content/browser/browsing_data/storage_partition_http_cache_data_remover.cc53
-rw-r--r--chromium/content/browser/browsing_data/storage_partition_http_cache_data_remover.h6
-rw-r--r--chromium/content/browser/browsing_instance.cc7
-rw-r--r--chromium/content/browser/cache_storage/OWNERS1
-rw-r--r--chromium/content/browser/cache_storage/cache_storage.cc15
-rw-r--r--chromium/content/browser/cache_storage/cache_storage.h17
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_cache.cc320
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_cache.h34
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_cache_unittest.cc779
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_context_impl.cc4
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_dispatcher_host.cc22
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_dispatcher_host.h2
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_manager.cc2
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_manager.h4
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_manager_unittest.cc75
-rw-r--r--chromium/content/browser/child_process_launcher.cc1
-rw-r--r--chromium/content/browser/child_process_launcher.h8
-rw-r--r--chromium/content/browser/child_process_launcher_helper.cc8
-rw-r--r--chromium/content/browser/child_process_launcher_helper_android.cc3
-rw-r--r--chromium/content/browser/child_process_launcher_helper_mac.cc20
-rw-r--r--chromium/content/browser/child_process_security_policy_impl.cc4
-rw-r--r--chromium/content/browser/cocoa/system_hotkey_helper_mac.mm8
-rw-r--r--chromium/content/browser/code_cache/generated_code_cache.cc179
-rw-r--r--chromium/content/browser/code_cache/generated_code_cache.h27
-rw-r--r--chromium/content/browser/code_cache/generated_code_cache_context.cc37
-rw-r--r--chromium/content/browser/code_cache/generated_code_cache_context.h51
-rw-r--r--chromium/content/browser/code_cache/generated_code_cache_unittest.cc95
-rw-r--r--chromium/content/browser/compositor/DEPS2
-rw-r--r--chromium/content/browser/compositor/browser_compositor_output_surface.cc2
-rw-r--r--chromium/content/browser/compositor/gpu_browser_compositor_output_surface.cc10
-rw-r--r--chromium/content/browser/compositor/gpu_browser_compositor_output_surface.h4
-rw-r--r--chromium/content/browser/compositor/gpu_output_surface_mac.cc4
-rw-r--r--chromium/content/browser/compositor/gpu_output_surface_mac.h2
-rw-r--r--chromium/content/browser/compositor/gpu_process_transport_factory.cc58
-rw-r--r--chromium/content/browser/compositor/gpu_process_transport_factory.h20
-rw-r--r--chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc9
-rw-r--r--chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h5
-rw-r--r--chromium/content/browser/compositor/image_transport_factory.h9
-rw-r--r--chromium/content/browser/compositor/image_transport_factory_browsertest.cc38
-rw-r--r--chromium/content/browser/compositor/offscreen_browser_compositor_output_surface.cc4
-rw-r--r--chromium/content/browser/compositor/offscreen_browser_compositor_output_surface.h4
-rw-r--r--chromium/content/browser/compositor/owned_mailbox.cc63
-rw-r--r--chromium/content/browser/compositor/owned_mailbox.h37
-rw-r--r--chromium/content/browser/compositor/reflector_impl.cc18
-rw-r--r--chromium/content/browser/compositor/reflector_impl_unittest.cc18
-rw-r--r--chromium/content/browser/compositor/reflector_texture.cc46
-rw-r--r--chromium/content/browser/compositor/reflector_texture.h11
-rw-r--r--chromium/content/browser/compositor/viz_process_transport_factory.cc50
-rw-r--r--chromium/content/browser/compositor/viz_process_transport_factory.h13
-rw-r--r--chromium/content/browser/compositor/vulkan_browser_compositor_output_surface.cc2
-rw-r--r--chromium/content/browser/cross_site_transfer_browsertest.cc24
-rw-r--r--chromium/content/browser/dedicated_worker/dedicated_worker_host.cc9
-rw-r--r--chromium/content/browser/devtools/DEPS1
-rw-r--r--chromium/content/browser/devtools/browser_devtools_agent_host.cc9
-rw-r--r--chromium/content/browser/devtools/browser_devtools_agent_host.h7
-rw-r--r--chromium/content/browser/devtools/devtools_agent_host_impl.cc14
-rw-r--r--chromium/content/browser/devtools/devtools_agent_host_impl.h7
-rw-r--r--chromium/content/browser/devtools/devtools_frame_trace_recorder.cc8
-rw-r--r--chromium/content/browser/devtools/devtools_frame_trace_recorder.h4
-rw-r--r--chromium/content/browser/devtools/devtools_http_handler.cc4
-rw-r--r--chromium/content/browser/devtools/devtools_http_handler_unittest.cc3
-rw-r--r--chromium/content/browser/devtools/devtools_pipe_handler.cc6
-rw-r--r--chromium/content/browser/devtools/devtools_session.cc64
-rw-r--r--chromium/content/browser/devtools/devtools_session.h23
-rw-r--r--chromium/content/browser/devtools/devtools_stream_file.cc8
-rw-r--r--chromium/content/browser/devtools/devtools_url_interceptor_request_job.cc31
-rw-r--r--chromium/content/browser/devtools/devtools_url_interceptor_request_job.h2
-rw-r--r--chromium/content/browser/devtools/devtools_url_loader_interceptor.cc64
-rw-r--r--chromium/content/browser/devtools/devtools_url_request_interceptor.cc28
-rw-r--r--chromium/content/browser/devtools/devtools_url_request_interceptor.h9
-rw-r--r--chromium/content/browser/devtools/devtools_video_consumer.cc38
-rw-r--r--chromium/content/browser/devtools/devtools_video_consumer.h4
-rw-r--r--chromium/content/browser/devtools/devtools_video_consumer_unittest.cc51
-rw-r--r--chromium/content/browser/devtools/protocol/browser_handler.cc133
-rw-r--r--chromium/content/browser/devtools/protocol/browser_handler.h21
-rw-r--r--chromium/content/browser/devtools/protocol/devtools_download_manager_delegate.cc2
-rw-r--r--chromium/content/browser/devtools/protocol/devtools_download_manager_helper.cc3
-rw-r--r--chromium/content/browser/devtools/protocol/devtools_protocol_browsertest.cc337
-rw-r--r--chromium/content/browser/devtools/protocol/devtools_protocol_test_support.cc285
-rw-r--r--chromium/content/browser/devtools/protocol/devtools_protocol_test_support.h150
-rw-r--r--chromium/content/browser/devtools/protocol/input_handler.cc52
-rw-r--r--chromium/content/browser/devtools/protocol/input_handler.h3
-rw-r--r--chromium/content/browser/devtools/protocol/memory_handler.cc32
-rw-r--r--chromium/content/browser/devtools/protocol/page_handler.cc83
-rw-r--r--chromium/content/browser/devtools/protocol/page_handler.h6
-rw-r--r--chromium/content/browser/devtools/protocol/service_worker_handler.cc7
-rw-r--r--chromium/content/browser/devtools/protocol/system_info_handler.cc3
-rw-r--r--chromium/content/browser/devtools/protocol/target_handler.cc108
-rw-r--r--chromium/content/browser/devtools/protocol/target_handler.h8
-rw-r--r--chromium/content/browser/devtools/protocol/tethering_handler.cc19
-rw-r--r--chromium/content/browser/devtools/protocol/tracing_handler.cc71
-rw-r--r--chromium/content/browser/devtools/protocol/tracing_handler.h6
-rw-r--r--chromium/content/browser/devtools/protocol_config.json11
-rw-r--r--chromium/content/browser/devtools/render_frame_devtools_agent_host.cc54
-rw-r--r--chromium/content/browser/devtools/render_frame_devtools_agent_host.h4
-rw-r--r--chromium/content/browser/devtools/service_worker_devtools_manager.h2
-rw-r--r--chromium/content/browser/devtools/target_registry.cc65
-rw-r--r--chromium/content/browser/devtools/target_registry.h18
-rw-r--r--chromium/content/browser/display_cutout/display_cutout_host_impl.cc37
-rw-r--r--chromium/content/browser/display_cutout/display_cutout_host_impl.h36
-rw-r--r--chromium/content/browser/do_not_track_browsertest.cc97
-rw-r--r--chromium/content/browser/dom_storage/OWNERS4
-rw-r--r--chromium/content/browser/dom_storage/README.md105
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_context_impl.h2
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_context_wrapper.cc20
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_context_wrapper.h2
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_database.cc58
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_database.h17
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_database_unittest.cc86
-rw-r--r--chromium/content/browser/dom_storage/local_storage_context_mojo.cc4
-rw-r--r--chromium/content/browser/dom_storage/local_storage_context_mojo_unittest.cc2
-rw-r--r--chromium/content/browser/dom_storage/session_storage_area_impl_unittest.cc2
-rw-r--r--chromium/content/browser/dom_storage/session_storage_context_mojo.cc87
-rw-r--r--chromium/content/browser/dom_storage/session_storage_context_mojo.h23
-rw-r--r--chromium/content/browser/dom_storage/session_storage_context_mojo_unittest.cc40
-rw-r--r--chromium/content/browser/dom_storage/session_storage_database.cc7
-rw-r--r--chromium/content/browser/dom_storage/session_storage_namespace_impl_mojo.cc53
-rw-r--r--chromium/content/browser/dom_storage/session_storage_namespace_impl_mojo.h46
-rw-r--r--chromium/content/browser/dom_storage/session_storage_namespace_impl_mojo_unittest.cc93
-rw-r--r--chromium/content/browser/dom_storage/storage_area_impl_unittest.cc157
-rw-r--r--chromium/content/browser/download/download_browsertest.cc22
-rw-r--r--chromium/content/browser/download/download_manager_impl.cc116
-rw-r--r--chromium/content/browser/download/download_manager_impl.h28
-rw-r--r--chromium/content/browser/download/download_manager_impl_unittest.cc1
-rw-r--r--chromium/content/browser/download/download_request_core.cc10
-rw-r--r--chromium/content/browser/download/download_request_core.h5
-rw-r--r--chromium/content/browser/download/download_url_loader_factory_getter_impl.cc25
-rw-r--r--chromium/content/browser/download/download_url_loader_factory_getter_impl.h39
-rw-r--r--chromium/content/browser/download/download_utils.cc2
-rw-r--r--chromium/content/browser/download/file_download_url_loader_factory_getter.cc6
-rw-r--r--chromium/content/browser/download/file_system_download_url_loader_factory_getter.cc52
-rw-r--r--chromium/content/browser/download/file_system_download_url_loader_factory_getter.h50
-rw-r--r--chromium/content/browser/download/mhtml_generation_browsertest.cc27
-rw-r--r--chromium/content/browser/download/save_package.cc6
-rw-r--r--chromium/content/browser/file_url_loader_factory.cc213
-rw-r--r--chromium/content/browser/fileapi/browser_file_system_helper.cc2
-rw-r--r--chromium/content/browser/fileapi/file_system_chooser.cc105
-rw-r--r--chromium/content/browser/fileapi/file_system_chooser.h55
-rw-r--r--chromium/content/browser/fileapi/file_system_manager_impl.cc872
-rw-r--r--chromium/content/browser/fileapi/file_system_manager_impl.h237
-rw-r--r--chromium/content/browser/fileapi/file_system_operation_runner_unittest.cc6
-rw-r--r--chromium/content/browser/fileapi/file_system_url_loader_factory.cc13
-rw-r--r--chromium/content/browser/fileapi/file_system_url_loader_factory_browsertest.cc1
-rw-r--r--chromium/content/browser/fileapi/fileapi_message_filter.cc642
-rw-r--r--chromium/content/browser/fileapi/fileapi_message_filter.h194
-rw-r--r--chromium/content/browser/fileapi/fileapi_message_filter_unittest.cc129
-rw-r--r--chromium/content/browser/find_in_page_client.cc67
-rw-r--r--chromium/content/browser/find_in_page_client.h54
-rw-r--r--chromium/content/browser/find_request_manager.cc203
-rw-r--r--chromium/content/browser/find_request_manager.h54
-rw-r--r--chromium/content/browser/find_request_manager_browsertest.cc17
-rw-r--r--chromium/content/browser/font_unique_name_lookup/OWNERS3
-rw-r--r--chromium/content/browser/font_unique_name_lookup/font_unique_name_browsertest.cc140
-rw-r--r--chromium/content/browser/font_unique_name_lookup/font_unique_name_lookup.cc347
-rw-r--r--chromium/content/browser/font_unique_name_lookup/font_unique_name_lookup.h138
-rw-r--r--chromium/content/browser/font_unique_name_lookup/font_unique_name_lookup_service.cc50
-rw-r--r--chromium/content/browser/font_unique_name_lookup/font_unique_name_lookup_service.h36
-rw-r--r--chromium/content/browser/font_unique_name_lookup/font_unique_name_lookup_unittest.cc334
-rw-r--r--chromium/content/browser/frame_host/cross_process_frame_connector.cc37
-rw-r--r--chromium/content/browser/frame_host/cross_process_frame_connector.h7
-rw-r--r--chromium/content/browser/frame_host/debug_urls.cc12
-rw-r--r--chromium/content/browser/frame_host/frame_tree_browsertest.cc177
-rw-r--r--chromium/content/browser/frame_host/frame_tree_node.h2
-rw-r--r--chromium/content/browser/frame_host/interstitial_page_impl.cc29
-rw-r--r--chromium/content/browser/frame_host/interstitial_page_impl.h5
-rw-r--r--chromium/content/browser/frame_host/interstitial_page_impl_browsertest.cc24
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_android.cc6
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_impl_browsertest.cc728
-rw-r--r--chromium/content/browser/frame_host/navigation_entry_screenshot_manager.cc2
-rw-r--r--chromium/content/browser/frame_host/navigation_handle_impl.cc67
-rw-r--r--chromium/content/browser/frame_host/navigation_handle_impl.h34
-rw-r--r--chromium/content/browser/frame_host/navigation_handle_impl_browsertest.cc11
-rw-r--r--chromium/content/browser/frame_host/navigation_request.cc23
-rw-r--r--chromium/content/browser/frame_host/navigation_request.h1
-rw-r--r--chromium/content/browser/frame_host/navigator_impl_unittest.cc10
-rw-r--r--chromium/content/browser/frame_host/origin_policy_throttle.cc43
-rw-r--r--chromium/content/browser/frame_host/origin_policy_throttle.h11
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_android.h2
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_delegate.cc5
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_delegate.h15
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_impl.cc453
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_impl.h70
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_impl_browsertest.cc85
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_manager.cc34
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_manager_browsertest.cc398
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_manager_unittest.cc8
-rw-r--r--chromium/content/browser/frame_host/render_frame_message_filter.cc54
-rw-r--r--chromium/content/browser/frame_host/render_frame_message_filter.h5
-rw-r--r--chromium/content/browser/frame_host/render_frame_proxy_host.cc28
-rw-r--r--chromium/content/browser/frame_host/render_widget_host_view_guest.cc36
-rw-r--r--chromium/content/browser/frame_host/render_widget_host_view_guest.h12
-rw-r--r--chromium/content/browser/frame_host/render_widget_host_view_guest_unittest.cc6
-rw-r--r--chromium/content/browser/geolocation/geolocation_service_impl.cc4
-rw-r--r--chromium/content/browser/geolocation/geolocation_service_impl_unittest.cc9
-rw-r--r--chromium/content/browser/gpu/browser_gpu_channel_host_factory.cc67
-rw-r--r--chromium/content/browser/gpu/browser_gpu_channel_host_factory.h10
-rw-r--r--chromium/content/browser/gpu/browser_gpu_client_delegate.cc82
-rw-r--r--chromium/content/browser/gpu/browser_gpu_client_delegate.h30
-rw-r--r--chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.cc498
-rw-r--r--chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.h143
-rw-r--r--chromium/content/browser/gpu/compositor_util.cc20
-rw-r--r--chromium/content/browser/gpu/gpu_client.cc28
-rw-r--r--chromium/content/browser/gpu/gpu_client_impl.cc220
-rw-r--r--chromium/content/browser/gpu/gpu_client_impl.h95
-rw-r--r--chromium/content/browser/gpu/gpu_data_manager_impl_private.cc7
-rw-r--r--chromium/content/browser/gpu/gpu_internals_ui.cc3
-rw-r--r--chromium/content/browser/gpu/gpu_ipc_browsertests.cc30
-rw-r--r--chromium/content/browser/gpu/gpu_memory_buffer_manager_singleton.cc50
-rw-r--r--chromium/content/browser/gpu/gpu_memory_buffer_manager_singleton.h28
-rw-r--r--chromium/content/browser/gpu/gpu_process_host.cc522
-rw-r--r--chromium/content/browser/gpu/gpu_process_host.h161
-rw-r--r--chromium/content/browser/histogram_controller.cc2
-rw-r--r--chromium/content/browser/hyphenation/hyphenation_impl.cc2
-rw-r--r--chromium/content/browser/indexed_db/OWNERS1
-rw-r--r--chromium/content/browser/indexed_db/cursor_impl.cc10
-rw-r--r--chromium/content/browser/indexed_db/cursor_impl.h26
-rw-r--r--chromium/content/browser/indexed_db/database_impl.cc46
-rw-r--r--chromium/content/browser/indexed_db/database_impl.h74
-rw-r--r--chromium/content/browser/indexed_db/fake_indexed_db_metadata_coding.cc11
-rw-r--r--chromium/content/browser/indexed_db/fake_indexed_db_metadata_coding.h49
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_backing_store.cc162
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_backing_store.h96
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_backing_store_unittest.cc152
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_blob_info.cc29
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_blob_info.h14
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_browsertest.cc2
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_callbacks.cc85
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_callbacks.h47
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_class_factory.h2
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_context_impl.cc13
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_context_impl.h4
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_cursor.cc2
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_cursor.h17
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_data_loss_info.h2
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_database.cc52
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_database.h103
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_database_callbacks.cc16
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_database_callbacks.h7
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_database_unittest.cc7
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_dispatcher_host.cc33
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_dispatcher_host.h32
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc141
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_factory.h1
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_factory_impl.cc14
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_factory_impl.h1
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_factory_unittest.cc7
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_fake_backing_store.cc7
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_fake_backing_store.h57
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_index_writer.cc8
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_index_writer.h30
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_internals_ui.cc66
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_internals_ui.h10
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_leveldb_coding.cc4
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_leveldb_coding.h34
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_leveldb_coding_unittest.cc4
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_leveldb_operations.cc3
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_leveldb_operations.h4
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_metadata_coding.cc7
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_metadata_coding.h52
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_observer.h2
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_pre_close_task_queue.cc10
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_pre_close_task_queue.h15
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_pre_close_task_queue_unittest.cc4
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_reporting.h1
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_return_value.h9
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_tombstone_sweeper.cc6
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_tombstone_sweeper.h20
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_tombstone_sweeper_unittest.cc10
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_transaction.cc14
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_transaction.h10
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_transaction_coordinator.cc2
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_unittest.cc1
-rw-r--r--chromium/content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.cc2
-rw-r--r--chromium/content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.h2
-rw-r--r--chromium/content/browser/indexed_db/mock_indexed_db_callbacks.cc5
-rw-r--r--chromium/content/browser/indexed_db/mock_indexed_db_callbacks.h11
-rw-r--r--chromium/content/browser/indexed_db/mock_indexed_db_factory.h1
-rw-r--r--chromium/content/browser/indexed_db/mock_mojo_indexed_db_callbacks.cc4
-rw-r--r--chromium/content/browser/indexed_db/mock_mojo_indexed_db_callbacks.h91
-rw-r--r--chromium/content/browser/indexed_db/mock_mojo_indexed_db_database_callbacks.cc4
-rw-r--r--chromium/content/browser/indexed_db/mock_mojo_indexed_db_database_callbacks.h12
-rw-r--r--chromium/content/browser/indexed_db/scopes/README.md184
-rw-r--r--chromium/content/browser/indexed_db/scopes/disjoint_range_lock_manager.cc166
-rw-r--r--chromium/content/browser/indexed_db/scopes/disjoint_range_lock_manager.h127
-rw-r--r--chromium/content/browser/indexed_db/scopes/disjoint_range_lock_manager_unittest.cc221
-rw-r--r--chromium/content/browser/indexed_db/scopes/scopes_lock_manager.cc61
-rw-r--r--chromium/content/browser/indexed_db/scopes/scopes_lock_manager.h103
-rw-r--r--chromium/content/browser/indexed_db/scopes/scopes_lock_manager_unittest.cc17
-rw-r--r--chromium/content/browser/isolated_origin_browsertest.cc20
-rw-r--r--chromium/content/browser/keyboard_lock/keyboard_lock_service_impl.cc18
-rw-r--r--chromium/content/browser/keyboard_lock/keyboard_lock_service_impl.h12
-rw-r--r--chromium/content/browser/loader/cross_site_document_blocking_browsertest.cc45
-rw-r--r--chromium/content/browser/loader/cross_site_document_resource_handler.cc74
-rw-r--r--chromium/content/browser/loader/cross_site_document_resource_handler.h8
-rw-r--r--chromium/content/browser/loader/cross_site_document_resource_handler_unittest.cc10
-rw-r--r--chromium/content/browser/loader/loader_browsertest.cc100
-rw-r--r--chromium/content/browser/loader/loader_io_thread_notifier.cc2
-rw-r--r--chromium/content/browser/loader/merkle_integrity_source_stream.cc36
-rw-r--r--chromium/content/browser/loader/merkle_integrity_source_stream.h4
-rw-r--r--chromium/content/browser/loader/merkle_integrity_source_stream_unittest.cc76
-rw-r--r--chromium/content/browser/loader/mime_sniffing_resource_handler.cc1
-rw-r--r--chromium/content/browser/loader/mime_sniffing_resource_handler_unittest.cc4
-rw-r--r--chromium/content/browser/loader/mojo_async_resource_handler.cc50
-rw-r--r--chromium/content/browser/loader/mojo_async_resource_handler.h16
-rw-r--r--chromium/content/browser/loader/mojo_async_resource_handler_unittest.cc57
-rw-r--r--chromium/content/browser/loader/navigation_loader_interceptor.h32
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_delegate.h3
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_impl.cc449
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_impl.h6
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_impl_unittest.cc14
-rw-r--r--chromium/content/browser/loader/prefetch_browsertest.cc74
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_impl.cc62
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_impl.h12
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_unittest.cc20
-rw-r--r--chromium/content/browser/loader/resource_hints_impl.cc2
-rw-r--r--chromium/content/browser/loader/resource_loader.cc6
-rw-r--r--chromium/content/browser/loader/resource_request_info_impl.cc6
-rw-r--r--chromium/content/browser/loader/resource_request_info_impl.h1
-rw-r--r--chromium/content/browser/loader/resource_requester_info.cc29
-rw-r--r--chromium/content/browser/loader/url_loader_factory_impl_unittest.cc29
-rw-r--r--chromium/content/browser/locks/lock_manager.cc2
-rw-r--r--chromium/content/browser/mach_broker_mac.mm14
-rw-r--r--chromium/content/browser/mach_broker_mac_unittest.cc4
-rw-r--r--chromium/content/browser/media/android/browser_media_player_manager.h13
-rw-r--r--chromium/content/browser/media/android/media_player_renderer_web_contents_observer.cc3
-rw-r--r--chromium/content/browser/media/android/media_resource_getter_impl.cc2
-rw-r--r--chromium/content/browser/media/audio_input_stream_broker.cc3
-rw-r--r--chromium/content/browser/media/audio_input_stream_broker.h3
-rw-r--r--chromium/content/browser/media/audio_input_stream_broker_unittest.cc25
-rw-r--r--chromium/content/browser/media/audio_output_stream_broker.cc4
-rw-r--r--chromium/content/browser/media/audio_output_stream_broker.h2
-rw-r--r--chromium/content/browser/media/audio_output_stream_broker_unittest.cc10
-rw-r--r--chromium/content/browser/media/audio_stream_broker.cc8
-rw-r--r--chromium/content/browser/media/audio_stream_broker.h4
-rw-r--r--chromium/content/browser/media/audio_stream_monitor.cc7
-rw-r--r--chromium/content/browser/media/capture/OWNERS4
-rw-r--r--chromium/content/browser/media/capture/audio_mirroring_manager.cc33
-rw-r--r--chromium/content/browser/media/capture/audio_mirroring_manager.h29
-rw-r--r--chromium/content/browser/media/capture/audio_mirroring_manager_unittest.cc40
-rw-r--r--chromium/content/browser/media/capture/aura_window_video_capture_device.cc27
-rw-r--r--chromium/content/browser/media/capture/cursor_renderer.cc353
-rw-r--r--chromium/content/browser/media/capture/cursor_renderer.h204
-rw-r--r--chromium/content/browser/media/capture/cursor_renderer_aura.cc142
-rw-r--r--chromium/content/browser/media/capture/cursor_renderer_aura.h43
-rw-r--r--chromium/content/browser/media/capture/cursor_renderer_aura_unittest.cc261
-rw-r--r--chromium/content/browser/media/capture/cursor_renderer_mac.h63
-rw-r--r--chromium/content/browser/media/capture/cursor_renderer_mac.mm140
-rw-r--r--chromium/content/browser/media/capture/cursor_renderer_mac_unittest.mm227
-rw-r--r--chromium/content/browser/media/capture/desktop_capture_device.cc4
-rw-r--r--chromium/content/browser/media/capture/desktop_capture_device_unittest.cc113
-rw-r--r--chromium/content/browser/media/capture/desktop_streams_registry_impl.cc113
-rw-r--r--chromium/content/browser/media/capture/desktop_streams_registry_impl.h66
-rw-r--r--chromium/content/browser/media/capture/fake_video_capture_stack.cc33
-rw-r--r--chromium/content/browser/media/capture/frame_sink_video_capture_device.cc144
-rw-r--r--chromium/content/browser/media/capture/frame_sink_video_capture_device.h42
-rw-r--r--chromium/content/browser/media/capture/frame_sink_video_capture_device_unittest.cc56
-rw-r--r--chromium/content/browser/media/capture/lame_capture_overlay_chromeos.cc178
-rw-r--r--chromium/content/browser/media/capture/lame_capture_overlay_chromeos.h88
-rw-r--r--chromium/content/browser/media/capture/lame_capture_overlay_chromeos_unittest.cc174
-rw-r--r--chromium/content/browser/media/capture/lame_window_capturer_chromeos.cc96
-rw-r--r--chromium/content/browser/media/capture/lame_window_capturer_chromeos.h16
-rw-r--r--chromium/content/browser/media/capture/mouse_cursor_overlay_controller.cc166
-rw-r--r--chromium/content/browser/media/capture/mouse_cursor_overlay_controller.h164
-rw-r--r--chromium/content/browser/media/capture/mouse_cursor_overlay_controller_aura.cc226
-rw-r--r--chromium/content/browser/media/capture/mouse_cursor_overlay_controller_browsertest.cc260
-rw-r--r--chromium/content/browser/media/capture/mouse_cursor_overlay_controller_mac.mm198
-rw-r--r--chromium/content/browser/media/capture/screen_capture_device_android.cc11
-rw-r--r--chromium/content/browser/media/capture/screen_capture_device_android_unittest.cc8
-rw-r--r--chromium/content/browser/media/capture/web_contents_audio_input_stream.cc33
-rw-r--r--chromium/content/browser/media/capture/web_contents_audio_input_stream_unittest.cc4
-rw-r--r--chromium/content/browser/media/capture/web_contents_audio_muter.cc25
-rw-r--r--chromium/content/browser/media/capture/web_contents_video_capture_device.cc25
-rw-r--r--chromium/content/browser/media/cdm_file_impl.cc2
-rw-r--r--chromium/content/browser/media/flinging_renderer.cc45
-rw-r--r--chromium/content/browser/media/flinging_renderer.h16
-rw-r--r--chromium/content/browser/media/flinging_renderer_unittest.cc64
-rw-r--r--chromium/content/browser/media/forwarding_audio_stream_factory.cc85
-rw-r--r--chromium/content/browser/media/forwarding_audio_stream_factory.h14
-rw-r--r--chromium/content/browser/media/forwarding_audio_stream_factory_unittest.cc43
-rw-r--r--chromium/content/browser/media/in_process_audio_loopback_stream_creator.cc44
-rw-r--r--chromium/content/browser/media/in_process_audio_loopback_stream_creator.h41
-rw-r--r--chromium/content/browser/media/media_browsertest.cc47
-rw-r--r--chromium/content/browser/media/media_canplaytype_browsertest.cc22
-rw-r--r--chromium/content/browser/media/media_color_browsertest.cc46
-rw-r--r--chromium/content/browser/media/media_devices_permission_checker.cc12
-rw-r--r--chromium/content/browser/media/media_devices_permission_checker_unittest.cc12
-rw-r--r--chromium/content/browser/media/media_internals.cc61
-rw-r--r--chromium/content/browser/media/media_internals.h17
-rw-r--r--chromium/content/browser/media/media_internals_proxy.cc5
-rw-r--r--chromium/content/browser/media/media_internals_unittest.cc151
-rw-r--r--chromium/content/browser/media/media_source_browsertest.cc7
-rw-r--r--chromium/content/browser/media/media_web_contents_observer.cc33
-rw-r--r--chromium/content/browser/media/media_web_contents_observer.h10
-rw-r--r--chromium/content/browser/media/session/audio_focus_delegate.h11
-rw-r--r--chromium/content/browser/media/session/audio_focus_delegate_android.cc15
-rw-r--r--chromium/content/browser/media/session/audio_focus_delegate_android.h9
-rw-r--r--chromium/content/browser/media/session/audio_focus_delegate_default.cc30
-rw-r--r--chromium/content/browser/media/session/audio_focus_delegate_default_browsertest.cc4
-rw-r--r--chromium/content/browser/media/session/audio_focus_manager.cc120
-rw-r--r--chromium/content/browser/media/session/audio_focus_manager.h45
-rw-r--r--chromium/content/browser/media/session/audio_focus_manager_unittest.cc217
-rw-r--r--chromium/content/browser/media/session/audio_focus_observer.cc46
-rw-r--r--chromium/content/browser/media/session/audio_focus_observer.h47
-rw-r--r--chromium/content/browser/media/session/media_session_android.cc3
-rw-r--r--chromium/content/browser/media/session/media_session_browsertest.cc24
-rw-r--r--chromium/content/browser/media/session/media_session_controller.cc25
-rw-r--r--chromium/content/browser/media/session/media_session_controller.h12
-rw-r--r--chromium/content/browser/media/session/media_session_controllers_manager.cc35
-rw-r--r--chromium/content/browser/media/session/media_session_controllers_manager.h3
-rw-r--r--chromium/content/browser/media/session/media_session_controllers_manager_unittest.cc6
-rw-r--r--chromium/content/browser/media/session/media_session_impl.cc91
-rw-r--r--chromium/content/browser/media/session/media_session_impl.h47
-rw-r--r--chromium/content/browser/media/session/media_session_impl_browsertest.cc58
-rw-r--r--chromium/content/browser/media/session/media_session_impl_visibility_browsertest.cc3
-rw-r--r--chromium/content/browser/media/session/pepper_playback_observer.cc7
-rw-r--r--chromium/content/browser/media/session/pepper_player_delegate.cc8
-rw-r--r--chromium/content/browser/media/video_decoder_proxy.cc96
-rw-r--r--chromium/content/browser/media/video_decoder_proxy.h58
-rw-r--r--chromium/content/browser/media/webaudio/OWNERS4
-rw-r--r--chromium/content/browser/media/webaudio/audio_context_manager_browsertest.cc75
-rw-r--r--chromium/content/browser/media/webaudio/audio_context_manager_impl.cc50
-rw-r--r--chromium/content/browser/media/webaudio/audio_context_manager_impl.h44
-rw-r--r--chromium/content/browser/net/quota_policy_cookie_store.cc14
-rw-r--r--chromium/content/browser/net/quota_policy_cookie_store_unittest.cc8
-rw-r--r--chromium/content/browser/net/reporting_service_proxy.cc19
-rw-r--r--chromium/content/browser/network_service_browsertest.cc25
-rw-r--r--chromium/content/browser/network_service_client.cc50
-rw-r--r--chromium/content/browser/network_service_client.h8
-rw-r--r--chromium/content/browser/network_service_instance.cc57
-rw-r--r--chromium/content/browser/network_service_restart_browsertest.cc42
-rw-r--r--chromium/content/browser/notification_service_impl.h3
-rw-r--r--chromium/content/browser/notifications/OWNERS1
-rw-r--r--chromium/content/browser/notifications/blink_notification_service_impl.cc6
-rw-r--r--chromium/content/browser/notifications/notification_database.cc29
-rw-r--r--chromium/content/browser/notifications/notification_database.h13
-rw-r--r--chromium/content/browser/notifications/notification_database_data_conversions.cc19
-rw-r--r--chromium/content/browser/notifications/notification_database_unittest.cc15
-rw-r--r--chromium/content/browser/notifications/notification_event_dispatcher_impl.cc26
-rw-r--r--chromium/content/browser/notifications/notification_storage.cc153
-rw-r--r--chromium/content/browser/notifications/notification_storage.h59
-rw-r--r--chromium/content/browser/notifications/notification_storage_unittest.cc253
-rw-r--r--chromium/content/browser/notifications/platform_notification_context_impl.cc21
-rw-r--r--chromium/content/browser/notifications/platform_notification_context_impl.h6
-rw-r--r--chromium/content/browser/notifications/platform_notification_context_unittest.cc34
-rw-r--r--chromium/content/browser/oop_browsertest.cc2
-rw-r--r--chromium/content/browser/payments/payment_app_browsertest.cc55
-rw-r--r--chromium/content/browser/payments/payment_app_content_unittest_base.h2
-rw-r--r--chromium/content/browser/payments/payment_app_context_impl.h2
-rw-r--r--chromium/content/browser/payments/payment_app_database.cc9
-rw-r--r--chromium/content/browser/payments/payment_app_database.h2
-rw-r--r--chromium/content/browser/payments/payment_app_info_fetcher.cc21
-rw-r--r--chromium/content/browser/payments/payment_app_info_fetcher.h5
-rw-r--r--chromium/content/browser/payments/payment_app_provider_impl_unittest.cc2
-rw-r--r--chromium/content/browser/payments/payment_instrument_icon_fetcher.cc21
-rw-r--r--chromium/content/browser/payments/payment_instrument_icon_fetcher.h6
-rw-r--r--chromium/content/browser/payments/payment_manager.h2
-rw-r--r--chromium/content/browser/payments/payment_manager_unittest.cc2
-rw-r--r--chromium/content/browser/permissions/permission_controller_impl.cc168
-rw-r--r--chromium/content/browser/permissions/permission_controller_impl.h21
-rw-r--r--chromium/content/browser/permissions/permission_service_context.cc7
-rw-r--r--chromium/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.cc31
-rw-r--r--chromium/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.h10
-rw-r--r--chromium/content/browser/plugin_data_remover_impl.cc2
-rw-r--r--chromium/content/browser/plugin_service_impl.cc54
-rw-r--r--chromium/content/browser/plugin_service_impl.h17
-rw-r--r--chromium/content/browser/plugin_service_impl_unittest.cc2
-rw-r--r--chromium/content/browser/pointer_lock_browsertest.cc183
-rw-r--r--chromium/content/browser/portal/portal.cc77
-rw-r--r--chromium/content/browser/portal/portal.h78
-rw-r--r--chromium/content/browser/portal/portal_browsertest.cc255
-rw-r--r--chromium/content/browser/portal/portal_unit_test.cc35
-rw-r--r--chromium/content/browser/ppapi_plugin_process_host.cc4
-rw-r--r--chromium/content/browser/presentation/OWNERS5
-rw-r--r--chromium/content/browser/presentation/presentation_service_impl.cc71
-rw-r--r--chromium/content/browser/presentation/presentation_service_impl.h32
-rw-r--r--chromium/content/browser/presentation/presentation_service_impl_unittest.cc323
-rw-r--r--chromium/content/browser/push_messaging/push_messaging_manager.cc11
-rw-r--r--chromium/content/browser/push_messaging/push_messaging_router.cc19
-rw-r--r--chromium/content/browser/push_messaging/push_messaging_router.h10
-rw-r--r--chromium/content/browser/renderer_host/DEPS2
-rw-r--r--chromium/content/browser/renderer_host/browser_compositor_view_mac.h6
-rw-r--r--chromium/content/browser/renderer_host/browser_compositor_view_mac.mm22
-rw-r--r--chromium/content/browser/renderer_host/compositor_impl_android.cc294
-rw-r--r--chromium/content/browser/renderer_host/compositor_impl_android.h17
-rw-r--r--chromium/content/browser/renderer_host/compositor_impl_android_browsertest.cc5
-rw-r--r--chromium/content/browser/renderer_host/cursor_manager.cc2
-rw-r--r--chromium/content/browser/renderer_host/delegated_frame_host.cc131
-rw-r--r--chromium/content/browser/renderer_host/delegated_frame_host.h26
-rw-r--r--chromium/content/browser/renderer_host/delegated_frame_host_client_android.cc45
-rw-r--r--chromium/content/browser/renderer_host/delegated_frame_host_client_android.h42
-rw-r--r--chromium/content/browser/renderer_host/delegated_frame_host_client_aura.cc13
-rw-r--r--chromium/content/browser/renderer_host/delegated_frame_host_client_aura.h1
-rw-r--r--chromium/content/browser/renderer_host/dwrite_font_proxy_message_filter_win.cc2
-rw-r--r--chromium/content/browser/renderer_host/frame_connector_delegate.h15
-rw-r--r--chromium/content/browser/renderer_host/input/autoscroll_browsertest.cc155
-rw-r--r--chromium/content/browser/renderer_host/input/fling_browsertest.cc309
-rw-r--r--chromium/content/browser/renderer_host/input/fling_controller.cc60
-rw-r--r--chromium/content/browser/renderer_host/input/fling_controller.h4
-rw-r--r--chromium/content/browser/renderer_host/input/fling_controller_unittest.cc148
-rw-r--r--chromium/content/browser/renderer_host/input/fling_scheduler.cc4
-rw-r--r--chromium/content/browser/renderer_host/input/fling_scheduler.h1
-rw-r--r--chromium/content/browser/renderer_host/input/fling_scheduler_android.cc8
-rw-r--r--chromium/content/browser/renderer_host/input/fling_scheduler_android.h1
-rw-r--r--chromium/content/browser/renderer_host/input/fling_scheduler_mac.mm23
-rw-r--r--chromium/content/browser/renderer_host/input/gesture_event_queue.cc3
-rw-r--r--chromium/content/browser/renderer_host/input/gesture_event_queue.h2
-rw-r--r--chromium/content/browser/renderer_host/input/gesture_event_queue_unittest.cc10
-rw-r--r--chromium/content/browser/renderer_host/input/input_router_client.h3
-rw-r--r--chromium/content/browser/renderer_host/input/input_router_impl.cc34
-rw-r--r--chromium/content/browser/renderer_host/input/input_router_impl.h4
-rw-r--r--chromium/content/browser/renderer_host/input/input_router_impl_unittest.cc154
-rw-r--r--chromium/content/browser/renderer_host/input/mock_input_router_client.cc7
-rw-r--r--chromium/content/browser/renderer_host/input/mock_input_router_client.h2
-rw-r--r--chromium/content/browser/renderer_host/input/motion_event_web.cc18
-rw-r--r--chromium/content/browser/renderer_host/input/motion_event_web.h2
-rw-r--r--chromium/content/browser/renderer_host/input/motion_event_web_unittest.cc9
-rw-r--r--chromium/content/browser/renderer_host/input/mouse_wheel_event_queue.cc6
-rw-r--r--chromium/content/browser/renderer_host/input/mouse_wheel_event_queue_unittest.cc26
-rw-r--r--chromium/content/browser/renderer_host/input/mouse_wheel_phase_handler.cc5
-rw-r--r--chromium/content/browser/renderer_host/input/mouse_wheel_rails_filter_mac.cc9
-rw-r--r--chromium/content/browser/renderer_host/input/passthrough_touch_event_queue.h2
-rw-r--r--chromium/content/browser/renderer_host/input/passthrough_touch_event_queue_unittest.cc2
-rw-r--r--chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc21
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc260
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture_target_aura.cc54
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture_target_base.cc13
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_mouse_driver.cc17
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_mouse_driver.h4
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_pen_driver.cc10
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_pen_driver.h2
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_pointer_action.cc3
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_pointer_action_unittest.cc59
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_pointer_driver.h1
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_smooth_move_gesture.cc39
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_smooth_move_gesture.h7
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.cc4
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_touch_driver.cc27
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_touch_driver.h4
-rw-r--r--chromium/content/browser/renderer_host/input/touch_action_filter.cc114
-rw-r--r--chromium/content/browser/renderer_host/input/touch_action_filter.h22
-rw-r--r--chromium/content/browser/renderer_host/input/touch_action_filter_unittest.cc260
-rw-r--r--chromium/content/browser/renderer_host/input/touch_emulator.cc12
-rw-r--r--chromium/content/browser/renderer_host/input/touch_emulator.h2
-rw-r--r--chromium/content/browser/renderer_host/input/touch_input_browsertest.cc62
-rw-r--r--chromium/content/browser/renderer_host/input/touch_selection_controller_client_aura.h2
-rw-r--r--chromium/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc6
-rw-r--r--chromium/content/browser/renderer_host/input/touch_selection_controller_client_manager_android.h2
-rw-r--r--chromium/content/browser/renderer_host/input/touchpad_pinch_browsertest.cc27
-rw-r--r--chromium/content/browser/renderer_host/input/touchpad_pinch_event_queue.cc94
-rw-r--r--chromium/content/browser/renderer_host/input/touchpad_pinch_event_queue.h3
-rw-r--r--chromium/content/browser/renderer_host/input/touchpad_pinch_event_queue_unittest.cc301
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_builders_android.cc4
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_builders_mac.h6
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_builders_mac.mm68
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_builders_mac_unittest.mm135
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_util_unittest.cc4
-rw-r--r--chromium/content/browser/renderer_host/input/wheel_event_listener_browsertest.cc135
-rw-r--r--chromium/content/browser/renderer_host/legacy_render_widget_host_win.cc7
-rw-r--r--chromium/content/browser/renderer_host/legacy_render_widget_host_win.h6
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_delegate_impl.cc10
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_device_manager.cc2
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_device_manager.h2
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc7
-rw-r--r--chromium/content/browser/renderer_host/media/audio_output_authorization_handler.cc4
-rw-r--r--chromium/content/browser/renderer_host/media/audio_output_authorization_handler_unittest.cc2
-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.cc6
-rw-r--r--chromium/content/browser/renderer_host/media/audio_service_listener_unittest.cc6
-rw-r--r--chromium/content/browser/renderer_host/media/in_process_video_capture_device_launcher.cc67
-rw-r--r--chromium/content/browser/renderer_host/media/in_process_video_capture_device_launcher.h9
-rw-r--r--chromium/content/browser/renderer_host/media/media_devices_dispatcher_host.cc2
-rw-r--r--chromium/content/browser/renderer_host/media/media_devices_dispatcher_host_unittest.cc4
-rw-r--r--chromium/content/browser/renderer_host/media/media_devices_manager.cc9
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc6
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_manager.cc324
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_manager.h31
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_manager_unittest.cc138
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_ui_proxy.cc16
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc19
-rw-r--r--chromium/content/browser/renderer_host/media/old_render_frame_audio_input_stream_factory.cc7
-rw-r--r--chromium/content/browser/renderer_host/media/old_render_frame_audio_input_stream_factory.h12
-rw-r--r--chromium/content/browser/renderer_host/media/old_render_frame_audio_input_stream_factory_unittest.cc4
-rw-r--r--chromium/content/browser/renderer_host/media/old_render_frame_audio_output_stream_factory_unittest.cc12
-rw-r--r--chromium/content/browser/renderer_host/media/render_frame_audio_input_stream_factory.cc18
-rw-r--r--chromium/content/browser/renderer_host/media/render_frame_audio_input_stream_factory.h14
-rw-r--r--chromium/content/browser/renderer_host/media/render_frame_audio_input_stream_factory_unittest.cc13
-rw-r--r--chromium/content/browser/renderer_host/media/render_frame_audio_output_stream_factory.cc5
-rw-r--r--chromium/content/browser/renderer_host/media/render_frame_audio_output_stream_factory_unittest.cc5
-rw-r--r--chromium/content/browser/renderer_host/media/service_video_capture_device_launcher.cc25
-rw-r--r--chromium/content/browser/renderer_host/media/service_video_capture_device_launcher_unittest.cc16
-rw-r--r--chromium/content/browser/renderer_host/media/service_video_capture_provider.cc1
-rw-r--r--chromium/content/browser/renderer_host/media/service_video_capture_provider.h4
-rw-r--r--chromium/content/browser/renderer_host/media/service_video_capture_provider_unittest.cc2
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_browsertest.cc5
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_controller.cc82
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_controller.h26
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_controller_event_handler.h3
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_controller_unittest.cc178
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_device_launch_observer.h4
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_host.cc25
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_host.h7
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_manager.cc32
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_manager.h9
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_manager_unittest.cc14
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_unittest.cc9
-rw-r--r--chromium/content/browser/renderer_host/p2p/DEPS3
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.cc438
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.h124
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host.cc332
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host.h183
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_tcp.cc620
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_tcp.h181
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_tcp_server.cc155
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_tcp_server.h78
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_tcp_server_unittest.cc173
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_tcp_unittest.cc581
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_test_utils.cc217
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_test_utils.h140
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_throttler.cc42
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_throttler.h41
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_udp.cc462
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_udp.h131
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_udp_unittest.cc595
-rw-r--r--chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.h2
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.cc2
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_file_io_host.cc3
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host.cc2
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_flash_file_message_filter.cc2
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_gamepad_host.h8
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.cc104
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.h29
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_lookup_request.h68
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_network_monitor_host.cc4
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_network_proxy_host.cc136
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_network_proxy_host.h46
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_proxy_lookup_helper.cc106
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_proxy_lookup_helper.h70
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_proxy_lookup_helper_unittest.cc203
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_socket_utils.cc89
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_socket_utils.h6
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.cc6
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc174
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.h28
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_truetype_font_host.cc4
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc652
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.h106
-rw-r--r--chromium/content/browser/renderer_host/render_frame_metadata_provider_impl.h2
-rw-r--r--chromium/content/browser/renderer_host/render_message_filter.cc126
-rw-r--r--chromium/content/browser/renderer_host/render_message_filter.h18
-rw-r--r--chromium/content/browser/renderer_host/render_process_host_browsertest.cc60
-rw-r--r--chromium/content/browser/renderer_host/render_process_host_impl.cc363
-rw-r--r--chromium/content/browser/renderer_host/render_process_host_impl.h122
-rw-r--r--chromium/content/browser/renderer_host/render_process_host_unittest.cc12
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_impl.cc14
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_delegate.cc9
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_delegate.h18
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_impl.cc153
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_impl.h52
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_input_event_router.cc87
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_input_event_router.h25
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_input_event_router_unittest.cc114
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_ns_view_client.h3
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_unittest.cc11
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_android.cc82
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_android.h37
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_aura.cc100
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_aura.h12
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc179
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_base.cc35
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_base.h39
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_child_frame.cc79
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_child_frame.h8
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_child_frame_browsertest.cc2
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc4
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_cocoa.h6
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_cocoa.mm44
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mac.h10
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mac.mm97
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm212
-rw-r--r--chromium/content/browser/renderer_host/render_widget_targeter.cc22
-rw-r--r--chromium/content/browser/renderer_host/render_widget_targeter.h10
-rw-r--r--chromium/content/browser/renderer_host/text_input_manager.cc5
-rw-r--r--chromium/content/browser/renderer_host/text_input_manager.h6
-rw-r--r--chromium/content/browser/renderer_host/ui_events_helper.cc5
-rw-r--r--chromium/content/browser/renderer_host/web_database_host_impl.cc61
-rw-r--r--chromium/content/browser/renderer_host/web_database_host_impl.h22
-rw-r--r--chromium/content/browser/renderer_host/web_database_host_impl_unittest.cc178
-rw-r--r--chromium/content/browser/renderer_interface_binders.cc2
-rw-r--r--chromium/content/browser/resolve_proxy_msg_helper.cc132
-rw-r--r--chromium/content/browser/resolve_proxy_msg_helper.h70
-rw-r--r--chromium/content/browser/resolve_proxy_msg_helper_unittest.cc303
-rw-r--r--chromium/content/browser/resources/accessibility/OWNERS4
-rw-r--r--chromium/content/browser/resources/accessibility/accessibility.css76
-rw-r--r--chromium/content/browser/resources/accessibility/accessibility.html147
-rw-r--r--chromium/content/browser/resources/accessibility/accessibility.js272
-rw-r--r--chromium/content/browser/resources/indexed_db/indexeddb_internals.html4
-rw-r--r--chromium/content/browser/resources/indexed_db/indexeddb_internals.js27
-rw-r--r--chromium/content/browser/resources/media/client_renderer.js32
-rw-r--r--chromium/content/browser/resources/media/main.js7
-rw-r--r--chromium/content/browser/resources/media/manager.js8
-rw-r--r--chromium/content/browser/resources/media/media_internals.css19
-rw-r--r--chromium/content/browser/resources/media/media_internals.html16
-rw-r--r--chromium/content/browser/scheduler/responsiveness/OWNERS2
-rw-r--r--chromium/content/browser/scheduler/responsiveness/README35
-rw-r--r--chromium/content/browser/scheduler/responsiveness/calculator.cc216
-rw-r--r--chromium/content/browser/scheduler/responsiveness/calculator.h130
-rw-r--r--chromium/content/browser/scheduler/responsiveness/calculator_unittest.cc235
-rw-r--r--chromium/content/browser/scheduler/responsiveness/message_loop_observer.cc34
-rw-r--r--chromium/content/browser/scheduler/responsiveness/message_loop_observer.h47
-rw-r--r--chromium/content/browser/scheduler/responsiveness/native_event_observer.cc157
-rw-r--r--chromium/content/browser/scheduler/responsiveness/native_event_observer.h99
-rw-r--r--chromium/content/browser/scheduler/responsiveness/native_event_observer_browsertest.mm72
-rw-r--r--chromium/content/browser/scheduler/responsiveness/native_event_observer_browsertest_win.cc76
-rw-r--r--chromium/content/browser/scheduler/responsiveness/native_event_observer_mac.mm36
-rw-r--r--chromium/content/browser/scheduler/responsiveness/watcher.cc257
-rw-r--r--chromium/content/browser/scheduler/responsiveness/watcher.h156
-rw-r--r--chromium/content/browser/scheduler/responsiveness/watcher_unittest.cc236
-rw-r--r--chromium/content/browser/security_exploit_browsertest.cc56
-rw-r--r--chromium/content/browser/service_manager/common_browser_interfaces.cc26
-rw-r--r--chromium/content/browser/service_manager/service_manager_context.cc26
-rw-r--r--chromium/content/browser/service_worker/README.md85
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_instance.cc145
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_instance.h4
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_registry.cc2
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_registry.h5
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_test_helper.cc150
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_test_helper.h61
-rw-r--r--chromium/content/browser/service_worker/service_worker_browsertest.cc446
-rw-r--r--chromium/content/browser/service_worker/service_worker_cache_writer.cc4
-rw-r--r--chromium/content/browser/service_worker/service_worker_cache_writer.h15
-rw-r--r--chromium/content/browser/service_worker/service_worker_cache_writer_unittest.cc61
-rw-r--r--chromium/content/browser/service_worker/service_worker_consts.cc3
-rw-r--r--chromium/content/browser/service_worker/service_worker_consts.h1
-rw-r--r--chromium/content/browser/service_worker/service_worker_content_settings_proxy_impl.cc6
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_core.cc45
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_core.h5
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_core_observer.h4
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_request_handler.cc2
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_request_handler.h2
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_request_handler_unittest.cc9
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_unittest.cc181
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_watcher.cc3
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_watcher.h3
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_wrapper.cc157
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_wrapper.h39
-rw-r--r--chromium/content/browser/service_worker/service_worker_controllee_request_handler.cc401
-rw-r--r--chromium/content/browser/service_worker/service_worker_controllee_request_handler.h47
-rw-r--r--chromium/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc155
-rw-r--r--chromium/content/browser/service_worker/service_worker_disk_cache.cc14
-rw-r--r--chromium/content/browser/service_worker/service_worker_disk_cache.h9
-rw-r--r--chromium/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc1
-rw-r--r--chromium/content/browser/service_worker/service_worker_fetch_dispatcher.cc200
-rw-r--r--chromium/content/browser/service_worker/service_worker_fetch_dispatcher.h15
-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.cc6
-rw-r--r--chromium/content/browser/service_worker/service_worker_metrics.cc208
-rw-r--r--chromium/content/browser/service_worker/service_worker_metrics.h57
-rw-r--r--chromium/content/browser/service_worker/service_worker_navigation_loader.cc143
-rw-r--r--chromium/content/browser/service_worker/service_worker_navigation_loader.h80
-rw-r--r--chromium/content/browser/service_worker/service_worker_navigation_loader_unittest.cc234
-rw-r--r--chromium/content/browser/service_worker/service_worker_new_script_loader.cc7
-rw-r--r--chromium/content/browser/service_worker/service_worker_object_host.cc49
-rw-r--r--chromium/content/browser/service_worker/service_worker_provider_host.cc207
-rw-r--r--chromium/content/browser/service_worker/service_worker_provider_host.h151
-rw-r--r--chromium/content/browser/service_worker/service_worker_provider_host_unittest.cc20
-rw-r--r--chromium/content/browser/service_worker/service_worker_read_from_cache_job_unittest.cc5
-rw-r--r--chromium/content/browser/service_worker/service_worker_register_job.cc1
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration.cc1
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration.h11
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration_object_host.cc97
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration_object_host.h23
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration_status.cc1
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration_unittest.cc176
-rw-r--r--chromium/content/browser/service_worker/service_worker_request_handler.cc12
-rw-r--r--chromium/content/browser/service_worker/service_worker_request_handler.h7
-rw-r--r--chromium/content/browser/service_worker/service_worker_request_handler_unittest.cc38
-rw-r--r--chromium/content/browser/service_worker/service_worker_response_info.cc3
-rw-r--r--chromium/content/browser/service_worker/service_worker_script_cache_map.cc6
-rw-r--r--chromium/content/browser/service_worker/service_worker_script_loader_factory.h3
-rw-r--r--chromium/content/browser/service_worker/service_worker_script_loader_factory_unittest.cc176
-rw-r--r--chromium/content/browser/service_worker/service_worker_storage.cc2
-rw-r--r--chromium/content/browser/service_worker/service_worker_storage_unittest.cc5
-rw-r--r--chromium/content/browser/service_worker/service_worker_test_utils.cc2
-rw-r--r--chromium/content/browser/service_worker/service_worker_url_job_wrapper.cc8
-rw-r--r--chromium/content/browser/service_worker/service_worker_url_job_wrapper.h10
-rw-r--r--chromium/content/browser/service_worker/service_worker_url_request_job.cc87
-rw-r--r--chromium/content/browser/service_worker/service_worker_url_request_job.h17
-rw-r--r--chromium/content/browser/service_worker/service_worker_url_request_job_unittest.cc125
-rw-r--r--chromium/content/browser/service_worker/service_worker_version.cc84
-rw-r--r--chromium/content/browser/service_worker/service_worker_version.h7
-rw-r--r--chromium/content/browser/service_worker/service_worker_version_unittest.cc47
-rw-r--r--chromium/content/browser/service_worker/service_worker_write_to_cache_job.cc8
-rw-r--r--chromium/content/browser/service_worker/service_worker_write_to_cache_job_unittest.cc49
-rw-r--r--chromium/content/browser/session_history_browsertest.cc41
-rw-r--r--chromium/content/browser/shared_worker/mock_shared_worker.cc2
-rw-r--r--chromium/content/browser/shared_worker/mock_shared_worker.h2
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_host.cc79
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_host.h35
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_host_unittest.cc13
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_script_loader.cc56
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_script_loader.h13
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_script_loader_factory.cc20
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_script_loader_factory.h5
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_service_impl.cc91
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_service_impl.h29
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_service_impl_unittest.cc62
-rw-r--r--chromium/content/browser/site_instance_impl.cc95
-rw-r--r--chromium/content/browser/site_instance_impl.h37
-rw-r--r--chromium/content/browser/site_instance_impl_unittest.cc112
-rw-r--r--chromium/content/browser/site_per_process_browsertest.cc1571
-rw-r--r--chromium/content/browser/site_per_process_hit_test_browsertest.cc1146
-rw-r--r--chromium/content/browser/speech/speech_recognition_dispatcher_host.cc23
-rw-r--r--chromium/content/browser/speech/speech_recognition_dispatcher_host.h6
-rw-r--r--chromium/content/browser/speech/speech_recognition_engine.cc29
-rw-r--r--chromium/content/browser/speech/speech_recognition_engine.h15
-rw-r--r--chromium/content/browser/speech/speech_recognition_engine_unittest.cc2
-rw-r--r--chromium/content/browser/speech/speech_recognition_manager_impl.cc5
-rw-r--r--chromium/content/browser/speech/speech_recognizer_impl.h1
-rw-r--r--chromium/content/browser/speech/speech_recognizer_impl_unittest.cc2
-rw-r--r--chromium/content/browser/storage_partition_impl.cc136
-rw-r--r--chromium/content/browser/storage_partition_impl.h24
-rw-r--r--chromium/content/browser/storage_partition_impl_map.cc10
-rw-r--r--chromium/content/browser/storage_partition_impl_unittest.cc83
-rw-r--r--chromium/content/browser/tracing/DEPS1
-rw-r--r--chromium/content/browser/tracing/background_startup_tracing_observer.cc130
-rw-r--r--chromium/content/browser/tracing/background_startup_tracing_observer.h69
-rw-r--r--chromium/content/browser/tracing/background_startup_tracing_observer_unittest.cc135
-rw-r--r--chromium/content/browser/tracing/background_tracing_config_impl.cc10
-rw-r--r--chromium/content/browser/tracing/background_tracing_config_impl.h1
-rw-r--r--chromium/content/browser/tracing/background_tracing_config_unittest.cc4
-rw-r--r--chromium/content/browser/tracing/background_tracing_manager_browsertest.cc133
-rw-r--r--chromium/content/browser/tracing/background_tracing_manager_impl.cc160
-rw-r--r--chromium/content/browser/tracing/background_tracing_manager_impl.h8
-rw-r--r--chromium/content/browser/tracing/background_tracing_rule.cc13
-rw-r--r--chromium/content/browser/tracing/cast_tracing_agent.cc9
-rw-r--r--chromium/content/browser/tracing/cros_tracing_agent.cc2
-rw-r--r--chromium/content/browser/tracing/power_tracing_agent.cc197
-rw-r--r--chromium/content/browser/tracing/power_tracing_agent.h98
-rw-r--r--chromium/content/browser/tracing/tracing_controller_browsertest.cc70
-rw-r--r--chromium/content/browser/tracing/tracing_controller_impl.cc15
-rw-r--r--chromium/content/browser/tracing/tracing_controller_impl_data_endpoint.cc6
-rw-r--r--chromium/content/browser/tracing/tracing_ui.cc9
-rw-r--r--chromium/content/browser/url_loader_factory_getter.cc59
-rw-r--r--chromium/content/browser/url_loader_factory_getter.h9
-rw-r--r--chromium/content/browser/utility_process_host.cc12
-rw-r--r--chromium/content/browser/web_contents/web_contents_android.cc15
-rw-r--r--chromium/content/browser/web_contents/web_contents_android.h8
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl.cc209
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl.h70
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl_browsertest.cc200
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl_unittest.cc3
-rw-r--r--chromium/content/browser/web_contents/web_contents_user_data_unittest.cc3
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_android.cc20
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_android.h5
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_aura.cc61
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_aura.h9
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_aura_unittest.cc146
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_guest.cc4
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_overscroll_animator_mac.h61
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_overscroll_animator_slider_mac.h60
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_overscroll_animator_slider_mac.mm259
-rw-r--r--chromium/content/browser/web_contents/web_drag_dest_mac.h2
-rw-r--r--chromium/content/browser/web_contents/web_drag_source_mac.mm7
-rw-r--r--chromium/content/browser/web_package/signed_exchange_cert_fetcher_unittest.cc11
-rw-r--r--chromium/content/browser/web_package/signed_exchange_certificate_chain.cc18
-rw-r--r--chromium/content/browser/web_package/signed_exchange_certificate_chain_fuzzer.cc2
-rw-r--r--chromium/content/browser/web_package/signed_exchange_certificate_chain_unittest.cc32
-rw-r--r--chromium/content/browser/web_package/signed_exchange_consts.h4
-rw-r--r--chromium/content/browser/web_package/signed_exchange_envelope.cc60
-rw-r--r--chromium/content/browser/web_package/signed_exchange_envelope.h10
-rw-r--r--chromium/content/browser/web_package/signed_exchange_envelope_unittest.cc172
-rw-r--r--chromium/content/browser/web_package/signed_exchange_handler.cc390
-rw-r--r--chromium/content/browser/web_package/signed_exchange_handler.h60
-rw-r--r--chromium/content/browser/web_package/signed_exchange_handler_unittest.cc76
-rw-r--r--chromium/content/browser/web_package/signed_exchange_loader.cc75
-rw-r--r--chromium/content/browser/web_package/signed_exchange_loader.h16
-rw-r--r--chromium/content/browser/web_package/signed_exchange_prefetch_handler.cc7
-rw-r--r--chromium/content/browser/web_package/signed_exchange_prologue.cc149
-rw-r--r--chromium/content/browser/web_package/signed_exchange_prologue.h137
-rw-r--r--chromium/content/browser/web_package/signed_exchange_prologue_unittest.cc136
-rw-r--r--chromium/content/browser/web_package/signed_exchange_request_handler.cc39
-rw-r--r--chromium/content/browser/web_package/signed_exchange_request_handler.h19
-rw-r--r--chromium/content/browser/web_package/signed_exchange_request_handler_browsertest.cc165
-rw-r--r--chromium/content/browser/web_package/signed_exchange_signature_header_field.cc4
-rw-r--r--chromium/content/browser/web_package/signed_exchange_signature_header_field_unittest.cc12
-rw-r--r--chromium/content/browser/web_package/signed_exchange_signature_verifier.cc142
-rw-r--r--chromium/content/browser/web_package/signed_exchange_signature_verifier_unittest.cc46
-rw-r--r--chromium/content/browser/webauth/authenticator_impl.cc320
-rw-r--r--chromium/content/browser/webauth/authenticator_impl.h56
-rw-r--r--chromium/content/browser/webauth/authenticator_impl_unittest.cc798
-rw-r--r--chromium/content/browser/webauth/authenticator_type_converters.cc28
-rw-r--r--chromium/content/browser/webauth/authenticator_type_converters.h11
-rw-r--r--chromium/content/browser/webauth/scoped_virtual_authenticator_environment.h2
-rw-r--r--chromium/content/browser/webauth/virtual_authenticator.cc5
-rw-r--r--chromium/content/browser/webauth/virtual_authenticator.h2
-rw-r--r--chromium/content/browser/webauth/webauth_browsertest.cc4
-rw-r--r--chromium/content/browser/webrtc/webrtc_audio_browsertest.cc38
-rw-r--r--chromium/content/browser/webrtc/webrtc_audio_debug_recordings_browsertest.cc34
-rw-r--r--chromium/content/browser/webrtc/webrtc_capture_from_element_browsertest.cc23
-rw-r--r--chromium/content/browser/webrtc/webrtc_internals.h2
-rw-r--r--chromium/content/browser/webrtc/webrtc_video_capture_service_browsertest.cc27
-rw-r--r--chromium/content/browser/webui/content_web_ui_controller_factory.cc4
-rw-r--r--chromium/content/browser/webui/url_data_manager.cc8
-rw-r--r--chromium/content/browser/webui/url_data_manager.h2
-rw-r--r--chromium/content/browser/webui/url_data_manager_backend.cc30
-rw-r--r--chromium/content/browser/webui/url_data_source_impl.cc4
-rw-r--r--chromium/content/browser/webui/url_data_source_impl.h5
-rw-r--r--chromium/content/browser/webui/web_ui_data_source_impl.cc5
-rw-r--r--chromium/content/browser/webui/web_ui_mojo_browsertest.cc6
-rw-r--r--chromium/content/browser/webui/web_ui_url_loader_factory.cc2
-rw-r--r--chromium/content/browser/zoom_browsertest.cc9
-rw-r--r--chromium/content/child/BUILD.gn2
-rw-r--r--chromium/content/child/blink_platform_impl.cc4
-rw-r--r--chromium/content/child/child_process.cc2
-rw-r--r--chromium/content/child/child_process.h2
-rw-r--r--chromium/content/child/child_thread_impl.cc39
-rw-r--r--chromium/content/child/child_thread_impl.h15
-rw-r--r--chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_win.cc2
-rw-r--r--chromium/content/child/field_trial.cc54
-rw-r--r--chromium/content/child/field_trial.h12
-rw-r--r--chromium/content/child/font_warmup_win_unittest.cc262
-rw-r--r--chromium/content/child/runtime_features.cc73
-rw-r--r--chromium/content/common/BUILD.gn46
-rw-r--r--chromium/content/common/DEPS8
-rw-r--r--chromium/content/common/android/gin_java_bridge_value.cc6
-rw-r--r--chromium/content/common/appcache_interfaces.cc3
-rw-r--r--chromium/content/common/appcache_interfaces.h10
-rw-r--r--chromium/content/common/associated_interface_provider_impl.cc82
-rw-r--r--chromium/content/common/associated_interface_provider_impl.h61
-rw-r--r--chromium/content/common/associated_interface_registry_impl.cc49
-rw-r--r--chromium/content/common/associated_interface_registry_impl.h43
-rw-r--r--chromium/content/common/associated_interfaces.mojom13
-rw-r--r--chromium/content/common/background_fetch/background_fetch_struct_traits.cc7
-rw-r--r--chromium/content/common/background_fetch/background_fetch_struct_traits.h22
-rw-r--r--chromium/content/common/background_fetch/background_fetch_struct_traits_unittest.cc9
-rw-r--r--chromium/content/common/background_fetch/background_fetch_types.cc63
-rw-r--r--chromium/content/common/background_fetch/background_fetch_types.h26
-rw-r--r--chromium/content/common/background_fetch/background_fetch_types.typemap3
-rw-r--r--chromium/content/common/content_constants_internal.cc4
-rw-r--r--chromium/content/common/content_constants_internal.h6
-rw-r--r--chromium/content/common/content_message_generator.h22
-rw-r--r--chromium/content/common/content_param_traits.cc24
-rw-r--r--chromium/content/common/content_param_traits_macros.h5
-rw-r--r--chromium/content/common/content_security_policy/csp_context.cc3
-rw-r--r--chromium/content/common/content_security_policy/csp_context_unittest.cc21
-rw-r--r--chromium/content/common/dom_storage/OWNERS3
-rw-r--r--chromium/content/common/fileapi/OWNERS5
-rw-r--r--chromium/content/common/fileapi/file_system_messages.h176
-rw-r--r--chromium/content/common/font_list.cc2
-rw-r--r--chromium/content/common/frame.mojom11
-rw-r--r--chromium/content/common/frame_messages.h39
-rw-r--r--chromium/content/common/gpu_stream_constants.h9
-rw-r--r--chromium/content/common/indexed_db/OWNERS15
-rw-r--r--chromium/content/common/indexed_db/indexed_db.mojom345
-rw-r--r--chromium/content/common/indexed_db/indexed_db.typemap28
-rw-r--r--chromium/content/common/indexed_db/indexed_db_constants.h24
-rw-r--r--chromium/content/common/indexed_db/indexed_db_key.cc143
-rw-r--r--chromium/content/common/indexed_db/indexed_db_key.h81
-rw-r--r--chromium/content/common/indexed_db/indexed_db_key_path.cc57
-rw-r--r--chromium/content/common/indexed_db/indexed_db_key_path.h44
-rw-r--r--chromium/content/common/indexed_db/indexed_db_key_range.cc45
-rw-r--r--chromium/content/common/indexed_db/indexed_db_key_range.h42
-rw-r--r--chromium/content/common/indexed_db/indexed_db_key_unittest.cc58
-rw-r--r--chromium/content/common/indexed_db/indexed_db_metadata.cc104
-rw-r--r--chromium/content/common/indexed_db/indexed_db_metadata.h94
-rw-r--r--chromium/content/common/indexed_db/indexed_db_struct_traits.cc450
-rw-r--r--chromium/content/common/indexed_db/indexed_db_struct_traits.h191
-rw-r--r--chromium/content/common/indexed_db/typemaps.gni5
-rw-r--r--chromium/content/common/input/ime_text_span_conversions.cc18
-rw-r--r--chromium/content/common/input/ime_text_span_conversions.h4
-rw-r--r--chromium/content/common/input/input_handler.mojom13
-rw-r--r--chromium/content/common/input/synthetic_gesture_params.h1
-rw-r--r--chromium/content/common/input/synthetic_pointer_action_params.h1
-rw-r--r--chromium/content/common/input/synthetic_smooth_scroll_gesture_params.cc14
-rw-r--r--chromium/content/common/input/synthetic_smooth_scroll_gesture_params.h4
-rw-r--r--chromium/content/common/input/synthetic_web_input_event_builders.cc40
-rw-r--r--chromium/content/common/input/synthetic_web_input_event_builders.h11
-rw-r--r--chromium/content/common/input/synthetic_web_input_event_builders_unittest.cc65
-rw-r--r--chromium/content/common/input_messages.h4
-rw-r--r--chromium/content/common/mac/font_loader.mm2
-rw-r--r--chromium/content/common/media/OWNERS6
-rw-r--r--chromium/content/common/media/media_devices.typemap4
-rw-r--r--chromium/content/common/media/media_devices_mojom_traits.cc (renamed from chromium/content/common/media/media_devices_typemap_traits.cc)2
-rw-r--r--chromium/content/common/media/media_devices_mojom_traits.h (renamed from chromium/content/common/media/media_devices_typemap_traits.h)6
-rw-r--r--chromium/content/common/media/media_player_delegate_messages.h18
-rw-r--r--chromium/content/common/media/media_stream.mojom11
-rw-r--r--chromium/content/common/media/media_stream.typemap4
-rw-r--r--chromium/content/common/media/media_stream_controls.cc13
-rw-r--r--chromium/content/common/media/media_stream_controls.h15
-rw-r--r--chromium/content/common/media/media_stream_mojom_traits.cc (renamed from chromium/content/common/media/media_stream_typemap_traits.cc)41
-rw-r--r--chromium/content/common/media/media_stream_mojom_traits.h (renamed from chromium/content/common/media/media_stream_typemap_traits.h)10
-rw-r--r--chromium/content/common/media/renderer_audio_input_stream_factory.mojom4
-rw-r--r--chromium/content/common/mime_sniffing_throttle.cc60
-rw-r--r--chromium/content/common/mime_sniffing_throttle.h36
-rw-r--r--chromium/content/common/mime_sniffing_throttle_unittest.cc459
-rw-r--r--chromium/content/common/mime_sniffing_url_loader.cc370
-rw-r--r--chromium/content/common/mime_sniffing_url_loader.h149
-rw-r--r--chromium/content/common/native_types.mojom3
-rw-r--r--chromium/content/common/native_types.typemap3
-rw-r--r--chromium/content/common/navigation_client.mojom6
-rw-r--r--chromium/content/common/navigation_params.cc8
-rw-r--r--chromium/content/common/navigation_params.h14
-rw-r--r--chromium/content/common/notifications/OWNERS2
-rw-r--r--chromium/content/common/notifications/notification_struct_traits.cc2
-rw-r--r--chromium/content/common/notifications/notification_struct_traits.h4
-rw-r--r--chromium/content/common/p2p_messages.h149
-rw-r--r--chromium/content/common/p2p_socket_type.h102
-rw-r--r--chromium/content/common/platform_notification_param_traits.h54
-rw-r--r--chromium/content/common/plugin_list.cc73
-rw-r--r--chromium/content/common/plugin_list.h66
-rw-r--r--chromium/content/common/presentation/OWNERS7
-rw-r--r--chromium/content/common/presentation/presentation.typemap12
-rw-r--r--chromium/content/common/presentation/presentation_struct_traits.cc26
-rw-r--r--chromium/content/common/presentation/presentation_struct_traits.h49
-rw-r--r--chromium/content/common/presentation/typemaps.gni5
-rw-r--r--chromium/content/common/render_message_filter.mojom8
-rw-r--r--chromium/content/common/render_widget_host_ns_view.mojom5
-rw-r--r--chromium/content/common/render_widget_window_tree_client_factory.mojom4
-rw-r--r--chromium/content/common/renderer.mojom1
-rw-r--r--chromium/content/common/renderer_host.mojom12
-rw-r--r--chromium/content/common/sandbox_init_mac.cc2
-rw-r--r--chromium/content/common/sandbox_policy_fuchsia.cc72
-rw-r--r--chromium/content/common/sandbox_policy_fuchsia.h6
-rw-r--r--chromium/content/common/service_worker/controller_service_worker.mojom7
-rw-r--r--chromium/content/common/service_worker/embedded_worker.mojom36
-rw-r--r--chromium/content/common/service_worker/service_worker.mojom79
-rw-r--r--chromium/content/common/service_worker/service_worker.typemap23
-rw-r--r--chromium/content/common/service_worker/service_worker_container.mojom33
-rw-r--r--chromium/content/common/service_worker/service_worker_fetch_request.typemap3
-rw-r--r--chromium/content/common/service_worker/service_worker_fetch_response.typemap13
-rw-r--r--chromium/content/common/service_worker/service_worker_fetch_response_callback.mojom35
-rw-r--r--chromium/content/common/service_worker/service_worker_fetch_response_mojom_traits.cc63
-rw-r--r--chromium/content/common/service_worker/service_worker_fetch_response_mojom_traits.h94
-rw-r--r--chromium/content/common/service_worker/service_worker_loader_helpers.cc80
-rw-r--r--chromium/content/common/service_worker/service_worker_loader_helpers.h14
-rw-r--r--chromium/content/common/service_worker/service_worker_messages.h75
-rw-r--r--chromium/content/common/service_worker/service_worker_provider.mojom19
-rw-r--r--chromium/content/common/service_worker/service_worker_types.cc59
-rw-r--r--chromium/content/common/service_worker/service_worker_types.h56
-rw-r--r--chromium/content/common/service_worker/service_worker_types_unittest.cc39
-rw-r--r--chromium/content/common/service_worker/service_worker_utils.cc49
-rw-r--r--chromium/content/common/service_worker/service_worker_utils.h9
-rw-r--r--chromium/content/common/shared_worker/shared_worker_factory.mojom16
-rw-r--r--chromium/content/common/single_request_url_loader_factory.cc13
-rw-r--r--chromium/content/common/single_request_url_loader_factory.h3
-rw-r--r--chromium/content/common/throttling_url_loader.cc236
-rw-r--r--chromium/content/common/throttling_url_loader.h35
-rw-r--r--chromium/content/common/throttling_url_loader_unittest.cc180
-rw-r--r--chromium/content/common/typemaps.gni2
-rw-r--r--chromium/content/common/url_loader_factory_bundle.cc15
-rw-r--r--chromium/content/common/url_loader_factory_bundle.h11
-rw-r--r--chromium/content/common/url_loader_factory_bundle.mojom4
-rw-r--r--chromium/content/common/url_loader_factory_bundle_struct_traits.cc7
-rw-r--r--chromium/content/common/url_loader_factory_bundle_struct_traits.h2
-rw-r--r--chromium/content/common/user_agent.cc43
-rw-r--r--chromium/content/common/view_messages.h81
-rw-r--r--chromium/content/content_resources.grd3
-rw-r--r--chromium/content/gpu/BUILD.gn1
-rw-r--r--chromium/content/gpu/DEPS2
-rw-r--r--chromium/content/gpu/gpu_child_thread.cc4
-rw-r--r--chromium/content/gpu/gpu_child_thread.h4
-rw-r--r--chromium/content/gpu/gpu_main.cc1
-rw-r--r--chromium/content/gpu/gpu_sandbox_hook_linux.cc66
-rw-r--r--chromium/content/gpu/gpu_service_factory.cc2
-rw-r--r--chromium/content/ppapi_plugin/DEPS2
-rw-r--r--chromium/content/ppapi_plugin/ppapi_blink_platform_impl.cc23
-rw-r--r--chromium/content/ppapi_plugin/ppapi_blink_platform_impl.h13
-rw-r--r--chromium/content/ppapi_plugin/ppapi_thread.cc18
-rw-r--r--chromium/content/public/android/BUILD.gn7
-rw-r--r--chromium/content/public/app/BUILD.gn6
-rw-r--r--chromium/content/public/app/content_main_delegate.h10
-rw-r--r--chromium/content/public/app/mojo/content_browser_manifest.json29
-rw-r--r--chromium/content/public/app/mojo/content_gpu_manifest.json1
-rw-r--r--chromium/content/public/app/mojo/content_packaged_services_manifest.json4
-rw-r--r--chromium/content/public/app/mojo/content_renderer_manifest.json1
-rw-r--r--chromium/content/public/browser/BUILD.gn19
-rw-r--r--chromium/content/public/browser/DEPS5
-rw-r--r--chromium/content/public/browser/android/synchronous_compositor.h4
-rw-r--r--chromium/content/public/browser/appcache_service.h4
-rw-r--r--chromium/content/public/browser/audio_loopback_stream_creator.cc19
-rw-r--r--chromium/content/public/browser/audio_loopback_stream_creator.h53
-rw-r--r--chromium/content/public/browser/authenticator_request_client_delegate.cc30
-rw-r--r--chromium/content/public/browser/authenticator_request_client_delegate.h55
-rw-r--r--chromium/content/public/browser/background_fetch_delegate.h21
-rw-r--r--chromium/content/public/browser/background_tracing_manager.h2
-rw-r--r--chromium/content/public/browser/browser_accessibility_state.h13
-rw-r--r--chromium/content/public/browser/browser_context.h16
-rw-r--r--chromium/content/public/browser/browser_plugin_guest_delegate.h2
-rw-r--r--chromium/content/public/browser/browser_task_traits.cc12
-rw-r--r--chromium/content/public/browser/browser_task_traits.h102
-rw-r--r--chromium/content/public/browser/browser_task_traits_unittest.nc20
-rw-r--r--chromium/content/public/browser/browser_thread.h40
-rw-r--r--chromium/content/public/browser/browsing_data_filter_builder.h2
-rw-r--r--chromium/content/public/browser/child_process_data.cc60
-rw-r--r--chromium/content/public/browser/child_process_data.h45
-rw-r--r--chromium/content/public/browser/content_browser_client.cc60
-rw-r--r--chromium/content/public/browser/content_browser_client.h80
-rw-r--r--chromium/content/public/browser/cookie_store_factory.h4
-rw-r--r--chromium/content/public/browser/desktop_capture.h2
-rw-r--r--chromium/content/public/browser/desktop_media_id.cc5
-rw-r--r--chromium/content/public/browser/desktop_media_id.h4
-rw-r--r--chromium/content/public/browser/desktop_streams_registry.h58
-rw-r--r--chromium/content/public/browser/devtools_manager_delegate.cc34
-rw-r--r--chromium/content/public/browser/devtools_manager_delegate.h33
-rw-r--r--chromium/content/public/browser/file_url_loader.h15
-rw-r--r--chromium/content/public/browser/global_routing_id.h (renamed from chromium/content/browser/loader/global_routing_id.h)42
-rw-r--r--chromium/content/public/browser/gpu_client.h21
-rw-r--r--chromium/content/public/browser/gpu_utils.cc4
-rw-r--r--chromium/content/public/browser/interstitial_page.h4
-rw-r--r--chromium/content/public/browser/media_session.h5
-rw-r--r--chromium/content/public/browser/native_event_processor_mac.h22
-rw-r--r--chromium/content/public/browser/native_event_processor_observer_mac.h50
-rw-r--r--chromium/content/public/browser/native_event_processor_observer_mac.mm57
-rw-r--r--chromium/content/public/browser/navigation_handle.h9
-rw-r--r--chromium/content/public/browser/network_connection_tracker.cc177
-rw-r--r--chromium/content/public/browser/network_connection_tracker.h136
-rw-r--r--chromium/content/public/browser/network_connection_tracker_unittest.cc343
-rw-r--r--chromium/content/public/browser/network_service_instance.h24
-rw-r--r--chromium/content/public/browser/notification_event_dispatcher.h2
-rw-r--r--chromium/content/public/browser/overlay_window.h6
-rw-r--r--chromium/content/public/browser/payment_app_provider.h2
-rw-r--r--chromium/content/public/browser/permission_controller_delegate.h10
-rw-r--r--chromium/content/public/browser/picture_in_picture_window_controller.h9
-rw-r--r--chromium/content/public/browser/platform_notification_context.h1
-rw-r--r--chromium/content/public/browser/platform_notification_service.h6
-rw-r--r--chromium/content/public/browser/plugin_service.h2
-rw-r--r--chromium/content/public/browser/presentation_request.cc2
-rw-r--r--chromium/content/public/browser/presentation_request.h5
-rw-r--r--chromium/content/public/browser/presentation_screen_availability_listener.h2
-rw-r--r--chromium/content/public/browser/presentation_service_delegate.h29
-rw-r--r--chromium/content/public/browser/render_frame_host.h4
-rw-r--r--chromium/content/public/browser/render_process_host.h14
-rw-r--r--chromium/content/public/browser/render_process_host_observer.h4
-rw-r--r--chromium/content/public/browser/render_widget_host.h2
-rw-r--r--chromium/content/public/browser/render_widget_host_view.h6
-rw-r--r--chromium/content/public/browser/resource_request_info.h3
-rw-r--r--chromium/content/public/browser/service_worker_context.h40
-rw-r--r--chromium/content/public/browser/service_worker_context_observer.h16
-rw-r--r--chromium/content/public/browser/site_instance.h4
-rw-r--r--chromium/content/public/browser/site_isolation_policy.cc2
-rw-r--r--chromium/content/public/browser/speech_recognition_session_config.h7
-rw-r--r--chromium/content/public/browser/storage_partition.h9
-rw-r--r--chromium/content/public/browser/tracing_delegate.h6
-rw-r--r--chromium/content/public/browser/url_data_source.cc12
-rw-r--r--chromium/content/public/browser/url_data_source.h8
-rw-r--r--chromium/content/public/browser/url_loader_request_interceptor.h10
-rw-r--r--chromium/content/public/browser/video_capture_device_launcher.h2
-rw-r--r--chromium/content/public/browser/web_contents.h23
-rw-r--r--chromium/content/public/browser/web_contents_observer.h23
-rw-r--r--chromium/content/public/browser/web_contents_user_data.h7
-rw-r--r--chromium/content/public/browser/webrtc_event_logger.cc3
-rw-r--r--chromium/content/public/browser/webrtc_event_logger.h36
-rw-r--r--chromium/content/public/common/BUILD.gn11
-rw-r--r--chromium/content/public/common/DEPS3
-rw-r--r--chromium/content/public/common/common_param_traits.cc50
-rw-r--r--chromium/content/public/common/common_param_traits.h25
-rw-r--r--chromium/content/public/common/common_param_traits_macros.h61
-rw-r--r--chromium/content/public/common/content_client.cc5
-rw-r--r--chromium/content/public/common/content_client.h9
-rw-r--r--chromium/content/public/common/content_features.cc134
-rw-r--r--chromium/content/public/common/content_features.h25
-rw-r--r--chromium/content/public/common/content_switches.cc35
-rw-r--r--chromium/content/public/common/content_switches.h6
-rw-r--r--chromium/content/public/common/media_stream_request.cc24
-rw-r--r--chromium/content/public/common/media_stream_request.h20
-rw-r--r--chromium/content/public/common/mime_handler_view_mode.cc17
-rw-r--r--chromium/content/public/common/mime_handler_view_mode.h25
-rw-r--r--chromium/content/public/common/persistent_notification_status.h19
-rw-r--r--chromium/content/public/common/presentation_connection_message.cc44
-rw-r--r--chromium/content/public/common/presentation_connection_message.h51
-rw-r--r--chromium/content/public/common/previews_state.h6
-rw-r--r--chromium/content/public/common/push_event_payload.h37
-rw-r--r--chromium/content/public/common/renderer_preference_watcher.mojom14
-rw-r--r--chromium/content/public/common/renderer_preferences.cc1
-rw-r--r--chromium/content/public/common/renderer_preferences.h11
-rw-r--r--chromium/content/public/common/renderer_preferences.mojom8
-rw-r--r--chromium/content/public/common/renderer_preferences.typemap9
-rw-r--r--chromium/content/public/common/typemaps.gni1
-rw-r--r--chromium/content/public/common/url_constants.cc6
-rw-r--r--chromium/content/public/common/url_constants.h4
-rw-r--r--chromium/content/public/common/url_loader_throttle.cc7
-rw-r--r--chromium/content/public/common/url_loader_throttle.h35
-rw-r--r--chromium/content/public/common/url_utils.cc28
-rw-r--r--chromium/content/public/common/url_utils.h4
-rw-r--r--chromium/content/public/common/url_utils_unittest.cc19
-rw-r--r--chromium/content/public/common/use_zoom_for_dsf_policy.cc9
-rw-r--r--chromium/content/public/common/user_agent.h13
-rw-r--r--chromium/content/public/common/web_preferences.cc3
-rw-r--r--chromium/content/public/common/web_preferences.h16
-rw-r--r--chromium/content/public/renderer/BUILD.gn2
-rw-r--r--chromium/content/public/renderer/content_renderer_client.cc38
-rw-r--r--chromium/content/public/renderer/content_renderer_client.h41
-rw-r--r--chromium/content/public/renderer/platform_event_observer.h133
-rw-r--r--chromium/content/public/renderer/render_frame_observer.cc6
-rw-r--r--chromium/content/public/renderer/render_frame_observer.h9
-rw-r--r--chromium/content/public/renderer/render_thread_observer.h2
-rw-r--r--chromium/content/public/renderer/render_view_observer.h2
-rw-r--r--chromium/content/public/renderer/renderer_gamepad_provider.h37
-rw-r--r--chromium/content/public/renderer/url_loader_throttle_provider.h3
-rw-r--r--chromium/content/public/test/android/BUILD.gn18
-rw-r--r--chromium/content/renderer/BUILD.gn34
-rw-r--r--chromium/content/renderer/OWNERS18
-rw-r--r--chromium/content/renderer/PRESUBMIT.py2
-rw-r--r--chromium/content/renderer/accessibility/blink_ax_enum_conversion.cc3
-rw-r--r--chromium/content/renderer/accessibility/blink_ax_tree_source.cc2
-rw-r--r--chromium/content/renderer/accessibility/render_accessibility_impl.cc27
-rw-r--r--chromium/content/renderer/accessibility/render_accessibility_impl.h10
-rw-r--r--chromium/content/renderer/android/disambiguation_popup_helper.cc119
-rw-r--r--chromium/content/renderer/android/disambiguation_popup_helper.h36
-rw-r--r--chromium/content/renderer/android/disambiguation_popup_helper_unittest.cc90
-rw-r--r--chromium/content/renderer/android/synchronous_compositor_proxy.h2
-rw-r--r--chromium/content/renderer/android/synchronous_layer_tree_frame_sink.cc6
-rw-r--r--chromium/content/renderer/appcache/OWNERS3
-rw-r--r--chromium/content/renderer/blob_storage/OWNERS2
-rw-r--r--chromium/content/renderer/browser_plugin/browser_plugin.cc10
-rw-r--r--chromium/content/renderer/browser_plugin/browser_plugin.h4
-rw-r--r--chromium/content/renderer/dom_serializer_browsertest.cc6
-rw-r--r--chromium/content/renderer/dom_storage/OWNERS3
-rw-r--r--chromium/content/renderer/dom_storage/local_storage_cached_area.cc1
-rw-r--r--chromium/content/renderer/dom_storage/local_storage_cached_areas.cc2
-rw-r--r--chromium/content/renderer/fileapi/OWNERS6
-rw-r--r--chromium/content/renderer/fileapi/file_system_dispatcher.cc605
-rw-r--r--chromium/content/renderer/fileapi/file_system_dispatcher.h163
-rw-r--r--chromium/content/renderer/fileapi/webfilesystem_impl.cc502
-rw-r--r--chromium/content/renderer/fileapi/webfilesystem_impl.h23
-rw-r--r--chromium/content/renderer/fileapi/webfilewriter_impl.cc179
-rw-r--r--chromium/content/renderer/fileapi/webfilewriter_impl.h26
-rw-r--r--chromium/content/renderer/gpu/actions_parser.cc3
-rw-r--r--chromium/content/renderer/gpu/frame_swap_message_queue.cc58
-rw-r--r--chromium/content/renderer/gpu/frame_swap_message_queue.h8
-rw-r--r--chromium/content/renderer/gpu/frame_swap_message_queue_unittest.cc12
-rw-r--r--chromium/content/renderer/gpu/gpu_benchmarking_extension.cc103
-rw-r--r--chromium/content/renderer/gpu/gpu_benchmarking_extension.h1
-rw-r--r--chromium/content/renderer/gpu/layer_tree_view.cc33
-rw-r--r--chromium/content/renderer/gpu/queue_message_swap_promise_unittest.cc101
-rw-r--r--chromium/content/renderer/ime_event_guard.cc2
-rw-r--r--chromium/content/renderer/ime_event_guard.h2
-rw-r--r--chromium/content/renderer/in_process_renderer_thread.cc9
-rw-r--r--chromium/content/renderer/indexed_db/indexed_db_callbacks_impl.cc230
-rw-r--r--chromium/content/renderer/indexed_db/indexed_db_callbacks_impl.h101
-rw-r--r--chromium/content/renderer/indexed_db/indexed_db_database_callbacks_impl.cc93
-rw-r--r--chromium/content/renderer/indexed_db/indexed_db_database_callbacks_impl.h14
-rw-r--r--chromium/content/renderer/indexed_db/indexed_db_dispatcher.cc36
-rw-r--r--chromium/content/renderer/indexed_db/indexed_db_dispatcher.h31
-rw-r--r--chromium/content/renderer/indexed_db/indexed_db_key_builders.cc10
-rw-r--r--chromium/content/renderer/indexed_db/indexed_db_key_builders.h20
-rw-r--r--chromium/content/renderer/indexed_db/webidbcursor_impl.cc124
-rw-r--r--chromium/content/renderer/indexed_db/webidbcursor_impl.h39
-rw-r--r--chromium/content/renderer/indexed_db/webidbcursor_impl_unittest.cc64
-rw-r--r--chromium/content/renderer/indexed_db/webidbdatabase_impl.cc519
-rw-r--r--chromium/content/renderer/indexed_db/webidbdatabase_impl.h24
-rw-r--r--chromium/content/renderer/indexed_db/webidbdatabase_impl_unittest.cc11
-rw-r--r--chromium/content/renderer/indexed_db/webidbfactory_impl.cc130
-rw-r--r--chromium/content/renderer/indexed_db/webidbfactory_impl.h19
-rw-r--r--chromium/content/renderer/input/frame_input_handler_impl.cc2
-rw-r--r--chromium/content/renderer/input/input_handler_manager_client.h1
-rw-r--r--chromium/content/renderer/input/input_target_client_impl.cc6
-rw-r--r--chromium/content/renderer/input/main_thread_event_queue.cc107
-rw-r--r--chromium/content/renderer/input/main_thread_event_queue.h6
-rw-r--r--chromium/content/renderer/input/main_thread_event_queue_task_list.cc10
-rw-r--r--chromium/content/renderer/input/main_thread_event_queue_task_list.h2
-rw-r--r--chromium/content/renderer/input/main_thread_event_queue_unittest.cc71
-rw-r--r--chromium/content/renderer/input/render_widget_input_handler.cc40
-rw-r--r--chromium/content/renderer/input/render_widget_input_handler.h6
-rw-r--r--chromium/content/renderer/input/widget_input_handler_impl.cc24
-rw-r--r--chromium/content/renderer/input/widget_input_handler_impl.h3
-rw-r--r--chromium/content/renderer/loader/child_url_loader_factory_bundle.cc14
-rw-r--r--chromium/content/renderer/loader/child_url_loader_factory_bundle.h5
-rw-r--r--chromium/content/renderer/loader/code_cache_loader_impl.cc108
-rw-r--r--chromium/content/renderer/loader/code_cache_loader_impl.h57
-rw-r--r--chromium/content/renderer/loader/frame_request_blocker.cc98
-rw-r--r--chromium/content/renderer/loader/frame_request_blocker.h64
-rw-r--r--chromium/content/renderer/loader/request_extra_data.h11
-rw-r--r--chromium/content/renderer/loader/resource_dispatcher.cc73
-rw-r--r--chromium/content/renderer/loader/resource_dispatcher.h1
-rw-r--r--chromium/content/renderer/loader/tracked_child_url_loader_factory_bundle.cc28
-rw-r--r--chromium/content/renderer/loader/tracked_child_url_loader_factory_bundle.h5
-rw-r--r--chromium/content/renderer/loader/url_loader_client_impl.cc27
-rw-r--r--chromium/content/renderer/loader/url_loader_client_impl.h6
-rw-r--r--chromium/content/renderer/loader/url_loader_client_impl_unittest.cc8
-rw-r--r--chromium/content/renderer/loader/web_url_loader_impl.cc44
-rw-r--r--chromium/content/renderer/loader/web_url_loader_impl.h3
-rw-r--r--chromium/content/renderer/loader/web_url_loader_impl_unittest.cc6
-rw-r--r--chromium/content/renderer/loader/web_url_request_util.cc2
-rw-r--r--chromium/content/renderer/loader/web_worker_fetch_context_impl.cc39
-rw-r--r--chromium/content/renderer/loader/web_worker_fetch_context_impl.h28
-rw-r--r--chromium/content/renderer/loader/weburlresponse_extradata_impl.h13
-rw-r--r--chromium/content/renderer/manifest/manifest_parser.cc41
-rw-r--r--chromium/content/renderer/manifest/manifest_parser.h8
-rw-r--r--chromium/content/renderer/manifest/manifest_parser_unittest.cc248
-rw-r--r--chromium/content/renderer/media/android/stream_texture_factory.cc6
-rw-r--r--chromium/content/renderer/media/android/stream_texture_factory.h8
-rw-r--r--chromium/content/renderer/media/audio/audio_device_factory.cc73
-rw-r--r--chromium/content/renderer/media/audio/audio_device_factory.h45
-rw-r--r--chromium/content/renderer/media/audio/audio_input_ipc_factory.cc28
-rw-r--r--chromium/content/renderer/media/audio/audio_input_ipc_factory.h3
-rw-r--r--chromium/content/renderer/media/audio/audio_renderer_sink_cache_impl.cc16
-rw-r--r--chromium/content/renderer/media/audio/audio_renderer_sink_cache_impl.h4
-rw-r--r--chromium/content/renderer/media/audio/audio_renderer_sink_cache_unittest.cc17
-rw-r--r--chromium/content/renderer/media/audio/mock_audio_device_factory.cc4
-rw-r--r--chromium/content/renderer/media/audio/mock_audio_device_factory.h28
-rw-r--r--chromium/content/renderer/media/audio/mojo_audio_input_ipc.cc40
-rw-r--r--chromium/content/renderer/media/audio/mojo_audio_input_ipc.h24
-rw-r--r--chromium/content/renderer/media/audio/mojo_audio_input_ipc_unittest.cc35
-rw-r--r--chromium/content/renderer/media/audio/mojo_audio_output_ipc.cc8
-rw-r--r--chromium/content/renderer/media/audio/mojo_audio_output_ipc.h6
-rw-r--r--chromium/content/renderer/media/audio/mojo_audio_output_ipc_unittest.cc25
-rw-r--r--chromium/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.cc48
-rw-r--r--chromium/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.h13
-rw-r--r--chromium/content/renderer/media/media_factory.cc121
-rw-r--r--chromium/content/renderer/media/media_factory.h11
-rw-r--r--chromium/content/renderer/media/render_media_log.cc17
-rw-r--r--chromium/content/renderer/media/render_media_log.h16
-rw-r--r--chromium/content/renderer/media/renderer_webaudiodevice_impl.cc6
-rw-r--r--chromium/content/renderer/media/renderer_webaudiodevice_impl_unittest.cc34
-rw-r--r--chromium/content/renderer/media/renderer_webmediaplayer_delegate.cc26
-rw-r--r--chromium/content/renderer/media/renderer_webmediaplayer_delegate.h7
-rw-r--r--chromium/content/renderer/media/stream/audio_service_audio_processor_proxy.cc167
-rw-r--r--chromium/content/renderer/media/stream/audio_service_audio_processor_proxy.h93
-rw-r--r--chromium/content/renderer/media/stream/local_media_stream_audio_source.cc3
-rw-r--r--chromium/content/renderer/media/stream/media_stream_audio_processor.cc37
-rw-r--r--chromium/content/renderer/media/stream/media_stream_audio_processor.h10
-rw-r--r--chromium/content/renderer/media/stream/media_stream_audio_processor_options.cc184
-rw-r--r--chromium/content/renderer/media/stream/media_stream_audio_processor_options.h47
-rw-r--r--chromium/content/renderer/media/stream/media_stream_constraints_util_audio.cc8
-rw-r--r--chromium/content/renderer/media/stream/media_stream_constraints_util_audio_unittest.cc15
-rw-r--r--chromium/content/renderer/media/stream/media_stream_constraints_util_sets_unittest.cc4
-rw-r--r--chromium/content/renderer/media/stream/media_stream_constraints_util_video_content.cc8
-rw-r--r--chromium/content/renderer/media/stream/media_stream_constraints_util_video_content.h3
-rw-r--r--chromium/content/renderer/media/stream/media_stream_constraints_util_video_content_unittest.cc9
-rw-r--r--chromium/content/renderer/media/stream/media_stream_constraints_util_video_device.cc8
-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_source.cc5
-rw-r--r--chromium/content/renderer/media/stream/media_stream_source.h7
-rw-r--r--chromium/content/renderer/media/stream/media_stream_video_track.h2
-rw-r--r--chromium/content/renderer/media/stream/processed_local_audio_source.cc127
-rw-r--r--chromium/content/renderer/media/stream/processed_local_audio_source.h39
-rw-r--r--chromium/content/renderer/media/stream/track_audio_renderer.cc6
-rw-r--r--chromium/content/renderer/media/stream/user_media_client_impl.cc24
-rw-r--r--chromium/content/renderer/media/stream/user_media_processor.cc122
-rw-r--r--chromium/content/renderer/media/stream/user_media_processor.h2
-rw-r--r--chromium/content/renderer/media/stream/webmediaplayer_ms.cc128
-rw-r--r--chromium/content/renderer/media/stream/webmediaplayer_ms.h48
-rw-r--r--chromium/content/renderer/media/stream/webmediaplayer_ms_compositor.cc4
-rw-r--r--chromium/content/renderer/media/stream/webmediaplayer_ms_compositor.h8
-rw-r--r--chromium/content/renderer/media/stream/webmediaplayer_ms_unittest.cc145
-rw-r--r--chromium/content/renderer/media/video_capture_impl.cc36
-rw-r--r--chromium/content/renderer/media/video_capture_impl_unittest.cc142
-rw-r--r--chromium/content/renderer/media/webrtc/OWNERS1
-rw-r--r--chromium/content/renderer/media/webrtc/media_stream_remote_video_source.cc28
-rw-r--r--chromium/content/renderer/media/webrtc/media_stream_remote_video_source_unittest.cc38
-rw-r--r--chromium/content/renderer/media/webrtc/mock_web_rtc_peer_connection_handler_client.h1
-rw-r--r--chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.cc44
-rw-r--r--chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.h8
-rw-r--r--chromium/content/renderer/media/webrtc/peer_connection_tracker.cc14
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_certificate.cc66
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_certificate.h45
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_certificate_generator.cc12
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_certificate_generator.h4
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_peer_connection_handler.cc403
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_peer_connection_handler.h32
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_peer_connection_handler_unittest.cc20
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_rtp_receiver_unittest.cc9
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_rtp_sender_unittest.cc9
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_stats.cc4
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_video_decoder_adapter.cc395
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_video_decoder_adapter.h137
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_video_decoder_adapter_unittest.cc276
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_video_encoder.cc19
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_video_encoder_unittest.cc11
-rw-r--r--chromium/content/renderer/media/webrtc/stun_field_trial.h2
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_audio_device_impl.cc35
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_audio_device_impl.h21
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_audio_device_not_impl.cc12
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_audio_device_not_impl.h2
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_audio_renderer.cc15
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_audio_renderer_unittest.cc74
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_audio_sink.cc4
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_audio_sink.h9
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter.cc6
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_set_description_observer_unittest.cc8
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_uma_histograms_unittest.cc47
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc23
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter.h2
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_video_utils.cc177
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_video_utils.h25
-rw-r--r--chromium/content/renderer/media/webrtc_local_audio_source_provider.cc9
-rw-r--r--chromium/content/renderer/media_capture_from_element/html_video_element_capturer_source_unittest.cc6
-rw-r--r--chromium/content/renderer/media_recorder/vea_encoder.cc41
-rw-r--r--chromium/content/renderer/media_recorder/vea_encoder.h12
-rw-r--r--chromium/content/renderer/media_recorder/video_track_recorder.cc57
-rw-r--r--chromium/content/renderer/media_recorder/video_track_recorder.h29
-rw-r--r--chromium/content/renderer/media_recorder/video_track_recorder_unittest.cc6
-rw-r--r--chromium/content/renderer/message_delivery_policy.h25
-rw-r--r--chromium/content/renderer/mojo/blink_interface_registry_impl.cc2
-rw-r--r--chromium/content/renderer/mojo/blink_interface_registry_impl.h6
-rw-r--r--chromium/content/renderer/mus/BUILD.gn4
-rw-r--r--chromium/content/renderer/mus/mus_embedded_frame.cc10
-rw-r--r--chromium/content/renderer/mus/mus_embedded_frame.h10
-rw-r--r--chromium/content/renderer/mus/render_widget_window_tree_client_factory.cc6
-rw-r--r--chromium/content/renderer/mus/renderer_window_tree_client.cc101
-rw-r--r--chromium/content/renderer/mus/renderer_window_tree_client.h119
-rw-r--r--chromium/content/renderer/navigation_client.cc11
-rw-r--r--chromium/content/renderer/navigation_client.h6
-rw-r--r--chromium/content/renderer/p2p/empty_network_manager.h2
-rw-r--r--chromium/content/renderer/p2p/filtering_network_manager.h2
-rw-r--r--chromium/content/renderer/p2p/host_address_request.cc63
-rw-r--r--chromium/content/renderer/p2p/host_address_request.h17
-rw-r--r--chromium/content/renderer/p2p/ipc_socket_factory.cc138
-rw-r--r--chromium/content/renderer/p2p/socket_client.h18
-rw-r--r--chromium/content/renderer/p2p/socket_client_delegate.h13
-rw-r--r--chromium/content/renderer/p2p/socket_client_impl.cc203
-rw-r--r--chromium/content/renderer/p2p/socket_client_impl.h82
-rw-r--r--chromium/content/renderer/p2p/socket_dispatcher.cc201
-rw-r--r--chromium/content/renderer/p2p/socket_dispatcher.h103
-rw-r--r--chromium/content/renderer/pepper/host_globals.cc2
-rw-r--r--chromium/content/renderer/pepper/pepper_broker_unittest.cc7
-rw-r--r--chromium/content/renderer/pepper/pepper_file_chooser_host.cc2
-rw-r--r--chromium/content/renderer/pepper/pepper_file_system_host.cc28
-rw-r--r--chromium/content/renderer/pepper/pepper_file_system_host.h8
-rw-r--r--chromium/content/renderer/pepper/pepper_graphics_2d_host.cc2
-rw-r--r--chromium/content/renderer/pepper/pepper_platform_audio_input.cc4
-rw-r--r--chromium/content/renderer/pepper/pepper_platform_audio_output.cc2
-rw-r--r--chromium/content/renderer/pepper/pepper_platform_audio_output_dev.cc10
-rw-r--r--chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc39
-rw-r--r--chromium/content/renderer/pepper/pepper_plugin_instance_impl.h4
-rw-r--r--chromium/content/renderer/pepper/pepper_plugin_registry.cc17
-rw-r--r--chromium/content/renderer/pepper/pepper_url_loader_host.cc4
-rw-r--r--chromium/content/renderer/pepper/pepper_video_encoder_host.cc6
-rw-r--r--chromium/content/renderer/pepper/plugin_instance_throttler_impl.h2
-rw-r--r--chromium/content/renderer/pepper/plugin_module.cc1
-rw-r--r--chromium/content/renderer/pepper/url_request_info_util.cc16
-rw-r--r--chromium/content/renderer/pepper/video_decoder_shim.cc30
-rw-r--r--chromium/content/renderer/pepper/video_decoder_shim.h4
-rw-r--r--chromium/content/renderer/pepper/video_encoder_shim.cc54
-rw-r--r--chromium/content/renderer/pepper/video_encoder_shim.h5
-rw-r--r--chromium/content/renderer/render_frame_impl.cc752
-rw-r--r--chromium/content/renderer/render_frame_impl.h112
-rw-r--r--chromium/content/renderer/render_frame_impl_browsertest.cc9
-rw-r--r--chromium/content/renderer/render_frame_proxy.cc45
-rw-r--r--chromium/content/renderer/render_frame_proxy.h9
-rw-r--r--chromium/content/renderer/render_process.h2
-rw-r--r--chromium/content/renderer/render_process_impl.cc8
-rw-r--r--chromium/content/renderer/render_process_impl.h2
-rw-r--r--chromium/content/renderer/render_thread_impl.cc226
-rw-r--r--chromium/content/renderer/render_thread_impl.h95
-rw-r--r--chromium/content/renderer/render_thread_impl_browsertest.cc44
-rw-r--r--chromium/content/renderer/render_view_browsertest.cc173
-rw-r--r--chromium/content/renderer/render_view_impl.cc917
-rw-r--r--chromium/content/renderer/render_view_impl.h194
-rw-r--r--chromium/content/renderer/render_widget.cc438
-rw-r--r--chromium/content/renderer/render_widget.h406
-rw-r--r--chromium/content/renderer/render_widget_browsertest.cc21
-rw-r--r--chromium/content/renderer/render_widget_fullscreen_pepper.cc6
-rw-r--r--chromium/content/renderer/render_widget_owner_delegate.h91
-rw-r--r--chromium/content/renderer/render_widget_unittest.cc75
-rw-r--r--chromium/content/renderer/renderer_blink_platform_impl.cc163
-rw-r--r--chromium/content/renderer/renderer_blink_platform_impl.h38
-rw-r--r--chromium/content/renderer/renderer_main.cc12
-rw-r--r--chromium/content/renderer/renderer_main_platform_delegate_mac.mm17
-rw-r--r--chromium/content/renderer/service_worker/controller_service_worker_connector.h2
-rw-r--r--chromium/content/renderer/service_worker/controller_service_worker_impl.cc2
-rw-r--r--chromium/content/renderer/service_worker/controller_service_worker_impl.h2
-rw-r--r--chromium/content/renderer/service_worker/embedded_worker_instance_client_impl.cc4
-rw-r--r--chromium/content/renderer/service_worker/embedded_worker_instance_client_impl.h5
-rw-r--r--chromium/content/renderer/service_worker/service_worker_context_client.cc743
-rw-r--r--chromium/content/renderer/service_worker/service_worker_context_client.h55
-rw-r--r--chromium/content/renderer/service_worker/service_worker_context_client_unittest.cc111
-rw-r--r--chromium/content/renderer/service_worker/service_worker_fetch_context_impl.cc13
-rw-r--r--chromium/content/renderer/service_worker/service_worker_fetch_context_impl.h17
-rw-r--r--chromium/content/renderer/service_worker/service_worker_network_provider.cc1
-rw-r--r--chromium/content/renderer/service_worker/service_worker_network_provider.h2
-rw-r--r--chromium/content/renderer/service_worker/service_worker_provider_context.cc86
-rw-r--r--chromium/content/renderer/service_worker/service_worker_provider_context.h7
-rw-r--r--chromium/content/renderer/service_worker/service_worker_provider_context_unittest.cc96
-rw-r--r--chromium/content/renderer/service_worker/service_worker_provider_state_for_client.cc18
-rw-r--r--chromium/content/renderer/service_worker/service_worker_provider_state_for_client.h106
-rw-r--r--chromium/content/renderer/service_worker/service_worker_subresource_loader.cc40
-rw-r--r--chromium/content/renderer/service_worker/service_worker_subresource_loader.h17
-rw-r--r--chromium/content/renderer/service_worker/service_worker_subresource_loader_unittest.cc86
-rw-r--r--chromium/content/renderer/service_worker/service_worker_timeout_timer.cc27
-rw-r--r--chromium/content/renderer/service_worker/service_worker_timeout_timer.h19
-rw-r--r--chromium/content/renderer/service_worker/service_worker_timeout_timer_unittest.cc47
-rw-r--r--chromium/content/renderer/service_worker/service_worker_type_converters.cc19
-rw-r--r--chromium/content/renderer/service_worker/service_worker_type_converters.h9
-rw-r--r--chromium/content/renderer/service_worker/service_worker_type_util.cc94
-rw-r--r--chromium/content/renderer/service_worker/service_worker_type_util.h5
-rw-r--r--chromium/content/renderer/service_worker/web_service_worker_impl.cc1
-rw-r--r--chromium/content/renderer/shared_worker/embedded_shared_worker_stub.cc22
-rw-r--r--chromium/content/renderer/shared_worker/embedded_shared_worker_stub.h7
-rw-r--r--chromium/content/renderer/shared_worker/shared_worker_factory_impl.cc11
-rw-r--r--chromium/content/renderer/shared_worker/shared_worker_factory_impl.h2
-rw-r--r--chromium/content/renderer/visual_state_browsertest.cc5
-rw-r--r--chromium/content/renderer/webclipboard_impl_browsertest.cc4
-rw-r--r--chromium/content/renderer/webgraphicscontext3d_provider_impl.cc13
-rw-r--r--chromium/content/renderer/webgraphicscontext3d_provider_impl.h15
-rw-r--r--chromium/content/renderer/worker_thread_registry.cc3
-rw-r--r--chromium/content/shell/BUILD.gn21
-rw-r--r--chromium/content/shell/android/BUILD.gn7
-rw-r--r--chromium/content/shell/common/layout_test.mojom5
-rw-r--r--chromium/content/shell/common/layout_test/layout_test_utils.cc28
-rw-r--r--chromium/content/shell/common/layout_test/layout_test_utils.h24
-rw-r--r--chromium/content/shell/common/shell_content_client.cc12
-rw-r--r--chromium/content/shell/common/shell_content_client.h1
-rw-r--r--chromium/content/shell/test_runner/BUILD.gn9
-rw-r--r--chromium/content/test/BUILD.gn144
-rw-r--r--chromium/content/utility/BUILD.gn14
-rw-r--r--chromium/content/utility/DEPS2
-rw-r--r--chromium/content/utility/utility_blink_platform_impl.cc24
-rw-r--r--chromium/content/utility/utility_blink_platform_impl.h37
-rw-r--r--chromium/content/utility/utility_blink_platform_with_sandbox_support_impl.h5
-rw-r--r--chromium/content/utility/utility_main.cc7
-rw-r--r--chromium/content/utility/utility_service_factory.cc40
-rw-r--r--chromium/content/utility/utility_thread_impl.cc10
-rw-r--r--chromium/content/utility/utility_thread_impl.h4
1769 files changed, 54428 insertions, 38188 deletions
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 e1952b748fd..ba226724fb5 100644
--- a/chromium/content/app/android/content_child_process_service_delegate.cc
+++ b/chromium/content/app/android/content_child_process_service_delegate.cc
@@ -46,16 +46,16 @@ class ChildProcessSurfaceManager : public gpu::ScopedSurfaceRequestConduit,
}
// Overriden from ScopedSurfaceRequestConduit:
- void ForwardSurfaceTextureForSurfaceRequest(
+ void ForwardSurfaceOwnerForSurfaceRequest(
const base::UnguessableToken& request_token,
- const gl::SurfaceTexture* surface_texture) override {
+ const gpu::SurfaceOwner* surface_owner) override {
JNIEnv* env = base::android::AttachCurrentThread();
content::
- Java_ContentChildProcessServiceDelegate_forwardSurfaceTextureForSurfaceRequest(
+ Java_ContentChildProcessServiceDelegate_forwardSurfaceForSurfaceRequest(
env, service_impl_,
base::android::UnguessableTokenAndroid::Create(env, request_token),
- surface_texture->j_surface_texture());
+ surface_owner->CreateJavaSurface().j_surface());
}
// Overridden from GpuSurfaceLookup:
diff --git a/chromium/content/app/content_main_runner_impl.cc b/chromium/content/app/content_main_runner_impl.cc
index 8d789ef1b9f..61ef09f6958 100644
--- a/chromium/content/app/content_main_runner_impl.cc
+++ b/chromium/content/app/content_main_runner_impl.cc
@@ -42,7 +42,9 @@
#include "components/tracing/common/trace_startup.h"
#include "content/app/mojo/mojo_init.h"
#include "content/browser/browser_process_sub_thread.h"
+#include "content/browser/browser_thread_impl.h"
#include "content/browser/startup_data_impl.h"
+#include "content/common/content_constants_internal.h"
#include "content/common/url_schemes.h"
#include "content/public/app/content_main_delegate.h"
#include "content/public/common/content_constants.h"
@@ -73,8 +75,8 @@
#include "base/trace_event/trace_event_etw_export_win.h"
#include "ui/display/win/dpi.h"
#elif defined(OS_MACOSX)
+#include "base/mac/mach_port_broker.h"
#include "base/power_monitor/power_monitor_device_source.h"
-#include "content/browser/mach_broker_mac.h"
#include "sandbox/mac/seatbelt_exec.h"
#endif // OS_WIN
@@ -119,6 +121,7 @@
#endif // OS_LINUX
#if !defined(CHROME_MULTIPLE_DLL_BROWSER)
+#include "content/child/field_trial.h"
#include "content/public/gpu/content_gpu_client.h"
#include "content/public/renderer/content_renderer_client.h"
#include "content/public/utility/content_utility_client.h"
@@ -169,40 +172,6 @@ namespace {
#endif
#endif
-// This sets up two singletons responsible for managing field trials. The
-// |field_trial_list| singleton lives on the stack and must outlive the Run()
-// method of the process.
-void InitializeFieldTrialAndFeatureList(
- std::unique_ptr<base::FieldTrialList>* field_trial_list) {
- const base::CommandLine& command_line =
- *base::CommandLine::ForCurrentProcess();
-
- // Initialize statistical testing infrastructure. We set the entropy
- // provider to nullptr to disallow non-browser processes from creating
- // their own one-time randomized trials; they should be created in the
- // browser process.
- field_trial_list->reset(new base::FieldTrialList(nullptr));
-
-// Ensure any field trials in browser are reflected into the child
-// process.
-#if defined(OS_WIN)
- base::FieldTrialList::CreateTrialsFromCommandLine(
- command_line, switches::kFieldTrialHandle, -1);
-#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
- // On POSIX systems that use the zygote, we get the trials from a shared
- // memory segment backed by an fd instead of the command line.
- base::FieldTrialList::CreateTrialsFromCommandLine(
- command_line, switches::kFieldTrialHandle,
- service_manager::kFieldTrialDescriptor);
-#endif
-
- std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
- base::FieldTrialList::CreateFeaturesFromCommandLine(
- command_line, switches::kEnableFeatures, switches::kDisableFeatures,
- feature_list.get());
- base::FeatureList::SetInstance(std::move(feature_list));
-}
-
#if defined(V8_USE_EXTERNAL_STARTUP_DATA)
void LoadV8SnapshotFile() {
#if defined(USE_V8_CONTEXT_SNAPSHOT)
@@ -434,57 +403,30 @@ bool IsRootProcess() {
} // namespace
-#if !defined(CHROME_MULTIPLE_DLL_CHILD)
-base::LazyInstance<ContentBrowserClient>::DestructorAtExit
- g_empty_content_browser_client = LAZY_INSTANCE_INITIALIZER;
-#endif // !CHROME_MULTIPLE_DLL_CHILD
-
-#if !defined(CHROME_MULTIPLE_DLL_BROWSER)
-base::LazyInstance<ContentGpuClient>::DestructorAtExit
- g_empty_content_gpu_client = LAZY_INSTANCE_INITIALIZER;
-base::LazyInstance<ContentRendererClient>::DestructorAtExit
- g_empty_content_renderer_client = LAZY_INSTANCE_INITIALIZER;
-base::LazyInstance<ContentUtilityClient>::DestructorAtExit
- g_empty_content_utility_client = LAZY_INSTANCE_INITIALIZER;
-#endif // !CHROME_MULTIPLE_DLL_BROWSER
-
class ContentClientInitializer {
public:
static void Set(const std::string& process_type,
ContentMainDelegate* delegate) {
ContentClient* content_client = GetContentClient();
#if !defined(CHROME_MULTIPLE_DLL_CHILD)
- if (process_type.empty()) {
+ if (process_type.empty())
content_client->browser_ = delegate->CreateContentBrowserClient();
- if (!content_client->browser_)
- content_client->browser_ = &g_empty_content_browser_client.Get();
- }
#endif // !CHROME_MULTIPLE_DLL_CHILD
#if !defined(CHROME_MULTIPLE_DLL_BROWSER)
base::CommandLine* cmd = base::CommandLine::ForCurrentProcess();
if (process_type == switches::kGpuProcess ||
cmd->HasSwitch(switches::kSingleProcess) ||
- (process_type.empty() && cmd->HasSwitch(switches::kInProcessGPU))) {
+ (process_type.empty() && cmd->HasSwitch(switches::kInProcessGPU)))
content_client->gpu_ = delegate->CreateContentGpuClient();
- if (!content_client->gpu_)
- content_client->gpu_ = &g_empty_content_gpu_client.Get();
- }
if (process_type == switches::kRendererProcess ||
- cmd->HasSwitch(switches::kSingleProcess)) {
+ cmd->HasSwitch(switches::kSingleProcess))
content_client->renderer_ = delegate->CreateContentRendererClient();
- if (!content_client->renderer_)
- content_client->renderer_ = &g_empty_content_renderer_client.Get();
- }
if (process_type == switches::kUtilityProcess ||
- cmd->HasSwitch(switches::kSingleProcess)) {
+ cmd->HasSwitch(switches::kSingleProcess))
content_client->utility_ = delegate->CreateContentUtilityClient();
- // TODO(scottmg): http://crbug.com/237249 Should be in _child.
- if (!content_client->utility_)
- content_client->utility_ = &g_empty_content_utility_client.Get();
- }
#endif // !CHROME_MULTIPLE_DLL_BROWSER
}
};
@@ -541,8 +483,7 @@ int RunZygote(ContentMainDelegate* delegate) {
MainFunctionParams main_params(command_line);
main_params.zygote_child = true;
- std::unique_ptr<base::FieldTrialList> field_trial_list;
- InitializeFieldTrialAndFeatureList(&field_trial_list);
+ InitializeFieldTrialAndFeatureList();
service_manager::SandboxType sandbox_type =
service_manager::SandboxTypeFromCommandLine(command_line);
@@ -779,7 +720,7 @@ int ContentMainRunnerImpl::Initialize(const ContentMainParams& params) {
}
if (!process_type.empty() && delegate_->ShouldSendMachPort(process_type)) {
- MachBroker::ChildSendTaskPortToParent();
+ base::MachPortBroker::ChildSendTaskPortToParent(kMachBootstrapName);
}
#endif
@@ -901,12 +842,13 @@ int ContentMainRunnerImpl::Run(bool start_service_manager_only) {
std::string process_type =
command_line.GetSwitchValueASCII(switches::kProcessType);
+#if !defined(CHROME_MULTIPLE_DLL_BROWSER)
// Run this logic on all child processes. Zygotes will run this at a later
// point in time when the command line has been updated.
- std::unique_ptr<base::FieldTrialList> field_trial_list;
if (!process_type.empty() &&
process_type != service_manager::switches::kZygoteProcess)
- InitializeFieldTrialAndFeatureList(&field_trial_list);
+ InitializeFieldTrialAndFeatureList();
+#endif
MainFunctionParams main_params(command_line);
main_params.ui_task = ui_task_;
@@ -936,7 +878,11 @@ int ContentMainRunnerImpl::Run(bool start_service_manager_only) {
base::TaskScheduler::Create("Browser");
}
- delegate_->PreContentInitialization();
+ // Register the TaskExecutor for posting task to the BrowserThreads. It is
+ // incorrect to post to a BrowserThread before this point.
+ BrowserThreadImpl::CreateTaskExecutor();
+
+ delegate_->PreCreateMainMessageLoop();
// Create a MessageLoop if one does not already exist for the current
// thread. This thread won't be promoted as BrowserThread::UI until
@@ -944,6 +890,7 @@ int ContentMainRunnerImpl::Run(bool start_service_manager_only) {
if (!base::MessageLoopCurrentForUI::IsSet())
main_message_loop_ = std::make_unique<base::MessageLoopForUI>();
+ delegate_->PostEarlyInitialization();
return RunBrowserProcessMain(main_params, delegate_);
}
#endif // !defined(CHROME_MULTIPLE_DLL_CHILD)
diff --git a/chromium/content/app/strings/content_strings.grd b/chromium/content/app/strings/content_strings.grd
index e08494f1c85..79f5ebed630 100644
--- a/chromium/content/app/strings/content_strings.grd
+++ b/chromium/content/app/strings/content_strings.grd
@@ -660,6 +660,10 @@ below:
exit full screen
</message>
+ <message name="IDS_AX_MEDIA_DISPLAY_CUT_OUT_FULL_SCREEN_BUTTON" desc="Accessibility role description for display cutout fullscreen button">
+ toggle display cutout fullscreen
+ </message>
+
<message name="IDS_AX_MEDIA_ENTER_PICTURE_IN_PICTURE_BUTTON" desc="Accessibility role description for enter Picture-in-Picture button">
enter picture-in-picture
</message>
@@ -740,6 +744,10 @@ below:
exit full screen
</message>
+ <message name="IDS_AX_MEDIA_DISPLAY_CUT_OUT_FULL_SCREEN_BUTTON_HELP" desc="Accessibility help description for display cutout fullscreen button">
+ toggle fullscreen into display cutout area
+ </message>
+
<message name="IDS_AX_MEDIA_ENTER_PICTURE_IN_PICTURE_BUTTON_HELP" desc="Accessibility help description for enter Picture-in-Picture button">
play video in picture-in-picture mode
</message>
diff --git a/chromium/content/app/strings/translations/content_strings_am.xtb b/chromium/content/app/strings/translations/content_strings_am.xtb
index e68c2ac0791..7213b247e5e 100644
--- a/chromium/content/app/strings/translations/content_strings_am.xtb
+++ b/chromium/content/app/strings/translations/content_strings_am.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">የዛፍ ፍርግርግ</translation>
<translation id="1822429046913737220">ጥዋት/ከሰዓት</translation>
<translation id="1832974991323546415">በርቀት መሳሪያ ላይ አጫውት</translation>
+<translation id="1838818994221231429">ሙሉ ማያ ገጽን ወደ የተቆረጠው የማሳያ አካባቢ ይቀይሩ</translation>
<translation id="190587075670221089">ስረዛ</translation>
<translation id="1907737156431278478">ምሳሌ</translation>
<translation id="1921819250265091946">ቀቀ</translation>
@@ -103,6 +104,7 @@
<translation id="4664250907885839816">ከ«<ph name="ATSIGN" />» በኋላ የሚመጣ ክፍል የ«<ph name="INVALIDCHARACTER" />» ምልክት መያዝ የለበትም።</translation>
<translation id="4668956016107839909">ቅጥያዎች</translation>
<translation id="4742539557769756338">ሽፋን</translation>
+<translation id="4748357248530471599">የተቆረጠው የማሳያ ክፍል ሙሉ ማያ ገጽን ይቀያይሩ</translation>
<translation id="4757246831282535685">የትር ፓነል</translation>
<translation id="4763480195061959176">ቪዲዮ</translation>
<translation id="479989351350248267">ፈልግ</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_ar.xtb b/chromium/content/app/strings/translations/content_strings_ar.xtb
index 380b81cc11d..e75e94de136 100644
--- a/chromium/content/app/strings/translations/content_strings_ar.xtb
+++ b/chromium/content/app/strings/translations/content_strings_ar.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">شبكة متفرعة</translation>
<translation id="1822429046913737220">صباحًا/مساءً</translation>
<translation id="1832974991323546415">تشغيل على جهاز بعيد</translation>
+<translation id="1838818994221231429">تبديل وضع ملء الشاشة إلى صورة مقطوعة للشاشة</translation>
<translation id="190587075670221089">حذف</translation>
<translation id="1907737156431278478">مثال</translation>
<translation id="1921819250265091946">يوم</translation>
@@ -103,6 +104,7 @@
<translation id="4664250907885839816">يجب ألا يشتمل الجزء الذي يلي العلامة "<ph name="ATSIGN" />" على الرمز "<ph name="INVALIDCHARACTER" />".</translation>
<translation id="4668956016107839909">ملحق</translation>
<translation id="4742539557769756338">غلاف</translation>
+<translation id="4748357248530471599">تبديل صورة مقطوعة للشاشة إلى وضع ملء الشاشة</translation>
<translation id="4757246831282535685">لوحة علامة التبويب</translation>
<translation id="4763480195061959176">فيديو</translation>
<translation id="479989351350248267">بحث</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_bg.xtb b/chromium/content/app/strings/translations/content_strings_bg.xtb
index a9d48c867bb..6a49487bf0f 100644
--- a/chromium/content/app/strings/translations/content_strings_bg.xtb
+++ b/chromium/content/app/strings/translations/content_strings_bg.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">дървовидна таблица</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">възпроизвеждане на отдалечено устройство</translation>
+<translation id="1838818994221231429">превключване между цял екран и екран с прорез</translation>
<translation id="190587075670221089">изтриване</translation>
<translation id="1907737156431278478">пример</translation>
<translation id="1921819250265091946">дд</translation>
@@ -103,6 +104,7 @@
<translation id="4664250907885839816">Текстът след „<ph name="ATSIGN" />“ не бива да съдържа символа „<ph name="INVALIDCHARACTER" />“.</translation>
<translation id="4668956016107839909">приложение</translation>
<translation id="4742539557769756338">корица</translation>
+<translation id="4748357248530471599">превключване между прорез на екрана и цял екран</translation>
<translation id="4757246831282535685">панел с раздели</translation>
<translation id="4763480195061959176">видео</translation>
<translation id="479989351350248267">search</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_bn.xtb b/chromium/content/app/strings/translations/content_strings_bn.xtb
index ed8003fb8cb..bf23203b1ac 100644
--- a/chromium/content/app/strings/translations/content_strings_bn.xtb
+++ b/chromium/content/app/strings/translations/content_strings_bn.xtb
@@ -5,7 +5,7 @@
<translation id="1020833440720551630">অডিও ট্র্যাক মিউট করুন</translation>
<translation id="10623998915015855">টগল বোতাম</translation>
<translation id="1088086359088493902">সেকেন্ড</translation>
-<translation id="1171774979989969504">অনুগ্রহ করে কোনও ইমেল আইডি লিখুন।</translation>
+<translation id="1171774979989969504">অনুগ্রহ করে কোন ইমেল আইডি লিখুন:</translation>
<translation id="1178581264944972037">বিরতি</translation>
<translation id="1188858454923323853">পরিপূরক</translation>
<translation id="1206619573307042055">marquee</translation>
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">ট্রি গ্রিড</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">রিমোট ডিভাইসে প্লে করুন</translation>
+<translation id="1838818994221231429">ডিসপ্লে কাট-আউট থেকে ফুল-স্ক্রিনে টগল করুন</translation>
<translation id="190587075670221089">মোছা হচ্ছে</translation>
<translation id="1907737156431278478">উদাহরণ</translation>
<translation id="1921819250265091946">dd</translation>
@@ -103,6 +104,7 @@
<translation id="4664250907885839816">'<ph name="ATSIGN" />' অনুসরণ করে এমন একটি অংশে '<ph name="INVALIDCHARACTER" />' চিহ্ন থাকা উচিত নয়৷</translation>
<translation id="4668956016107839909">পরিশিষ্ট</translation>
<translation id="4742539557769756338">কভার</translation>
+<translation id="4748357248530471599">ডিসপ্লে কাট-আউট ফুল-স্ক্রিনে টগল করুন</translation>
<translation id="4757246831282535685">ট্যাব প্যানেল</translation>
<translation id="4763480195061959176">ভিডিও</translation>
<translation id="479989351350248267">search</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_ca.xtb b/chromium/content/app/strings/translations/content_strings_ca.xtb
index 391d68d1d31..d396d40d4bb 100644
--- a/chromium/content/app/strings/translations/content_strings_ca.xtb
+++ b/chromium/content/app/strings/translations/content_strings_ca.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">quadrícula d'arbre</translation>
<translation id="1822429046913737220">a. m./p. m.</translation>
<translation id="1832974991323546415">reprodueix al dispositiu remot</translation>
+<translation id="1838818994221231429">activa o desactiva la pantalla completa a l'àrea del retall de pantalla</translation>
<translation id="190587075670221089">supressió</translation>
<translation id="1907737156431278478">exemple</translation>
<translation id="1921819250265091946">dd</translation>
@@ -103,6 +104,7 @@
<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="4742539557769756338">portada</translation>
+<translation id="4748357248530471599">activa o desactiva la pantalla completa al retall de pantalla</translation>
<translation id="4757246831282535685">tauler de pestanyes</translation>
<translation id="4763480195061959176">vídeo</translation>
<translation id="479989351350248267">cerca</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_cs.xtb b/chromium/content/app/strings/translations/content_strings_cs.xtb
index f6e35d6f41a..bfa537c9a77 100644
--- a/chromium/content/app/strings/translations/content_strings_cs.xtb
+++ b/chromium/content/app/strings/translations/content_strings_cs.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">stromová mřížka</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">přehrát ve vzdáleném zařízení</translation>
+<translation id="1838818994221231429">přepnout celou obrazovku na oblast výřezu displeje</translation>
<translation id="190587075670221089">smazání</translation>
<translation id="1907737156431278478">příklad</translation>
<translation id="1921819250265091946">dd</translation>
@@ -103,6 +104,7 @@
<translation id="4664250907885839816">Část za znakem <ph name="ATSIGN" /> nesmí obsahovat znak <ph name="INVALIDCHARACTER" />.</translation>
<translation id="4668956016107839909">příloha</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>
<translation id="4763480195061959176">video</translation>
<translation id="479989351350248267">search</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_da.xtb b/chromium/content/app/strings/translations/content_strings_da.xtb
index 836c37f9680..2f768137392 100644
--- a/chromium/content/app/strings/translations/content_strings_da.xtb
+++ b/chromium/content/app/strings/translations/content_strings_da.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">trægitter</translation>
<translation id="1822429046913737220">f.m./e.m.</translation>
<translation id="1832974991323546415">afspil på en enhed via fjernadgang</translation>
+<translation id="1838818994221231429">skift fra fuld skærm til skærmhak</translation>
<translation id="190587075670221089">sletning</translation>
<translation id="1907737156431278478">eksempel</translation>
<translation id="1921819250265091946">dd</translation>
@@ -103,6 +104,7 @@
<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="4742539557769756338">forside</translation>
+<translation id="4748357248530471599">skift fra skærmhak til fuld skærm</translation>
<translation id="4757246831282535685">fanepanel</translation>
<translation id="4763480195061959176">video</translation>
<translation id="479989351350248267">søg</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_de.xtb b/chromium/content/app/strings/translations/content_strings_de.xtb
index f2f2ca89074..93cebecf40a 100644
--- a/chromium/content/app/strings/translations/content_strings_de.xtb
+++ b/chromium/content/app/strings/translations/content_strings_de.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">Baumraster</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">auf Remote-Gerät wiedergeben</translation>
+<translation id="1838818994221231429">Ansicht von Vollbildmodus in Display-Aussparung ein-/ausschalten</translation>
<translation id="190587075670221089">Löschen</translation>
<translation id="1907737156431278478">Beispiel</translation>
<translation id="1921819250265091946">tt</translation>
@@ -103,6 +104,7 @@
<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="4742539557769756338">Titelseite</translation>
+<translation id="4748357248530471599">Vollbildmodus mit Display-Aussparung ein-/ausschalten</translation>
<translation id="4757246831282535685">Tabsteuerfeld</translation>
<translation id="4763480195061959176">Video</translation>
<translation id="479989351350248267">Suchen</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_el.xtb b/chromium/content/app/strings/translations/content_strings_el.xtb
index 5d16e526ad0..1b24c5048c8 100644
--- a/chromium/content/app/strings/translations/content_strings_el.xtb
+++ b/chromium/content/app/strings/translations/content_strings_el.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">πλέγμα δέντρου</translation>
<translation id="1822429046913737220">Π.Μ./Μ.Μ.</translation>
<translation id="1832974991323546415">αναπαραγωγή σε απομακρυσμένη συσκευή</translation>
+<translation id="1838818994221231429">εναλλαγή πλήρους οθόνης σε περιοχή εγκοπής οθόνης</translation>
<translation id="190587075670221089">διαγραφή</translation>
<translation id="1907737156431278478">παράδειγμα</translation>
<translation id="1921819250265091946">ηη</translation>
@@ -103,6 +104,7 @@
<translation id="4664250907885839816">Το τμήμα της διεύθυνσης μετά το σύμβολο "<ph name="ATSIGN" />" δεν πρέπει να περιέχει το σύμβολο "<ph name="INVALIDCHARACTER" />".</translation>
<translation id="4668956016107839909">παράρτημα</translation>
<translation id="4742539557769756338">εξώφυλλο</translation>
+<translation id="4748357248530471599">εναλλαγή πλήρους οθόνης εγκοπής οθόνης</translation>
<translation id="4757246831282535685">παράθυρο καρτέλας</translation>
<translation id="4763480195061959176">βίντεο</translation>
<translation id="479989351350248267">search</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 c63e0611cc2..229660dd131 100644
--- a/chromium/content/app/strings/translations/content_strings_en-GB.xtb
+++ b/chromium/content/app/strings/translations/content_strings_en-GB.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">tree grid</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">play on remote device</translation>
+<translation id="1838818994221231429">toggle full screen into display cutout area</translation>
<translation id="190587075670221089">deletion</translation>
<translation id="1907737156431278478">example</translation>
<translation id="1921819250265091946">dd</translation>
@@ -103,6 +104,7 @@
<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="4742539557769756338">cover</translation>
+<translation id="4748357248530471599">toggle display cutout full screen</translation>
<translation id="4757246831282535685">tab panel</translation>
<translation id="4763480195061959176">video</translation>
<translation id="479989351350248267">search</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 6c990c4fa8b..546330e9062 100644
--- a/chromium/content/app/strings/translations/content_strings_es-419.xtb
+++ b/chromium/content/app/strings/translations/content_strings_es-419.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">cuadrícula de árbol</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">jugar en el dispositivo remoto</translation>
+<translation id="1838818994221231429">activar o desactivar la pantalla completa en el área de corte de pantalla</translation>
<translation id="190587075670221089">contenido borrado</translation>
<translation id="1907737156431278478">ejemplo</translation>
<translation id="1921819250265091946">dd</translation>
@@ -103,6 +104,7 @@
<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="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>
<translation id="4763480195061959176">video</translation>
<translation id="479989351350248267">search</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_es.xtb b/chromium/content/app/strings/translations/content_strings_es.xtb
index 370c170033c..decbe9e4df0 100644
--- a/chromium/content/app/strings/translations/content_strings_es.xtb
+++ b/chromium/content/app/strings/translations/content_strings_es.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">cuadrícula de árbol</translation>
<translation id="1822429046913737220">A.M./P.M.</translation>
<translation id="1832974991323546415">reproducir en dispositivo remoto</translation>
+<translation id="1838818994221231429">activar pantalla completa en el área de recorte de la pantalla</translation>
<translation id="190587075670221089">eliminación</translation>
<translation id="1907737156431278478">ejemplo</translation>
<translation id="1921819250265091946">dd</translation>
@@ -103,6 +104,7 @@
<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="4742539557769756338">portada</translation>
+<translation id="4748357248530471599">activar pantalla completa en el recorte de la pantalla</translation>
<translation id="4757246831282535685">panel de pestaña</translation>
<translation id="4763480195061959176">vídeo</translation>
<translation id="479989351350248267">buscar</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_et.xtb b/chromium/content/app/strings/translations/content_strings_et.xtb
index 0490fd119df..7e674c7db33 100644
--- a/chromium/content/app/strings/translations/content_strings_et.xtb
+++ b/chromium/content/app/strings/translations/content_strings_et.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">puuruudustik</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">kaugseadmes esitamine</translation>
+<translation id="1838818994221231429">ekraani väljalõike piirkonnas täisekraanrežiimi sisse-/väljalülitamine</translation>
<translation id="190587075670221089">kustutamine</translation>
<translation id="1907737156431278478">näide</translation>
<translation id="1921819250265091946">pp</translation>
@@ -103,6 +104,7 @@
<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="4742539557769756338">kaas</translation>
+<translation id="4748357248530471599">ekraani väljalõike täisekraanrežiimi sisse-/väljalülitamine</translation>
<translation id="4757246831282535685">vahelehepaneel</translation>
<translation id="4763480195061959176">video</translation>
<translation id="479989351350248267">otsing</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_fa.xtb b/chromium/content/app/strings/translations/content_strings_fa.xtb
index 6a0cbe17b8f..1fbae91dccb 100644
--- a/chromium/content/app/strings/translations/content_strings_fa.xtb
+++ b/chromium/content/app/strings/translations/content_strings_fa.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">شبکه درختی</translation>
<translation id="1822429046913737220">ق.ظ/ب.ظ</translation>
<translation id="1832974991323546415">پخش در دستگاه راه دور</translation>
+<translation id="1838818994221231429">جابه‌جایی تمام‌صفحه به ناحیه برش نمایشگر</translation>
<translation id="190587075670221089">حذف</translation>
<translation id="1907737156431278478">مثال</translation>
<translation id="1921819250265091946">dd</translation>
@@ -103,6 +104,7 @@
<translation id="4664250907885839816">قسمت بعد از «<ph name="ATSIGN" />» نباید حاوی نماد «<ph name="INVALIDCHARACTER" />» باشد.</translation>
<translation id="4668956016107839909">ضمیمه</translation>
<translation id="4742539557769756338">جلد</translation>
+<translation id="4748357248530471599">جابجایی برش نمایشگر تمام‌صفحه</translation>
<translation id="4757246831282535685">پانل برگه</translation>
<translation id="4763480195061959176">ویدئو</translation>
<translation id="479989351350248267">جستجو</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_fi.xtb b/chromium/content/app/strings/translations/content_strings_fi.xtb
index 7d8bdda97b3..43e44a61b07 100644
--- a/chromium/content/app/strings/translations/content_strings_fi.xtb
+++ b/chromium/content/app/strings/translations/content_strings_fi.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">puuruudukko</translation>
<translation id="1822429046913737220">AP/IP</translation>
<translation id="1832974991323546415">toista etälaitteella</translation>
+<translation id="1838818994221231429">näyttölovi on/ei ole osa koko näytön tilaa</translation>
<translation id="190587075670221089">poisto</translation>
<translation id="1907737156431278478">esimerkki</translation>
<translation id="1921819250265091946">pp</translation>
@@ -103,6 +104,7 @@
<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="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>
<translation id="4763480195061959176">video</translation>
<translation id="479989351350248267">haku</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_fil.xtb b/chromium/content/app/strings/translations/content_strings_fil.xtb
index 16304048147..b57abce9893 100644
--- a/chromium/content/app/strings/translations/content_strings_fil.xtb
+++ b/chromium/content/app/strings/translations/content_strings_fil.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">tree grid</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">i-play sa malayuang device</translation>
+<translation id="1838818994221231429">i-toggle ang fullscreen sa bahagi ng cutout ng display</translation>
<translation id="190587075670221089">pag-delete</translation>
<translation id="1907737156431278478">halimbawa</translation>
<translation id="1921819250265091946">dd</translation>
@@ -103,6 +104,7 @@
<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="4742539557769756338">cover</translation>
+<translation id="4748357248530471599">i-toggle ang fullscreen ng cutout ng display</translation>
<translation id="4757246831282535685">panel ng tab</translation>
<translation id="4763480195061959176">video</translation>
<translation id="479989351350248267">search</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_fr.xtb b/chromium/content/app/strings/translations/content_strings_fr.xtb
index f7877500711..391f83d95ef 100644
--- a/chromium/content/app/strings/translations/content_strings_fr.xtb
+++ b/chromium/content/app/strings/translations/content_strings_fr.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">arborescence</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">lire sur un appareil à distance</translation>
+<translation id="1838818994221231429">activer/désactiver le passage du mode plein écran en encoche</translation>
<translation id="190587075670221089">suppression</translation>
<translation id="1907737156431278478">exemple</translation>
<translation id="1921819250265091946">jj</translation>
@@ -103,6 +104,7 @@
<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="4742539557769756338">couverture</translation>
+<translation id="4748357248530471599">activer/désactiver plein écran en encoche</translation>
<translation id="4757246831282535685">panneau des onglets</translation>
<translation id="4763480195061959176">vidéo</translation>
<translation id="479989351350248267">rechercher</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_gu.xtb b/chromium/content/app/strings/translations/content_strings_gu.xtb
index 3fd9c62cdf7..ac414a8a3a7 100644
--- a/chromium/content/app/strings/translations/content_strings_gu.xtb
+++ b/chromium/content/app/strings/translations/content_strings_gu.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">ટ્રી ગ્રિડ</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">રિમોટ ઉપકરણ પર ચલાવો</translation>
+<translation id="1838818994221231429">પૂર્ણસ્ક્રીનને ડિસ્પ્લેમાં જ સામેલ વિસ્તારમાં જ ટૉગલ કરો</translation>
<translation id="190587075670221089">ડિલીટ કરો</translation>
<translation id="1907737156431278478">ઉદાહરણ</translation>
<translation id="1921819250265091946">dd</translation>
@@ -103,6 +104,7 @@
<translation id="4664250907885839816">'<ph name="ATSIGN" />' ને અનુસરી રહેલા ભાગમાં '<ph name="INVALIDCHARACTER" />' પ્રતીક શામેલ હોવું જોઈએ નહીં.</translation>
<translation id="4668956016107839909">જોડાણ</translation>
<translation id="4742539557769756338">કવર</translation>
+<translation id="4748357248530471599">ડિસ્પ્લેમાં જ સામેલ પૂર્ણસ્ક્રીન ટૉગલ કરો</translation>
<translation id="4757246831282535685">ટેબ પેનલ</translation>
<translation id="4763480195061959176">વિડિઓ</translation>
<translation id="479989351350248267">search</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_hi.xtb b/chromium/content/app/strings/translations/content_strings_hi.xtb
index d9dee1f9355..5f9ac7f2f5b 100644
--- a/chromium/content/app/strings/translations/content_strings_hi.xtb
+++ b/chromium/content/app/strings/translations/content_strings_hi.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">ट्री ग्रिड</translation>
<translation id="1822429046913737220">पूर्वाह्न/अपराह्न</translation>
<translation id="1832974991323546415">दूरस्थ डिवाइस पर चलाएं</translation>
+<translation id="1838818994221231429">डिसप्ले कटआउट क्षेत्र में फ़ुलस्क्रीन टॉगल करें</translation>
<translation id="190587075670221089">मिटाना</translation>
<translation id="1907737156431278478">उदाहरण</translation>
<translation id="1921819250265091946">dd</translation>
@@ -85,7 +86,7 @@
<translation id="3920932319529768807">निष्कर्ष</translation>
<translation id="3924558731517983934">ऐप्लिकेशन</translation>
<translation id="3944740393230681990">प्रस्तावना</translation>
-<translation id="3960700977367013758">स्क्रॉल बार</translation>
+<translation id="3960700977367013758">स्क्रोल बार</translation>
<translation id="4103419683916926126">मिलीसेकंड</translation>
<translation id="4151657705144244502">ग्राफ़‍िक</translation>
<translation id="4193965531860883258">भूमिका</translation>
@@ -103,6 +104,7 @@
<translation id="4664250907885839816">'<ph name="ATSIGN" />' के बाद आने वाले भाग में '<ph name="INVALIDCHARACTER" />' प्रतीक शामिल नहीं होना चाहिए.</translation>
<translation id="4668956016107839909">परिशिष्ट</translation>
<translation id="4742539557769756338">कवर</translation>
+<translation id="4748357248530471599">डिसप्ले कटआउट फ़ुलस्क्रीन टॉगल करें</translation>
<translation id="4757246831282535685">टैब फलक</translation>
<translation id="4763480195061959176">वीडियो</translation>
<translation id="479989351350248267">search</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_hr.xtb b/chromium/content/app/strings/translations/content_strings_hr.xtb
index bbf447885d3..354c4accefd 100644
--- a/chromium/content/app/strings/translations/content_strings_hr.xtb
+++ b/chromium/content/app/strings/translations/content_strings_hr.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">rešetka u obliku stabla</translation>
<translation id="1822429046913737220">prijepodne/poslijepodne</translation>
<translation id="1832974991323546415">reproduciraj na udaljenom uređaju</translation>
+<translation id="1838818994221231429">prebacite cijeli zaslon u područje za urez na zaslonu</translation>
<translation id="190587075670221089">brisanje</translation>
<translation id="1907737156431278478">primjer</translation>
<translation id="1921819250265091946">dd</translation>
@@ -103,6 +104,7 @@
<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="4742539557769756338">naslovnica</translation>
+<translation id="4748357248530471599">prebacite urez na zaslonu u cijeli zaslon</translation>
<translation id="4757246831282535685">ploča kartice</translation>
<translation id="4763480195061959176">videozapis</translation>
<translation id="479989351350248267">search</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_hu.xtb b/chromium/content/app/strings/translations/content_strings_hu.xtb
index a5ba319109d..c16b586fb98 100644
--- a/chromium/content/app/strings/translations/content_strings_hu.xtb
+++ b/chromium/content/app/strings/translations/content_strings_hu.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">farács</translation>
<translation id="1822429046913737220">de./du.</translation>
<translation id="1832974991323546415">lejátszás távoli eszközön</translation>
+<translation id="1838818994221231429">váltás teljes képernyőre a képernyőkivágás területén</translation>
<translation id="190587075670221089">törlés</translation>
<translation id="1907737156431278478">példa</translation>
<translation id="1921819250265091946">nn</translation>
@@ -103,6 +104,7 @@
<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="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>
<translation id="4763480195061959176">video</translation>
<translation id="479989351350248267">search</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_id.xtb b/chromium/content/app/strings/translations/content_strings_id.xtb
index e1c21fd0162..adc14868eb9 100644
--- a/chromium/content/app/strings/translations/content_strings_id.xtb
+++ b/chromium/content/app/strings/translations/content_strings_id.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">kisi pohon</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">putar di perangkat jarak jauh</translation>
+<translation id="1838818994221231429">mengalihkan layar penuh ke area potongan layar</translation>
<translation id="190587075670221089">penghapusan</translation>
<translation id="1907737156431278478">contoh</translation>
<translation id="1921819250265091946">hh</translation>
@@ -103,6 +104,7 @@
<translation id="4664250907885839816">Bagian setelah '<ph name="ATSIGN" />' tidak boleh berisi simbol '<ph name="INVALIDCHARACTER" />'.</translation>
<translation id="4668956016107839909">lampiran</translation>
<translation id="4742539557769756338">sampul</translation>
+<translation id="4748357248530471599">mengalihkan ke layar penuh potongan layar</translation>
<translation id="4757246831282535685">panel tab</translation>
<translation id="4763480195061959176">video</translation>
<translation id="479989351350248267">search</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_it.xtb b/chromium/content/app/strings/translations/content_strings_it.xtb
index 283ac3b20d4..ecbcfe24e78 100644
--- a/chromium/content/app/strings/translations/content_strings_it.xtb
+++ b/chromium/content/app/strings/translations/content_strings_it.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">griglia ad albero</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">riproduci su dispositivo remoto</translation>
+<translation id="1838818994221231429">attiva/disattiva lo schermo intero nell'area tagliata dalla visualizzazione</translation>
<translation id="190587075670221089">eliminazione</translation>
<translation id="1907737156431278478">esempio</translation>
<translation id="1921819250265091946">gg</translation>
@@ -103,6 +104,7 @@
<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="4742539557769756338">copertina</translation>
+<translation id="4748357248530471599">attiva/disattiva lo schermo intero tagliato dalla visualizzazione</translation>
<translation id="4757246831282535685">riquadro a schede</translation>
<translation id="4763480195061959176">video</translation>
<translation id="479989351350248267">ricerca</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_iw.xtb b/chromium/content/app/strings/translations/content_strings_iw.xtb
index e0a2ae56a94..05c05d45950 100644
--- a/chromium/content/app/strings/translations/content_strings_iw.xtb
+++ b/chromium/content/app/strings/translations/content_strings_iw.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">רשת של עץ</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">הפעלה במכשיר מרוחק</translation>
+<translation id="1838818994221231429">מעבר ממסך מלא לתצוגה באזור המגרעת של המסך</translation>
<translation id="190587075670221089">מחיקה</translation>
<translation id="1907737156431278478">דוגמה</translation>
<translation id="1921819250265091946">dd</translation>
@@ -103,6 +104,7 @@
<translation id="4664250907885839816">חלק ולאחריו '<ph name="ATSIGN" />' לא אמור לכלול את הסמל '<ph name="INVALIDCHARACTER" />'.</translation>
<translation id="4668956016107839909">נספח</translation>
<translation id="4742539557769756338">שער</translation>
+<translation id="4748357248530471599">מעבר מתצוגה באזור המגרעת של המסך למסך מלא</translation>
<translation id="4757246831282535685">חלונית כרטיסיות</translation>
<translation id="4763480195061959176">סרטוני וידאו</translation>
<translation id="479989351350248267">Search</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_ja.xtb b/chromium/content/app/strings/translations/content_strings_ja.xtb
index c8de1475332..8d633af1344 100644
--- a/chromium/content/app/strings/translations/content_strings_ja.xtb
+++ b/chromium/content/app/strings/translations/content_strings_ja.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">ツリーグリッド</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">リモート デバイスで再生</translation>
+<translation id="1838818994221231429">全画面表示をディスプレイ カットアウト領域に合わせた表示に切り替えます</translation>
<translation id="190587075670221089">削除</translation>
<translation id="1907737156431278478">例</translation>
<translation id="1921819250265091946">日</translation>
@@ -103,6 +104,7 @@
<translation id="4664250907885839816">「<ph name="ATSIGN" />」に続く文字列に記号「<ph name="INVALIDCHARACTER" />」を使用しないでください。</translation>
<translation id="4668956016107839909">付録</translation>
<translation id="4742539557769756338">表紙</translation>
+<translation id="4748357248530471599">ディスプレイ カットアウトに合わせた全画面表示に切り替えます</translation>
<translation id="4757246831282535685">タブパネル</translation>
<translation id="4763480195061959176">動画</translation>
<translation id="479989351350248267">検索</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_kn.xtb b/chromium/content/app/strings/translations/content_strings_kn.xtb
index 0783881a705..61ca4f14f37 100644
--- a/chromium/content/app/strings/translations/content_strings_kn.xtb
+++ b/chromium/content/app/strings/translations/content_strings_kn.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">ಟ್ರೀ ಗ್ರಿಡ್</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">ರಿಮೋಟ್ ಸಾಧನದಲ್ಲಿ ಪ್ಲೇ ಮಾಡಿ</translation>
+<translation id="1838818994221231429">ಪೂರ್ಣ ಸ್ಕ್ರೀನ್ ಅನ್ನು ಡಿಸ್‌ಪ್ಲೇ ಕಟ್‌ಔಟ್ ಪ್ರದೇಶವಾಗಿ ಟಾಗಲ್ ಮಾಡಿ</translation>
<translation id="190587075670221089">ಅಳಿಸುವಿಕೆ</translation>
<translation id="1907737156431278478">ಉದಾಹರಣೆ</translation>
<translation id="1921819250265091946">ದಿದಿ</translation>
@@ -103,6 +104,7 @@
<translation id="4664250907885839816">'<ph name="ATSIGN" />' ನಂತರದ ಭಾಗವು '<ph name="INVALIDCHARACTER" />' ಚಿಹ್ನೆಯನ್ನು ಒಳಗೊಂಡಿರಬಾರದು.</translation>
<translation id="4668956016107839909">ಅನುಬಂಧ</translation>
<translation id="4742539557769756338">ಕವರ್</translation>
+<translation id="4748357248530471599">ಡಿಸ್‌ಪ್ಲೇ ಕಟ್‌ಔಟ್ ಪೂರ್ಣ ಸ್ಕ್ರೀನ್ ಟಾಗಲ್ ಮಾಡಿ</translation>
<translation id="4757246831282535685">ಟ್ಯಾಬ್ ಫಲಕ</translation>
<translation id="4763480195061959176">ವೀಡಿಯೊ</translation>
<translation id="479989351350248267">search</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_ko.xtb b/chromium/content/app/strings/translations/content_strings_ko.xtb
index b9f4f9eac1e..4e41361c2e3 100644
--- a/chromium/content/app/strings/translations/content_strings_ko.xtb
+++ b/chromium/content/app/strings/translations/content_strings_ko.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">트리 격자</translation>
<translation id="1822429046913737220">오전/오후</translation>
<translation id="1832974991323546415">원격 기기에서 재생</translation>
+<translation id="1838818994221231429">전체화면을 디스플레이 컷아웃 영역으로 전환</translation>
<translation id="190587075670221089">삭제</translation>
<translation id="1907737156431278478">예시</translation>
<translation id="1921819250265091946">일</translation>
@@ -103,6 +104,7 @@
<translation id="4664250907885839816">'<ph name="ATSIGN" />' 다음 부분에 '<ph name="INVALIDCHARACTER" />' 기호가 포함되면 안됩니다.</translation>
<translation id="4668956016107839909">부록</translation>
<translation id="4742539557769756338">표지</translation>
+<translation id="4748357248530471599">디스플레이 컷아웃을 전체화면으로 전환</translation>
<translation id="4757246831282535685">탭 패널</translation>
<translation id="4763480195061959176">동영상</translation>
<translation id="479989351350248267">검색</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_lt.xtb b/chromium/content/app/strings/translations/content_strings_lt.xtb
index d3c644686ea..234fba4791e 100644
--- a/chromium/content/app/strings/translations/content_strings_lt.xtb
+++ b/chromium/content/app/strings/translations/content_strings_lt.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">medžio tinklelis</translation>
<translation id="1822429046913737220">iki pietų / po pietų</translation>
<translation id="1832974991323546415">leisti naudojant nuotolinį įrenginį</translation>
+<translation id="1838818994221231429">perjungti visą ekraną į ekrano išpjovos zoną</translation>
<translation id="190587075670221089">trynimas</translation>
<translation id="1907737156431278478">pavyzdys</translation>
<translation id="1921819250265091946">dd</translation>
@@ -103,6 +104,7 @@
<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="4742539557769756338">viršelis</translation>
+<translation id="4748357248530471599">perjungti ekrano išpjovą į visą ekraną</translation>
<translation id="4757246831282535685">skirtuko skydelis</translation>
<translation id="4763480195061959176">vaizdo įrašas</translation>
<translation id="479989351350248267">ieškoti</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_lv.xtb b/chromium/content/app/strings/translations/content_strings_lv.xtb
index cadacb3f77e..bfe6fa5bc27 100644
--- a/chromium/content/app/strings/translations/content_strings_lv.xtb
+++ b/chromium/content/app/strings/translations/content_strings_lv.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">koka režģis</translation>
<translation id="1822429046913737220">priekšpusdienā/pēcpusdienā</translation>
<translation id="1832974991323546415">atskaņot attālinātā ierīcē</translation>
+<translation id="1838818994221231429">pārslēdz pilnekrāna režīmu displeja izgriezuma apgabalā</translation>
<translation id="190587075670221089">dzēšana</translation>
<translation id="1907737156431278478">piemērs</translation>
<translation id="1921819250265091946">dd</translation>
@@ -103,6 +104,7 @@
<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="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>
<translation id="4763480195061959176">video</translation>
<translation id="479989351350248267">meklēt</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_ml.xtb b/chromium/content/app/strings/translations/content_strings_ml.xtb
index 55dd899dc52..55a7feb6e98 100644
--- a/chromium/content/app/strings/translations/content_strings_ml.xtb
+++ b/chromium/content/app/strings/translations/content_strings_ml.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">ട്രീ ഗ്രിഡ്</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">വിദൂര ഉപകരണത്തിൽ പ്ലേ ചെയ്യുക</translation>
+<translation id="1838818994221231429">പൂർണ്ണ സ്ക്രീൻ, ഡിസ്‌പ്ലേ കട്ടൗട്ട് മേഖലയിലേക്ക് മാറ്റുക</translation>
<translation id="190587075670221089">ഇല്ലാതാക്കൽ</translation>
<translation id="1907737156431278478">ഉദാഹരണം</translation>
<translation id="1921819250265091946">തീയതി</translation>
@@ -40,7 +41,7 @@
<translation id="2226276347425096477">ഈ വാചകത്തെ <ph name="MAX_CHARACTERS" /> അല്ലെങ്കില്‍ അതില്‍‌ക്കുറവ് പ്രതീകങ്ങളായി ദയവായി കുറയ്ക്കുക (നിങ്ങള്‍ നിലവില്‍ <ph name="CURRENT_LENGTH" /> പ്രതീകങ്ങള്‍ ഉപയോഗിക്കുകയാണ്).</translation>
<translation id="2247351761944213033">ആഴ്‌ച <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">ട്രാക്ക് <ph name="NUMBER" /></translation>
-<translation id="2291999235780842123">ചെക്ക്‌ബോക്‌സ്</translation>
+<translation id="2291999235780842123">ചെക്ക്‌ ബോക്‌സ്</translation>
<translation id="2311842470354187719">പേജ് ബ്രേക്ക്</translation>
<translation id="2335594187091864976">തീയതിയും സമയ പിക്കറും</translation>
<translation id="248395913932153421">ദിവസം</translation>
@@ -103,6 +104,7 @@
<translation id="4664250907885839816">'<ph name="ATSIGN" />' എന്നതിനുശേഷം വരുന്ന ഭാഗത്തിൽ '<ph name="INVALIDCHARACTER" />' ചിഹ്നം ഉണ്ടാകരുത്.</translation>
<translation id="4668956016107839909">അനുബന്ധം</translation>
<translation id="4742539557769756338">കവർ</translation>
+<translation id="4748357248530471599">ഡിസ്‌പ്ലേ കട്ടൗട്ട് പൂർണ്ണ സ്ക്രീൻ മാറ്റുക</translation>
<translation id="4757246831282535685">ടാബ് പാനൽ</translation>
<translation id="4763480195061959176">വീഡിയോ</translation>
<translation id="479989351350248267">search</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_mr.xtb b/chromium/content/app/strings/translations/content_strings_mr.xtb
index b44b3df08c5..ad7e167229a 100644
--- a/chromium/content/app/strings/translations/content_strings_mr.xtb
+++ b/chromium/content/app/strings/translations/content_strings_mr.xtb
@@ -21,12 +21,13 @@
<translation id="1591562245178063882">या महिन्यात</translation>
<translation id="1637811476055996098">फायली निवडा</translation>
<translation id="1650423536718072820">पुलकोट</translation>
-<translation id="1729654308190250600">कृपया एक रिक्त-नसलेला ईमेल अॅड्रेस एंटर करा.</translation>
+<translation id="1729654308190250600">कृपया एक रिक्त नसलेला ईमेल अॅड्रेस एंटर करा.</translation>
<translation id="1758486001363313524">अन्य...</translation>
<translation id="1806710327868736751">सूचना_संवाद</translation>
<translation id="1821985195704844674">ट्री ग्रीड</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">दूरस्थ डिव्हाइसवर प्ले करा</translation>
+<translation id="1838818994221231429">डिस्प्ले कटआउट भागामध्ये फुलस्क्रीन टॉगल करा</translation>
<translation id="190587075670221089">हटवणे</translation>
<translation id="1907737156431278478">उदाहरण</translation>
<translation id="1921819250265091946">dd</translation>
@@ -64,7 +65,7 @@
<translation id="2942448076852699108">हायलाइट केलेली सामग्री</translation>
<translation id="3040011195152428237">दुवा</translation>
<translation id="3049748772180311791"><ph name="QUANTITY" /> MB</translation>
-<translation id="3075154866155599887">कृपया एक वैध मूल्य एंटर करा. फील्ड अपूर्ण आहे किंवा अवैध तारीख आहे.</translation>
+<translation id="3075154866155599887">कृपया एक वैध मूल्य एंटर करा. भाग अपूर्ण आहे किंवा चुकीची तारीख आहे.</translation>
<translation id="3078740164268491126">सारणी</translation>
<translation id="3086746722712840547">टीप</translation>
<translation id="310520048233152454">कृपया एखादी URL एंटर करा.</translation>
@@ -103,6 +104,7 @@
<translation id="4664250907885839816">'<ph name="ATSIGN" />' चे फॉलो करणार्‍या भागामध्ये '<ph name="INVALIDCHARACTER" />' चिन्ह नसावे.</translation>
<translation id="4668956016107839909">परिशिष्ट</translation>
<translation id="4742539557769756338">कव्हर</translation>
+<translation id="4748357248530471599">डिस्प्ले कटआउट फुलस्क्रीन टॉगल करा</translation>
<translation id="4757246831282535685">टॅब पॅनेल</translation>
<translation id="4763480195061959176">व्हिडिओ</translation>
<translation id="479989351350248267">search</translation>
@@ -152,7 +154,7 @@
<translation id="6453774872122745852">श्रेयनिर्देश</translation>
<translation id="648732519525291180">वेळ निवडक</translation>
<translation id="6550675742724504774">पर्याय</translation>
-<translation id="658823671542763450">पूर्ण स्क्रीन एंटर करा</translation>
+<translation id="658823671542763450">फुल स्क्रीन एंटर करा</translation>
<translation id="663493177488814956">फीड</translation>
<translation id="6637586476836377253">लॉग</translation>
<translation id="6643016212128521049">साफ करा</translation>
@@ -202,10 +204,10 @@
<translation id="8105797009065549151">टीप संदर्भ</translation>
<translation id="8115662671911883373">बंद मथळा प्रदर्शित करणे प्रारंभ करा</translation>
<translation id="8117451130807776954">या आठवड्यात</translation>
-<translation id="819205353528511139">पूर्ण स्क्रीन मोडमध्ये चित्रपट प्ले करा</translation>
+<translation id="819205353528511139">फुल स्क्रीन मोडमध्ये चित्रपट प्ले करा</translation>
<translation id="8199524924445686405">yyyy</translation>
<translation id="8284326494547611709">मथळे</translation>
-<translation id="835897206747267392">अवैध मूल्य.</translation>
+<translation id="835897206747267392">चुकीचे मूल्य.</translation>
<translation id="8415319359811155763">भाग</translation>
<translation id="8433900881053900389">टूलबार</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> फायली</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_ms.xtb b/chromium/content/app/strings/translations/content_strings_ms.xtb
index 4a46a11a1fc..fd00a061d61 100644
--- a/chromium/content/app/strings/translations/content_strings_ms.xtb
+++ b/chromium/content/app/strings/translations/content_strings_ms.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">grid pohon</translation>
<translation id="1822429046913737220">PG / P/M</translation>
<translation id="1832974991323546415">main pada peranti jauh</translation>
+<translation id="1838818994221231429">togol skrin penuh menjadi kawasan potongan paparan</translation>
<translation id="190587075670221089">pemadaman</translation>
<translation id="1907737156431278478">contoh</translation>
<translation id="1921819250265091946">dd</translation>
@@ -103,6 +104,7 @@
<translation id="4664250907885839816">Bahagian selepas '<ph name="ATSIGN" />' tidak boleh mengandungi simbol '<ph name="INVALIDCHARACTER" />'.</translation>
<translation id="4668956016107839909">lampiran</translation>
<translation id="4742539557769756338">muka depan</translation>
+<translation id="4748357248530471599">togol skrin penuh potongan paparan</translation>
<translation id="4757246831282535685">panel tab</translation>
<translation id="4763480195061959176">video</translation>
<translation id="479989351350248267">search</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_nl.xtb b/chromium/content/app/strings/translations/content_strings_nl.xtb
index 8d1cea60130..4bf78229f72 100644
--- a/chromium/content/app/strings/translations/content_strings_nl.xtb
+++ b/chromium/content/app/strings/translations/content_strings_nl.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">boomstructuur</translation>
<translation id="1822429046913737220">a.m./p.m.</translation>
<translation id="1832974991323546415">afspelen op extern apparaat</translation>
+<translation id="1838818994221231429">volledig scherm met display-cutoutgebied schakelen</translation>
<translation id="190587075670221089">verwijdering</translation>
<translation id="1907737156431278478">voorbeeld</translation>
<translation id="1921819250265091946">dd</translation>
@@ -103,6 +104,7 @@
<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="4742539557769756338">omslag</translation>
+<translation id="4748357248530471599">volledig scherm met display-cutout schakelen</translation>
<translation id="4757246831282535685">deelvenster met tabblad</translation>
<translation id="4763480195061959176">video</translation>
<translation id="479989351350248267">zoeken</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_no.xtb b/chromium/content/app/strings/translations/content_strings_no.xtb
index 2b165a6bb31..5eb145f1c33 100644
--- a/chromium/content/app/strings/translations/content_strings_no.xtb
+++ b/chromium/content/app/strings/translations/content_strings_no.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">trerutenett</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">spill på ekstern enhet</translation>
+<translation id="1838818994221231429">slå av/på fullskjermsvisning av området med skjermutklipp</translation>
<translation id="190587075670221089">sletting</translation>
<translation id="1907737156431278478">eksempel</translation>
<translation id="1921819250265091946">dd</translation>
@@ -103,6 +104,7 @@
<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="4742539557769756338">omslag</translation>
+<translation id="4748357248530471599">slå av/på fullskjermsvisning av skjermutklipp</translation>
<translation id="4757246831282535685">fanepanel</translation>
<translation id="4763480195061959176">video</translation>
<translation id="479989351350248267">søk</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_pl.xtb b/chromium/content/app/strings/translations/content_strings_pl.xtb
index 95213b71476..b65e5526e4e 100644
--- a/chromium/content/app/strings/translations/content_strings_pl.xtb
+++ b/chromium/content/app/strings/translations/content_strings_pl.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">siatka drzewa</translation>
<translation id="1822429046913737220">rano/po południu</translation>
<translation id="1832974991323546415">odtwarzanie na urządzeniu zdalnym</translation>
+<translation id="1838818994221231429">przełącz z trybu pełnoekranowego na obszar z wycięciem w ekranie</translation>
<translation id="190587075670221089">usunięcie</translation>
<translation id="1907737156431278478">przykład</translation>
<translation id="1921819250265091946">dd</translation>
@@ -103,6 +104,7 @@
<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="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>
<translation id="4763480195061959176">film</translation>
<translation id="479989351350248267">search</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 1f50ea13a7d..300d7385116 100644
--- a/chromium/content/app/strings/translations/content_strings_pt-BR.xtb
+++ b/chromium/content/app/strings/translations/content_strings_pt-BR.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">grade de árvore</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">reproduzir em dispositivo remoto</translation>
+<translation id="1838818994221231429">alternar tela cheia para área com corte da tela</translation>
<translation id="190587075670221089">exclusão</translation>
<translation id="1907737156431278478">exemplo</translation>
<translation id="1921819250265091946">dd</translation>
@@ -103,6 +104,7 @@
<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="4742539557769756338">capa</translation>
+<translation id="4748357248530471599">ativa tela cheia com corte de tela</translation>
<translation id="4757246831282535685">painel da guia</translation>
<translation id="4763480195061959176">vídeo</translation>
<translation id="479989351350248267">pesquisar</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 54070127810..7c1b85cf66e 100644
--- a/chromium/content/app/strings/translations/content_strings_pt-PT.xtb
+++ b/chromium/content/app/strings/translations/content_strings_pt-PT.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">grelha de árvore</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">reproduzir no dispositivo remoto</translation>
+<translation id="1838818994221231429">ativar/desativar o ecrã inteiro na área de recorte no ecrã</translation>
<translation id="190587075670221089">eliminação</translation>
<translation id="1907737156431278478">exemplo</translation>
<translation id="1921819250265091946">dd</translation>
@@ -103,6 +104,7 @@
<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="4742539557769756338">capa</translation>
+<translation id="4748357248530471599">ativar/desativar o ecrã inteiro de recorte no ecrã</translation>
<translation id="4757246831282535685">painel de separadores</translation>
<translation id="4763480195061959176">vídeo</translation>
<translation id="479989351350248267">search</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_ro.xtb b/chromium/content/app/strings/translations/content_strings_ro.xtb
index 50d67946821..028076ef823 100644
--- a/chromium/content/app/strings/translations/content_strings_ro.xtb
+++ b/chromium/content/app/strings/translations/content_strings_ro.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">grilă arbore</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">redă pe dispozitiv la distanță</translation>
+<translation id="1838818994221231429">decupaj inclus în ecranul complet</translation>
<translation id="190587075670221089">ștergere</translation>
<translation id="1907737156431278478">exemplu</translation>
<translation id="1921819250265091946">zz</translation>
@@ -103,6 +104,7 @@
<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="4742539557769756338">copertă</translation>
+<translation id="4748357248530471599">decupaj inclus în ecranul complet</translation>
<translation id="4757246831282535685">panou de file</translation>
<translation id="4763480195061959176">video</translation>
<translation id="479989351350248267">căutați</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_ru.xtb b/chromium/content/app/strings/translations/content_strings_ru.xtb
index 4ebbc1c31a9..ab654d5186d 100644
--- a/chromium/content/app/strings/translations/content_strings_ru.xtb
+++ b/chromium/content/app/strings/translations/content_strings_ru.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">сетка в виде дерева</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">воспроизвести на удаленном устройстве</translation>
+<translation id="1838818994221231429">Переключить полный экран на вырезанную область</translation>
<translation id="190587075670221089">удаление</translation>
<translation id="1907737156431278478">пример</translation>
<translation id="1921819250265091946">дд</translation>
@@ -103,6 +104,7 @@
<translation id="4664250907885839816">Часть адреса после символа "<ph name="ATSIGN" />" не должна содержать символ "<ph name="INVALIDCHARACTER" />".</translation>
<translation id="4668956016107839909">приложение</translation>
<translation id="4742539557769756338">обложка</translation>
+<translation id="4748357248530471599">Переключить вырезанную область на полный экран</translation>
<translation id="4757246831282535685">панель вкладок</translation>
<translation id="4763480195061959176">видео</translation>
<translation id="479989351350248267">поиск</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_sk.xtb b/chromium/content/app/strings/translations/content_strings_sk.xtb
index 799bcaff015..9ec872f3b36 100644
--- a/chromium/content/app/strings/translations/content_strings_sk.xtb
+++ b/chromium/content/app/strings/translations/content_strings_sk.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">stromová mriežka</translation>
<translation id="1822429046913737220">AM / PM</translation>
<translation id="1832974991323546415">prehrať na vzdialenom zariadení</translation>
+<translation id="1838818994221231429">prepnúť celú obrazovku na výrez obrazovky</translation>
<translation id="190587075670221089">odstránenie</translation>
<translation id="1907737156431278478">príklad</translation>
<translation id="1921819250265091946">dd</translation>
@@ -103,6 +104,7 @@
<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="4742539557769756338">titulná strana</translation>
+<translation id="4748357248530471599">prepnúť výrez obrazovky na celú obrazovku</translation>
<translation id="4757246831282535685">panel karty</translation>
<translation id="4763480195061959176">video</translation>
<translation id="479989351350248267">search</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_sl.xtb b/chromium/content/app/strings/translations/content_strings_sl.xtb
index 56db58d546b..8a00c66a491 100644
--- a/chromium/content/app/strings/translations/content_strings_sl.xtb
+++ b/chromium/content/app/strings/translations/content_strings_sl.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">drevesna mreža</translation>
<translation id="1822429046913737220">Dopoldne/popoldne</translation>
<translation id="1832974991323546415">predvajanje v oddaljeni napravi</translation>
+<translation id="1838818994221231429">preklop celozaslonskega načina na območje zareze zaslona</translation>
<translation id="190587075670221089">brisanje</translation>
<translation id="1907737156431278478">primer</translation>
<translation id="1921819250265091946">dd</translation>
@@ -103,6 +104,7 @@
<translation id="4664250907885839816">Del po »<ph name="ATSIGN" />« ne sme vsebovati znaka »<ph name="INVALIDCHARACTER" />«.</translation>
<translation id="4668956016107839909">dodatek</translation>
<translation id="4742539557769756338">naslovnica</translation>
+<translation id="4748357248530471599">preklop celozaslonskega načina na zarezo zaslona</translation>
<translation id="4757246831282535685">podokno z zavihki</translation>
<translation id="4763480195061959176">video</translation>
<translation id="479989351350248267">search</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_sr.xtb b/chromium/content/app/strings/translations/content_strings_sr.xtb
index 676581cd90b..cfc909163ee 100644
--- a/chromium/content/app/strings/translations/content_strings_sr.xtb
+++ b/chromium/content/app/strings/translations/content_strings_sr.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">мрежа стабла</translation>
<translation id="1822429046913737220">пре подне/по подне</translation>
<translation id="1832974991323546415">пуштајте на удаљеном уређају</translation>
+<translation id="1838818994221231429">укључује/искључује приказ на целом екрану без области изрезаног приказа</translation>
<translation id="190587075670221089">брисање</translation>
<translation id="1907737156431278478">пример</translation>
<translation id="1921819250265091946">дд</translation>
@@ -103,6 +104,7 @@
<translation id="4664250907885839816">Део после „<ph name="ATSIGN" />“ не треба да садржи симбол „<ph name="INVALIDCHARACTER" />“.</translation>
<translation id="4668956016107839909">додатак</translation>
<translation id="4742539557769756338">корицe</translation>
+<translation id="4748357248530471599">укључи/искључи цео екран без области изрезаног приказа</translation>
<translation id="4757246831282535685">табла са картицама</translation>
<translation id="4763480195061959176">видео</translation>
<translation id="479989351350248267">search</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_sv.xtb b/chromium/content/app/strings/translations/content_strings_sv.xtb
index 3f94cd192e0..c3b676be786 100644
--- a/chromium/content/app/strings/translations/content_strings_sv.xtb
+++ b/chromium/content/app/strings/translations/content_strings_sv.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">träddiagram</translation>
<translation id="1822429046913737220">FM/EM</translation>
<translation id="1832974991323546415">spela på en fjärrenhet</translation>
+<translation id="1838818994221231429">aktivera och inaktivera helskärm till området för utskärning</translation>
<translation id="190587075670221089">borttagning</translation>
<translation id="1907737156431278478">exempel</translation>
<translation id="1921819250265091946">dd</translation>
@@ -103,6 +104,7 @@
<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="4742539557769756338">omslag</translation>
+<translation id="4748357248530471599">aktivera och inaktivera skärmutskärning i helskärm</translation>
<translation id="4757246831282535685">flikpanel</translation>
<translation id="4763480195061959176">video</translation>
<translation id="479989351350248267">sök</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_sw.xtb b/chromium/content/app/strings/translations/content_strings_sw.xtb
index 686d61b6184..540815ff666 100644
--- a/chromium/content/app/strings/translations/content_strings_sw.xtb
+++ b/chromium/content/app/strings/translations/content_strings_sw.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">gridi ya mti</translation>
<translation id="1822429046913737220">AM / PM</translation>
<translation id="1832974991323546415">cheza kwenye kifaa cha mbali</translation>
+<translation id="1838818994221231429">tumia skrini nzima katika eneo la mkato kwenye skrini</translation>
<translation id="190587075670221089">ufutaji</translation>
<translation id="1907737156431278478">mfano</translation>
<translation id="1921819250265091946">dd</translation>
@@ -103,6 +104,7 @@
<translation id="4664250907885839816">Sehemu inayofuata '<ph name="ATSIGN" />' haipaswi kuwa na alama ya '<ph name="INVALIDCHARACTER" />'.</translation>
<translation id="4668956016107839909">kiambatisho</translation>
<translation id="4742539557769756338">jalada</translation>
+<translation id="4748357248530471599">tumia mkato kwenye skrini nzima</translation>
<translation id="4757246831282535685">kisanduku cha kichupo</translation>
<translation id="4763480195061959176">video</translation>
<translation id="479989351350248267">tafuta</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_ta.xtb b/chromium/content/app/strings/translations/content_strings_ta.xtb
index f785f67adcc..3c9bb1331d6 100644
--- a/chromium/content/app/strings/translations/content_strings_ta.xtb
+++ b/chromium/content/app/strings/translations/content_strings_ta.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">ட்ரீ கிரிட்</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">தொலைநிலைச் சாதனத்தில் இயக்கு</translation>
+<translation id="1838818994221231429">முழுத்திரைக் காட்சியை டிஸ்ப்ளே கட்அவுட் பகுதிக்கு நிலைமாற்றும்</translation>
<translation id="190587075670221089">நீக்கும்</translation>
<translation id="1907737156431278478">உதாரணம்</translation>
<translation id="1921819250265091946">dd</translation>
@@ -103,6 +104,7 @@
<translation id="4664250907885839816">'<ph name="ATSIGN" />' ஐத் தொடரும் பகுதியில், '<ph name="INVALIDCHARACTER" />' சின்னம் இருக்கக்கூடாது.</translation>
<translation id="4668956016107839909">பிற்சேர்க்கை</translation>
<translation id="4742539557769756338">அட்டை</translation>
+<translation id="4748357248530471599">டிஸ்ப்ளே கட்அவுட் முழுத்திரை நிலைமாற்ற பட்டன்</translation>
<translation id="4757246831282535685">தாவல் பலகம்</translation>
<translation id="4763480195061959176">வீடியோ</translation>
<translation id="479989351350248267">Search</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_te.xtb b/chromium/content/app/strings/translations/content_strings_te.xtb
index 2638aa25a08..4b6b9fd9953 100644
--- a/chromium/content/app/strings/translations/content_strings_te.xtb
+++ b/chromium/content/app/strings/translations/content_strings_te.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">వృక్షాంశ గ్రిడ్</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">రిమోట్ పరికరంలో ప్లే చేస్తుంది</translation>
+<translation id="1838818994221231429">పూర్తి స్క్రీన్‌ను డిస్‌ప్లే కత్తిరింపు భాగానికి తగినట్లు సక్రియం చేస్తుంది</translation>
<translation id="190587075670221089">తొలగింపు</translation>
<translation id="1907737156431278478">ఉదాహరణ</translation>
<translation id="1921819250265091946">dd</translation>
@@ -103,6 +104,7 @@
<translation id="4664250907885839816">'<ph name="ATSIGN" />'కి తర్వాత ఉన్న భాగంలో '<ph name="INVALIDCHARACTER" />' చిహ్నం ఉండకూడదు.</translation>
<translation id="4668956016107839909">అనుబంధం</translation>
<translation id="4742539557769756338">ముఖచిత్రం</translation>
+<translation id="4748357248530471599">డిస్‌ప్లే కత్తిరింపు పూర్తి స్క్రీన్‌ని సక్రియం చేస్తుంది</translation>
<translation id="4757246831282535685">ట్యాబ్ ప్యానెల్</translation>
<translation id="4763480195061959176">వీడియో</translation>
<translation id="479989351350248267">search</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_th.xtb b/chromium/content/app/strings/translations/content_strings_th.xtb
index c805447d181..57e893a8868 100644
--- a/chromium/content/app/strings/translations/content_strings_th.xtb
+++ b/chromium/content/app/strings/translations/content_strings_th.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">แผนผังต้นไม้</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">เล่นในอุปกรณ์ระยะไกล</translation>
+<translation id="1838818994221231429">สลับจากเต็มหน้าจอเป็นพื้นที่หน้าจอรอยบาก</translation>
<translation id="190587075670221089">การลบ</translation>
<translation id="1907737156431278478">ตัวอย่าง</translation>
<translation id="1921819250265091946">วว</translation>
@@ -103,6 +104,7 @@
<translation id="4664250907885839816">ส่วนที่ต่อท้าย "<ph name="ATSIGN" />" ต้องไม่มีสัญลักษณ์ "<ph name="INVALIDCHARACTER" />"</translation>
<translation id="4668956016107839909">ภาคผนวก</translation>
<translation id="4742539557769756338">หน้าปก</translation>
+<translation id="4748357248530471599">สลับเป็นแบบเต็มหน้าจอสำหรับหน้าจอรอยบาก</translation>
<translation id="4757246831282535685">แผงแท็บ</translation>
<translation id="4763480195061959176">วิดีโอ</translation>
<translation id="479989351350248267">ค้นหา</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_tr.xtb b/chromium/content/app/strings/translations/content_strings_tr.xtb
index 3f4ee0731a4..2ad6bf39f6d 100644
--- a/chromium/content/app/strings/translations/content_strings_tr.xtb
+++ b/chromium/content/app/strings/translations/content_strings_tr.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">ağaç tablo</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">uzaktan cihazda oynat</translation>
+<translation id="1838818994221231429">tam ekranı ekran kesimi alanı olarak değiştirin</translation>
<translation id="190587075670221089">silme</translation>
<translation id="1907737156431278478">örnek</translation>
<translation id="1921819250265091946">gg</translation>
@@ -103,6 +104,7 @@
<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="4742539557769756338">kapak</translation>
+<translation id="4748357248530471599">ekran kesimi alanını tam ekran olarak değiştirin</translation>
<translation id="4757246831282535685">sekme paneli</translation>
<translation id="4763480195061959176">video</translation>
<translation id="479989351350248267">ara</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_uk.xtb b/chromium/content/app/strings/translations/content_strings_uk.xtb
index 0b0bfbb02f5..a3a041c9c11 100644
--- a/chromium/content/app/strings/translations/content_strings_uk.xtb
+++ b/chromium/content/app/strings/translations/content_strings_uk.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">сітка дерева</translation>
<translation id="1822429046913737220">д.п./п.п.</translation>
<translation id="1832974991323546415">відтворити на віддаленому пристрої</translation>
+<translation id="1838818994221231429">використовувати або не використовувати зону вирізу екрана в повноекранному режимі</translation>
<translation id="190587075670221089">видалення</translation>
<translation id="1907737156431278478">приклад</translation>
<translation id="1921819250265091946">дд</translation>
@@ -103,6 +104,7 @@
<translation id="4664250907885839816">Частина після знака "<ph name="ATSIGN" />" не може містити символ "<ph name="INVALIDCHARACTER" />".</translation>
<translation id="4668956016107839909">додаток</translation>
<translation id="4742539557769756338">обкладинка</translation>
+<translation id="4748357248530471599">перемкнути виріз у повноекранному режимі</translation>
<translation id="4757246831282535685">панель вкладок</translation>
<translation id="4763480195061959176">відео</translation>
<translation id="479989351350248267">пошук</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_vi.xtb b/chromium/content/app/strings/translations/content_strings_vi.xtb
index b3129498b79..87b3e3c9f68 100644
--- a/chromium/content/app/strings/translations/content_strings_vi.xtb
+++ b/chromium/content/app/strings/translations/content_strings_vi.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">lưới dạng cây</translation>
<translation id="1822429046913737220">SA/CH</translation>
<translation id="1832974991323546415">phát trên thiết bị từ xa</translation>
+<translation id="1838818994221231429">chuyển từ chế độ toàn màn hình sang màn hình có vết cắt</translation>
<translation id="190587075670221089">xóa</translation>
<translation id="1907737156431278478">ví dụ</translation>
<translation id="1921819250265091946">dd</translation>
@@ -103,6 +104,7 @@
<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="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>
<translation id="4763480195061959176">video</translation>
<translation id="479989351350248267">search</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 1cee8ea1c59..f5f5dfa4818 100644
--- a/chromium/content/app/strings/translations/content_strings_zh-CN.xtb
+++ b/chromium/content/app/strings/translations/content_strings_zh-CN.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">树状网格</translation>
<translation id="1822429046913737220">上午/下午</translation>
<translation id="1832974991323546415">在远程设备上播放</translation>
+<translation id="1838818994221231429">切换到包含刘海屏区域的全屏模式</translation>
<translation id="190587075670221089">删除</translation>
<translation id="1907737156431278478">示例</translation>
<translation id="1921819250265091946">日</translation>
@@ -103,6 +104,7 @@
<translation id="4664250907885839816">“<ph name="ATSIGN" />”后面的内容不应包含符号“<ph name="INVALIDCHARACTER" />”。</translation>
<translation id="4668956016107839909">附录</translation>
<translation id="4742539557769756338">封面</translation>
+<translation id="4748357248530471599">开启/关闭全屏模式中的刘海屏</translation>
<translation id="4757246831282535685">标签面板</translation>
<translation id="4763480195061959176">视频</translation>
<translation id="479989351350248267">搜索</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 0f1c53576b2..857bab97a0e 100644
--- a/chromium/content/app/strings/translations/content_strings_zh-TW.xtb
+++ b/chromium/content/app/strings/translations/content_strings_zh-TW.xtb
@@ -27,6 +27,7 @@
<translation id="1821985195704844674">樹狀目錄網格</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">在遠端裝置上播放</translation>
+<translation id="1838818994221231429">切換為包含螢幕凹口區域的全螢幕模式</translation>
<translation id="190587075670221089">刪除</translation>
<translation id="1907737156431278478">範例</translation>
<translation id="1921819250265091946">日</translation>
@@ -103,6 +104,7 @@
<translation id="4664250907885839816">「<ph name="ATSIGN" />」後面的部分不應包含「<ph name="INVALIDCHARACTER" />」符號。</translation>
<translation id="4668956016107839909">附錄</translation>
<translation id="4742539557769756338">封面</translation>
+<translation id="4748357248530471599">切換螢幕凹口全螢幕模式</translation>
<translation id="4757246831282535685">分頁面板</translation>
<translation id="4763480195061959176">影片</translation>
<translation id="479989351350248267">search</translation>
diff --git a/chromium/content/browser/BUILD.gn b/chromium/content/browser/BUILD.gn
index abaa573b8f1..02d6ebe936c 100644
--- a/chromium/content/browser/BUILD.gn
+++ b/chromium/content/browser/BUILD.gn
@@ -7,6 +7,7 @@ import("//build/config/features.gni")
import("//build/config/jumbo.gni")
import("//build/config/linux/pangocairo/pangocairo.gni")
import("//build/config/ui.gni")
+import("//chromeos/assistant/assistant.gni")
import("//gpu/vulkan/features.gni")
import("//media/media_options.gni")
import("//net/features.gni")
@@ -98,7 +99,6 @@ jumbo_source_set("browser") {
"//gpu/ipc:gl_in_process_context",
"//gpu/ipc/host",
"//gpu/vulkan:buildflags",
- "//jingle:jingle_glue",
"//media",
"//media:media_buildflags",
"//media/capture",
@@ -109,6 +109,7 @@ jumbo_source_set("browser") {
"//media/mojo/interfaces",
"//media/mojo/interfaces:constants",
"//media/mojo/services",
+ "//media/webrtc",
"//mojo/core/embedder",
"//mojo/public/cpp/bindings",
"//mojo/public/cpp/platform",
@@ -126,6 +127,7 @@ jumbo_source_set("browser") {
"//services/catalog/public/cpp",
"//services/catalog/public/mojom:constants",
"//services/content:impl",
+ "//services/content/public/cpp",
"//services/content/public/mojom",
"//services/data_decoder/public/cpp",
"//services/data_decoder/public/mojom",
@@ -136,6 +138,8 @@ jumbo_source_set("browser") {
"//services/device/public/mojom:generic_sensor",
"//services/file:lib",
"//services/file/public/mojom",
+ "//services/media_session/public/cpp",
+ "//services/media_session/public/mojom",
"//services/metrics",
"//services/metrics/public/cpp:metrics_cpp",
"//services/network:network_service",
@@ -154,13 +158,13 @@ jumbo_source_set("browser") {
"//services/shape_detection/public/mojom",
"//services/tracing:lib",
"//services/tracing/public/cpp",
- "//services/ui/public/cpp/gpu",
"//services/video_capture:lib",
"//services/video_capture/public/cpp",
"//services/video_capture/public/mojom:constants",
"//services/video_capture/public/uma",
"//services/viz/privileged/interfaces",
"//services/viz/public/interfaces",
+ "//services/ws/public/cpp/gpu",
"//skia",
"//sql",
"//storage/browser",
@@ -178,7 +182,7 @@ jumbo_source_set("browser") {
"//third_party/icu",
"//third_party/libyuv",
"//third_party/re2",
- "//third_party/webrtc/media:rtc_media_base",
+ "//third_party/sqlite",
"//third_party/webrtc/modules/desktop_capture:primitives",
"//third_party/webrtc/rtc_base:rtc_base",
"//third_party/zlib",
@@ -273,8 +277,6 @@ jumbo_source_set("browser") {
"accessibility/accessibility_tree_formatter_utils_win.cc",
"accessibility/accessibility_tree_formatter_utils_win.h",
"accessibility/accessibility_tree_formatter_win.cc",
- "accessibility/accessibility_ui.cc",
- "accessibility/accessibility_ui.h",
"accessibility/browser_accessibility.cc",
"accessibility/browser_accessibility.h",
"accessibility/browser_accessibility_cocoa.h",
@@ -422,7 +424,8 @@ jumbo_source_set("browser") {
"background_fetch/background_fetch_registration_notifier.h",
"background_fetch/background_fetch_request_info.cc",
"background_fetch/background_fetch_request_info.h",
- "background_fetch/background_fetch_request_manager.h",
+ "background_fetch/background_fetch_request_match_params.cc",
+ "background_fetch/background_fetch_request_match_params.h",
"background_fetch/background_fetch_scheduler.cc",
"background_fetch/background_fetch_scheduler.h",
"background_fetch/background_fetch_service_impl.cc",
@@ -443,8 +446,12 @@ jumbo_source_set("browser") {
"background_fetch/storage/get_initialization_data_task.h",
"background_fetch/storage/get_metadata_task.cc",
"background_fetch/storage/get_metadata_task.h",
+ "background_fetch/storage/get_registration_task.cc",
+ "background_fetch/storage/get_registration_task.h",
"background_fetch/storage/get_settled_fetches_task.cc",
"background_fetch/storage/get_settled_fetches_task.h",
+ "background_fetch/storage/image_helpers.cc",
+ "background_fetch/storage/image_helpers.h",
"background_fetch/storage/mark_registration_for_deletion_task.cc",
"background_fetch/storage/mark_registration_for_deletion_task.h",
"background_fetch/storage/mark_request_complete_task.cc",
@@ -524,6 +531,8 @@ jumbo_source_set("browser") {
"browsing_data/browsing_data_filter_builder_impl.h",
"browsing_data/browsing_data_remover_impl.cc",
"browsing_data/browsing_data_remover_impl.h",
+ "browsing_data/clear_site_data_handler.cc",
+ "browsing_data/clear_site_data_handler.h",
"browsing_data/clear_site_data_throttle.cc",
"browsing_data/clear_site_data_throttle.h",
"browsing_data/conditional_cache_deletion_helper.cc",
@@ -575,6 +584,8 @@ jumbo_source_set("browser") {
"cocoa/system_hotkey_map.mm",
"code_cache/generated_code_cache.cc",
"code_cache/generated_code_cache.h",
+ "code_cache/generated_code_cache_context.cc",
+ "code_cache/generated_code_cache_context.h",
"startup_data_impl.cc",
"startup_data_impl.h",
@@ -747,8 +758,6 @@ jumbo_source_set("browser") {
"download/download_request_utils.cc",
"download/download_resource_handler.cc",
"download/download_resource_handler.h",
- "download/download_url_loader_factory_getter_impl.cc",
- "download/download_url_loader_factory_getter_impl.h",
"download/download_utils.cc",
"download/download_utils.h",
"download/drag_download_file.cc",
@@ -757,6 +766,8 @@ jumbo_source_set("browser") {
"download/drag_download_util.h",
"download/file_download_url_loader_factory_getter.cc",
"download/file_download_url_loader_factory_getter.h",
+ "download/file_system_download_url_loader_factory_getter.cc",
+ "download/file_system_download_url_loader_factory_getter.h",
"download/mhtml_extra_parts_impl.cc",
"download/mhtml_extra_parts_impl.h",
"download/mhtml_generation_manager.cc",
@@ -785,10 +796,14 @@ 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",
"fileapi/file_system_url_loader_factory.h",
- "fileapi/fileapi_message_filter.cc",
- "fileapi/fileapi_message_filter.h",
+ "find_in_page_client.cc",
+ "find_in_page_client.h",
"find_request_manager.cc",
"find_request_manager.h",
"font_list_async.cc",
@@ -867,12 +882,11 @@ jumbo_source_set("browser") {
"geolocation/geolocation_service_impl.h",
"gpu/browser_gpu_channel_host_factory.cc",
"gpu/browser_gpu_channel_host_factory.h",
- "gpu/browser_gpu_memory_buffer_manager.cc",
- "gpu/browser_gpu_memory_buffer_manager.h",
+ "gpu/browser_gpu_client_delegate.cc",
+ "gpu/browser_gpu_client_delegate.h",
"gpu/compositor_util.cc",
"gpu/compositor_util.h",
- "gpu/gpu_client_impl.cc",
- "gpu/gpu_client_impl.h",
+ "gpu/gpu_client.cc",
"gpu/gpu_data_manager_impl.cc",
"gpu/gpu_data_manager_impl.h",
"gpu/gpu_data_manager_impl_private.cc",
@@ -883,6 +897,8 @@ jumbo_source_set("browser") {
"gpu/gpu_internals_ui.h",
"gpu/gpu_main_thread_factory.cc",
"gpu/gpu_main_thread_factory.h",
+ "gpu/gpu_memory_buffer_manager_singleton.cc",
+ "gpu/gpu_memory_buffer_manager_singleton.h",
"gpu/gpu_process_host.cc",
"gpu/gpu_process_host.h",
"gpu/shader_cache_factory.cc",
@@ -976,6 +992,10 @@ jumbo_source_set("browser") {
"indexed_db/leveldb/leveldb_write_batch.cc",
"indexed_db/leveldb/leveldb_write_batch.h",
"indexed_db/list_set.h",
+ "indexed_db/scopes/disjoint_range_lock_manager.cc",
+ "indexed_db/scopes/disjoint_range_lock_manager.h",
+ "indexed_db/scopes/scopes_lock_manager.cc",
+ "indexed_db/scopes/scopes_lock_manager.h",
"initiator_csp_context.cc",
"initiator_csp_context.h",
"installedapp/installed_app_provider_impl_default.cc",
@@ -995,7 +1015,6 @@ jumbo_source_set("browser") {
"loader/detachable_resource_handler.h",
"loader/download_utils_impl.cc",
"loader/download_utils_impl.h",
- "loader/global_routing_id.h",
"loader/intercepting_resource_handler.cc",
"loader/intercepting_resource_handler.h",
"loader/layered_resource_handler.cc",
@@ -1091,6 +1110,8 @@ jumbo_source_set("browser") {
"media/capture/audio_mirroring_manager.h",
"media/capture/desktop_capture_device_uma_types.cc",
"media/capture/desktop_capture_device_uma_types.h",
+ "media/capture/desktop_streams_registry_impl.cc",
+ "media/capture/desktop_streams_registry_impl.h",
"media/capture/web_contents_audio_input_stream.cc",
"media/capture/web_contents_audio_input_stream.h",
"media/capture/web_contents_audio_muter.cc",
@@ -1103,6 +1124,8 @@ jumbo_source_set("browser") {
"media/flinging_renderer.h",
"media/forwarding_audio_stream_factory.cc",
"media/forwarding_audio_stream_factory.h",
+ "media/in_process_audio_loopback_stream_creator.cc",
+ "media/in_process_audio_loopback_stream_creator.h",
"media/media_devices_permission_checker.cc",
"media/media_devices_permission_checker.h",
"media/media_devices_util.cc",
@@ -1127,6 +1150,8 @@ jumbo_source_set("browser") {
"media/session/audio_focus_delegate_default.cc",
"media/session/audio_focus_manager.cc",
"media/session/audio_focus_manager.h",
+ "media/session/audio_focus_observer.cc",
+ "media/session/audio_focus_observer.h",
"media/session/media_metadata_sanitizer.cc",
"media/session/media_metadata_sanitizer.h",
"media/session/media_session_android.cc",
@@ -1144,6 +1169,10 @@ jumbo_source_set("browser") {
"media/session/media_session_uma_helper.h",
"media/url_provision_fetcher.cc",
"media/url_provision_fetcher.h",
+ "media/video_decoder_proxy.cc",
+ "media/video_decoder_proxy.h",
+ "media/webaudio/audio_context_manager_impl.cc",
+ "media/webaudio/audio_context_manager_impl.h",
"memory/memory_condition_observer.cc",
"memory/memory_condition_observer.h",
"memory/memory_coordinator_default_policy.cc",
@@ -1193,6 +1222,8 @@ jumbo_source_set("browser") {
"notifications/notification_event_dispatcher_impl.h",
"notifications/notification_id_generator.cc",
"notifications/notification_id_generator.h",
+ "notifications/notification_storage.cc",
+ "notifications/notification_storage.h",
"notifications/platform_notification_context_impl.cc",
"notifications/platform_notification_context_impl.h",
"payments/payment_app_context_impl.cc",
@@ -1219,6 +1250,8 @@ jumbo_source_set("browser") {
"picture_in_picture/overlay_surface_embedder.h",
"picture_in_picture/picture_in_picture_window_controller_impl.cc",
"picture_in_picture/picture_in_picture_window_controller_impl.h",
+ "portal/portal.cc",
+ "portal/portal.h",
"presentation/presentation_service_impl.cc",
"presentation/presentation_service_impl.h",
"process_internals/process_internals_handler_impl.cc",
@@ -1432,16 +1465,6 @@ jumbo_source_set("browser") {
"renderer_host/overscroll_controller_delegate.h",
"renderer_host/p2p/socket_dispatcher_host.cc",
"renderer_host/p2p/socket_dispatcher_host.h",
- "renderer_host/p2p/socket_host.cc",
- "renderer_host/p2p/socket_host.h",
- "renderer_host/p2p/socket_host_tcp.cc",
- "renderer_host/p2p/socket_host_tcp.h",
- "renderer_host/p2p/socket_host_tcp_server.cc",
- "renderer_host/p2p/socket_host_tcp_server.h",
- "renderer_host/p2p/socket_host_throttler.cc",
- "renderer_host/p2p/socket_host_throttler.h",
- "renderer_host/p2p/socket_host_udp.cc",
- "renderer_host/p2p/socket_host_udp.h",
"renderer_host/render_frame_metadata_provider_impl.cc",
"renderer_host/render_frame_metadata_provider_impl.h",
"renderer_host/render_message_filter.cc",
@@ -1505,6 +1528,15 @@ jumbo_source_set("browser") {
"sandbox_ipc_linux.h",
"sandbox_parameters_mac.h",
"sandbox_parameters_mac.mm",
+ "scheduler/responsiveness/calculator.cc",
+ "scheduler/responsiveness/calculator.h",
+ "scheduler/responsiveness/message_loop_observer.cc",
+ "scheduler/responsiveness/message_loop_observer.h",
+ "scheduler/responsiveness/native_event_observer.cc",
+ "scheduler/responsiveness/native_event_observer.h",
+ "scheduler/responsiveness/native_event_observer_mac.mm",
+ "scheduler/responsiveness/watcher.cc",
+ "scheduler/responsiveness/watcher.h",
"scoped_active_url.cc",
"scoped_active_url.h",
"screen_orientation/screen_orientation_provider.cc",
@@ -1674,6 +1706,8 @@ jumbo_source_set("browser") {
"theme_helper_mac.mm",
"tracing/background_memory_tracing_observer.cc",
"tracing/background_memory_tracing_observer.h",
+ "tracing/background_startup_tracing_observer.cc",
+ "tracing/background_startup_tracing_observer.h",
"tracing/background_tracing_config_impl.cc",
"tracing/background_tracing_config_impl.h",
"tracing/background_tracing_manager_impl.cc",
@@ -1874,25 +1908,18 @@ jumbo_source_set("browser") {
"//content/browser/tracing:resources",
]
}
- if ((use_udev && is_posix) || is_mac || is_win) {
- deps += [ "//tools/battor_agent:battor_agent_lib" ]
- sources += [
- "tracing/power_tracing_agent.cc",
- "tracing/power_tracing_agent.h",
- ]
- }
# Desktop/Window/WebContents screen capture implementations, conditionally
# built depending on the available implementations for each platform.
if (is_linux || is_mac || is_win) {
defines += [ "ENABLE_SCREEN_CAPTURE=1" ]
sources += [
- "media/capture/cursor_renderer.cc",
- "media/capture/cursor_renderer.h",
"media/capture/desktop_capture_device.cc",
"media/capture/desktop_capture_device.h",
"media/capture/frame_sink_video_capture_device.cc",
"media/capture/frame_sink_video_capture_device.h",
+ "media/capture/mouse_cursor_overlay_controller.cc",
+ "media/capture/mouse_cursor_overlay_controller.h",
"media/capture/web_contents_video_capture_device.cc",
"media/capture/web_contents_video_capture_device.h",
]
@@ -1902,21 +1929,19 @@ jumbo_source_set("browser") {
sources += [
"media/capture/aura_window_video_capture_device.cc",
"media/capture/aura_window_video_capture_device.h",
- "media/capture/cursor_renderer_aura.cc",
- "media/capture/cursor_renderer_aura.h",
+ "media/capture/mouse_cursor_overlay_controller_aura.cc",
]
}
if (is_chromeos) {
sources += [
+ "media/capture/lame_capture_overlay_chromeos.cc",
+ "media/capture/lame_capture_overlay_chromeos.h",
"media/capture/lame_window_capturer_chromeos.cc",
"media/capture/lame_window_capturer_chromeos.h",
]
}
if (is_mac) {
- sources += [
- "media/capture/cursor_renderer_mac.h",
- "media/capture/cursor_renderer_mac.mm",
- ]
+ sources += [ "media/capture/mouse_cursor_overlay_controller_mac.mm" ]
deps += [
"//sandbox/mac:seatbelt",
"//sandbox/mac:seatbelt_extension",
@@ -1993,7 +2018,6 @@ jumbo_source_set("browser") {
"renderer_host/pepper/pepper_host_resolver_message_filter.h",
"renderer_host/pepper/pepper_internal_file_ref_backend.cc",
"renderer_host/pepper/pepper_internal_file_ref_backend.h",
- "renderer_host/pepper/pepper_lookup_request.h",
"renderer_host/pepper/pepper_message_filter.cc",
"renderer_host/pepper/pepper_message_filter.h",
"renderer_host/pepper/pepper_network_monitor_host.cc",
@@ -2004,6 +2028,8 @@ jumbo_source_set("browser") {
"renderer_host/pepper/pepper_print_settings_manager.h",
"renderer_host/pepper/pepper_printing_host.cc",
"renderer_host/pepper/pepper_printing_host.h",
+ "renderer_host/pepper/pepper_proxy_lookup_helper.cc",
+ "renderer_host/pepper/pepper_proxy_lookup_helper.h",
"renderer_host/pepper/pepper_renderer_connection.cc",
"renderer_host/pepper/pepper_renderer_connection.h",
"renderer_host/pepper/pepper_security_helper.cc",
@@ -2086,7 +2112,10 @@ jumbo_source_set("browser") {
if (use_x11) {
configs += [ "//build/config/linux:x11" ]
- deps += [ "//ui/gfx/x" ]
+ deps += [
+ "//ui/events/platform/x11",
+ "//ui/gfx/x",
+ ]
}
if (use_pangocairo) {
@@ -2154,18 +2183,22 @@ jumbo_source_set("browser") {
"android/synchronous_compositor_host.h",
"android/synchronous_compositor_sync_call_bridge.cc",
"android/synchronous_compositor_sync_call_bridge.h",
- "android/tap_disambiguator.cc",
- "android/tap_disambiguator.h",
"android/tracing_controller_android.cc",
"android/tracing_controller_android.h",
"android/web_contents_observer_proxy.cc",
"android/web_contents_observer_proxy.h",
+ "font_unique_name_lookup/font_unique_name_lookup.cc",
+ "font_unique_name_lookup/font_unique_name_lookup.h",
+ "font_unique_name_lookup/font_unique_name_lookup_service.cc",
+ "font_unique_name_lookup/font_unique_name_lookup_service.h",
"frame_host/render_frame_host_android.cc",
"frame_host/render_frame_host_android.h",
"media/capture/screen_capture_device_android.cc",
"media/capture/screen_capture_device_android.h",
"renderer_host/compositor_impl_android.cc",
"renderer_host/compositor_impl_android.h",
+ "renderer_host/delegated_frame_host_client_android.cc",
+ "renderer_host/delegated_frame_host_client_android.h",
"renderer_host/input/fling_scheduler_android.cc",
"renderer_host/input/fling_scheduler_android.h",
"renderer_host/input/synthetic_gesture_target_android.cc",
@@ -2206,11 +2239,14 @@ jumbo_source_set("browser") {
]
deps += [
":reflection_jni_headers",
+ "//build/config/freetype",
"//content/public/android:jni",
"//device/gamepad/public/mojom",
"//media",
"//media/capture/content/android",
"//media/capture/video/android",
+ "//third_party/blink/public/common:font_unique_name_table_proto",
+ "//third_party/icu",
"//ui/accessibility:ax_assistant",
"//ui/accessibility/mojom",
"//ui/android",
@@ -2297,14 +2333,18 @@ jumbo_source_set("browser") {
deps += [
"//chromeos",
"//chromeos:power_manager_proto",
+ "//chromeos/assistant:buildflags",
]
}
+ if (enable_cros_libassistant) {
+ deps += [ "//chromeos/services/assistant/public/mojom" ]
+ }
+
if (use_aura) {
deps += [
- "//services/ui:lib",
- "//services/ui/public/cpp",
- "//services/ui/public/interfaces",
+ "//services/ws/public/cpp",
+ "//services/ws/public/mojom",
"//ui/aura",
"//ui/aura_extra",
"//ui/strings",
@@ -2445,7 +2485,10 @@ if (is_android) {
# See comment at the top of //content/BUILD.gn for how this works.
group("for_content_tests") {
- visibility = [ "//content/test/*" ]
+ visibility = [
+ "//content/test/*",
+ "//content/public/test/*",
+ ]
if (!is_component_build) {
public_deps = [
":browser",
diff --git a/chromium/content/browser/DEPS b/chromium/content/browser/DEPS
index afd8cb019fb..a065eb289c4 100644
--- a/chromium/content/browser/DEPS
+++ b/chromium/content/browser/DEPS
@@ -101,9 +101,9 @@ include_rules = [
"+third_party/blink/public/platform/web_touch_event.h",
"+third_party/blink/public/platform/web_text_input_type.h",
"+third_party/blink/public/platform/mac/web_scrollbar_theme.h",
- "+third_party/blink/public/platform/modules/locks/lock_manager.mojom.h",
+ "+third_party/blink/public/platform/modules/font_unique_name_lookup/font_unique_name_lookup.mojom.h",
"+third_party/blink/public/platform/modules/indexeddb/web_idb_database_exception.h",
- "+third_party/blink/public/platform/modules/indexeddb/web_idb_types.h",
+ "+third_party/blink/public/platform/modules/locks/lock_manager.mojom.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/public_buildflags.h",
@@ -145,12 +145,10 @@ include_rules = [
"+third_party/blink/public/platform/modules/mediastream/media_devices.mojom.h",
"+third_party/blink/public/platform/modules/notifications/notification_service.mojom.h",
"+third_party/blink/public/platform/modules/frame_sinks/embedded_frame_sink.mojom.h",
- "+third_party/blink/public/platform/modules/payments/payment_app.mojom.h",
"+third_party/blink/public/platform/modules/permissions/permission.mojom.h",
"+third_party/blink/public/platform/modules/permissions/permission_status.mojom.h",
- "+third_party/blink/public/platform/modules/presentation/presentation.mojom.h",
- "+third_party/blink/public/platform/modules/webauth/authenticator.mojom.h",
- "+third_party/blink/public/platform/modules/webauth/virtual_authenticator.mojom.h",
+ "+third_party/blink/public/platform/modules/webauthn/authenticator.mojom.h",
+ "+third_party/blink/public/platform/modules/webauthn/virtual_authenticator.mojom.h",
"+third_party/blink/public/platform/modules/webdatabase/web_database.mojom.h",
"+third_party/blink/public/platform/modules/websockets/websocket.mojom.h",
"+third_party/blink/public/platform/oom_intervention.mojom.h",
diff --git a/chromium/content/browser/OWNERS b/chromium/content/browser/OWNERS
index 223a5fa2d14..61804ae5596 100644
--- a/chromium/content/browser/OWNERS
+++ b/chromium/content/browser/OWNERS
@@ -1,6 +1,10 @@
# For Android
boliu@chromium.org
+# These are for the common case of adding or renaming files. If you're doing
+# structural changes, please get a review from a reviewer in this file.
+per-file BUILD.gn=*
+
# For security review.
per-file child_process_security_policy_impl.*=set noparent
per-file child_process_security_policy_impl.*=creis@chromium.org
diff --git a/chromium/content/browser/accessibility/accessibility_event_recorder.cc b/chromium/content/browser/accessibility/accessibility_event_recorder.cc
index 88390e8d004..a2de95e816a 100644
--- a/chromium/content/browser/accessibility/accessibility_event_recorder.cc
+++ b/chromium/content/browser/accessibility/accessibility_event_recorder.cc
@@ -5,6 +5,7 @@
#include "content/browser/accessibility/accessibility_event_recorder.h"
#include "build/build_config.h"
+#include "content/browser/accessibility/browser_accessibility_manager.h"
namespace content {
@@ -13,19 +14,19 @@ AccessibilityEventRecorder::AccessibilityEventRecorder(
base::ProcessId pid)
: manager_(manager) {}
-AccessibilityEventRecorder::~AccessibilityEventRecorder() {
-}
+AccessibilityEventRecorder::~AccessibilityEventRecorder() = default;
#if !defined(OS_WIN) && !defined(OS_MACOSX)
// static
-AccessibilityEventRecorder* AccessibilityEventRecorder::Create(
+AccessibilityEventRecorder& AccessibilityEventRecorder::GetInstance(
BrowserAccessibilityManager* manager,
base::ProcessId pid) {
- return new AccessibilityEventRecorder(manager, pid);
+ static base::NoDestructor<AccessibilityEventRecorder> instance(manager, pid);
+ return *instance;
}
#endif
-void AccessibilityEventRecorder::OnEvent(std::string event) {
+void AccessibilityEventRecorder::OnEvent(const std::string& event) {
event_logs_.push_back(event);
if (callback_)
callback_.Run(event);
diff --git a/chromium/content/browser/accessibility/accessibility_event_recorder.h b/chromium/content/browser/accessibility/accessibility_event_recorder.h
index 7ff5879926e..4d03a1dbc01 100644
--- a/chromium/content/browser/accessibility/accessibility_event_recorder.h
+++ b/chromium/content/browser/accessibility/accessibility_event_recorder.h
@@ -10,12 +10,13 @@
#include "base/callback.h"
#include "base/macros.h"
+#include "base/no_destructor.h"
#include "base/process/process_handle.h"
-#include "content/common/content_export.h"
namespace content {
-using AccessibilityEventCallback = base::RepeatingCallback<void(std::string)>;
+using AccessibilityEventCallback =
+ base::RepeatingCallback<void(const std::string&)>;
class BrowserAccessibilityManager;
@@ -32,12 +33,14 @@ class BrowserAccessibilityManager;
//
// The implementation is highly platform-specific; a subclass is needed for
// each platform does most of the work.
+//
+// As currently designed, there should only be one instance of this class.
class AccessibilityEventRecorder {
public:
- // Construct the right platform-specific subclass.
- static AccessibilityEventRecorder* Create(
- BrowserAccessibilityManager* manager,
- base::ProcessId pid);
+ // Get the right platform-specific subclass.
+ static AccessibilityEventRecorder& GetInstance(
+ BrowserAccessibilityManager* manager = nullptr,
+ base::ProcessId pid = 0);
virtual ~AccessibilityEventRecorder();
void set_only_web_events(bool only_web_events) {
@@ -52,14 +55,16 @@ class AccessibilityEventRecorder {
const std::vector<std::string>& event_logs() { return event_logs_; }
protected:
- explicit AccessibilityEventRecorder(BrowserAccessibilityManager* manager,
- base::ProcessId pid);
+ AccessibilityEventRecorder(BrowserAccessibilityManager* manager,
+ base::ProcessId pid);
- void OnEvent(std::string event);
+ void OnEvent(const std::string& event);
- BrowserAccessibilityManager* manager_;
+ BrowserAccessibilityManager* const manager_;
bool only_web_events_ = false;
+ friend class base::NoDestructor<AccessibilityEventRecorder>;
+
private:
std::vector<std::string> event_logs_;
AccessibilityEventCallback callback_;
diff --git a/chromium/content/browser/accessibility/accessibility_event_recorder_mac.mm b/chromium/content/browser/accessibility/accessibility_event_recorder_mac.mm
index f8efd01bfc7..0245a037230 100644
--- a/chromium/content/browser/accessibility/accessibility_event_recorder_mac.mm
+++ b/chromium/content/browser/accessibility/accessibility_event_recorder_mac.mm
@@ -4,10 +4,10 @@
#include "content/browser/accessibility/accessibility_event_recorder.h"
-#include <string>
-
#import <Cocoa/Cocoa.h>
+#include <string>
+
#include "base/mac/foundation_util.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/strings/stringprintf.h"
@@ -20,14 +20,15 @@ namespace content {
// watch for NSAccessibility events.
class AccessibilityEventRecorderMac : public AccessibilityEventRecorder {
public:
- explicit AccessibilityEventRecorderMac(BrowserAccessibilityManager* manager,
- base::ProcessId pid);
~AccessibilityEventRecorderMac() override;
// Callback executed every time we receive an event notification.
void EventReceived(AXUIElementRef element, CFStringRef notification);
private:
+ AccessibilityEventRecorderMac(BrowserAccessibilityManager* manager,
+ base::ProcessId pid);
+
// Add one notification to the list of notifications monitored by our
// observer.
void AddNotification(NSString* notification);
@@ -43,6 +44,9 @@ class AccessibilityEventRecorderMac : public AccessibilityEventRecorder {
// The AXObserver we use to monitor AX notifications.
base::ScopedCFTypeRef<AXObserverRef> observer_ref_;
CFRunLoopSourceRef observer_run_loop_source_;
+
+ friend class base::NoDestructor<AccessibilityEventRecorderMac>;
+ DISALLOW_COPY_AND_ASSIGN(AccessibilityEventRecorderMac);
};
// Callback function registered using AXObserverCreate.
@@ -57,10 +61,12 @@ static void EventReceivedThunk(
}
// static
-AccessibilityEventRecorder* AccessibilityEventRecorder::Create(
+AccessibilityEventRecorder& AccessibilityEventRecorder::GetInstance(
BrowserAccessibilityManager* manager,
base::ProcessId pid) {
- return new AccessibilityEventRecorderMac(manager, pid);
+ static base::NoDestructor<AccessibilityEventRecorderMac> instance(manager,
+ pid);
+ return *instance;
}
AccessibilityEventRecorderMac::AccessibilityEventRecorderMac(
@@ -126,7 +132,7 @@ std::string AccessibilityEventRecorderMac::GetAXAttributeValue(
return base::SysCFStringRefToUTF8(value_string);
// TODO(dmazzoni): And if it's not a string, can we return something better?
- return std::string();
+ return {};
}
void AccessibilityEventRecorderMac::EventReceived(AXUIElementRef element,
diff --git a/chromium/content/browser/accessibility/accessibility_event_recorder_win.cc b/chromium/content/browser/accessibility/accessibility_event_recorder_win.cc
index a71a156a72e..07c26adb4c0 100644
--- a/chromium/content/browser/accessibility/accessibility_event_recorder_win.cc
+++ b/chromium/content/browser/accessibility/accessibility_event_recorder_win.cc
@@ -16,7 +16,6 @@
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/win/scoped_bstr.h"
-#include "base/win/scoped_com_initializer.h"
#include "base/win/scoped_variant.h"
#include "content/browser/accessibility/accessibility_tree_formatter_utils_win.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
@@ -76,23 +75,22 @@ std::string AccessibilityEventToStringUTF8(int32_t event_id) {
class AccessibilityEventRecorderWin : public AccessibilityEventRecorder {
public:
- explicit AccessibilityEventRecorderWin(BrowserAccessibilityManager* manager,
- base::ProcessId pid);
-
~AccessibilityEventRecorderWin() override;
// Callback registered by SetWinEventHook. Just calls OnWinEventHook.
- static void CALLBACK WinEventHookThunk(
- HWINEVENTHOOK handle,
- DWORD event,
- HWND hwnd,
- LONG obj_id,
- LONG child_id,
- DWORD event_thread,
- DWORD event_time);
+ static CALLBACK void WinEventHookThunk(HWINEVENTHOOK handle,
+ DWORD event,
+ HWND hwnd,
+ LONG obj_id,
+ LONG child_id,
+ DWORD event_thread,
+ DWORD event_time);
private:
- // Called by the thunk registered by SetWinEventHook. Retrives accessibility
+ AccessibilityEventRecorderWin(BrowserAccessibilityManager* manager,
+ base::ProcessId pid);
+
+ // Called by the thunk registered by SetWinEventHook. Retrieves accessibility
// info about the node the event was fired on and appends a string to
// the event log.
void OnWinEventHook(HWINEVENTHOOK handle,
@@ -109,25 +107,22 @@ class AccessibilityEventRecorderWin : public AccessibilityEventRecorder {
HWND hwnd, DWORD dwId, REFIID riid, void **ppvObject);
HWINEVENTHOOK win_event_hook_handle_;
- static AccessibilityEventRecorderWin* instance_;
- // Initializes COM services when standalone dump events tool is used.
- base::win::ScopedCOMInitializer com_initializer;
+ friend class base::NoDestructor<AccessibilityEventRecorderWin>;
+ DISALLOW_COPY_AND_ASSIGN(AccessibilityEventRecorderWin);
};
// static
-AccessibilityEventRecorderWin*
-AccessibilityEventRecorderWin::instance_ = nullptr;
-
-// static
-AccessibilityEventRecorder* AccessibilityEventRecorder::Create(
+AccessibilityEventRecorder& AccessibilityEventRecorder::GetInstance(
BrowserAccessibilityManager* manager,
base::ProcessId pid) {
- return new AccessibilityEventRecorderWin(manager, pid);
+ static base::NoDestructor<AccessibilityEventRecorderWin> instance(manager,
+ pid);
+ return *instance;
}
// static
-void CALLBACK AccessibilityEventRecorderWin::WinEventHookThunk(
+CALLBACK void AccessibilityEventRecorderWin::WinEventHookThunk(
HWINEVENTHOOK handle,
DWORD event,
HWND hwnd,
@@ -135,20 +130,15 @@ void CALLBACK AccessibilityEventRecorderWin::WinEventHookThunk(
LONG child_id,
DWORD event_thread,
DWORD event_time) {
- if (instance_) {
- instance_->OnWinEventHook(handle, event, hwnd, obj_id, child_id,
- event_thread, event_time);
- }
+ static_cast<AccessibilityEventRecorderWin&>(GetInstance())
+ .OnWinEventHook(handle, event, hwnd, obj_id, child_id, event_thread,
+ event_time);
}
AccessibilityEventRecorderWin::AccessibilityEventRecorderWin(
BrowserAccessibilityManager* manager,
base::ProcessId pid)
: AccessibilityEventRecorder(manager, pid) {
- CHECK(!instance_) << "There can be only one instance of"
- << " WinAccessibilityEventMonitor at a time.";
- instance_ = this;
-
// For now, just use out of context events when running as a utility to watch
// events (no BrowserAccessibilityManager), because otherwise Chrome events
// are not getting reported. Being in context is better so that for
@@ -165,7 +155,6 @@ AccessibilityEventRecorderWin::AccessibilityEventRecorderWin(
AccessibilityEventRecorderWin::~AccessibilityEventRecorderWin() {
UnhookWinEvent(win_event_hook_handle_);
- instance_ = NULL;
}
void AccessibilityEventRecorderWin::OnWinEventHook(
@@ -180,7 +169,7 @@ void AccessibilityEventRecorderWin::OnWinEventHook(
HRESULT hr = AccessibleObjectFromWindowWrapper(
hwnd, obj_id, IID_IAccessible,
reinterpret_cast<void**>(browser_accessible.GetAddressOf()));
- if (!SUCCEEDED(hr)) {
+ if (FAILED(hr)) {
// Note: our event hook will pick up some superfluous events we
// don't care about, so it's safe to just ignore these failures.
// Same below for other HRESULT checks.
@@ -192,7 +181,7 @@ void AccessibilityEventRecorderWin::OnWinEventHook(
Microsoft::WRL::ComPtr<IDispatch> dispatch;
hr = browser_accessible->get_accChild(childid_variant,
dispatch.GetAddressOf());
- if (!SUCCEEDED(hr) || !dispatch) {
+ if (hr != S_OK || !dispatch) {
VLOG(1) << "Ignoring result " << hr << " and result " << dispatch.Get()
<< " from get_accChild";
return;
@@ -200,7 +189,7 @@ void AccessibilityEventRecorderWin::OnWinEventHook(
Microsoft::WRL::ComPtr<IAccessible> iaccessible;
hr = dispatch.CopyTo(iaccessible.GetAddressOf());
- if (!SUCCEEDED(hr)) {
+ if (FAILED(hr)) {
VLOG(1) << "Ignoring result " << hr << " from QueryInterface";
return;
}
@@ -212,13 +201,13 @@ void AccessibilityEventRecorderWin::OnWinEventHook(
Microsoft::WRL::ComPtr<IServiceProvider> service_provider;
hr = iaccessible->QueryInterface(service_provider.GetAddressOf());
- if (!SUCCEEDED(hr))
+ if (FAILED(hr))
return;
Microsoft::WRL::ComPtr<IAccessible> content_document;
hr = service_provider->QueryService(GUID_IAccessibleContentDocument,
content_document.GetAddressOf());
- if (!SUCCEEDED(hr))
+ if (FAILED(hr))
return;
}
@@ -301,8 +290,15 @@ void AccessibilityEventRecorderWin::OnWinEventHook(
log += base::StringPrintf(" role=%s", RoleVariantToString(role).c_str());
if (name_bstr.Length() > 0)
log += base::StringPrintf(" name=\"%s\"", BstrToUTF8(name_bstr).c_str());
- if (value_bstr.Length() > 0)
- log += base::StringPrintf(" value=\"%s\"", BstrToUTF8(value_bstr).c_str());
+ if (value_bstr.Length() > 0) {
+ bool is_document =
+ role.type() == VT_I4 && ROLE_SYSTEM_DOCUMENT == V_I4(role.ptr());
+ // Don't show actual document value, which is a URL, in order to avoid
+ // machine-based differences in tests.
+ log += is_document ? " value~=[doc-url]"
+ : base::StringPrintf(" value=\"%s\"",
+ BstrToUTF8(value_bstr).c_str());
+ }
log += " ";
log += base::UTF16ToUTF8(IAccessibleStateToString(ia_state));
log += " ";
diff --git a/chromium/content/browser/accessibility/accessibility_ipc_error_browsertest.cc b/chromium/content/browser/accessibility/accessibility_ipc_error_browsertest.cc
index c91e712b57c..b6e8ad2423f 100644
--- a/chromium/content/browser/accessibility/accessibility_ipc_error_browsertest.cc
+++ b/chromium/content/browser/accessibility/accessibility_ipc_error_browsertest.cc
@@ -132,9 +132,11 @@ IN_PROC_BROWSER_TEST_F(AccessibilityIpcErrorBrowserTest,
#if defined(OS_ANDROID)
// http://crbug.com/542704
-#define MAYBE_MultipleBadAccessibilityIPCsKillsRenderer DISABLED_MultipleBadAccessibilityIPCsKillsRenderer
+#define MAYBE_MultipleBadAccessibilityIPCsKillsRenderer \
+ DISABLED_MultipleBadAccessibilityIPCsKillsRenderer
#else
-#define MAYBE_MultipleBadAccessibilityIPCsKillsRenderer MultipleBadAccessibilityIPCsKillsRenderer
+#define MAYBE_MultipleBadAccessibilityIPCsKillsRenderer \
+ MultipleBadAccessibilityIPCsKillsRenderer
#endif
IN_PROC_BROWSER_TEST_F(AccessibilityIpcErrorBrowserTest,
MAYBE_MultipleBadAccessibilityIPCsKillsRenderer) {
@@ -161,7 +163,10 @@ IN_PROC_BROWSER_TEST_F(AccessibilityIpcErrorBrowserTest,
// will reject.
AXEventNotificationDetails bad_accessibility_event;
bad_accessibility_event.updates.resize(1);
- bad_accessibility_event.updates[0].node_id_to_clear = -2;
+ bad_accessibility_event.updates[0].root_id = 1;
+ bad_accessibility_event.updates[0].nodes.resize(1);
+ bad_accessibility_event.updates[0].nodes[0].id = 1;
+ bad_accessibility_event.updates[0].nodes[0].child_ids.push_back(2);
// We should be able to reset accessibility |max_iterations-1| times
// (see render_frame_host_impl.cc - kMaxAccessibilityResets),
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter.cc b/chromium/content/browser/accessibility/accessibility_tree_formatter.cc
index 5236a97ee06..d095d80b4fd 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter.cc
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter.cc
@@ -15,6 +15,7 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
+#include "content/browser/accessibility/accessibility_tree_formatter_blink.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/browser/web_contents/web_contents_impl.h"
@@ -50,6 +51,23 @@ void AccessibilityTreeFormatter::FormatAccessibilityTree(
RecursiveFormatAccessibilityTree(dict, contents);
}
+base::string16 AccessibilityTreeFormatter::DumpAccessibilityTreeFromManager(
+ BrowserAccessibilityManager* ax_mgr,
+ bool internal) {
+ std::unique_ptr<AccessibilityTreeFormatter> formatter;
+ if (internal)
+ formatter.reset(new AccessibilityTreeFormatterBlink());
+ else
+ formatter.reset(Create());
+ base::string16 accessibility_contents_utf16;
+ std::vector<Filter> filters;
+ filters.push_back(Filter(base::ASCIIToUTF16("*"), Filter::ALLOW));
+ formatter->SetFilters(filters);
+ formatter->FormatAccessibilityTree(ax_mgr->GetRoot(),
+ &accessibility_contents_utf16);
+ return accessibility_contents_utf16;
+}
+
std::unique_ptr<base::DictionaryValue>
AccessibilityTreeFormatter::FilterAccessibilityTree(
const base::DictionaryValue& dict) {
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter.h b/chromium/content/browser/accessibility/accessibility_tree_formatter.h
index 536fcb617e7..51b8bc52c6a 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter.h
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter.h
@@ -99,6 +99,10 @@ class CONTENT_EXPORT AccessibilityTreeFormatter {
void FormatAccessibilityTree(const base::DictionaryValue& tree_node,
base::string16* contents);
+ static base::string16 DumpAccessibilityTreeFromManager(
+ BrowserAccessibilityManager* ax_mgr,
+ bool internal);
+
// Set regular expression filters that apply to each component of every
// line before it's output.
void SetFilters(const std::vector<Filter>& filters);
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc b/chromium/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc
index 568088325e4..596b7d7ebc6 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc
@@ -56,6 +56,43 @@ void AccessibilityTreeFormatterAuraLinux::AddProperties(
acc_obj->GetNode()->AddAccessibilityTreeProperties(dict);
}
+const char* const ATK_OBJECT_ATTRIBUTES[] = {
+ "atomic",
+ "autocomplete",
+ "busy",
+ "checkable",
+ "class",
+ "colcount",
+ "colindex",
+ "container-atomic",
+ "container-busy",
+ "container-live",
+ "container-relevant",
+ "display",
+ "explicit-name",
+ "haspopup",
+ "id",
+ "keyshortcuts",
+ "level",
+ "live",
+ "placeholder",
+ "posinset",
+ "relevant",
+ "roledescription",
+ "rowcount",
+ "rowindex",
+ "setsize",
+ "src",
+ "table-cell-index",
+ "tag",
+ "text-input-type",
+ "valuemin",
+ "valuemax",
+ "valuenow",
+ "valuetext",
+ "xml-roles",
+};
+
base::string16 AccessibilityTreeFormatterAuraLinux::ProcessTreeForOutput(
const base::DictionaryValue& node,
base::DictionaryValue* filtered_dict_result) {
@@ -87,14 +124,24 @@ base::string16 AccessibilityTreeFormatterAuraLinux::ProcessTreeForOutput(
it != states_value->end(); ++it) {
std::string state_value;
if (it->GetAsString(&state_value))
- WriteAttribute(true, state_value, &line);
+ WriteAttribute(false, state_value, &line);
}
int id_value;
node.GetInteger("id", &id_value);
WriteAttribute(false, base::StringPrintf("id=%d", id_value), &line);
- return line + base::ASCIIToUTF16("\n");
+ for (const char* attribute_name : ATK_OBJECT_ATTRIBUTES) {
+ std::string attribute_value;
+ if (node.GetString(attribute_name, &attribute_value)) {
+ WriteAttribute(
+ false,
+ base::StringPrintf("%s:%s", attribute_name, attribute_value.c_str()),
+ &line);
+ }
+ }
+
+ return line;
}
const base::FilePath::StringType
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_win.cc b/chromium/content/browser/accessibility/accessibility_tree_formatter_win.cc
index 10b1967d4b5..20fd3b776fc 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter_win.cc
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_win.cc
@@ -20,8 +20,8 @@
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
+#include "base/win/com_init_util.h"
#include "base/win/scoped_bstr.h"
-#include "base/win/scoped_com_initializer.h"
#include "base/win/scoped_variant.h"
#include "content/browser/accessibility/accessibility_tree_formatter_utils_win.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
@@ -113,13 +113,11 @@ class AccessibilityTreeFormatterWin : public AccessibilityTreeFormatter {
base::string16 ProcessTreeForOutput(
const base::DictionaryValue& node,
base::DictionaryValue* filtered_dict_result = nullptr) override;
-
- // Initializes COM services when standalone dump events tool is used.
- base::win::ScopedCOMInitializer com_initializer;
};
// static
AccessibilityTreeFormatter* AccessibilityTreeFormatter::Create() {
+ base::win::AssertComInitialized();
return new AccessibilityTreeFormatterWin();
}
diff --git a/chromium/content/browser/accessibility/accessibility_ui.cc b/chromium/content/browser/accessibility/accessibility_ui.cc
deleted file mode 100644
index 4dada7363d2..00000000000
--- a/chromium/content/browser/accessibility/accessibility_ui.cc
+++ /dev/null
@@ -1,416 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/accessibility/accessibility_ui.h"
-
-#include <memory>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/command_line.h"
-#include "base/json/json_writer.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/values.h"
-#include "content/browser/accessibility/accessibility_tree_formatter.h"
-#include "content/browser/accessibility/accessibility_tree_formatter_blink.h"
-#include "content/browser/accessibility/browser_accessibility_manager.h"
-#include "content/browser/accessibility/browser_accessibility_state_impl.h"
-#include "content/browser/renderer_host/render_view_host_impl.h"
-#include "content/browser/renderer_host/render_widget_host_impl.h"
-#include "content/browser/renderer_host/render_widget_host_view_base.h"
-#include "content/browser/web_contents/web_contents_impl.h"
-#include "content/browser/web_contents/web_contents_view.h"
-#include "content/browser/webui/web_ui_data_source_impl.h"
-#include "content/common/view_message_enums.h"
-#include "content/grit/content_resources.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/favicon_status.h"
-#include "content/public/browser/navigation_entry.h"
-#include "content/public/browser/render_process_host.h"
-#include "content/public/browser/render_view_host.h"
-#include "content/public/browser/render_widget_host.h"
-#include "content/public/browser/render_widget_host_iterator.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_ui_data_source.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/common/url_constants.h"
-#include "net/base/escape.h"
-#include "ui/accessibility/platform/ax_platform_node.h"
-#include "ui/base/webui/web_ui_util.h"
-
-static const char kTargetsDataFile[] = "targets-data.json";
-
-static const char kProcessIdField[] = "processId";
-static const char kRouteIdField[] = "routeId";
-static const char kUrlField[] = "url";
-static const char kNameField[] = "name";
-static const char kFaviconUrlField[] = "favicon_url";
-static const char kPidField[] = "pid";
-static const char kAccessibilityModeField[] = "a11y_mode";
-
-// Global flags
-static const char kInternal[] = "internal";
-static const char kNative[] = "native";
-static const char kWeb[] = "web";
-static const char kText[] = "text";
-static const char kScreenReader[] = "screenreader";
-static const char kHTML[] = "html";
-
-// Possible global flag values
-static const char kOff[]= "off";
-static const char kOn[] = "on";
-static const char kDisabled[] = "disabled";
-
-namespace content {
-
-namespace {
-
-bool g_show_internal_accessibility_tree = false;
-
-std::unique_ptr<base::DictionaryValue> BuildTargetDescriptor(
- const GURL& url,
- const std::string& name,
- const GURL& favicon_url,
- int process_id,
- int route_id,
- ui::AXMode accessibility_mode,
- base::ProcessHandle handle = base::kNullProcessHandle) {
- std::unique_ptr<base::DictionaryValue> target_data(
- new base::DictionaryValue());
- target_data->SetInteger(kProcessIdField, process_id);
- target_data->SetInteger(kRouteIdField, route_id);
- target_data->SetString(kUrlField, url.spec());
- target_data->SetString(kNameField, net::EscapeForHTML(name));
- target_data->SetInteger(kPidField, base::GetProcId(handle));
- target_data->SetString(kFaviconUrlField, favicon_url.spec());
- target_data->SetInteger(kAccessibilityModeField, accessibility_mode.mode());
- return target_data;
-}
-
-std::unique_ptr<base::DictionaryValue> BuildTargetDescriptor(
- RenderViewHost* rvh) {
- WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
- WebContents::FromRenderViewHost(rvh));
- ui::AXMode accessibility_mode;
-
- std::string title;
- GURL url;
- GURL favicon_url;
- if (web_contents) {
- // TODO(nasko): Fix the following code to use a consistent set of data
- // across the URL, title, and favicon.
- url = web_contents->GetURL();
- title = base::UTF16ToUTF8(web_contents->GetTitle());
- NavigationController& controller = web_contents->GetController();
- NavigationEntry* entry = controller.GetVisibleEntry();
- if (entry != nullptr && entry->GetURL().is_valid()) {
- gfx::Image favicon_image = entry->GetFavicon().image;
- if (!favicon_image.IsEmpty()) {
- const SkBitmap* favicon_bitmap = favicon_image.ToSkBitmap();
- favicon_url = GURL(webui::GetBitmapDataUrl(*favicon_bitmap));
- }
- }
- accessibility_mode = web_contents->GetAccessibilityMode();
- }
-
- return BuildTargetDescriptor(url,
- title,
- favicon_url,
- rvh->GetProcess()->GetID(),
- rvh->GetRoutingID(),
- accessibility_mode);
-}
-
-bool HandleAccessibilityRequestCallback(
- BrowserContext* current_context,
- const std::string& path,
- const WebUIDataSource::GotDataCallback& callback) {
- if (path != kTargetsDataFile)
- return false;
- std::unique_ptr<base::ListValue> rvh_list(new base::ListValue());
-
- std::unique_ptr<RenderWidgetHostIterator> widgets(
- RenderWidgetHost::GetRenderWidgetHosts());
-
- while (RenderWidgetHost* widget = widgets->GetNextHost()) {
- // Ignore processes that don't have a connection, such as crashed tabs.
- if (!widget->GetProcess()->IsInitializedAndNotDead())
- continue;
- RenderViewHost* rvh = RenderViewHost::From(widget);
- if (!rvh)
- continue;
- // Ignore views that are never visible, like background pages.
- if (static_cast<RenderViewHostImpl*>(rvh)->GetDelegate()->IsNeverVisible())
- continue;
- BrowserContext* context = rvh->GetProcess()->GetBrowserContext();
- if (context != current_context)
- continue;
-
- rvh_list->Append(BuildTargetDescriptor(rvh));
- }
-
- base::DictionaryValue data;
- data.Set("list", std::move(rvh_list));
- ui::AXMode mode =
- BrowserAccessibilityStateImpl::GetInstance()->accessibility_mode();
- bool disabled = base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableRendererAccessibility);
- bool native = mode.has_mode(ui::AXMode::kNativeAPIs);
- bool web = mode.has_mode(ui::AXMode::kWebContents);
- bool text = mode.has_mode(ui::AXMode::kInlineTextBoxes);
- bool screenreader = mode.has_mode(ui::AXMode::kScreenReader);
- bool html = mode.has_mode(ui::AXMode::kHTML);
-
- // The "native" and "web" flags are disabled if
- // --disable-renderer-accessibility is set.
- data.SetString(kNative, disabled ? kDisabled : (native ? kOn : kOff));
- data.SetString(kWeb, disabled ? kDisabled : (web ? kOn : kOff));
-
- // The "text", "screenreader", and "html" flags are only meaningful if
- // "web" is enabled.
- data.SetString(kText, web ? (text ? kOn : kOff) : kDisabled);
- data.SetString(kScreenReader, web ? (screenreader ? kOn : kOff) : kDisabled);
- data.SetString(kHTML, web ? (html ? kOn : kOff) : kDisabled);
-
- data.SetString(kInternal,
- g_show_internal_accessibility_tree ? kOn : kOff);
-
- std::string json_string;
- base::JSONWriter::Write(data, &json_string);
-
- callback.Run(base::RefCountedString::TakeString(&json_string));
- return true;
-}
-
-std::string RecursiveDumpAXPlatformNodeAsString(ui::AXPlatformNode* node,
- int indent) {
- std::string str(2 * indent, '+');
- str += node->GetDelegate()->GetData().ToString() + "\n";
- for (int i = 0; i < node->GetDelegate()->GetChildCount(); i++) {
- gfx::NativeViewAccessible child = node->GetDelegate()->ChildAtIndex(i);
- ui::AXPlatformNode* child_node =
- ui::AXPlatformNode::FromNativeViewAccessible(child);
- if (child_node)
- str += RecursiveDumpAXPlatformNodeAsString(child_node, indent + 1);
- }
- return str;
-}
-
-} // namespace
-
-AccessibilityUI::AccessibilityUI(WebUI* web_ui) : WebUIController(web_ui) {
- // Set up the chrome://accessibility source.
- WebUIDataSourceImpl* html_source = static_cast<WebUIDataSourceImpl*>(
- WebUIDataSource::Create(kChromeUIAccessibilityHost));
-
- // Add required resources.
- html_source->SetJsonPath("strings.js");
- html_source->AddResourcePath("accessibility.css", IDR_ACCESSIBILITY_CSS);
- html_source->AddResourcePath("accessibility.js", IDR_ACCESSIBILITY_JS);
- html_source->SetDefaultResource(IDR_ACCESSIBILITY_HTML);
- html_source->SetRequestFilter(
- base::Bind(&HandleAccessibilityRequestCallback,
- web_ui->GetWebContents()->GetBrowserContext()));
-
- html_source->UseGzip({kTargetsDataFile});
-
- BrowserContext* browser_context =
- web_ui->GetWebContents()->GetBrowserContext();
- WebUIDataSource::Add(browser_context, html_source);
-
- web_ui->AddMessageHandler(std::make_unique<AccessibilityUIMessageHandler>());
-}
-
-AccessibilityUI::~AccessibilityUI() {}
-
-AccessibilityUIMessageHandler::AccessibilityUIMessageHandler() {}
-
-AccessibilityUIMessageHandler::~AccessibilityUIMessageHandler() {}
-
-void AccessibilityUIMessageHandler::RegisterMessages() {
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-
- web_ui()->RegisterMessageCallback(
- "toggleAccessibility",
- base::BindRepeating(&AccessibilityUIMessageHandler::ToggleAccessibility,
- base::Unretained(this)));
- web_ui()->RegisterMessageCallback(
- "setGlobalFlag",
- base::BindRepeating(&AccessibilityUIMessageHandler::SetGlobalFlag,
- base::Unretained(this)));
- web_ui()->RegisterMessageCallback(
- "requestWebContentsTree",
- base::BindRepeating(
- &AccessibilityUIMessageHandler::RequestWebContentsTree,
- base::Unretained(this)));
- web_ui()->RegisterMessageCallback(
- "requestNativeUITree",
- base::BindRepeating(&AccessibilityUIMessageHandler::RequestNativeUITree,
- base::Unretained(this)));
-}
-
-void AccessibilityUIMessageHandler::ToggleAccessibility(
- const base::ListValue* args) {
- std::string process_id_str;
- std::string route_id_str;
- int process_id;
- int route_id;
- int mode;
- CHECK_EQ(3U, args->GetSize());
- CHECK(args->GetString(0, &process_id_str));
- CHECK(args->GetString(1, &route_id_str));
- // TODO(695247): We should pass each ax flag seperately
- CHECK(args->GetInteger(2, &mode));
- CHECK(base::StringToInt(process_id_str, &process_id));
- CHECK(base::StringToInt(route_id_str, &route_id));
-
- AllowJavascript();
- RenderViewHost* rvh = RenderViewHost::FromID(process_id, route_id);
- if (!rvh)
- return;
- auto* web_contents =
- static_cast<WebContentsImpl*>(WebContents::FromRenderViewHost(rvh));
- ui::AXMode current_mode = web_contents->GetAccessibilityMode();
-
- if (mode & ui::AXMode::kNativeAPIs)
- current_mode.set_mode(ui::AXMode::kNativeAPIs, true);
-
- if (mode & ui::AXMode::kWebContents)
- current_mode.set_mode(ui::AXMode::kWebContents, true);
-
- if (mode & ui::AXMode::kInlineTextBoxes)
- current_mode.set_mode(ui::AXMode::kInlineTextBoxes, true);
-
- if (mode & ui::AXMode::kScreenReader)
- current_mode.set_mode(ui::AXMode::kScreenReader, true);
-
- if (mode & ui::AXMode::kHTML)
- current_mode.set_mode(ui::AXMode::kHTML, true);
-
- web_contents->SetAccessibilityMode(current_mode);
-}
-
-void AccessibilityUIMessageHandler::SetGlobalFlag(const base::ListValue* args) {
- std::string flag_name_str;
- bool enabled;
- CHECK_EQ(2U, args->GetSize());
- CHECK(args->GetString(0, &flag_name_str));
- CHECK(args->GetBoolean(1, &enabled));
-
- AllowJavascript();
- if (flag_name_str == kInternal) {
- g_show_internal_accessibility_tree = enabled;
- LOG(ERROR) << "INTERNAL: " << g_show_internal_accessibility_tree;
- return;
- }
-
- ui::AXMode new_mode;
- if (flag_name_str == kNative) {
- new_mode = ui::AXMode::kNativeAPIs;
- } else if (flag_name_str == kWeb) {
- new_mode = ui::AXMode::kWebContents;
- } else if (flag_name_str == kText) {
- new_mode = ui::AXMode::kInlineTextBoxes;
- } else if (flag_name_str == kScreenReader) {
- new_mode = ui::AXMode::kScreenReader;
- } else if (flag_name_str == kHTML) {
- new_mode = ui::AXMode::kHTML;
- } else {
- NOTREACHED();
- return;
- }
-
- // It doesn't make sense to enable one of the flags that depends on
- // web contents without enabling web contents accessibility too.
- if (enabled && (new_mode.has_mode(ui::AXMode::kInlineTextBoxes) ||
- new_mode.has_mode(ui::AXMode::kScreenReader) ||
- new_mode.has_mode(ui::AXMode::kHTML))) {
- new_mode.set_mode(ui::AXMode::kWebContents, true);
- }
-
- // Similarly if you disable web accessibility we should remove all
- // flags that depend on it.
- if (!enabled && new_mode.has_mode(ui::AXMode::kWebContents)) {
- new_mode.set_mode(ui::AXMode::kInlineTextBoxes, true);
- new_mode.set_mode(ui::AXMode::kScreenReader, true);
- new_mode.set_mode(ui::AXMode::kHTML, true);
- }
-
- BrowserAccessibilityStateImpl* state =
- BrowserAccessibilityStateImpl::GetInstance();
- if (enabled)
- state->AddAccessibilityModeFlags(new_mode);
- else
- state->RemoveAccessibilityModeFlags(new_mode);
-}
-
-void AccessibilityUIMessageHandler::RequestWebContentsTree(
- const base::ListValue* args) {
- std::string process_id_str;
- std::string route_id_str;
- int process_id;
- int route_id;
- CHECK_EQ(2U, args->GetSize());
- CHECK(args->GetString(0, &process_id_str));
- CHECK(args->GetString(1, &route_id_str));
- CHECK(base::StringToInt(process_id_str, &process_id));
- CHECK(base::StringToInt(route_id_str, &route_id));
-
- AllowJavascript();
- RenderViewHost* rvh = RenderViewHost::FromID(process_id, route_id);
- if (!rvh) {
- std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue());
- result->SetInteger(kProcessIdField, process_id);
- result->SetInteger(kRouteIdField, route_id);
- result->SetString("error", "Renderer no longer exists.");
- CallJavascriptFunction("accessibility.showTree", *(result.get()));
- return;
- }
-
- std::unique_ptr<base::DictionaryValue> result(BuildTargetDescriptor(rvh));
- auto* web_contents =
- static_cast<WebContentsImpl*>(WebContents::FromRenderViewHost(rvh));
- // No matter the state of the current web_contents, we want to force the mode
- // because we are about to show the accessibility tree
- web_contents->SetAccessibilityMode(
- ui::AXMode(ui::AXMode::kNativeAPIs | ui::AXMode::kWebContents));
-
- std::unique_ptr<AccessibilityTreeFormatter> formatter;
- if (g_show_internal_accessibility_tree)
- formatter.reset(new AccessibilityTreeFormatterBlink());
- else
- formatter.reset(AccessibilityTreeFormatter::Create());
- base::string16 accessibility_contents_utf16;
- std::vector<AccessibilityTreeFormatter::Filter> filters;
- filters.push_back(AccessibilityTreeFormatter::Filter(
- base::ASCIIToUTF16("*"),
- AccessibilityTreeFormatter::Filter::ALLOW));
- formatter->SetFilters(filters);
- auto* ax_mgr = web_contents->GetOrCreateRootBrowserAccessibilityManager();
- DCHECK(ax_mgr);
- formatter->FormatAccessibilityTree(ax_mgr->GetRoot(),
- &accessibility_contents_utf16);
- result->SetString("tree", base::UTF16ToUTF8(accessibility_contents_utf16));
- CallJavascriptFunction("accessibility.showTree", *(result.get()));
-}
-
-void AccessibilityUIMessageHandler::RequestNativeUITree(
- const base::ListValue* args) {
- AllowJavascript();
- WebContentsImpl* web_contents =
- static_cast<WebContentsImpl*>(web_ui()->GetWebContents());
- gfx::NativeWindow native_window =
- web_contents->GetView()->GetTopLevelNativeWindow();
- ui::AXPlatformNode* node =
- ui::AXPlatformNode::FromNativeWindow(native_window);
- std::string str = RecursiveDumpAXPlatformNodeAsString(node, 0);
-
- std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue());
- result->SetString("tree", str);
- CallJavascriptFunction("accessibility.showNativeUITree", *(result.get()));
-}
-
-} // namespace content
diff --git a/chromium/content/browser/accessibility/accessibility_ui.h b/chromium/content/browser/accessibility/accessibility_ui.h
deleted file mode 100644
index a54f23d3502..00000000000
--- a/chromium/content/browser/accessibility/accessibility_ui.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_ACCESSIBILITY_ACCESSIBILITY_UI_H_
-#define CONTENT_BROWSER_ACCESSIBILITY_ACCESSIBILITY_UI_H_
-
-#include "base/macros.h"
-#include "content/public/browser/web_ui_controller.h"
-#include "content/public/browser/web_ui_data_source.h"
-#include "content/public/browser/web_ui_message_handler.h"
-
-namespace base {
- class ListValue;
-} // namespace base
-
-namespace content {
-
-class AccessibilityUI : public WebUIController {
- public:
- explicit AccessibilityUI(WebUI* web_ui);
- ~AccessibilityUI() override;
-};
-
-class AccessibilityUIMessageHandler : public content::WebUIMessageHandler {
- public:
- AccessibilityUIMessageHandler();
- ~AccessibilityUIMessageHandler() override;
-
- void RegisterMessages() override;
-
- private:
- void ToggleAccessibility(const base::ListValue* args);
- void SetGlobalFlag(const base::ListValue* args);
- void RequestWebContentsTree(const base::ListValue* args);
- void RequestNativeUITree(const base::ListValue* args);
-
- DISALLOW_COPY_AND_ASSIGN(AccessibilityUIMessageHandler);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_ACCESSIBILITY_ACCESSIBILITY_UI_H_
diff --git a/chromium/content/browser/accessibility/accessibility_win_browsertest.cc b/chromium/content/browser/accessibility/accessibility_win_browsertest.cc
index 4ab51921d62..9bb5760cfdb 100644
--- a/chromium/content/browser/accessibility/accessibility_win_browsertest.cc
+++ b/chromium/content/browser/accessibility/accessibility_win_browsertest.cc
@@ -683,7 +683,7 @@ void AccessibilityWinBrowserTest::AccessibleChecker::CheckIA2Role(
Microsoft::WRL::ComPtr<IAccessible2> accessible2;
HRESULT hr = QueryIAccessible2(accessible, accessible2.GetAddressOf());
ASSERT_EQ(S_OK, hr);
- long ia2_role = 0;
+ LONG ia2_role = 0;
hr = accessible2->role(&ia2_role);
ASSERT_EQ(S_OK, hr);
EXPECT_EQ(ia2_role_, ia2_role)
@@ -771,14 +771,14 @@ class NativeWinEventWaiter {
NativeWinEventWaiter(BrowserAccessibilityManager* manager,
const std::string& match_pattern)
: event_recorder_(
- AccessibilityEventRecorder::Create(manager,
- base::GetCurrentProcId())),
+ AccessibilityEventRecorder::GetInstance(manager,
+ base::GetCurrentProcId())),
match_pattern_(match_pattern) {
- event_recorder_->ListenToEvents(base::BindRepeating(
+ event_recorder_.ListenToEvents(base::BindRepeating(
&NativeWinEventWaiter::OnEvent, base::Unretained(this)));
}
- void OnEvent(std::string event_str) {
+ void OnEvent(const std::string& event_str) {
DLOG(INFO) << "Got event " + event_str;
if (base::MatchPattern(event_str, match_pattern_))
run_loop_.QuitClosure().Run();
@@ -787,7 +787,7 @@ class NativeWinEventWaiter {
void Wait() { run_loop_.Run(); }
private:
- std::unique_ptr<AccessibilityEventRecorder> event_recorder_;
+ AccessibilityEventRecorder& event_recorder_;
std::string match_pattern_;
base::RunLoop run_loop_;
};
@@ -1290,16 +1290,12 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
EXPECT_EQ(previous_height, height) << "at offset " << offset;
}
- // Vertically offscreen objects should have a height of 1px so that if an
- // assistive aid ignores the offscreen state, they will still be too small
- // to be visible and thus not appear outside the window. Note that a height
- // of 0 is not used because it signifies an invalid size.
EXPECT_HRESULT_SUCCEEDED(editable_container->get_characterExtents(
last_line_start, coordinate_type, &x, &y, &width, &height));
EXPECT_LT(0, x) << "at offset " << last_line_start;
EXPECT_LT(previous_y, y) << "at offset " << last_line_start;
EXPECT_LT(1, width) << "at offset " << last_line_start;
- EXPECT_EQ(1, height) << "at offset " << last_line_start;
+ EXPECT_EQ(previous_height, height) << "at offset " << last_line_start;
for (LONG offset = last_line_start + 1; offset < n_characters; ++offset) {
previous_x = x;
@@ -1310,7 +1306,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
EXPECT_LT(previous_x, x) << "at offset " << offset;
EXPECT_EQ(previous_y, y) << "at offset " << offset;
EXPECT_LT(1, width) << "at offset " << offset;
- EXPECT_EQ(1, height) << "at offset " << offset;
+ EXPECT_EQ(previous_height, height) << "at offset " << offset;
}
}
}
@@ -1334,21 +1330,13 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
coordinate <= IA2_COORDTYPE_PARENT_RELATIVE; ++coordinate) {
auto coordinate_type = static_cast<IA2CoordinateType>(coordinate);
- // Horizontally offscreen objects should have a width of 1px so that if an
- // assistive aid ignores the offscreen state, they will still be too small
- // to be visible and thus not appear outside the window. Note that a width
- // of 0 is not used because it signifies an invalid size.
EXPECT_HRESULT_SUCCEEDED(input_text->get_characterExtents(
0, coordinate_type, &x, &y, &width, &height));
- EXPECT_LT(0, x + width) << "at offset 0";
+ EXPECT_GT(0, x + width) << "at offset 0";
EXPECT_LT(0, y) << "at offset 0";
- EXPECT_EQ(1, width) << "at offset 0";
+ EXPECT_LT(1, width) << "at offset 0";
EXPECT_LT(1, height) << "at offset 0";
- // Test that characters at the start of the input field are offscreen by
- // checking that their x coordinate is at the start of the field and their
- // width is 1.
- // Exclude the character that is partly visible.
for (LONG offset = 1; offset < (visible_characters_start - 1); ++offset) {
previous_x = x;
previous_y = y;
@@ -1356,9 +1344,9 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
EXPECT_HRESULT_SUCCEEDED(input_text->get_characterExtents(
offset, coordinate_type, &x, &y, &width, &height));
- EXPECT_EQ(previous_x, x) << "at offset " << offset;
+ EXPECT_LT(previous_x, x) << "at offset " << offset;
EXPECT_EQ(previous_y, y) << "at offset " << offset;
- EXPECT_EQ(1, width) << "at offset " << offset;
+ EXPECT_LT(1, width) << "at offset " << offset;
EXPECT_EQ(previous_height, height) << "at offset " << offset;
}
@@ -1366,7 +1354,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
// width that is greater than 1px.
EXPECT_HRESULT_SUCCEEDED(input_text->get_characterExtents(
visible_characters_start, coordinate_type, &x, &y, &width, &height));
- EXPECT_EQ(previous_x, x) << "at offset " << visible_characters_start;
+ EXPECT_LT(previous_x, x) << "at offset " << visible_characters_start;
EXPECT_EQ(previous_y, y) << "at offset " << visible_characters_start;
EXPECT_LT(1, width) << "at offset " << visible_characters_start;
EXPECT_EQ(previous_height, height)
diff --git a/chromium/content/browser/accessibility/browser_accessibility.cc b/chromium/content/browser/accessibility/browser_accessibility.cc
index 68e62b1db86..10485315e69 100644
--- a/chromium/content/browser/accessibility/browser_accessibility.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility.cc
@@ -343,8 +343,9 @@ gfx::Rect BrowserAccessibility::GetPageBoundsRect(bool* offscreen,
return RelativeToAbsoluteBounds(gfx::RectF(), false, offscreen, clip_bounds);
}
-gfx::Rect BrowserAccessibility::GetPageBoundsForRange(int start, int len)
- const {
+gfx::Rect BrowserAccessibility::GetPageBoundsForRange(int start,
+ int len,
+ bool clipped) const {
DCHECK_GE(start, 0);
DCHECK_GE(len, 0);
@@ -464,9 +465,11 @@ gfx::Rect BrowserAccessibility::GetPageBoundsForRange(int start, int len)
}
}
+ // 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, false /* frame_only */, nullptr /* offscreen */,
- true /* clip_bounds */);
+ clipped /* clip_bounds */);
if (bounds.width() == 0 && bounds.height() == 0) {
bounds = absolute_child_rect;
} else {
@@ -477,9 +480,10 @@ gfx::Rect BrowserAccessibility::GetPageBoundsForRange(int start, int len)
return bounds;
}
-gfx::Rect BrowserAccessibility::GetScreenBoundsForRange(int start, int len)
- const {
- gfx::Rect bounds = GetPageBoundsForRange(start, len);
+gfx::Rect BrowserAccessibility::GetScreenBoundsForRange(int start,
+ int len,
+ bool clipped) const {
+ gfx::Rect bounds = GetPageBoundsForRange(start, len, clipped);
// Adjust the bounds by the top left corner of the containing view's bounds
// in screen coordinates.
@@ -687,20 +691,24 @@ bool BrowserAccessibility::HasAction(ax::mojom::Action action_enum) const {
return GetData().HasAction(action_enum);
}
-bool BrowserAccessibility::HasCaret() const {
- if (IsPlainTextField() &&
- HasIntAttribute(ax::mojom::IntAttribute::kTextSelStart) &&
- HasIntAttribute(ax::mojom::IntAttribute::kTextSelEnd)) {
- return true;
- }
-
- // The caret is always at the focus of the selection.
+bool BrowserAccessibility::HasVisibleCaretOrSelection() const {
int32_t focus_id = manager()->GetTreeData().sel_focus_object_id;
BrowserAccessibility* focus_object = manager()->GetFromID(focus_id);
if (!focus_object)
return false;
- return focus_object->IsDescendantOf(this);
+ // Selection or caret will be visible in a focused editable area.
+ if (HasState(ax::mojom::State::kEditable)) {
+ return IsPlainTextField() ? focus_object == this
+ : focus_object->IsDescendantOf(this);
+ }
+
+ // The selection will be visible in non-editable content only if it is not
+ // collapsed into a caret.
+ return (focus_id != manager()->GetTreeData().sel_anchor_object_id ||
+ manager()->GetTreeData().sel_focus_offset !=
+ manager()->GetTreeData().sel_anchor_offset) &&
+ focus_object->IsDescendantOf(this);
}
bool BrowserAccessibility::IsWebAreaForPresentationalIframe() const {
@@ -764,6 +772,24 @@ std::string BrowserAccessibility::ComputeAccessibleNameFromDescendants() const {
return name;
}
+std::string BrowserAccessibility::GetLiveRegionText() const {
+ if (GetRole() == ax::mojom::Role::kIgnored)
+ return "";
+
+ std::string text = GetStringAttribute(ax::mojom::StringAttribute::kName);
+ if (!text.empty())
+ return text;
+
+ for (size_t i = 0; i < InternalChildCount(); ++i) {
+ BrowserAccessibility* child = InternalGetChild(i);
+ if (!child)
+ continue;
+
+ text += child->GetLiveRegionText();
+ }
+ return text;
+}
+
std::vector<int> BrowserAccessibility::GetLineStartOffsets() const {
if (!instance_active())
return std::vector<int>();
diff --git a/chromium/content/browser/accessibility/browser_accessibility.h b/chromium/content/browser/accessibility/browser_accessibility.h
index f3d85b39061..b66d5e86384 100644
--- a/chromium/content/browser/accessibility/browser_accessibility.h
+++ b/chromium/content/browser/accessibility/browser_accessibility.h
@@ -160,10 +160,14 @@ class CONTENT_EXPORT BrowserAccessibility : public ui::AXPlatformNodeDelegate {
// Returns the bounds of the given range in coordinates relative to the
// top-left corner of the overall web area. Only valid when the
// role is WebAXRoleStaticText.
- gfx::Rect GetPageBoundsForRange(int start, int len) const;
+ gfx::Rect GetPageBoundsForRange(int start,
+ int len,
+ bool clipped = false) const;
// Same as |GetPageBoundsForRange| but in screen coordinates.
- gfx::Rect GetScreenBoundsForRange(int start, int len) const;
+ gfx::Rect GetScreenBoundsForRange(int start,
+ int len,
+ bool clipped = false) const;
// Convert a bounding rectangle from this node's coordinate system
// (which is relative to its nearest scrollable ancestor) to
@@ -299,8 +303,8 @@ class CONTENT_EXPORT BrowserAccessibility : public ui::AXPlatformNodeDelegate {
bool HasState(ax::mojom::State state_enum) const;
bool HasAction(ax::mojom::Action action_enum) const;
- // Returns true if the caret is active on this object.
- bool HasCaret() const;
+ // Returns true if the caret or selection is visible on this object.
+ bool HasVisibleCaretOrSelection() const;
// True if this is a web area, and its grandparent is a presentational iframe.
bool IsWebAreaForPresentationalIframe() const;
@@ -316,6 +320,9 @@ class CONTENT_EXPORT BrowserAccessibility : public ui::AXPlatformNodeDelegate {
// to compute a name from its descendants.
std::string ComputeAccessibleNameFromDescendants() const;
+ // Get text to announce for a live region change if AT does not implement.
+ std::string GetLiveRegionText() const;
+
// Creates a text position rooted at this object.
BrowserAccessibilityPosition::AXPositionInstance CreatePositionAt(
int offset,
diff --git a/chromium/content/browser/accessibility/browser_accessibility_android.cc b/chromium/content/browser/accessibility/browser_accessibility_android.cc
index 3dd224bd18d..95b60d9f0d0 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_android.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_android.cc
@@ -761,6 +761,9 @@ base::string16 BrowserAccessibilityAndroid::GetRoleDescription() const {
case ax::mojom::Role::kInputTime:
message_id = IDS_AX_ROLE_INPUT_TIME;
break;
+ case ax::mojom::Role::kKeyboard:
+ // No role description.
+ break;
case ax::mojom::Role::kLabelText:
// No role description.
break;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_auralinux.cc b/chromium/content/browser/accessibility/browser_accessibility_auralinux.cc
index 3921dd72764..3d63387ab0e 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_auralinux.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_auralinux.cc
@@ -46,6 +46,10 @@ void BrowserAccessibilityAuraLinux::OnDataChanged() {
node_->DataChanged();
}
+void BrowserAccessibilityAuraLinux::UpdatePlatformAttributes() {
+ GetNode()->UpdateHypertext();
+}
+
bool BrowserAccessibilityAuraLinux::IsNative() const {
return true;
}
diff --git a/chromium/content/browser/accessibility/browser_accessibility_auralinux.h b/chromium/content/browser/accessibility/browser_accessibility_auralinux.h
index 6ba7d6f6b31..ba263d95bdf 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_auralinux.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_auralinux.h
@@ -22,7 +22,11 @@ class BrowserAccessibilityAuraLinux : public BrowserAccessibility {
~BrowserAccessibilityAuraLinux() override;
- ui::AXPlatformNodeAuraLinux* GetNode() const;
+ CONTENT_EXPORT ui::AXPlatformNodeAuraLinux* GetNode() const;
+
+ // This is used to call UpdateHypertext, when a node needs to be
+ // updated for some other reason other than via OnAtomicUpdateFinished.
+ void UpdatePlatformAttributes() override;
// BrowserAccessibility methods.
void OnDataChanged() override;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_auralinux_unittest.cc b/chromium/content/browser/accessibility/browser_accessibility_auralinux_unittest.cc
new file mode 100644
index 00000000000..3d31036acac
--- /dev/null
+++ b/chromium/content/browser/accessibility/browser_accessibility_auralinux_unittest.cc
@@ -0,0 +1,121 @@
+// Copyright (c) 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/accessibility/browser_accessibility_auralinux.h"
+
+#include <atk/atk.h>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "content/browser/accessibility/browser_accessibility_manager.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/accessibility/platform/ax_platform_node_auralinux.h"
+
+namespace content {
+
+class BrowserAccessibilityAuraLinuxTest : public testing::Test {
+ public:
+ BrowserAccessibilityAuraLinuxTest();
+ ~BrowserAccessibilityAuraLinuxTest() override;
+
+ private:
+ void SetUp() override;
+
+ content::TestBrowserThreadBundle thread_bundle_;
+
+ DISALLOW_COPY_AND_ASSIGN(BrowserAccessibilityAuraLinuxTest);
+};
+
+BrowserAccessibilityAuraLinuxTest::BrowserAccessibilityAuraLinuxTest() {}
+
+BrowserAccessibilityAuraLinuxTest::~BrowserAccessibilityAuraLinuxTest() {}
+
+void BrowserAccessibilityAuraLinuxTest::SetUp() {}
+
+TEST_F(BrowserAccessibilityAuraLinuxTest, TestSimpleAtkText) {
+ ui::AXNodeData root_data;
+ root_data.id = 1;
+ root_data.role = ax::mojom::Role::kStaticText;
+ root_data.SetName("\xE2\x98\xBA Multiple Words");
+
+ std::unique_ptr<BrowserAccessibilityManager> manager(
+ BrowserAccessibilityManager::Create(MakeAXTreeUpdate(root_data), nullptr,
+ new BrowserAccessibilityFactory()));
+
+ ui::AXPlatformNodeAuraLinux* root_obj =
+ ToBrowserAccessibilityAuraLinux(manager->GetRoot())->GetNode();
+ AtkObject* root_atk_object(root_obj->GetNativeViewAccessible());
+ ASSERT_TRUE(ATK_IS_OBJECT(root_atk_object));
+ ASSERT_TRUE(ATK_IS_TEXT(root_atk_object));
+ g_object_ref(root_atk_object);
+
+ AtkText* atk_text = ATK_TEXT(root_atk_object);
+
+ auto verify_atk_text_contents = [&](const char* expected_text,
+ int start_offset, int end_offset) {
+ gchar* text = atk_text_get_text(atk_text, start_offset, end_offset);
+ EXPECT_STREQ(expected_text, text);
+ g_free(text);
+ };
+
+ verify_atk_text_contents("\xE2\x98\xBA Multiple Words", 0, -1);
+ verify_atk_text_contents("Multiple Words", 2, -1);
+ verify_atk_text_contents("\xE2\x98\xBA", 0, 1);
+
+ EXPECT_EQ(16, atk_text_get_character_count(atk_text));
+
+ g_object_unref(root_atk_object);
+
+ manager.reset();
+}
+
+TEST_F(BrowserAccessibilityAuraLinuxTest, TestCompositeAtkText) {
+ const std::string text1_name = "One two three.";
+ const std::string text2_name = " Four five six.";
+ const int text_name_len = text1_name.length() + text2_name.length();
+
+ ui::AXNodeData text1;
+ text1.id = 11;
+ text1.role = ax::mojom::Role::kStaticText;
+ text1.SetName(text1_name);
+
+ ui::AXNodeData text2;
+ text2.id = 12;
+ text2.role = ax::mojom::Role::kStaticText;
+ text2.SetName(text2_name);
+
+ ui::AXNodeData root;
+ root.id = 1;
+ root.role = ax::mojom::Role::kRootWebArea;
+ root.child_ids.push_back(text1.id);
+ root.child_ids.push_back(text2.id);
+
+ std::unique_ptr<BrowserAccessibilityManager> manager(
+ BrowserAccessibilityManager::Create(MakeAXTreeUpdate(root, text1, text2),
+ nullptr,
+ new BrowserAccessibilityFactory()));
+
+ ui::AXPlatformNodeAuraLinux* root_obj =
+ ToBrowserAccessibilityAuraLinux(manager->GetRoot())->GetNode();
+ AtkObject* root_atk_object(root_obj->GetNativeViewAccessible());
+
+ ASSERT_TRUE(ATK_IS_OBJECT(root_atk_object));
+ ASSERT_TRUE(ATK_IS_TEXT(root_atk_object));
+ g_object_ref(root_atk_object);
+ AtkText* atk_text = ATK_TEXT(root_atk_object);
+
+ EXPECT_EQ(text_name_len, atk_text_get_character_count(atk_text));
+
+ gchar* text = atk_text_get_text(atk_text, 0, -1);
+ EXPECT_STREQ((text1_name + text2_name).c_str(), text);
+ g_free(text);
+
+ g_object_unref(root_atk_object);
+
+ manager.reset();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm b/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm
index 07e9862b76a..06db282cd74 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm
+++ b/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm
@@ -833,7 +833,9 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
if (![self isIgnored]) {
children_.reset();
} else {
- [ToBrowserAccessibilityCocoa(owner_->PlatformGetParent()) childrenChanged];
+ auto* parent = owner_->PlatformGetParent();
+ if (parent)
+ [ToBrowserAccessibilityCocoa(parent) childrenChanged];
}
}
@@ -1720,8 +1722,11 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
std::string role_attribute;
if (owner_->GetHtmlAttribute("role", &role_attribute)) {
ax::mojom::Role internalRole = [self internalRole];
- if ((internalRole != ax::mojom::Role::kGroup &&
- internalRole != ax::mojom::Role::kListItem) ||
+ if ((internalRole != ax::mojom::Role::kBlockquote &&
+ internalRole != ax::mojom::Role::kCaption &&
+ internalRole != ax::mojom::Role::kGroup &&
+ internalRole != ax::mojom::Role::kListItem &&
+ internalRole != ax::mojom::Role::kParagraph) ||
internalRole == ax::mojom::Role::kTab) {
// TODO(dtseng): This is not localized; see crbug/84814.
return base::SysUTF8ToNSString(role_attribute);
@@ -2276,6 +2281,7 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
return base::SysUTF16ToNSString(owner_->GetValue());
}
+// TODO(crbug.com/865101) Remove this once the autofill state works.
- (BOOL)isFocusedInputWithSuggestions {
if (!owner_->IsPlainTextField())
return false;
@@ -2288,6 +2294,8 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
- (NSNumber*)valueAutofillAvailable {
if (![self instanceActive])
return nil;
+ // TODO(crbug.com/865101) Use this instead:
+ // return owner_->HasState(ax::mojom::State::kAutofillAvailable) ? @YES : @NO;
return [self isFocusedInputWithSuggestions] ? @YES : @NO;
}
diff --git a/chromium/content/browser/accessibility/browser_accessibility_com_win.cc b/chromium/content/browser/accessibility/browser_accessibility_com_win.cc
index ce687913fb2..c874c05dd94 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_com_win.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_com_win.cc
@@ -70,12 +70,12 @@ BrowserAccessibilityComWin::~BrowserAccessibilityComWin() {
// IAccessible2 overrides:
//
-STDMETHODIMP BrowserAccessibilityComWin::get_attributes(BSTR* attributes) {
+IFACEMETHODIMP BrowserAccessibilityComWin::get_attributes(BSTR* attributes) {
// This can be removed once ISimpleDOMNode is migrated
return AXPlatformNodeWin::get_attributes(attributes);
}
-STDMETHODIMP BrowserAccessibilityComWin::scrollTo(IA2ScrollType scroll_type) {
+IFACEMETHODIMP BrowserAccessibilityComWin::scrollTo(IA2ScrollType scroll_type) {
// This can be removed once ISimpleDOMNode is migrated
return AXPlatformNodeWin::scrollTo(scroll_type);
}
@@ -84,7 +84,7 @@ STDMETHODIMP BrowserAccessibilityComWin::scrollTo(IA2ScrollType scroll_type) {
// IAccessibleApplication methods.
//
-STDMETHODIMP BrowserAccessibilityComWin::get_appName(BSTR* app_name) {
+IFACEMETHODIMP BrowserAccessibilityComWin::get_appName(BSTR* app_name) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_APP_NAME);
if (!app_name)
@@ -103,7 +103,7 @@ STDMETHODIMP BrowserAccessibilityComWin::get_appName(BSTR* app_name) {
return *app_name ? S_OK : E_FAIL;
}
-STDMETHODIMP BrowserAccessibilityComWin::get_appVersion(BSTR* app_version) {
+IFACEMETHODIMP BrowserAccessibilityComWin::get_appVersion(BSTR* app_version) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_APP_VERSION);
if (!app_version)
@@ -123,7 +123,7 @@ STDMETHODIMP BrowserAccessibilityComWin::get_appVersion(BSTR* app_version) {
return *app_version ? S_OK : E_FAIL;
}
-STDMETHODIMP BrowserAccessibilityComWin::get_toolkitName(BSTR* toolkit_name) {
+IFACEMETHODIMP BrowserAccessibilityComWin::get_toolkitName(BSTR* toolkit_name) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_TOOLKIT_NAME);
if (!toolkit_name)
return E_INVALIDARG;
@@ -136,7 +136,7 @@ STDMETHODIMP BrowserAccessibilityComWin::get_toolkitName(BSTR* toolkit_name) {
return *toolkit_name ? S_OK : E_FAIL;
}
-STDMETHODIMP BrowserAccessibilityComWin::get_toolkitVersion(
+IFACEMETHODIMP BrowserAccessibilityComWin::get_toolkitVersion(
BSTR* toolkit_version) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_TOOLKIT_VERSION);
if (!toolkit_version)
@@ -152,7 +152,7 @@ STDMETHODIMP BrowserAccessibilityComWin::get_toolkitVersion(
// IAccessibleImage methods.
//
-STDMETHODIMP BrowserAccessibilityComWin::get_description(BSTR* desc) {
+IFACEMETHODIMP BrowserAccessibilityComWin::get_description(BSTR* desc) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_DESCRIPTION);
if (!owner())
return E_FAIL;
@@ -169,7 +169,7 @@ STDMETHODIMP BrowserAccessibilityComWin::get_description(BSTR* desc) {
return S_OK;
}
-STDMETHODIMP BrowserAccessibilityComWin::get_imagePosition(
+IFACEMETHODIMP BrowserAccessibilityComWin::get_imagePosition(
IA2CoordinateType coordinate_type,
LONG* x,
LONG* y) {
@@ -199,8 +199,8 @@ STDMETHODIMP BrowserAccessibilityComWin::get_imagePosition(
return S_OK;
}
-STDMETHODIMP BrowserAccessibilityComWin::get_imageSize(LONG* height,
- LONG* width) {
+IFACEMETHODIMP BrowserAccessibilityComWin::get_imageSize(LONG* height,
+ LONG* width) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_IMAGE_SIZE);
if (!owner())
return E_FAIL;
@@ -217,15 +217,15 @@ STDMETHODIMP BrowserAccessibilityComWin::get_imageSize(LONG* height,
// IAccessibleText methods.
//
-STDMETHODIMP BrowserAccessibilityComWin::get_nCharacters(LONG* n_characters) {
+IFACEMETHODIMP BrowserAccessibilityComWin::get_nCharacters(LONG* n_characters) {
return AXPlatformNodeWin::get_nCharacters(n_characters);
}
-STDMETHODIMP BrowserAccessibilityComWin::get_caretOffset(LONG* offset) {
+IFACEMETHODIMP BrowserAccessibilityComWin::get_caretOffset(LONG* offset) {
return AXPlatformNodeWin::get_caretOffset(offset);
}
-STDMETHODIMP BrowserAccessibilityComWin::get_characterExtents(
+IFACEMETHODIMP BrowserAccessibilityComWin::get_characterExtents(
LONG offset,
IA2CoordinateType coordinate_type,
LONG* out_x,
@@ -241,7 +241,7 @@ STDMETHODIMP 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 = GetTextAsString16();
HandleSpecialTextOffset(&offset);
if (offset < 0 || offset > static_cast<LONG>(text_str.size()))
return E_INVALIDARG;
@@ -267,20 +267,20 @@ STDMETHODIMP BrowserAccessibilityComWin::get_characterExtents(
return S_OK;
}
-STDMETHODIMP BrowserAccessibilityComWin::get_nSelections(LONG* n_selections) {
+IFACEMETHODIMP BrowserAccessibilityComWin::get_nSelections(LONG* n_selections) {
return AXPlatformNodeWin::get_nSelections(n_selections);
}
-STDMETHODIMP BrowserAccessibilityComWin::get_selection(LONG selection_index,
- LONG* start_offset,
- LONG* end_offset) {
+IFACEMETHODIMP BrowserAccessibilityComWin::get_selection(LONG selection_index,
+ LONG* start_offset,
+ LONG* end_offset) {
return AXPlatformNodeWin::get_selection(selection_index, start_offset,
end_offset);
}
-STDMETHODIMP BrowserAccessibilityComWin::get_text(LONG start_offset,
- LONG end_offset,
- BSTR* text) {
+IFACEMETHODIMP BrowserAccessibilityComWin::get_text(LONG start_offset,
+ LONG end_offset,
+ BSTR* text) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_TEXT);
AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
if (!owner())
@@ -289,7 +289,7 @@ STDMETHODIMP BrowserAccessibilityComWin::get_text(LONG start_offset,
if (!text)
return E_INVALIDARG;
- const base::string16& text_str = GetText();
+ const base::string16& text_str = GetTextAsString16();
HandleSpecialTextOffset(&start_offset);
HandleSpecialTextOffset(&end_offset);
@@ -313,7 +313,7 @@ STDMETHODIMP BrowserAccessibilityComWin::get_text(LONG start_offset,
return S_OK;
}
-STDMETHODIMP BrowserAccessibilityComWin::get_textAtOffset(
+IFACEMETHODIMP BrowserAccessibilityComWin::get_textAtOffset(
LONG offset,
IA2TextBoundaryType boundary_type,
LONG* start_offset,
@@ -336,7 +336,7 @@ STDMETHODIMP BrowserAccessibilityComWin::get_textAtOffset(
if (offset < 0)
return E_INVALIDARG;
- const base::string16& text_str = GetText();
+ const base::string16& text_str = GetTextAsString16();
LONG text_len = text_str.length();
if (offset > text_len)
return E_INVALIDARG;
@@ -361,7 +361,7 @@ STDMETHODIMP BrowserAccessibilityComWin::get_textAtOffset(
return get_text(start, end, text);
}
-STDMETHODIMP BrowserAccessibilityComWin::get_textBeforeOffset(
+IFACEMETHODIMP BrowserAccessibilityComWin::get_textBeforeOffset(
LONG offset,
IA2TextBoundaryType boundary_type,
LONG* start_offset,
@@ -380,7 +380,7 @@ STDMETHODIMP BrowserAccessibilityComWin::get_textBeforeOffset(
*end_offset = 0;
*text = NULL;
- const base::string16& text_str = GetText();
+ const base::string16& text_str = GetTextAsString16();
LONG text_len = text_str.length();
if (offset > text_len)
return E_INVALIDARG;
@@ -395,7 +395,7 @@ STDMETHODIMP BrowserAccessibilityComWin::get_textBeforeOffset(
return get_text(*start_offset, *end_offset, text);
}
-STDMETHODIMP BrowserAccessibilityComWin::get_textAfterOffset(
+IFACEMETHODIMP BrowserAccessibilityComWin::get_textAfterOffset(
LONG offset,
IA2TextBoundaryType boundary_type,
LONG* start_offset,
@@ -414,7 +414,7 @@ STDMETHODIMP BrowserAccessibilityComWin::get_textAfterOffset(
*end_offset = 0;
*text = NULL;
- const base::string16& text_str = GetText();
+ const base::string16& text_str = GetTextAsString16();
LONG text_len = text_str.length();
if (offset > text_len)
return E_INVALIDARG;
@@ -429,7 +429,8 @@ STDMETHODIMP BrowserAccessibilityComWin::get_textAfterOffset(
return get_text(*start_offset, *end_offset, text);
}
-STDMETHODIMP BrowserAccessibilityComWin::get_newText(IA2TextSegment* new_text) {
+IFACEMETHODIMP BrowserAccessibilityComWin::get_newText(
+ IA2TextSegment* new_text) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_NEW_TEXT);
AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
if (!owner())
@@ -441,19 +442,20 @@ STDMETHODIMP BrowserAccessibilityComWin::get_newText(IA2TextSegment* new_text) {
if (!old_win_attributes_)
return E_FAIL;
- int start, old_len, new_len;
+ size_t start, old_len, new_len;
ComputeHypertextRemovedAndInserted(&start, &old_len, &new_len);
if (new_len == 0)
return E_FAIL;
- base::string16 substr = GetText().substr(start, new_len);
+ base::string16 substr = GetTextAsString16().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);
+ new_text->start = static_cast<LONG>(start);
+ new_text->end = static_cast<LONG>(start + new_len);
return S_OK;
}
-STDMETHODIMP BrowserAccessibilityComWin::get_oldText(IA2TextSegment* old_text) {
+IFACEMETHODIMP BrowserAccessibilityComWin::get_oldText(
+ IA2TextSegment* old_text) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_OLD_TEXT);
AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
if (!owner())
@@ -465,7 +467,7 @@ STDMETHODIMP BrowserAccessibilityComWin::get_oldText(IA2TextSegment* old_text) {
if (!old_win_attributes_)
return E_FAIL;
- int start, old_len, new_len;
+ size_t start, old_len, new_len;
ComputeHypertextRemovedAndInserted(&start, &old_len, &new_len);
if (old_len == 0)
return E_FAIL;
@@ -473,12 +475,12 @@ STDMETHODIMP BrowserAccessibilityComWin::get_oldText(IA2TextSegment* old_text) {
base::string16 old_hypertext = old_hypertext_.hypertext;
base::string16 substr = old_hypertext.substr(start, old_len);
old_text->text = SysAllocString(substr.c_str());
- old_text->start = static_cast<long>(start);
- old_text->end = static_cast<long>(start + old_len);
+ old_text->start = static_cast<LONG>(start);
+ old_text->end = static_cast<LONG>(start + old_len);
return S_OK;
}
-STDMETHODIMP BrowserAccessibilityComWin::get_offsetAtPoint(
+IFACEMETHODIMP BrowserAccessibilityComWin::get_offsetAtPoint(
LONG x,
LONG y,
IA2CoordinateType coord_type,
@@ -499,7 +501,7 @@ STDMETHODIMP BrowserAccessibilityComWin::get_offsetAtPoint(
return S_OK;
}
-STDMETHODIMP BrowserAccessibilityComWin::scrollSubstringTo(
+IFACEMETHODIMP BrowserAccessibilityComWin::scrollSubstringTo(
LONG start_index,
LONG end_index,
IA2ScrollType scroll_type) {
@@ -510,7 +512,7 @@ STDMETHODIMP BrowserAccessibilityComWin::scrollSubstringTo(
return scrollTo(scroll_type);
}
-STDMETHODIMP BrowserAccessibilityComWin::scrollSubstringToPoint(
+IFACEMETHODIMP BrowserAccessibilityComWin::scrollSubstringToPoint(
LONG start_index,
LONG end_index,
IA2CoordinateType coordinate_type,
@@ -535,16 +537,17 @@ STDMETHODIMP BrowserAccessibilityComWin::scrollSubstringToPoint(
return scrollToPoint(coordinate_type, x, y);
}
-STDMETHODIMP BrowserAccessibilityComWin::addSelection(LONG start_offset,
- LONG end_offset) {
+IFACEMETHODIMP BrowserAccessibilityComWin::addSelection(LONG start_offset,
+ LONG end_offset) {
return AXPlatformNodeWin::addSelection(start_offset, end_offset);
}
-STDMETHODIMP BrowserAccessibilityComWin::removeSelection(LONG selection_index) {
+IFACEMETHODIMP BrowserAccessibilityComWin::removeSelection(
+ LONG selection_index) {
return AXPlatformNodeWin::removeSelection(selection_index);
}
-STDMETHODIMP BrowserAccessibilityComWin::setCaretOffset(LONG offset) {
+IFACEMETHODIMP BrowserAccessibilityComWin::setCaretOffset(LONG offset) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_SET_CARET_OFFSET);
AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
if (!owner())
@@ -553,9 +556,9 @@ STDMETHODIMP BrowserAccessibilityComWin::setCaretOffset(LONG offset) {
return S_OK;
}
-STDMETHODIMP BrowserAccessibilityComWin::setSelection(LONG selection_index,
- LONG start_offset,
- LONG end_offset) {
+IFACEMETHODIMP BrowserAccessibilityComWin::setSelection(LONG selection_index,
+ LONG start_offset,
+ LONG end_offset) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_SET_SELECTION);
AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
if (!owner())
@@ -566,10 +569,11 @@ STDMETHODIMP BrowserAccessibilityComWin::setSelection(LONG selection_index,
return S_OK;
}
-STDMETHODIMP BrowserAccessibilityComWin::get_attributes(LONG offset,
- LONG* start_offset,
- LONG* end_offset,
- BSTR* text_attributes) {
+IFACEMETHODIMP BrowserAccessibilityComWin::get_attributes(
+ LONG offset,
+ LONG* start_offset,
+ LONG* end_offset,
+ BSTR* text_attributes) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_IATEXT_GET_ATTRIBUTES);
AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
if (!start_offset || !end_offset || !text_attributes)
@@ -580,7 +584,7 @@ STDMETHODIMP BrowserAccessibilityComWin::get_attributes(LONG offset,
if (!owner())
return E_FAIL;
- const base::string16 text = GetText();
+ const base::string16 text = GetTextAsString16();
HandleSpecialTextOffset(&offset);
if (offset < 0 || offset > static_cast<LONG>(text.size()))
return E_INVALIDARG;
@@ -608,8 +612,8 @@ STDMETHODIMP BrowserAccessibilityComWin::get_attributes(LONG offset,
// IAccessibleHypertext methods.
//
-STDMETHODIMP BrowserAccessibilityComWin::get_nHyperlinks(
- long* hyperlink_count) {
+IFACEMETHODIMP BrowserAccessibilityComWin::get_nHyperlinks(
+ LONG* hyperlink_count) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_N_HYPERLINKS);
AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
if (!owner())
@@ -622,8 +626,8 @@ STDMETHODIMP BrowserAccessibilityComWin::get_nHyperlinks(
return S_OK;
}
-STDMETHODIMP BrowserAccessibilityComWin::get_hyperlink(
- long index,
+IFACEMETHODIMP BrowserAccessibilityComWin::get_hyperlink(
+ LONG index,
IAccessibleHyperlink** hyperlink) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_HYPERLINK);
AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
@@ -631,7 +635,7 @@ STDMETHODIMP BrowserAccessibilityComWin::get_hyperlink(
return E_FAIL;
if (!hyperlink || index < 0 ||
- index >= static_cast<long>(hypertext_.hyperlinks.size())) {
+ index >= static_cast<LONG>(hypertext_.hyperlinks.size())) {
return E_INVALIDARG;
}
@@ -645,9 +649,9 @@ STDMETHODIMP BrowserAccessibilityComWin::get_hyperlink(
return S_OK;
}
-STDMETHODIMP BrowserAccessibilityComWin::get_hyperlinkIndex(
- long char_index,
- long* hyperlink_index) {
+IFACEMETHODIMP BrowserAccessibilityComWin::get_hyperlinkIndex(
+ LONG char_index,
+ LONG* hyperlink_index) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_HYPERLINK_INDEX);
AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
if (!owner())
@@ -656,7 +660,8 @@ STDMETHODIMP 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>(GetTextAsString16().size())) {
return E_INVALIDARG;
}
@@ -676,8 +681,8 @@ STDMETHODIMP BrowserAccessibilityComWin::get_hyperlinkIndex(
//
// Currently, only text links are supported.
-STDMETHODIMP BrowserAccessibilityComWin::get_anchor(long index,
- VARIANT* anchor) {
+IFACEMETHODIMP BrowserAccessibilityComWin::get_anchor(LONG index,
+ VARIANT* anchor) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_ANCHOR);
AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
if (!owner() || !IsHyperlink())
@@ -687,7 +692,7 @@ STDMETHODIMP BrowserAccessibilityComWin::get_anchor(long index,
if (index != 0 || !anchor)
return E_INVALIDARG;
- BSTR ia2_hypertext = SysAllocString(GetText().c_str());
+ BSTR ia2_hypertext = SysAllocString(GetTextAsString16().c_str());
DCHECK(ia2_hypertext);
anchor->vt = VT_BSTR;
anchor->bstrVal = ia2_hypertext;
@@ -701,8 +706,8 @@ STDMETHODIMP BrowserAccessibilityComWin::get_anchor(long index,
}
// Currently, only text links are supported.
-STDMETHODIMP BrowserAccessibilityComWin::get_anchorTarget(
- long index,
+IFACEMETHODIMP BrowserAccessibilityComWin::get_anchorTarget(
+ LONG index,
VARIANT* anchor_target) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_ANCHOR_TARGET);
AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
@@ -732,7 +737,7 @@ STDMETHODIMP BrowserAccessibilityComWin::get_anchorTarget(
return S_OK;
}
-STDMETHODIMP BrowserAccessibilityComWin::get_startIndex(long* index) {
+IFACEMETHODIMP BrowserAccessibilityComWin::get_startIndex(LONG* index) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_START_INDEX);
AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
if (!owner() || !IsHyperlink())
@@ -751,7 +756,7 @@ STDMETHODIMP BrowserAccessibilityComWin::get_startIndex(long* index) {
return S_OK;
}
-STDMETHODIMP BrowserAccessibilityComWin::get_endIndex(long* index) {
+IFACEMETHODIMP BrowserAccessibilityComWin::get_endIndex(LONG* index) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_END_INDEX);
AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
LONG start_index;
@@ -762,7 +767,7 @@ STDMETHODIMP BrowserAccessibilityComWin::get_endIndex(long* index) {
}
// This method is deprecated in the IA2 Spec.
-STDMETHODIMP BrowserAccessibilityComWin::get_valid(boolean* valid) {
+IFACEMETHODIMP BrowserAccessibilityComWin::get_valid(boolean* valid) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_VALID);
AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
return E_NOTIMPL;
@@ -772,7 +777,7 @@ STDMETHODIMP BrowserAccessibilityComWin::get_valid(boolean* valid) {
// IAccessibleAction partly implemented.
//
-STDMETHODIMP BrowserAccessibilityComWin::nActions(long* n_actions) {
+IFACEMETHODIMP BrowserAccessibilityComWin::nActions(LONG* n_actions) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_N_ACTIONS);
AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
if (!owner())
@@ -794,7 +799,7 @@ STDMETHODIMP BrowserAccessibilityComWin::nActions(long* n_actions) {
return S_OK;
}
-STDMETHODIMP BrowserAccessibilityComWin::doAction(long action_index) {
+IFACEMETHODIMP BrowserAccessibilityComWin::doAction(LONG action_index) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_DO_ACTION);
AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
if (!owner())
@@ -808,25 +813,25 @@ STDMETHODIMP BrowserAccessibilityComWin::doAction(long action_index) {
return S_OK;
}
-STDMETHODIMP
-BrowserAccessibilityComWin::get_description(long action_index,
+IFACEMETHODIMP
+BrowserAccessibilityComWin::get_description(LONG action_index,
BSTR* description) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_IAACTION_GET_DESCRIPTION);
AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
return E_NOTIMPL;
}
-STDMETHODIMP BrowserAccessibilityComWin::get_keyBinding(long action_index,
- long n_max_bindings,
- BSTR** key_bindings,
- long* n_bindings) {
+IFACEMETHODIMP BrowserAccessibilityComWin::get_keyBinding(LONG action_index,
+ LONG n_max_bindings,
+ BSTR** key_bindings,
+ LONG* n_bindings) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_KEY_BINDING);
AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
return E_NOTIMPL;
}
-STDMETHODIMP BrowserAccessibilityComWin::get_name(long action_index,
- BSTR* name) {
+IFACEMETHODIMP BrowserAccessibilityComWin::get_name(LONG action_index,
+ BSTR* name) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_NAME);
AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
if (!owner())
@@ -855,8 +860,8 @@ STDMETHODIMP BrowserAccessibilityComWin::get_name(long action_index,
return S_OK;
}
-STDMETHODIMP
-BrowserAccessibilityComWin::get_localizedName(long action_index,
+IFACEMETHODIMP
+BrowserAccessibilityComWin::get_localizedName(LONG action_index,
BSTR* localized_name) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_LOCALIZED_NAME);
AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
@@ -890,7 +895,7 @@ BrowserAccessibilityComWin::get_localizedName(long action_index,
// IAccessibleValue methods.
//
-STDMETHODIMP BrowserAccessibilityComWin::get_currentValue(VARIANT* value) {
+IFACEMETHODIMP BrowserAccessibilityComWin::get_currentValue(VARIANT* value) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_CURRENT_VALUE);
AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
if (!owner())
@@ -911,7 +916,7 @@ STDMETHODIMP BrowserAccessibilityComWin::get_currentValue(VARIANT* value) {
return S_FALSE;
}
-STDMETHODIMP BrowserAccessibilityComWin::get_minimumValue(VARIANT* value) {
+IFACEMETHODIMP BrowserAccessibilityComWin::get_minimumValue(VARIANT* value) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_MINIMUM_VALUE);
AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
if (!owner())
@@ -932,7 +937,7 @@ STDMETHODIMP BrowserAccessibilityComWin::get_minimumValue(VARIANT* value) {
return S_FALSE;
}
-STDMETHODIMP BrowserAccessibilityComWin::get_maximumValue(VARIANT* value) {
+IFACEMETHODIMP BrowserAccessibilityComWin::get_maximumValue(VARIANT* value) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_MAXIMUM_VALUE);
AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
if (!owner())
@@ -953,7 +958,7 @@ STDMETHODIMP BrowserAccessibilityComWin::get_maximumValue(VARIANT* value) {
return S_FALSE;
}
-STDMETHODIMP BrowserAccessibilityComWin::setCurrentValue(VARIANT new_value) {
+IFACEMETHODIMP BrowserAccessibilityComWin::setCurrentValue(VARIANT new_value) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_SET_CURRENT_VALUE);
AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
// TODO(dmazzoni): Implement this.
@@ -964,7 +969,7 @@ STDMETHODIMP BrowserAccessibilityComWin::setCurrentValue(VARIANT new_value) {
// ISimpleDOMDocument methods.
//
-STDMETHODIMP BrowserAccessibilityComWin::get_URL(BSTR* url) {
+IFACEMETHODIMP BrowserAccessibilityComWin::get_URL(BSTR* url) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_URL);
if (!owner())
return E_FAIL;
@@ -989,7 +994,7 @@ STDMETHODIMP BrowserAccessibilityComWin::get_URL(BSTR* url) {
return S_OK;
}
-STDMETHODIMP BrowserAccessibilityComWin::get_title(BSTR* title) {
+IFACEMETHODIMP BrowserAccessibilityComWin::get_title(BSTR* title) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_TITLE);
if (!owner())
return E_FAIL;
@@ -1011,7 +1016,7 @@ STDMETHODIMP BrowserAccessibilityComWin::get_title(BSTR* title) {
return S_OK;
}
-STDMETHODIMP BrowserAccessibilityComWin::get_mimeType(BSTR* mime_type) {
+IFACEMETHODIMP BrowserAccessibilityComWin::get_mimeType(BSTR* mime_type) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_MIME_TYPE);
if (!owner())
return E_FAIL;
@@ -1033,7 +1038,7 @@ STDMETHODIMP BrowserAccessibilityComWin::get_mimeType(BSTR* mime_type) {
return S_OK;
}
-STDMETHODIMP BrowserAccessibilityComWin::get_docType(BSTR* doc_type) {
+IFACEMETHODIMP BrowserAccessibilityComWin::get_docType(BSTR* doc_type) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_DOC_TYPE);
if (!owner())
return E_FAIL;
@@ -1055,14 +1060,14 @@ STDMETHODIMP BrowserAccessibilityComWin::get_docType(BSTR* doc_type) {
return S_OK;
}
-STDMETHODIMP
+IFACEMETHODIMP
BrowserAccessibilityComWin::get_nameSpaceURIForID(short name_space_id,
BSTR* name_space_uri) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_NAMESPACE_URI_FOR_ID);
return E_NOTIMPL;
}
-STDMETHODIMP
+IFACEMETHODIMP
BrowserAccessibilityComWin::put_alternateViewMediaTypes(
BSTR* comma_separated_media_types) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_PUT_ALTERNATE_VIEW_MEDIA_TYPES);
@@ -1073,7 +1078,7 @@ BrowserAccessibilityComWin::put_alternateViewMediaTypes(
// ISimpleDOMNode methods.
//
-STDMETHODIMP BrowserAccessibilityComWin::get_nodeInfo(
+IFACEMETHODIMP BrowserAccessibilityComWin::get_nodeInfo(
BSTR* node_name,
short* name_space_id,
BSTR* node_value,
@@ -1112,7 +1117,7 @@ STDMETHODIMP BrowserAccessibilityComWin::get_nodeInfo(
return S_OK;
}
-STDMETHODIMP BrowserAccessibilityComWin::get_attributes(
+IFACEMETHODIMP BrowserAccessibilityComWin::get_attributes(
unsigned short max_attribs,
BSTR* attrib_names,
short* name_space_id,
@@ -1140,7 +1145,7 @@ STDMETHODIMP BrowserAccessibilityComWin::get_attributes(
return S_OK;
}
-STDMETHODIMP BrowserAccessibilityComWin::get_attributesForNames(
+IFACEMETHODIMP BrowserAccessibilityComWin::get_attributesForNames(
unsigned short num_attribs,
BSTR* attrib_names,
short* name_space_id,
@@ -1172,7 +1177,7 @@ STDMETHODIMP BrowserAccessibilityComWin::get_attributesForNames(
return S_OK;
}
-STDMETHODIMP BrowserAccessibilityComWin::get_computedStyle(
+IFACEMETHODIMP BrowserAccessibilityComWin::get_computedStyle(
unsigned short max_style_properties,
boolean use_alternate_view,
BSTR* style_properties,
@@ -1203,7 +1208,7 @@ STDMETHODIMP BrowserAccessibilityComWin::get_computedStyle(
return S_OK;
}
-STDMETHODIMP BrowserAccessibilityComWin::get_computedStyleForProperties(
+IFACEMETHODIMP BrowserAccessibilityComWin::get_computedStyleForProperties(
unsigned short num_style_properties,
boolean use_alternate_view,
BSTR* style_properties,
@@ -1233,13 +1238,14 @@ STDMETHODIMP BrowserAccessibilityComWin::get_computedStyleForProperties(
return S_OK;
}
-STDMETHODIMP BrowserAccessibilityComWin::scrollTo(boolean placeTopLeft) {
+IFACEMETHODIMP BrowserAccessibilityComWin::scrollTo(boolean placeTopLeft) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_ISIMPLEDOMNODE_SCROLL_TO);
return scrollTo(placeTopLeft ? IA2_SCROLL_TYPE_TOP_LEFT
: IA2_SCROLL_TYPE_ANYWHERE);
}
-STDMETHODIMP BrowserAccessibilityComWin::get_parentNode(ISimpleDOMNode** node) {
+IFACEMETHODIMP BrowserAccessibilityComWin::get_parentNode(
+ ISimpleDOMNode** node) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_PARENT_NODE);
if (!owner())
return E_FAIL;
@@ -1252,7 +1258,8 @@ STDMETHODIMP BrowserAccessibilityComWin::get_parentNode(ISimpleDOMNode** node) {
return S_OK;
}
-STDMETHODIMP BrowserAccessibilityComWin::get_firstChild(ISimpleDOMNode** node) {
+IFACEMETHODIMP BrowserAccessibilityComWin::get_firstChild(
+ ISimpleDOMNode** node) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_FIRST_CHILD);
if (!owner())
return E_FAIL;
@@ -1270,7 +1277,8 @@ STDMETHODIMP BrowserAccessibilityComWin::get_firstChild(ISimpleDOMNode** node) {
return S_OK;
}
-STDMETHODIMP BrowserAccessibilityComWin::get_lastChild(ISimpleDOMNode** node) {
+IFACEMETHODIMP BrowserAccessibilityComWin::get_lastChild(
+ ISimpleDOMNode** node) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_LAST_CHILD);
if (!owner())
return E_FAIL;
@@ -1289,7 +1297,7 @@ STDMETHODIMP BrowserAccessibilityComWin::get_lastChild(ISimpleDOMNode** node) {
return S_OK;
}
-STDMETHODIMP BrowserAccessibilityComWin::get_previousSibling(
+IFACEMETHODIMP BrowserAccessibilityComWin::get_previousSibling(
ISimpleDOMNode** node) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_PREVIOUS_SIBLING);
if (!owner())
@@ -1310,7 +1318,7 @@ STDMETHODIMP BrowserAccessibilityComWin::get_previousSibling(
return S_OK;
}
-STDMETHODIMP BrowserAccessibilityComWin::get_nextSibling(
+IFACEMETHODIMP BrowserAccessibilityComWin::get_nextSibling(
ISimpleDOMNode** node) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_NEXT_SIBLING);
if (!owner())
@@ -1334,8 +1342,8 @@ STDMETHODIMP BrowserAccessibilityComWin::get_nextSibling(
return S_OK;
}
-STDMETHODIMP BrowserAccessibilityComWin::get_childAt(unsigned int child_index,
- ISimpleDOMNode** node) {
+IFACEMETHODIMP BrowserAccessibilityComWin::get_childAt(unsigned int child_index,
+ ISimpleDOMNode** node) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_CHILD_AT);
if (!owner())
return E_FAIL;
@@ -1357,7 +1365,7 @@ STDMETHODIMP BrowserAccessibilityComWin::get_childAt(unsigned int child_index,
}
// We only support this method for retrieving MathML content.
-STDMETHODIMP BrowserAccessibilityComWin::get_innerHTML(BSTR* innerHTML) {
+IFACEMETHODIMP BrowserAccessibilityComWin::get_innerHTML(BSTR* innerHTML) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_INNER_HTML);
AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
if (!owner())
@@ -1372,14 +1380,14 @@ STDMETHODIMP BrowserAccessibilityComWin::get_innerHTML(BSTR* innerHTML) {
return S_OK;
}
-STDMETHODIMP
+IFACEMETHODIMP
BrowserAccessibilityComWin::get_localInterface(void** local_interface) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_LOCAL_INTERFACE);
AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
return E_NOTIMPL;
}
-STDMETHODIMP BrowserAccessibilityComWin::get_language(BSTR* language) {
+IFACEMETHODIMP BrowserAccessibilityComWin::get_language(BSTR* language) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_LANGUAGE);
AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
if (!language)
@@ -1403,7 +1411,7 @@ STDMETHODIMP BrowserAccessibilityComWin::get_language(BSTR* language) {
// ISimpleDOMText methods.
//
-STDMETHODIMP BrowserAccessibilityComWin::get_domText(BSTR* dom_text) {
+IFACEMETHODIMP BrowserAccessibilityComWin::get_domText(BSTR* dom_text) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_DOM_TEXT);
AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
if (!owner())
@@ -1415,7 +1423,7 @@ STDMETHODIMP BrowserAccessibilityComWin::get_domText(BSTR* dom_text) {
return GetStringAttributeAsBstr(ax::mojom::StringAttribute::kName, dom_text);
}
-STDMETHODIMP BrowserAccessibilityComWin::get_clippedSubstringBounds(
+IFACEMETHODIMP BrowserAccessibilityComWin::get_clippedSubstringBounds(
unsigned int start_index,
unsigned int end_index,
int* out_x,
@@ -1431,7 +1439,7 @@ STDMETHODIMP BrowserAccessibilityComWin::get_clippedSubstringBounds(
out_width, out_height);
}
-STDMETHODIMP BrowserAccessibilityComWin::get_unclippedSubstringBounds(
+IFACEMETHODIMP BrowserAccessibilityComWin::get_unclippedSubstringBounds(
unsigned int start_index,
unsigned int end_index,
int* out_x,
@@ -1447,7 +1455,8 @@ STDMETHODIMP 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>(GetTextAsString16().size());
if (start_index > text_length || end_index > text_length ||
start_index > end_index) {
return E_INVALIDARG;
@@ -1462,7 +1471,7 @@ STDMETHODIMP BrowserAccessibilityComWin::get_unclippedSubstringBounds(
return S_OK;
}
-STDMETHODIMP BrowserAccessibilityComWin::scrollToSubstring(
+IFACEMETHODIMP BrowserAccessibilityComWin::scrollToSubstring(
unsigned int start_index,
unsigned int end_index) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_SCROLL_TO_SUBSTRING);
@@ -1475,7 +1484,8 @@ STDMETHODIMP 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>(GetTextAsString16().size());
if (start_index > text_length || end_index > text_length ||
start_index > end_index) {
return E_INVALIDARG;
@@ -1488,7 +1498,7 @@ STDMETHODIMP BrowserAccessibilityComWin::scrollToSubstring(
return S_OK;
}
-STDMETHODIMP BrowserAccessibilityComWin::get_fontFamily(BSTR* font_family) {
+IFACEMETHODIMP BrowserAccessibilityComWin::get_fontFamily(BSTR* font_family) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_FONT_FAMILY);
AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
if (!font_family)
@@ -1512,9 +1522,9 @@ STDMETHODIMP BrowserAccessibilityComWin::get_fontFamily(BSTR* font_family) {
// IServiceProvider methods.
//
-STDMETHODIMP BrowserAccessibilityComWin::QueryService(REFGUID guid_service,
- REFIID riid,
- void** object) {
+IFACEMETHODIMP BrowserAccessibilityComWin::QueryService(REFGUID guid_service,
+ REFIID riid,
+ void** object) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_QUERY_SERVICE);
if (!owner())
return E_FAIL;
@@ -1556,7 +1566,7 @@ STDMETHODIMP BrowserAccessibilityComWin::QueryService(REFGUID guid_service,
//
// static
-HRESULT WINAPI BrowserAccessibilityComWin::InternalQueryInterface(
+STDMETHODIMP BrowserAccessibilityComWin::InternalQueryInterface(
void* this_ptr,
const _ATL_INTMAP_ENTRY* entries,
REFIID iid,
@@ -1648,7 +1658,7 @@ void BrowserAccessibilityComWin::ComputeStylesIfNeeded() {
child->GetSpellingAttributes();
MergeSpellingIntoTextAttributes(spelling_attributes, start_offset,
&attributes_map);
- start_offset += child->GetText().length();
+ start_offset += child->GetTextAsString16().length();
} else {
start_offset += 1;
}
@@ -1790,7 +1800,7 @@ void BrowserAccessibilityComWin::UpdateStep3FireEvents(
// they are providing redundant information and will lead to duplicate
// announcements.
if (!did_fire_namechange) {
- int start, old_len, new_len;
+ size_t start, old_len, new_len;
ComputeHypertextRemovedAndInserted(&start, &old_len, &new_len);
if (old_len > 0) {
// In-process screen readers may call IAccessibleText::get_oldText
@@ -2068,7 +2078,8 @@ 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->GetTextAsString16().length());
}
}
}
@@ -2242,14 +2253,14 @@ LONG BrowserAccessibilityComWin::FindBoundary(
// TODO(nektar): |AXPosition| can handle other types of boundaries as well.
ui::TextBoundaryType boundary = IA2TextBoundaryToTextBoundary(ia2_boundary);
return ui::FindAccessibleTextBoundary(
- GetText(), owner()->GetLineStartOffsets(), boundary, start_offset,
- direction, affinity);
+ GetTextAsString16(), owner()->GetLineStartOffsets(), boundary,
+ start_offset, direction, affinity);
}
LONG BrowserAccessibilityComWin::FindStartOfStyle(
LONG start_offset,
ui::TextBoundaryDirection direction) {
- LONG text_length = static_cast<LONG>(GetText().length());
+ LONG text_length = static_cast<LONG>(GetTextAsString16().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 4ce9c39ccf7..775cbb6ccfd 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_com_win.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_com_win.h
@@ -5,8 +5,6 @@
#ifndef CONTENT_BROWSER_ACCESSIBILITY_BROWSER_ACCESSIBILITY_COM_WIN_H_
#define CONTENT_BROWSER_ACCESSIBILITY_BROWSER_ACCESSIBILITY_COM_WIN_H_
-#include <atlbase.h>
-#include <atlcom.h>
#include <oleacc.h>
#include <stddef.h>
#include <stdint.h>
@@ -15,6 +13,7 @@
#include "base/compiler_specific.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
+#include "base/win/atl.h"
#include "content/browser/accessibility/browser_accessibility.h"
#include "content/browser/accessibility/browser_accessibility_win.h"
#include "content/common/content_export.h"
@@ -100,43 +99,45 @@ class __declspec(uuid("562072fe-3390-43b1-9e2c-dd4118f5ac79"))
//
// IAccessible2 methods.
//
- CONTENT_EXPORT STDMETHODIMP get_attributes(BSTR* attributes) override;
+ CONTENT_EXPORT IFACEMETHODIMP get_attributes(BSTR* attributes) override;
- CONTENT_EXPORT STDMETHODIMP scrollTo(enum IA2ScrollType scroll_type) override;
+ CONTENT_EXPORT IFACEMETHODIMP
+ scrollTo(enum IA2ScrollType scroll_type) override;
//
// IAccessibleApplication methods.
//
- CONTENT_EXPORT STDMETHODIMP get_appName(BSTR* app_name) override;
+ CONTENT_EXPORT IFACEMETHODIMP get_appName(BSTR* app_name) override;
- CONTENT_EXPORT STDMETHODIMP get_appVersion(BSTR* app_version) override;
+ CONTENT_EXPORT IFACEMETHODIMP get_appVersion(BSTR* app_version) override;
- CONTENT_EXPORT STDMETHODIMP get_toolkitName(BSTR* toolkit_name) override;
+ CONTENT_EXPORT IFACEMETHODIMP get_toolkitName(BSTR* toolkit_name) override;
- CONTENT_EXPORT STDMETHODIMP
+ CONTENT_EXPORT IFACEMETHODIMP
get_toolkitVersion(BSTR* toolkit_version) override;
//
// IAccessibleImage methods.
//
- CONTENT_EXPORT STDMETHODIMP get_description(BSTR* description) override;
+ CONTENT_EXPORT IFACEMETHODIMP get_description(BSTR* description) override;
- CONTENT_EXPORT STDMETHODIMP
+ CONTENT_EXPORT IFACEMETHODIMP
get_imagePosition(enum IA2CoordinateType coordinate_type,
LONG* x,
LONG* y) override;
- CONTENT_EXPORT STDMETHODIMP get_imageSize(LONG* height, LONG* width) override;
+ CONTENT_EXPORT IFACEMETHODIMP get_imageSize(LONG* height,
+ LONG* width) override;
//
// IAccessibleText methods.
//
- CONTENT_EXPORT STDMETHODIMP get_nCharacters(LONG* n_characters) override;
+ CONTENT_EXPORT IFACEMETHODIMP get_nCharacters(LONG* n_characters) override;
- CONTENT_EXPORT STDMETHODIMP get_caretOffset(LONG* offset) override;
+ CONTENT_EXPORT IFACEMETHODIMP get_caretOffset(LONG* offset) override;
- CONTENT_EXPORT STDMETHODIMP
+ CONTENT_EXPORT IFACEMETHODIMP
get_characterExtents(LONG offset,
enum IA2CoordinateType coord_type,
LONG* out_x,
@@ -144,206 +145,209 @@ class __declspec(uuid("562072fe-3390-43b1-9e2c-dd4118f5ac79"))
LONG* out_width,
LONG* out_height) override;
- CONTENT_EXPORT STDMETHODIMP get_nSelections(LONG* n_selections) override;
+ CONTENT_EXPORT IFACEMETHODIMP get_nSelections(LONG* n_selections) override;
- CONTENT_EXPORT STDMETHODIMP get_selection(LONG selection_index,
- LONG* start_offset,
- LONG* end_offset) override;
+ CONTENT_EXPORT IFACEMETHODIMP get_selection(LONG selection_index,
+ LONG* start_offset,
+ LONG* end_offset) override;
- CONTENT_EXPORT STDMETHODIMP get_text(LONG start_offset,
- LONG end_offset,
- BSTR* text) override;
+ CONTENT_EXPORT IFACEMETHODIMP get_text(LONG start_offset,
+ LONG end_offset,
+ BSTR* text) override;
- CONTENT_EXPORT STDMETHODIMP
+ CONTENT_EXPORT IFACEMETHODIMP
get_textAtOffset(LONG offset,
enum IA2TextBoundaryType boundary_type,
LONG* start_offset,
LONG* end_offset,
BSTR* text) override;
- CONTENT_EXPORT STDMETHODIMP
+ CONTENT_EXPORT IFACEMETHODIMP
get_textBeforeOffset(LONG offset,
enum IA2TextBoundaryType boundary_type,
LONG* start_offset,
LONG* end_offset,
BSTR* text) override;
- CONTENT_EXPORT STDMETHODIMP
+ CONTENT_EXPORT IFACEMETHODIMP
get_textAfterOffset(LONG offset,
enum IA2TextBoundaryType boundary_type,
LONG* start_offset,
LONG* end_offset,
BSTR* text) override;
- CONTENT_EXPORT STDMETHODIMP get_newText(IA2TextSegment* new_text) override;
+ CONTENT_EXPORT IFACEMETHODIMP get_newText(IA2TextSegment* new_text) override;
- CONTENT_EXPORT STDMETHODIMP get_oldText(IA2TextSegment* old_text) override;
+ CONTENT_EXPORT IFACEMETHODIMP get_oldText(IA2TextSegment* old_text) override;
- CONTENT_EXPORT STDMETHODIMP
+ CONTENT_EXPORT IFACEMETHODIMP
get_offsetAtPoint(LONG x,
LONG y,
enum IA2CoordinateType coord_type,
LONG* offset) override;
- CONTENT_EXPORT STDMETHODIMP
+ CONTENT_EXPORT IFACEMETHODIMP
scrollSubstringTo(LONG start_index,
LONG end_index,
enum IA2ScrollType scroll_type) override;
- CONTENT_EXPORT STDMETHODIMP
+ CONTENT_EXPORT IFACEMETHODIMP
scrollSubstringToPoint(LONG start_index,
LONG end_index,
enum IA2CoordinateType coordinate_type,
LONG x,
LONG y) override;
- CONTENT_EXPORT STDMETHODIMP addSelection(LONG start_offset,
- LONG end_offset) override;
+ CONTENT_EXPORT IFACEMETHODIMP addSelection(LONG start_offset,
+ LONG end_offset) override;
- CONTENT_EXPORT STDMETHODIMP removeSelection(LONG selection_index) override;
+ CONTENT_EXPORT IFACEMETHODIMP removeSelection(LONG selection_index) override;
- CONTENT_EXPORT STDMETHODIMP setCaretOffset(LONG offset) override;
+ CONTENT_EXPORT IFACEMETHODIMP setCaretOffset(LONG offset) override;
- CONTENT_EXPORT STDMETHODIMP setSelection(LONG selection_index,
- LONG start_offset,
- LONG end_offset) override;
+ CONTENT_EXPORT IFACEMETHODIMP setSelection(LONG selection_index,
+ LONG start_offset,
+ LONG end_offset) override;
// IAccessibleText methods not implemented.
- CONTENT_EXPORT STDMETHODIMP get_attributes(LONG offset,
- LONG* start_offset,
- LONG* end_offset,
- BSTR* text_attributes) override;
+ CONTENT_EXPORT IFACEMETHODIMP get_attributes(LONG offset,
+ LONG* start_offset,
+ LONG* end_offset,
+ BSTR* text_attributes) override;
//
// IAccessibleHypertext methods.
//
- CONTENT_EXPORT STDMETHODIMP get_nHyperlinks(long* hyperlink_count) override;
+ CONTENT_EXPORT IFACEMETHODIMP get_nHyperlinks(LONG* hyperlink_count) override;
- CONTENT_EXPORT STDMETHODIMP
- get_hyperlink(long index, IAccessibleHyperlink** hyperlink) override;
+ CONTENT_EXPORT IFACEMETHODIMP
+ get_hyperlink(LONG index, IAccessibleHyperlink** hyperlink) override;
- CONTENT_EXPORT STDMETHODIMP
- get_hyperlinkIndex(long char_index, long* hyperlink_index) override;
+ CONTENT_EXPORT IFACEMETHODIMP
+ get_hyperlinkIndex(LONG char_index, LONG* hyperlink_index) override;
// IAccessibleHyperlink methods.
- CONTENT_EXPORT STDMETHODIMP get_anchor(long index, VARIANT* anchor) override;
- CONTENT_EXPORT STDMETHODIMP get_anchorTarget(long index,
- VARIANT* anchor_target) override;
- CONTENT_EXPORT STDMETHODIMP get_startIndex(long* index) override;
- CONTENT_EXPORT STDMETHODIMP get_endIndex(long* index) override;
+ CONTENT_EXPORT IFACEMETHODIMP get_anchor(LONG index,
+ VARIANT* anchor) override;
+ CONTENT_EXPORT IFACEMETHODIMP
+ get_anchorTarget(LONG index, VARIANT* anchor_target) override;
+ CONTENT_EXPORT IFACEMETHODIMP get_startIndex(LONG* index) override;
+ CONTENT_EXPORT IFACEMETHODIMP get_endIndex(LONG* index) override;
// This method is deprecated in the IA2 Spec and so we don't implement it.
- CONTENT_EXPORT STDMETHODIMP get_valid(boolean* valid) override;
+ CONTENT_EXPORT IFACEMETHODIMP get_valid(boolean* valid) override;
// IAccessibleAction mostly not implemented.
- CONTENT_EXPORT STDMETHODIMP nActions(long* n_actions) override;
- CONTENT_EXPORT STDMETHODIMP doAction(long action_index) override;
- CONTENT_EXPORT STDMETHODIMP get_description(long action_index,
- BSTR* description) override;
- CONTENT_EXPORT STDMETHODIMP get_keyBinding(long action_index,
- long n_max_bindings,
- BSTR** key_bindings,
- long* n_bindings) override;
- CONTENT_EXPORT STDMETHODIMP get_name(long action_index, BSTR* name) override;
- CONTENT_EXPORT STDMETHODIMP get_localizedName(long action_index,
- BSTR* localized_name) override;
+ CONTENT_EXPORT IFACEMETHODIMP nActions(LONG* n_actions) override;
+ CONTENT_EXPORT IFACEMETHODIMP doAction(LONG action_index) override;
+ CONTENT_EXPORT IFACEMETHODIMP get_description(LONG action_index,
+ BSTR* description) override;
+ CONTENT_EXPORT IFACEMETHODIMP get_keyBinding(LONG action_index,
+ LONG n_max_bindings,
+ BSTR** key_bindings,
+ LONG* n_bindings) override;
+ CONTENT_EXPORT IFACEMETHODIMP get_name(LONG action_index,
+ BSTR* name) override;
+ CONTENT_EXPORT IFACEMETHODIMP
+ get_localizedName(LONG action_index, BSTR* localized_name) override;
//
// IAccessibleValue methods.
//
- CONTENT_EXPORT STDMETHODIMP get_currentValue(VARIANT* value) override;
+ CONTENT_EXPORT IFACEMETHODIMP get_currentValue(VARIANT* value) override;
- CONTENT_EXPORT STDMETHODIMP get_minimumValue(VARIANT* value) override;
+ CONTENT_EXPORT IFACEMETHODIMP get_minimumValue(VARIANT* value) override;
- CONTENT_EXPORT STDMETHODIMP get_maximumValue(VARIANT* value) override;
+ CONTENT_EXPORT IFACEMETHODIMP get_maximumValue(VARIANT* value) override;
- CONTENT_EXPORT STDMETHODIMP setCurrentValue(VARIANT new_value) override;
+ CONTENT_EXPORT IFACEMETHODIMP setCurrentValue(VARIANT new_value) override;
//
// ISimpleDOMDocument methods.
//
- CONTENT_EXPORT STDMETHODIMP get_URL(BSTR* url) override;
+ CONTENT_EXPORT IFACEMETHODIMP get_URL(BSTR* url) override;
- CONTENT_EXPORT STDMETHODIMP get_title(BSTR* title) override;
+ CONTENT_EXPORT IFACEMETHODIMP get_title(BSTR* title) override;
- CONTENT_EXPORT STDMETHODIMP get_mimeType(BSTR* mime_type) override;
+ CONTENT_EXPORT IFACEMETHODIMP get_mimeType(BSTR* mime_type) override;
- CONTENT_EXPORT STDMETHODIMP get_docType(BSTR* doc_type) override;
+ CONTENT_EXPORT IFACEMETHODIMP get_docType(BSTR* doc_type) override;
- CONTENT_EXPORT STDMETHODIMP
+ CONTENT_EXPORT IFACEMETHODIMP
get_nameSpaceURIForID(short name_space_id, BSTR* name_space_uri) override;
- CONTENT_EXPORT STDMETHODIMP
+ CONTENT_EXPORT IFACEMETHODIMP
put_alternateViewMediaTypes(BSTR* comma_separated_media_types) override;
//
// ISimpleDOMNode methods.
//
- CONTENT_EXPORT STDMETHODIMP get_nodeInfo(BSTR* node_name,
- short* name_space_id,
- BSTR* node_value,
- unsigned int* num_children,
- unsigned int* unique_id,
- unsigned short* node_type) override;
+ CONTENT_EXPORT IFACEMETHODIMP
+ get_nodeInfo(BSTR* node_name,
+ short* name_space_id,
+ BSTR* node_value,
+ unsigned int* num_children,
+ unsigned int* unique_id,
+ unsigned short* node_type) override;
- CONTENT_EXPORT STDMETHODIMP
+ CONTENT_EXPORT IFACEMETHODIMP
get_attributes(unsigned short max_attribs,
BSTR* attrib_names,
short* name_space_id,
BSTR* attrib_values,
unsigned short* num_attribs) override;
- CONTENT_EXPORT STDMETHODIMP
+ CONTENT_EXPORT IFACEMETHODIMP
get_attributesForNames(unsigned short num_attribs,
BSTR* attrib_names,
short* name_space_id,
BSTR* attrib_values) override;
- CONTENT_EXPORT STDMETHODIMP
+ CONTENT_EXPORT IFACEMETHODIMP
get_computedStyle(unsigned short max_style_properties,
boolean use_alternate_view,
BSTR* style_properties,
BSTR* style_values,
unsigned short* num_style_properties) override;
- CONTENT_EXPORT STDMETHODIMP
+ CONTENT_EXPORT IFACEMETHODIMP
get_computedStyleForProperties(unsigned short num_style_properties,
boolean use_alternate_view,
BSTR* style_properties,
BSTR* style_values) override;
- CONTENT_EXPORT STDMETHODIMP scrollTo(boolean placeTopLeft) override;
+ CONTENT_EXPORT IFACEMETHODIMP scrollTo(boolean placeTopLeft) override;
- CONTENT_EXPORT STDMETHODIMP get_parentNode(ISimpleDOMNode** node) override;
+ CONTENT_EXPORT IFACEMETHODIMP get_parentNode(ISimpleDOMNode** node) override;
- CONTENT_EXPORT STDMETHODIMP get_firstChild(ISimpleDOMNode** node) override;
+ CONTENT_EXPORT IFACEMETHODIMP get_firstChild(ISimpleDOMNode** node) override;
- CONTENT_EXPORT STDMETHODIMP get_lastChild(ISimpleDOMNode** node) override;
+ CONTENT_EXPORT IFACEMETHODIMP get_lastChild(ISimpleDOMNode** node) override;
- CONTENT_EXPORT STDMETHODIMP
+ CONTENT_EXPORT IFACEMETHODIMP
get_previousSibling(ISimpleDOMNode** node) override;
- CONTENT_EXPORT STDMETHODIMP get_nextSibling(ISimpleDOMNode** node) override;
+ CONTENT_EXPORT IFACEMETHODIMP get_nextSibling(ISimpleDOMNode** node) override;
- CONTENT_EXPORT STDMETHODIMP get_childAt(unsigned int child_index,
- ISimpleDOMNode** node) override;
+ CONTENT_EXPORT IFACEMETHODIMP get_childAt(unsigned int child_index,
+ ISimpleDOMNode** node) override;
- CONTENT_EXPORT STDMETHODIMP get_innerHTML(BSTR* innerHTML) override;
+ CONTENT_EXPORT IFACEMETHODIMP get_innerHTML(BSTR* innerHTML) override;
- CONTENT_EXPORT STDMETHODIMP
+ CONTENT_EXPORT IFACEMETHODIMP
get_localInterface(void** local_interface) override;
- CONTENT_EXPORT STDMETHODIMP get_language(BSTR* language) override;
+ CONTENT_EXPORT IFACEMETHODIMP get_language(BSTR* language) override;
//
// ISimpleDOMText methods.
//
- CONTENT_EXPORT STDMETHODIMP get_domText(BSTR* dom_text) override;
+ CONTENT_EXPORT IFACEMETHODIMP get_domText(BSTR* dom_text) override;
- CONTENT_EXPORT STDMETHODIMP
+ CONTENT_EXPORT IFACEMETHODIMP
get_clippedSubstringBounds(unsigned int start_index,
unsigned int end_index,
int* out_x,
@@ -351,7 +355,7 @@ class __declspec(uuid("562072fe-3390-43b1-9e2c-dd4118f5ac79"))
int* out_width,
int* out_height) override;
- CONTENT_EXPORT STDMETHODIMP
+ CONTENT_EXPORT IFACEMETHODIMP
get_unclippedSubstringBounds(unsigned int start_index,
unsigned int end_index,
int* out_x,
@@ -359,25 +363,25 @@ class __declspec(uuid("562072fe-3390-43b1-9e2c-dd4118f5ac79"))
int* out_width,
int* out_height) override;
- CONTENT_EXPORT STDMETHODIMP
+ CONTENT_EXPORT IFACEMETHODIMP
scrollToSubstring(unsigned int start_index, unsigned int end_index) override;
- CONTENT_EXPORT STDMETHODIMP get_fontFamily(BSTR* font_family) override;
+ CONTENT_EXPORT IFACEMETHODIMP get_fontFamily(BSTR* font_family) override;
//
// IServiceProvider methods.
//
- CONTENT_EXPORT STDMETHODIMP QueryService(REFGUID guidService,
- REFIID riid,
- void** object) override;
+ CONTENT_EXPORT IFACEMETHODIMP QueryService(REFGUID guidService,
+ REFIID riid,
+ void** object) override;
//
// CComObjectRootEx methods.
//
// Called by BEGIN_COM_MAP() / END_COM_MAP().
- static CONTENT_EXPORT HRESULT WINAPI
+ static CONTENT_EXPORT STDMETHODIMP
InternalQueryInterface(void* this_ptr,
const _ATL_INTMAP_ENTRY* entries,
REFIID iid,
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager.cc b/chromium/content/browser/accessibility/browser_accessibility_manager.cc
index 2cfe76080a1..3ab440e85ad 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager.cc
@@ -20,27 +20,6 @@ namespace content {
namespace {
-// Search the tree recursively from |node| and return any node that has
-// a child tree ID of |ax_tree_id|.
-BrowserAccessibility* FindNodeWithChildTreeId(BrowserAccessibility* node,
- int ax_tree_id) {
- if (!node)
- return nullptr;
-
- if (node->GetIntAttribute(ax::mojom::IntAttribute::kChildTreeId) ==
- ax_tree_id)
- return node;
-
- for (unsigned int i = 0; i < node->InternalChildCount(); ++i) {
- BrowserAccessibility* child = node->InternalGetChild(i);
- BrowserAccessibility* result = FindNodeWithChildTreeId(child, ax_tree_id);
- if (result)
- return result;
- }
-
- return nullptr;
-}
-
// Map from AXTreeID to BrowserAccessibilityManager
using AXTreeIDMap = base::hash_map<ui::AXTreeIDRegistry::AXTreeID,
BrowserAccessibilityManager*>;
@@ -145,7 +124,6 @@ BrowserAccessibilityManager::BrowserAccessibilityManager(
last_focused_manager_(nullptr),
connected_to_parent_tree_node_(false),
ax_tree_id_(ui::AXTreeIDRegistry::kNoAXTreeID),
- parent_node_id_from_parent_tree_(0),
device_scale_factor_(1.0f),
use_custom_device_scale_factor_for_testing_(false) {
SetTree(tree_.get());
@@ -163,7 +141,6 @@ BrowserAccessibilityManager::BrowserAccessibilityManager(
last_focused_node_(nullptr),
last_focused_manager_(nullptr),
ax_tree_id_(ui::AXTreeIDRegistry::kNoAXTreeID),
- parent_node_id_from_parent_tree_(0),
device_scale_factor_(1.0f),
use_custom_device_scale_factor_for_testing_(false) {
SetTree(tree_.get());
@@ -286,27 +263,23 @@ BrowserAccessibilityManager::GetParentNodeFromParentTree() {
if (!parent_manager)
return nullptr;
- // Try to use the cached parent node from the most recent time this
- // was called.
- if (parent_node_id_from_parent_tree_) {
- BrowserAccessibility* parent_node = parent_manager->GetFromID(
- parent_node_id_from_parent_tree_);
+ 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) {
- int parent_child_tree_id =
- parent_node->GetIntAttribute(ax::mojom::IntAttribute::kChildTreeId);
- if (parent_child_tree_id == ax_tree_id_)
- return parent_node;
+ DCHECK_EQ(ax_tree_id_, parent_node->GetIntAttribute(
+ ax::mojom::IntAttribute::kChildTreeId));
+ return parent_node;
}
}
- // If that fails, search for it and cache it for next time.
- BrowserAccessibility* parent_node = FindNodeWithChildTreeId(
- parent_manager->GetRoot(), ax_tree_id_);
- if (parent_node) {
- parent_node_id_from_parent_tree_ = parent_node->GetId();
- return parent_node;
- }
-
return nullptr;
}
@@ -493,11 +466,16 @@ BrowserAccessibility* BrowserAccessibilityManager::GetActiveDescendant(
if (focus->GetRole() == ax::mojom::Role::kPopUpButton) {
BrowserAccessibility* child = focus->InternalGetChild(0);
- if (child && child->GetRole() == ax::mojom::Role::kMenuListPopup) {
+ if (child && child->GetRole() == ax::mojom::Role::kMenuListPopup &&
+ !child->GetData().HasState(ax::mojom::State::kInvisible)) {
// The active descendant is found on the menu list popup, i.e. on the
// actual list and not on the button that opens it.
// If there is no active descendant, focus should stay on the button so
// that Windows screen readers would enable their virtual cursor.
+ // Do not expose an activedescendant in a hidden/collapsed list, as
+ // screen readers expect the focus event to go to the button itself.
+ // Note that the AX hierarchy in this case is strange -- the active
+ // option is the only visible option, and is inside an invisible list.
if (child->GetIntAttribute(ax::mojom::IntAttribute::kActivedescendantId,
&active_descendant_id)) {
active_descendant = child->manager()->GetFromID(active_descendant_id);
@@ -505,7 +483,8 @@ BrowserAccessibility* BrowserAccessibilityManager::GetActiveDescendant(
}
}
- if (active_descendant)
+ if (active_descendant &&
+ !active_descendant->GetData().HasState(ax::mojom::State::kInvisible))
return active_descendant;
return focus;
@@ -1101,32 +1080,6 @@ void BrowserAccessibilityManager::OnSubtreeWillBeDeleted(ui::AXTree* tree,
obj->OnSubtreeWillBeDeleted();
}
-void BrowserAccessibilityManager::OnNodeWillBeReparented(ui::AXTree* tree,
- ui::AXNode* node) {
- AXEventGenerator::OnNodeWillBeReparented(tree, node);
- // BrowserAccessibility should probably ask the tree source for the AXNode via
- // an id rather than weakly holding a pointer to a AXNode that might have been
- // destroyed under the hood and re-created later on. Treat this as a delete to
- // make things work.
- if (id_wrapper_map_.find(node->id()) == id_wrapper_map_.end())
- return;
- GetFromAXNode(node)->Destroy();
- id_wrapper_map_.erase(node->id());
-}
-
-void BrowserAccessibilityManager::OnSubtreeWillBeReparented(ui::AXTree* tree,
- ui::AXNode* node) {
- AXEventGenerator::OnSubtreeWillBeReparented(tree, node);
- // BrowserAccessibility should probably ask the tree source for the AXNode via
- // an id rather than weakly holding a pointer to a AXNode that might have been
- // destroyed under the hood and re-created later on. Treat this as a delete to
- // make things work.
- DCHECK(node);
- BrowserAccessibility* obj = GetFromAXNode(node);
- if (obj)
- obj->OnSubtreeWillBeDeleted();
-}
-
void BrowserAccessibilityManager::OnNodeCreated(ui::AXTree* tree,
ui::AXNode* node) {
AXEventGenerator::OnNodeCreated(tree, node);
@@ -1139,13 +1092,13 @@ void BrowserAccessibilityManager::OnNodeCreated(ui::AXTree* tree,
void BrowserAccessibilityManager::OnNodeReparented(ui::AXTree* tree,
ui::AXNode* node) {
AXEventGenerator::OnNodeReparented(tree, node);
- // BrowserAccessibility should probably ask the tree source for the AXNode via
- // an id rather than weakly holding a pointer to a AXNode that might have been
- // destroyed under the hood and re-created later on. Treat this as a create to
- // make things work.
- BrowserAccessibility* wrapper = factory_->Create();
+ BrowserAccessibility* wrapper = GetFromID(node->id());
+ if (!wrapper) {
+ wrapper = factory_->Create();
+ id_wrapper_map_[node->id()] = wrapper;
+ }
+
wrapper->Init(this, node);
- id_wrapper_map_[node->id()] = wrapper;
wrapper->OnDataChanged();
}
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager.h b/chromium/content/browser/accessibility/browser_accessibility_manager.h
index 6279fdbe5f5..397df50cb4b 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager.h
@@ -347,8 +347,6 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXEventGenerator {
// AXTreeDelegate implementation.
void OnNodeWillBeDeleted(ui::AXTree* tree, ui::AXNode* node) override;
void OnSubtreeWillBeDeleted(ui::AXTree* tree, ui::AXNode* node) override;
- void OnNodeWillBeReparented(ui::AXTree* tree, ui::AXNode* node) override;
- void OnSubtreeWillBeReparented(ui::AXTree* tree, ui::AXNode* node) override;
void OnNodeCreated(ui::AXTree* tree, ui::AXNode* node) override;
void OnNodeReparented(ui::AXTree* tree, ui::AXNode* node) override;
void OnNodeChanged(ui::AXTree* tree, ui::AXNode* node) override;
@@ -455,11 +453,6 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXEventGenerator {
// The global ID of this accessibility tree.
ui::AXTreeIDRegistry::AXTreeID ax_tree_id_;
- // If this tree has a parent tree, this is the cached ID of the parent
- // node within that parent tree. It's computed as needed and cached for
- // speed so that it can be accessed quickly if it hasn't changed.
- int parent_node_id_from_parent_tree_;
-
// The device scale factor for the view associated with this frame,
// cached each time there's any update to the accessibility tree.
float device_scale_factor_;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_auralinux.cc b/chromium/content/browser/accessibility/browser_accessibility_manager_auralinux.cc
index f57d21a1195..1caa0621b77 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_auralinux.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_auralinux.cc
@@ -4,6 +4,8 @@
#include "content/browser/accessibility/browser_accessibility_manager_auralinux.h"
+#include <vector>
+
#include "content/browser/accessibility/browser_accessibility_auralinux.h"
#include "content/common/accessibility_messages.h"
#include "ui/accessibility/platform/ax_platform_node_auralinux.h"
@@ -72,4 +74,22 @@ void BrowserAccessibilityManagerAuraLinux::FireGeneratedEvent(
// Need to implement.
}
+void BrowserAccessibilityManagerAuraLinux::OnAtomicUpdateFinished(
+ ui::AXTree* tree,
+ bool root_changed,
+ const std::vector<ui::AXTreeDelegate::Change>& changes) {
+ BrowserAccessibilityManager::OnAtomicUpdateFinished(tree, root_changed,
+ changes);
+
+ // This is the second step in what will be a three step process mirroring that
+ // used in BrowserAccessibilityManagerWin.
+ for (const auto& change : changes) {
+ const ui::AXNode* changed_node = change.node;
+ DCHECK(changed_node);
+ BrowserAccessibility* obj = GetFromAXNode(changed_node);
+ if (obj && obj->IsNative())
+ ToBrowserAccessibilityAuraLinux(obj)->GetNode()->UpdateHypertext();
+ }
+}
+
} // namespace content
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_auralinux.h b/chromium/content/browser/accessibility/browser_accessibility_manager_auralinux.h
index c7537427ff1..7de682076c4 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_auralinux.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_auralinux.h
@@ -5,6 +5,8 @@
#ifndef CONTENT_BROWSER_ACCESSIBILITY_BROWSER_ACCESSIBILITY_MANAGER_AURALINUX_H_
#define CONTENT_BROWSER_ACCESSIBILITY_BROWSER_ACCESSIBILITY_MANAGER_AURALINUX_H_
+#include <vector>
+
#include "base/macros.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
@@ -34,6 +36,13 @@ class CONTENT_EXPORT BrowserAccessibilityManagerAuraLinux
AtkObject* parent_object() { return parent_object_; }
+ protected:
+ // AXTreeDelegate methods.
+ void OnAtomicUpdateFinished(
+ ui::AXTree* tree,
+ bool root_changed,
+ const std::vector<ui::AXTreeDelegate::Change>& changes) override;
+
private:
AtkObject* parent_object_;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm b/chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm
index 8e32a082260..09cb7f8a55d 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm
@@ -180,6 +180,16 @@ void BrowserAccessibilityManagerMac::FireBlinkEvent(
FireNativeMacNotification(mac_notification, node);
}
+void PostAnnouncementNotification(NSString* announcement) {
+ NSDictionary* notification_info = @{
+ NSAccessibilityAnnouncementKey : announcement,
+ NSAccessibilityPriorityKey : @(NSAccessibilityPriorityLow)
+ };
+ NSAccessibilityPostNotificationWithUserInfo(
+ [NSApp mainWindow], NSAccessibilityAnnouncementRequestedNotification,
+ notification_info);
+}
+
void BrowserAccessibilityManagerMac::FireGeneratedEvent(
AXEventGenerator::Event event_type,
BrowserAccessibility* node) {
@@ -313,6 +323,18 @@ void BrowserAccessibilityManagerMac::FireGeneratedEvent(
return;
}
+ if (base::mac::IsAtMostOS10_13()) {
+ // Use the announcement API to get around OS <= 10.13 VoiceOver bug
+ // where it stops announcing live regions after the first time focus
+ // leaves any content area.
+ // Unfortunately this produces an annoying boing sound with each live
+ // announcement, but the alternative is almost no live region support.
+ PostAnnouncementNotification(
+ base::SysUTF8ToNSString(node->GetLiveRegionText()));
+ return;
+ }
+
+ // Use native VoiceOver support for live regions.
base::scoped_nsobject<BrowserAccessibilityCocoa> retained_node(
[native_node retain]);
BrowserThread::PostDelayedTask(
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_win.cc b/chromium/content/browser/accessibility/browser_accessibility_manager_win.cc
index f6179284bb4..1a3eecf5de2 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_win.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_win.cc
@@ -179,10 +179,18 @@ void BrowserAccessibilityManagerWin::FireGeneratedEvent(
FireWinAccessibilityEvent(EVENT_OBJECT_REORDER, node);
break;
case Event::LIVE_REGION_CHANGED:
- // NVDA and JAWS are inconsistent about speaking this event in content.
- // Because of this, and because Firefox does not currently fire it, we
- // are avoiding this event for now.
- // FireWinAccessibilityEvent(EVENT_OBJECT_LIVEREGIONCHANGED, node);
+ // This event is redundant with the IA2_EVENT_TEXT_INSERTED events;
+ // however, JAWS 2018 and earlier do not process the text inserted
+ // events when "virtual cursor mode" is turned off (Insert+Z).
+ // Fortunately, firing the redudant event does not cause duplicate
+ // verbalizations in either screen reader.
+ // Future versions of JAWS may process the text inserted event when
+ // in focus mode, and so at some point the live region
+ // changed events may truly become redundant with the text inserted
+ // events. Note: Firefox does not fire this event, but JAWS processes
+ // Firefox live region events differently (utilizes MSAA's
+ // EVENT_OBJECT_SHOW).
+ FireWinAccessibilityEvent(EVENT_OBJECT_LIVEREGIONCHANGED, node);
break;
case Event::LOAD_COMPLETE:
FireWinAccessibilityEvent(IA2_EVENT_DOCUMENT_LOAD_COMPLETE, node);
@@ -197,7 +205,7 @@ void BrowserAccessibilityManagerWin::FireGeneratedEvent(
// Fire the event on the object where the focus of the selection is.
int32_t focus_id = GetTreeData().sel_focus_object_id;
BrowserAccessibility* focus_object = GetFromID(focus_id);
- if (focus_object)
+ if (focus_object && focus_object->HasVisibleCaretOrSelection())
FireWinAccessibilityEvent(IA2_EVENT_TEXT_CARET_MOVED, focus_object);
break;
}
diff --git a/chromium/content/browser/accessibility/browser_accessibility_state_impl.cc b/chromium/content/browser/accessibility/browser_accessibility_state_impl.cc
index 0c5ec83a271..15faf68df8a 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_state_impl.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_state_impl.cc
@@ -8,7 +8,7 @@
#include "base/command_line.h"
#include "base/metrics/histogram_macros.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "build/build_config.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
@@ -72,7 +72,7 @@ BrowserAccessibilityStateImpl::BrowserAccessibilityStateImpl()
// detected until after the user interacts in some way, so a reasonable delay
// gives us better numbers.
base::PostDelayedTaskWithTraits(
- FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND},
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
base::Bind(&BrowserAccessibilityStateImpl::UpdateHistograms, this),
base::TimeDelta::FromSeconds(ACCESSIBILITY_HISTOGRAM_DELAY_SECS));
#else
@@ -106,6 +106,11 @@ void BrowserAccessibilityStateImpl::DisableAccessibility() {
ResetAccessibilityMode();
}
+bool BrowserAccessibilityStateImpl::IsRendererAccessibilityEnabled() {
+ return !base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableRendererAccessibility);
+}
+
void BrowserAccessibilityStateImpl::ResetAccessibilityModeValue() {
accessibility_mode_ = ui::AXMode();
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
@@ -120,7 +125,7 @@ void BrowserAccessibilityStateImpl::ResetAccessibilityMode() {
std::vector<WebContentsImpl*> web_contents_vector =
WebContentsImpl::GetAllWebContents();
for (size_t i = 0; i < web_contents_vector.size(); ++i)
- web_contents_vector[i]->SetAccessibilityMode(accessibility_mode());
+ web_contents_vector[i]->SetAccessibilityMode(accessibility_mode_);
}
bool BrowserAccessibilityStateImpl::IsAccessibleBrowser() {
@@ -157,6 +162,10 @@ void BrowserAccessibilityStateImpl::OnAXModeAdded(ui::AXMode mode) {
AddAccessibilityModeFlags(mode);
}
+ui::AXMode BrowserAccessibilityStateImpl::GetAccessibilityMode() const {
+ return accessibility_mode_;
+}
+
#if !defined(OS_WIN) && !defined(OS_MACOSX)
void BrowserAccessibilityStateImpl::UpdatePlatformSpecificHistograms() {
}
@@ -207,7 +216,7 @@ void BrowserAccessibilityStateImpl::RemoveAccessibilityModeFlags(
std::vector<WebContentsImpl*> web_contents_vector =
WebContentsImpl::GetAllWebContents();
for (size_t i = 0; i < web_contents_vector.size(); ++i)
- web_contents_vector[i]->SetAccessibilityMode(accessibility_mode());
+ web_contents_vector[i]->SetAccessibilityMode(accessibility_mode_);
}
} // namespace content
diff --git a/chromium/content/browser/accessibility/browser_accessibility_state_impl.h b/chromium/content/browser/accessibility/browser_accessibility_state_impl.h
index 1eb3033e6d8..9b57bbd68d8 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_state_impl.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_state_impl.h
@@ -44,6 +44,10 @@ class CONTENT_EXPORT BrowserAccessibilityStateImpl
void EnableAccessibility() override;
void DisableAccessibility() override;
+ bool IsRendererAccessibilityEnabled() override;
+ ui::AXMode GetAccessibilityMode() const override;
+ void AddAccessibilityModeFlags(ui::AXMode mode) override;
+ void RemoveAccessibilityModeFlags(ui::AXMode mode) override;
void ResetAccessibilityMode() override;
void OnScreenReaderDetected() override;
bool IsAccessibleBrowser() override;
@@ -54,16 +58,6 @@ class CONTENT_EXPORT BrowserAccessibilityStateImpl
// AXModeObserver
void OnAXModeAdded(ui::AXMode mode) override;
- ui::AXMode accessibility_mode() const { return accessibility_mode_; };
-
- // Adds the given accessibility mode flags to the current accessibility
- // mode bitmap.
- void AddAccessibilityModeFlags(ui::AXMode mode);
-
- // Remove the given accessibility mode flags from the current accessibility
- // mode bitmap.
- void RemoveAccessibilityModeFlags(ui::AXMode mode);
-
// Accessibility objects can have the "hot tracked" state set when
// the mouse is hovering over them, but this makes tests flaky because
// the test behaves differently when the mouse happens to be over an
diff --git a/chromium/content/browser/accessibility/browser_accessibility_win.cc b/chromium/content/browser/accessibility/browser_accessibility_win.cc
index 5b1585a981c..fbeb12c539e 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_win.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_win.cc
@@ -53,7 +53,7 @@ void BrowserAccessibilityWin::OnLocationChanged() {
}
base::string16 BrowserAccessibilityWin::GetText() const {
- return GetCOM()->AXPlatformNodeWin::GetText();
+ return GetCOM()->AXPlatformNodeWin::GetTextAsString16();
}
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 ec38830ef55..b8cf5cd5380 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_win.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_win.h
@@ -5,9 +5,7 @@
#ifndef CONTENT_BROWSER_ACCESSIBILITY_BROWSER_ACCESSIBILITY_WIN_H_
#define CONTENT_BROWSER_ACCESSIBILITY_BROWSER_ACCESSIBILITY_WIN_H_
-#include <atlbase.h>
-#include <atlcom.h>
-
+#include "base/win/atl.h"
#include "content/browser/accessibility/browser_accessibility.h"
#include "content/browser/accessibility/browser_accessibility_com_win.h"
#include "content/common/content_export.h"
diff --git a/chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc b/chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc
index 611d6959723..2950d2d28e4 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc
@@ -326,7 +326,7 @@ TEST_F(BrowserAccessibilityTest, TestTextBoundaries) {
ToBrowserAccessibilityWin(root_obj->PlatformGetChild(0))->GetCOM();
ASSERT_NE(nullptr, text_field_obj);
- long text_len;
+ LONG text_len;
EXPECT_EQ(S_OK, text_field_obj->get_nCharacters(&text_len));
base::win::ScopedBstr text;
@@ -338,8 +338,8 @@ TEST_F(BrowserAccessibilityTest, TestTextBoundaries) {
EXPECT_STREQ(L"One ", text);
text.Reset();
- long start;
- long end;
+ LONG start;
+ LONG end;
EXPECT_EQ(S_OK, text_field_obj->get_textAtOffset(
1, IA2_TEXT_BOUNDARY_CHAR, &start, &end, text.Receive()));
EXPECT_EQ(1, start);
@@ -408,7 +408,7 @@ TEST_F(BrowserAccessibilityTest, TestTextBoundaries) {
TEST_F(BrowserAccessibilityTest, TestSimpleHypertext) {
const std::string text1_name = "One two three.";
const std::string text2_name = " Four five six.";
- const long text_name_len = text1_name.length() + text2_name.length();
+ const LONG text_name_len = text1_name.length() + text2_name.length();
ui::AXNodeData text1;
text1.id = 11;
@@ -434,7 +434,7 @@ TEST_F(BrowserAccessibilityTest, TestSimpleHypertext) {
BrowserAccessibilityComWin* root_obj =
ToBrowserAccessibilityWin(manager->GetRoot())->GetCOM();
- long text_len;
+ LONG text_len;
EXPECT_EQ(S_OK, root_obj->get_nCharacters(&text_len));
EXPECT_EQ(text_name_len, text_len);
@@ -442,7 +442,7 @@ TEST_F(BrowserAccessibilityTest, TestSimpleHypertext) {
EXPECT_EQ(S_OK, root_obj->get_text(0, text_name_len, text.Receive()));
EXPECT_EQ(text1_name + text2_name, base::UTF16ToUTF8(base::string16(text)));
- long hyperlink_count;
+ LONG hyperlink_count;
EXPECT_EQ(S_OK, root_obj->get_nHyperlinks(&hyperlink_count));
EXPECT_EQ(0, hyperlink_count);
@@ -455,7 +455,7 @@ TEST_F(BrowserAccessibilityTest, TestSimpleHypertext) {
EXPECT_EQ(E_INVALIDARG, root_obj->get_hyperlink(text_name_len + 1,
hyperlink.GetAddressOf()));
- long hyperlink_index;
+ LONG hyperlink_index;
EXPECT_EQ(S_FALSE, root_obj->get_hyperlinkIndex(0, &hyperlink_index));
EXPECT_EQ(-1, hyperlink_index);
// Invalid arguments should not be modified.
@@ -486,7 +486,7 @@ TEST_F(BrowserAccessibilityTest, TestComplexHypertext) {
const base::string16 embed(1, BrowserAccessibilityComWin::kEmbeddedCharacter);
const base::string16 root_hypertext =
text1_name + embed + text2_name + embed + embed + embed;
- const long root_hypertext_len = root_hypertext.length();
+ const LONG root_hypertext_len = root_hypertext.length();
ui::AXNodeData text1;
text1.id = 11;
@@ -547,7 +547,7 @@ TEST_F(BrowserAccessibilityTest, TestComplexHypertext) {
BrowserAccessibilityComWin* root_obj =
ToBrowserAccessibilityWin(manager->GetRoot())->GetCOM();
- long text_len;
+ LONG text_len;
EXPECT_EQ(S_OK, root_obj->get_nCharacters(&text_len));
EXPECT_EQ(root_hypertext_len, text_len);
@@ -556,7 +556,7 @@ TEST_F(BrowserAccessibilityTest, TestComplexHypertext) {
EXPECT_STREQ(root_hypertext.c_str(), text);
text.Reset();
- long hyperlink_count;
+ LONG hyperlink_count;
EXPECT_EQ(S_OK, root_obj->get_nHyperlinks(&hyperlink_count));
EXPECT_EQ(4, hyperlink_count);
@@ -607,7 +607,7 @@ TEST_F(BrowserAccessibilityTest, TestComplexHypertext) {
hyperlink.Reset();
hypertext.Reset();
- long hyperlink_index;
+ LONG hyperlink_index;
EXPECT_EQ(S_FALSE, root_obj->get_hyperlinkIndex(0, &hyperlink_index));
EXPECT_EQ(-1, hyperlink_index);
// Invalid arguments should not be modified.
@@ -937,7 +937,7 @@ TEST_F(BrowserAccessibilityTest, TestValueAttributeInTextControls) {
}
TEST_F(BrowserAccessibilityTest, TestWordBoundariesInTextControls) {
- const base::string16 line1(L"This is a very long line of text that ");
+ const base::string16 line1(L"This is a very LONG line of text that ");
const base::string16 line2(L"should wrap on more than one lines ");
const base::string16 text(line1 + line2);
diff --git a/chromium/content/browser/accessibility/cross_platform_accessibility_browsertest.cc b/chromium/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
index 4541b57ade6..b1942ea3546 100644
--- a/chromium/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
+++ b/chromium/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
@@ -23,8 +23,7 @@
#include "ui/accessibility/ax_tree.h"
#if defined(OS_WIN)
-#include <atlbase.h>
-#include <atlcom.h>
+#include "base/win/atl.h"
#include "base/win/scoped_com_initializer.h"
#include "ui/base/win/atl_module.h"
#endif
diff --git a/chromium/content/browser/accessibility/dump_accessibility_browsertest_base.cc b/chromium/content/browser/accessibility/dump_accessibility_browsertest_base.cc
index c97d5c92642..76f0ccee205 100644
--- a/chromium/content/browser/accessibility/dump_accessibility_browsertest_base.cc
+++ b/chromium/content/browser/accessibility/dump_accessibility_browsertest_base.cc
@@ -213,7 +213,7 @@ void DumpAccessibilityTestBase::RunTestForPlatform(
base::FilePath expected_file;
std::string expected_contents_raw;
{
- base::ThreadRestrictions::ScopedAllowIO allow_io_for_test_setup;
+ base::ScopedAllowBlockingForTesting allow_blocking;
base::ReadFileToString(file_path, &html_contents);
// Read the expected file.
diff --git a/chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc b/chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc
index bc91d524e85..b914cec0d63 100644
--- a/chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc
+++ b/chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc
@@ -83,10 +83,9 @@ std::vector<std::string> DumpAccessibilityEventsTest::Dump() {
WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
shell()->web_contents());
base::ProcessId pid = base::GetCurrentProcId();
- std::unique_ptr<AccessibilityEventRecorder> event_recorder(
- AccessibilityEventRecorder::Create(
- web_contents->GetRootBrowserAccessibilityManager(), pid));
- event_recorder->set_only_web_events(true);
+ auto& event_recorder = AccessibilityEventRecorder::GetInstance(
+ web_contents->GetRootBrowserAccessibilityManager(), pid);
+ event_recorder.set_only_web_events(true);
// Save a copy of the accessibility tree (as a text dump); we'll
// log this for the user later if the test fails.
@@ -124,7 +123,7 @@ std::vector<std::string> DumpAccessibilityEventsTest::Dump() {
// Dump the event logs, running them through any filters specified
// in the HTML file.
- std::vector<std::string> event_logs = event_recorder->event_logs();
+ std::vector<std::string> event_logs = event_recorder.event_logs();
std::vector<std::string> result;
for (size_t i = 0; i < event_logs.size(); ++i) {
if (AccessibilityTreeFormatter::MatchesFilters(
@@ -156,7 +155,7 @@ void DumpAccessibilityEventsTest::RunEventTest(
base::FilePath test_path = GetTestFilePath("accessibility", "event");
{
- base::ThreadRestrictions::ScopedAllowIO allow_io_for_test_verification;
+ base::ScopedAllowBlockingForTesting allow_blocking;
ASSERT_TRUE(base::PathExists(test_path)) << test_path.LossyDisplayName();
}
@@ -340,6 +339,11 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest,
}
IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest,
+ AccessibilityEventsLiveRegionElemReparent) {
+ RunEventTest(FILE_PATH_LITERAL("live-region-elem-reparent.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest,
AccessibilityEventsLiveRegionIgnoresClick) {
RunEventTest(FILE_PATH_LITERAL("live-region-ignores-click.html"));
}
@@ -355,6 +359,11 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest,
RunEventTest(FILE_PATH_LITERAL("menulist-collapse.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest,
+ AccessibilityEventsMenuListCollapseNext) {
+ RunEventTest(FILE_PATH_LITERAL("menulist-collapse-next.html"));
+}
+
// https://crbug.com/719030
IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest,
DISABLED_AccessibilityEventsMenuListExpand) {
diff --git a/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
index b0c2af3f667..6de78219107 100644
--- a/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
+++ b/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -77,7 +77,7 @@ class DumpAccessibilityTreeTest : public DumpAccessibilityTestBase {
void RunAriaTest(const base::FilePath::CharType* file_path) {
base::FilePath test_path = GetTestFilePath("accessibility", "aria");
{
- base::ThreadRestrictions::ScopedAllowIO allow_io_for_test_setup;
+ base::ScopedAllowBlockingForTesting allow_blocking;
ASSERT_TRUE(base::PathExists(test_path)) << test_path.LossyDisplayName();
}
base::FilePath aria_file = test_path.Append(base::FilePath(file_path));
@@ -88,7 +88,7 @@ class DumpAccessibilityTreeTest : public DumpAccessibilityTestBase {
void RunAomTest(const base::FilePath::CharType* file_path) {
base::FilePath test_path = GetTestFilePath("accessibility", "aom");
{
- base::ThreadRestrictions::ScopedAllowIO allow_io_for_test_setup;
+ base::ScopedAllowBlockingForTesting allow_blocking;
ASSERT_TRUE(base::PathExists(test_path)) << test_path.LossyDisplayName();
}
base::FilePath aom_file = test_path.Append(base::FilePath(file_path));
@@ -99,7 +99,7 @@ class DumpAccessibilityTreeTest : public DumpAccessibilityTestBase {
void RunCSSTest(const base::FilePath::CharType* file_path) {
base::FilePath test_path = GetTestFilePath("accessibility", "css");
{
- base::ThreadRestrictions::ScopedAllowIO allow_io_for_test_setup;
+ base::ScopedAllowBlockingForTesting allow_blocking;
ASSERT_TRUE(base::PathExists(test_path)) << test_path.LossyDisplayName();
}
base::FilePath css_file = test_path.Append(base::FilePath(file_path));
@@ -110,7 +110,7 @@ class DumpAccessibilityTreeTest : public DumpAccessibilityTestBase {
void RunHtmlTest(const base::FilePath::CharType* file_path) {
base::FilePath test_path = GetTestFilePath("accessibility", "html");
{
- base::ThreadRestrictions::ScopedAllowIO allow_io_for_test_setup;
+ base::ScopedAllowBlockingForTesting allow_blocking;
ASSERT_TRUE(base::PathExists(test_path)) << test_path.LossyDisplayName();
}
base::FilePath html_file = test_path.Append(base::FilePath(file_path));
@@ -412,6 +412,10 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaBanner) {
RunAriaTest(FILE_PATH_LITERAL("aria-banner.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaBlockquote) {
+ RunAriaTest(FILE_PATH_LITERAL("aria-blockquote.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaBusy) {
RunAriaTest(FILE_PATH_LITERAL("aria-busy.html"));
}
@@ -420,6 +424,10 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaButton) {
RunAriaTest(FILE_PATH_LITERAL("aria-button.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaCaption) {
+ RunAriaTest(FILE_PATH_LITERAL("aria-caption.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaCell) {
RunAriaTest(FILE_PATH_LITERAL("aria-cell.html"));
}
@@ -733,6 +741,10 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaOption) {
RunAriaTest(FILE_PATH_LITERAL("aria-option.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaParagraph) {
+ RunAriaTest(FILE_PATH_LITERAL("aria-paragraph.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaPosinset) {
RunAriaTest(FILE_PATH_LITERAL("aria-posinset.html"));
}
@@ -991,6 +1003,10 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityBody) {
RunHtmlTest(FILE_PATH_LITERAL("body.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityBodyTabIndex) {
+ RunHtmlTest(FILE_PATH_LITERAL("body-tabindex.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityBoundsInherits) {
RunHtmlTest(FILE_PATH_LITERAL("bounds-inherits.html"));
}
@@ -1414,6 +1430,21 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityInputSearch) {
RunHtmlTest(FILE_PATH_LITERAL("input-search.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ AccessibilityScrollableInput) {
+ RunHtmlTest(FILE_PATH_LITERAL("scrollable-input.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ AccessibilityScrollableOverflow) {
+ RunHtmlTest(FILE_PATH_LITERAL("scrollable-overflow.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ AccessibilityScrollableTextarea) {
+ RunHtmlTest(FILE_PATH_LITERAL("scrollable-textarea.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilitySmall) {
RunHtmlTest(FILE_PATH_LITERAL("small.html"));
}
diff --git a/chromium/content/browser/accessibility/web_contents_accessibility_android.cc b/chromium/content/browser/accessibility/web_contents_accessibility_android.cc
index ee2bfb27fd3..8007c45a720 100644
--- a/chromium/content/browser/accessibility/web_contents_accessibility_android.cc
+++ b/chromium/content/browser/accessibility/web_contents_accessibility_android.cc
@@ -350,6 +350,7 @@ WebContentsAccessibilityAndroid::WebContentsAccessibilityAndroid(
: java_ref_(env, obj),
web_contents_(static_cast<WebContentsImpl*>(web_contents)),
frame_info_initialized_(false),
+ use_zoom_for_dsf_enabled_(IsUseZoomForDSFEnabled()),
root_manager_(nullptr),
connector_(new Connector(web_contents, this)) {
CollectStats();
@@ -550,7 +551,7 @@ bool WebContentsAccessibilityAndroid::OnHoverEvent(
if (event.GetAction() != ui::MotionEvent::Action::HOVER_EXIT &&
root_manager_) {
gfx::PointF point =
- IsUseZoomForDSFEnabled() ? event.GetPointPix() : event.GetPoint();
+ use_zoom_for_dsf_enabled_ ? event.GetPointPix() : event.GetPoint();
point.Scale(1 / page_scale_);
root_manager_->HitTest(gfx::ToFlooredPoint(point));
}
@@ -694,10 +695,15 @@ jboolean WebContentsAccessibilityAndroid::PopulateAccessibilityNodeInfo(
base::android::ConvertUTF16ToJavaString(env, element_id));
}
- gfx::Rect absolute_rect = node->GetPageBoundsRect();
+ float dip_scale = use_zoom_for_dsf_enabled_
+ ? 1 / root_manager_->device_scale_factor()
+ : 1.0;
+ gfx::Rect absolute_rect = gfx::ScaleToEnclosingRect(node->GetPageBoundsRect(),
+ dip_scale, dip_scale);
gfx::Rect parent_relative_rect = absolute_rect;
if (node->PlatformGetParent()) {
- gfx::Rect parent_rect = node->PlatformGetParent()->GetPageBoundsRect();
+ gfx::Rect parent_rect = gfx::ScaleToEnclosingRect(
+ node->PlatformGetParent()->GetPageBoundsRect(), dip_scale, dip_scale);
parent_relative_rect.Offset(-parent_rect.OffsetFromOrigin());
}
bool is_root = node->PlatformGetParent() == NULL;
@@ -1189,7 +1195,7 @@ WebContentsAccessibilityAndroid::GetCharacterBoundingBoxes(
gfx::Rect object_bounds = node->GetPageBoundsRect();
int coords[4 * len];
for (int i = 0; i < len; i++) {
- gfx::Rect char_bounds = node->GetPageBoundsForRange(start + i, 1);
+ gfx::Rect char_bounds = node->GetPageBoundsForRange(start + i, 1, false);
if (char_bounds.IsEmpty())
char_bounds = object_bounds;
coords[4 * i + 0] = char_bounds.x();
diff --git a/chromium/content/browser/accessibility/web_contents_accessibility_android.h b/chromium/content/browser/accessibility/web_contents_accessibility_android.h
index 51343b13f97..de47526f888 100644
--- a/chromium/content/browser/accessibility/web_contents_accessibility_android.h
+++ b/chromium/content/browser/accessibility/web_contents_accessibility_android.h
@@ -261,6 +261,8 @@ class CONTENT_EXPORT WebContentsAccessibilityAndroid
float page_scale_ = 1.f;
+ bool use_zoom_for_dsf_enabled_;
+
BrowserAccessibilityManagerAndroid* root_manager_;
// Manages the connection between web contents and the RenderFrameHost that
diff --git a/chromium/content/browser/android/dialog_overlay_impl.h b/chromium/content/browser/android/dialog_overlay_impl.h
index 51e40678668..4cb4cbef524 100644
--- a/chromium/content/browser/android/dialog_overlay_impl.h
+++ b/chromium/content/browser/android/dialog_overlay_impl.h
@@ -16,7 +16,7 @@
namespace content {
// Native counterpart to DialogOverlayImpl java class. This is created by the
-// java side. When the ContentViewCore for the provided token is attached or
+// java side. When the WebContents for the provided token is attached or
// detached from a WindowAndroid, we get the Android window token and notify the
// java side.
class DialogOverlayImpl : public ui::ViewAndroidObserver,
diff --git a/chromium/content/browser/android/java/gin_java_bridge_dispatcher_host.h b/chromium/content/browser/android/java/gin_java_bridge_dispatcher_host.h
index 7404fcfeba5..8e55c6434e9 100644
--- a/chromium/content/browser/android/java/gin_java_bridge_dispatcher_host.h
+++ b/chromium/content/browser/android/java/gin_java_bridge_dispatcher_host.h
@@ -25,7 +25,7 @@ class ListValue;
namespace content {
-// This class handles injecting Java objects into a single ContentViewCore /
+// This class handles injecting Java objects into a single WebContents /
// WebView. The Java object itself lives in the browser process on a background
// thread, while multiple JavaScript wrapper objects (one per frame) are created
// on the renderer side. The injected Java objects are identified by ObjectID,
diff --git a/chromium/content/browser/android/java/gin_java_bridge_message_filter.cc b/chromium/content/browser/android/java/gin_java_bridge_message_filter.cc
index 33051e165fa..9c2feb1a847 100644
--- a/chromium/content/browser/android/java/gin_java_bridge_message_filter.cc
+++ b/chromium/content/browser/android/java/gin_java_bridge_message_filter.cc
@@ -102,7 +102,8 @@ scoped_refptr<GinJavaBridgeMessageFilter> GinJavaBridgeMessageFilter::FromHost(
return filter;
}
-GinJavaBridgeDispatcherHost* GinJavaBridgeMessageFilter::FindHost() {
+scoped_refptr<GinJavaBridgeDispatcherHost>
+GinJavaBridgeMessageFilter::FindHost() {
base::AutoLock locker(hosts_lock_);
auto iter = hosts_.find(current_routing_id_);
if (iter != hosts_.end())
@@ -110,7 +111,7 @@ GinJavaBridgeDispatcherHost* GinJavaBridgeMessageFilter::FindHost() {
// Not being able to find a host is OK -- we can receive messages from
// RenderFrames for which the corresponding host part has already been
// destroyed. That means, any references to Java objects that the host was
- // holding were already released (with the death of ContentViewCore), so we
+ // holding were already released (with the death of WebContents), so we
// can just ignore such messages.
// RenderProcessHostImpl does the same -- if it can't find a listener
// for the message's routing id, it just drops the message silently.
@@ -124,7 +125,7 @@ void GinJavaBridgeMessageFilter::OnGetMethods(
GinJavaBoundObject::ObjectID object_id,
std::set<std::string>* returned_method_names) {
DCHECK(JavaBridgeThread::CurrentlyOn());
- GinJavaBridgeDispatcherHost* host = FindHost();
+ scoped_refptr<GinJavaBridgeDispatcherHost> host = FindHost();
if (host) {
host->OnGetMethods(object_id, returned_method_names);
} else {
@@ -137,7 +138,7 @@ void GinJavaBridgeMessageFilter::OnHasMethod(
const std::string& method_name,
bool* result) {
DCHECK(JavaBridgeThread::CurrentlyOn());
- GinJavaBridgeDispatcherHost* host = FindHost();
+ scoped_refptr<GinJavaBridgeDispatcherHost> host = FindHost();
if (host) {
host->OnHasMethod(object_id, method_name, result);
} else {
@@ -152,7 +153,7 @@ void GinJavaBridgeMessageFilter::OnInvokeMethod(
base::ListValue* wrapped_result,
content::GinJavaBridgeError* error_code) {
DCHECK(JavaBridgeThread::CurrentlyOn());
- GinJavaBridgeDispatcherHost* host = FindHost();
+ scoped_refptr<GinJavaBridgeDispatcherHost> host = FindHost();
if (host) {
host->OnInvokeMethod(current_routing_id_, object_id, method_name, arguments,
wrapped_result, error_code);
@@ -165,7 +166,7 @@ void GinJavaBridgeMessageFilter::OnInvokeMethod(
void GinJavaBridgeMessageFilter::OnObjectWrapperDeleted(
GinJavaBoundObject::ObjectID object_id) {
DCHECK(JavaBridgeThread::CurrentlyOn());
- GinJavaBridgeDispatcherHost* host = FindHost();
+ scoped_refptr<GinJavaBridgeDispatcherHost> host = FindHost();
if (host)
host->OnObjectWrapperDeleted(current_routing_id_, object_id);
}
diff --git a/chromium/content/browser/android/java/gin_java_bridge_message_filter.h b/chromium/content/browser/android/java/gin_java_bridge_message_filter.h
index 5a269664f7e..b117d2d5d53 100644
--- a/chromium/content/browser/android/java/gin_java_bridge_message_filter.h
+++ b/chromium/content/browser/android/java/gin_java_bridge_message_filter.h
@@ -54,10 +54,6 @@ class GinJavaBridgeMessageFilter : public BrowserMessageFilter {
friend class BrowserThread;
friend class base::DeleteHelper<GinJavaBridgeMessageFilter>;
- // GinJavaBridgeDispatcherHost removes itself from the map on
- // WebContents destruction, so there is no risk that the pointer would become
- // stale.
- //
// The filter keeps its own routing map of RenderFrames for two reasons:
// 1. Message dispatching must be done on the background thread,
// without resorting to the UI thread, which can be in fact currently
@@ -65,13 +61,13 @@ class GinJavaBridgeMessageFilter : public BrowserMessageFilter {
// 2. As RenderFrames pass away earlier than JavaScript wrappers,
// messages from the latter can arrive after the RenderFrame has been
// removed from the WebContents' routing table.
- typedef std::map<int32_t, GinJavaBridgeDispatcherHost*> HostMap;
+ typedef std::map<int32_t, scoped_refptr<GinJavaBridgeDispatcherHost>> HostMap;
GinJavaBridgeMessageFilter();
~GinJavaBridgeMessageFilter() override;
// Called on the background thread.
- GinJavaBridgeDispatcherHost* FindHost();
+ scoped_refptr<GinJavaBridgeDispatcherHost> FindHost();
void OnGetMethods(GinJavaBoundObject::ObjectID object_id,
std::set<std::string>* returned_method_names);
void OnHasMethod(GinJavaBoundObject::ObjectID object_id,
diff --git a/chromium/content/browser/android/javascript_injector.cc b/chromium/content/browser/android/javascript_injector.cc
index a4585487f4a..2c60177e40f 100644
--- a/chromium/content/browser/android/javascript_injector.cc
+++ b/chromium/content/browser/android/javascript_injector.cc
@@ -15,8 +15,6 @@ using base::android::ScopedJavaLocalRef;
namespace content {
-DEFINE_WEB_CONTENTS_USER_DATA_KEY(JavascriptInjector);
-
JavascriptInjector::JavascriptInjector(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
diff --git a/chromium/content/browser/android/launcher_thread.cc b/chromium/content/browser/android/launcher_thread.cc
index 06a7f234fc1..995bc5a6117 100644
--- a/chromium/content/browser/android/launcher_thread.cc
+++ b/chromium/content/browser/android/launcher_thread.cc
@@ -18,8 +18,9 @@ base::MessageLoop* LauncherThread::GetMessageLoop() {
}
LauncherThread::LauncherThread()
- : java_handler_thread_(Java_LauncherThread_getHandlerThread(
- base::android::AttachCurrentThread())) {
+ : java_handler_thread_(nullptr,
+ Java_LauncherThread_getHandlerThread(
+ base::android::AttachCurrentThread())) {
java_handler_thread_.Start();
}
diff --git a/chromium/content/browser/android/overscroll_controller_android_unittest.cc b/chromium/content/browser/android/overscroll_controller_android_unittest.cc
index 29fb140cdb0..707084f673e 100644
--- a/chromium/content/browser/android/overscroll_controller_android_unittest.cc
+++ b/chromium/content/browser/android/overscroll_controller_android_unittest.cc
@@ -48,6 +48,7 @@ class MockCompositor : public WindowAndroidCompositor {
return nullptr;
}
bool IsDrawingFirstVisibleFrame() const override { return false; }
+ void SetVSyncPaused(bool paused) override {}
};
class MockGlowClient : public OverscrollGlowClient {
diff --git a/chromium/content/browser/android/scoped_surface_request_manager.cc b/chromium/content/browser/android/scoped_surface_request_manager.cc
index 0a092c5aa18..6d67c9f810d 100644
--- a/chromium/content/browser/android/scoped_surface_request_manager.cc
+++ b/chromium/content/browser/android/scoped_surface_request_manager.cc
@@ -52,11 +52,11 @@ ScopedSurfaceRequestManager::GetAndUnregisterInternal(
return request;
}
-void ScopedSurfaceRequestManager::ForwardSurfaceTextureForSurfaceRequest(
+void ScopedSurfaceRequestManager::ForwardSurfaceOwnerForSurfaceRequest(
const base::UnguessableToken& request_token,
- const gl::SurfaceTexture* surface_texture) {
+ const gpu::SurfaceOwner* surface_owner) {
FulfillScopedSurfaceRequest(request_token,
- gl::ScopedJavaSurface(surface_texture));
+ surface_owner->CreateJavaSurface());
}
void ScopedSurfaceRequestManager::FulfillScopedSurfaceRequest(
diff --git a/chromium/content/browser/android/scoped_surface_request_manager.h b/chromium/content/browser/android/scoped_surface_request_manager.h
index aee96e95796..2030ec86f01 100644
--- a/chromium/content/browser/android/scoped_surface_request_manager.h
+++ b/chromium/content/browser/android/scoped_surface_request_manager.h
@@ -49,9 +49,9 @@ class CONTENT_EXPORT ScopedSurfaceRequestManager
// Implementation of ScopedSurfaceRequestConduit.
// To be used in the single process case.
// Can be called from any thread.
- void ForwardSurfaceTextureForSurfaceRequest(
+ void ForwardSurfaceOwnerForSurfaceRequest(
const base::UnguessableToken& request_token,
- const gl::SurfaceTexture* surface_texture) override;
+ const gpu::SurfaceOwner* surface_owner) override;
void clear_requests_for_testing() { request_callbacks_.clear(); }
diff --git a/chromium/content/browser/android/scoped_surface_request_manager_unittest.cc b/chromium/content/browser/android/scoped_surface_request_manager_unittest.cc
index 30e8fa3e4b6..bdff6917a0e 100644
--- a/chromium/content/browser/android/scoped_surface_request_manager_unittest.cc
+++ b/chromium/content/browser/android/scoped_surface_request_manager_unittest.cc
@@ -8,6 +8,7 @@
#include "base/callback_forward.h"
#include "base/run_loop.h"
#include "content/public/test/test_browser_thread_bundle.h"
+#include "gpu/ipc/common/android/surface_owner_android.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gl/android/scoped_java_surface.h"
#include "ui/gl/android/surface_texture.h"
@@ -26,7 +27,7 @@ class ScopedSurfaceRequestManagerUnitTest : public testing::Test {
last_received_request_ = 0;
dummy_token_ = base::UnguessableToken::Deserialize(123, 456);
- surface_texture = gl::SurfaceTexture::Create(0);
+ surface_owner = gpu::SurfaceOwner::Create(0);
dummy_request_ =
base::Bind(&ScopedSurfaceRequestManagerUnitTest::DummyCallback,
base::Unretained(this));
@@ -46,7 +47,7 @@ class ScopedSurfaceRequestManagerUnitTest : public testing::Test {
ScopedSurfaceRequestManager::ScopedSurfaceRequestCB dummy_request_;
ScopedSurfaceRequestManager::ScopedSurfaceRequestCB specific_logging_request_;
- scoped_refptr<gl::SurfaceTexture> surface_texture;
+ std::unique_ptr<gpu::SurfaceOwner> surface_owner;
int last_received_request_;
const int kSpecificCallbackId = 1357;
@@ -139,8 +140,8 @@ TEST_F(ScopedSurfaceRequestManagerUnitTest,
FulfillUnregisteredRequest_ShouldDoNothing) {
manager_->RegisterScopedSurfaceRequest(specific_logging_request_);
- manager_->FulfillScopedSurfaceRequest(
- dummy_token_, gl::ScopedJavaSurface(surface_texture.get()));
+ manager_->FulfillScopedSurfaceRequest(dummy_token_,
+ surface_owner->CreateJavaSurface());
EXPECT_EQ(1, manager_->request_count_for_testing());
EXPECT_NE(kSpecificCallbackId, last_received_request_);
@@ -158,8 +159,8 @@ TEST_F(ScopedSurfaceRequestManagerUnitTest,
base::Bind(&ScopedSurfaceRequestManagerUnitTest::LoggingCallback,
base::Unretained(this), kOtherCallbackId));
- manager_->FulfillScopedSurfaceRequest(
- specific_token, gl::ScopedJavaSurface(surface_texture.get()));
+ manager_->FulfillScopedSurfaceRequest(specific_token,
+ surface_owner->CreateJavaSurface());
base::RunLoop().RunUntilIdle();
@@ -170,12 +171,11 @@ TEST_F(ScopedSurfaceRequestManagerUnitTest,
// Makes sure that the ScopedSurfaceRequestConduit implementation properly
// fulfills requests.
TEST_F(ScopedSurfaceRequestManagerUnitTest,
- ForwardSurfaceTexture_ShouldFulfillRequest) {
+ ForwardSurfaceOwner_ShouldFulfillRequest) {
base::UnguessableToken token =
manager_->RegisterScopedSurfaceRequest(specific_logging_request_);
- manager_->ForwardSurfaceTextureForSurfaceRequest(token,
- surface_texture.get());
+ manager_->ForwardSurfaceOwnerForSurfaceRequest(token, surface_owner.get());
base::RunLoop().RunUntilIdle();
diff --git a/chromium/content/browser/android/select_popup.cc b/chromium/content/browser/android/select_popup.cc
index 1ec666da9e6..44d187ced2e 100644
--- a/chromium/content/browser/android/select_popup.cc
+++ b/chromium/content/browser/android/select_popup.cc
@@ -13,7 +13,6 @@
#include "content/public/common/menu_item.h"
#include "content/public/common/use_zoom_for_dsf_policy.h"
#include "jni/SelectPopup_jni.h"
-#include "ui/android/window_android.h"
#include "ui/gfx/geometry/rect_f.h"
using base::android::AttachCurrentThread;
@@ -41,27 +40,14 @@ enum PopupItemType {
} // namespace
-jlong JNI_SelectPopup_Init(JNIEnv* env,
- const JavaParamRef<jobject>& obj,
- const JavaParamRef<jobject>& jweb_contents) {
- WebContents* web_contents = WebContents::FromJavaWebContents(jweb_contents);
- DCHECK(web_contents);
-
- auto* wc_impl = static_cast<WebContentsImpl*>(web_contents);
- auto* wcv = static_cast<WebContentsViewAndroid*>(wc_impl->GetView());
-
- // Owned by |WebContentsViewAndroid|.
- auto select_popup = std::make_unique<SelectPopup>(env, obj, wc_impl);
- SelectPopup* select_popup_ptr = select_popup.get();
- wcv->SetSelectPopup(std::move(select_popup));
- return reinterpret_cast<intptr_t>(select_popup_ptr);
+SelectPopup::SelectPopup(WebContentsImpl* web_contents)
+ : web_contents_(web_contents) {
+ JNIEnv* env = AttachCurrentThread();
+ java_obj_ = JavaObjectWeakGlobalRef(
+ env, Java_SelectPopup_create(env, web_contents_->GetJavaWebContents(),
+ reinterpret_cast<intptr_t>(this)));
}
-SelectPopup::SelectPopup(JNIEnv* env,
- const JavaParamRef<jobject>& obj,
- WebContentsImpl* web_contents)
- : web_contents_(web_contents), java_obj_(env, obj) {}
-
SelectPopup::~SelectPopup() {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> j_obj = java_obj_.get(env);
@@ -162,11 +148,4 @@ void SelectPopup::SelectMenuItems(JNIEnv* env,
rfhi->DidSelectPopupMenuItems(selected_indices);
}
-base::android::ScopedJavaLocalRef<jobject> SelectPopup::GetWindowAndroid(
- JNIEnv* env,
- const JavaParamRef<jobject>& obj) {
- auto* window = web_contents_->GetNativeView()->GetWindowAndroid();
- return window ? window->GetJavaObject() : ScopedJavaLocalRef<jobject>();
-}
-
} // namespace content
diff --git a/chromium/content/browser/android/select_popup.h b/chromium/content/browser/android/select_popup.h
index bef949c1ae9..3ef5def0c0a 100644
--- a/chromium/content/browser/android/select_popup.h
+++ b/chromium/content/browser/android/select_popup.h
@@ -23,12 +23,7 @@ struct MenuItem;
class SelectPopup {
public:
- SelectPopup(JNIEnv* env,
- const base::android::JavaParamRef<jobject>& obj,
- WebContentsImpl* web_contents);
- base::android::ScopedJavaLocalRef<jobject> GetWindowAndroid(
- JNIEnv* env,
- const base::android::JavaParamRef<jobject>& obj);
+ explicit SelectPopup(WebContentsImpl* web_contents);
~SelectPopup();
// Creates a popup menu with |items|.
diff --git a/chromium/content/browser/android/synchronous_compositor_host.cc b/chromium/content/browser/android/synchronous_compositor_host.cc
index 953c10ab3a4..58d7822c4aa 100644
--- a/chromium/content/browser/android/synchronous_compositor_host.cc
+++ b/chromium/content/browser/android/synchronous_compositor_host.cc
@@ -504,6 +504,11 @@ void SynchronousCompositorHost::UpdateState(
renderer_param_version_ = params.version;
need_animate_scroll_ = params.need_animate_scroll;
root_scroll_offset_ = params.total_scroll_offset;
+ max_scroll_offset_ = params.max_scroll_offset;
+ scrollable_size_ = params.scrollable_size;
+ page_scale_factor_ = params.page_scale_factor;
+ min_page_scale_factor_ = params.min_page_scale_factor;
+ max_page_scale_factor_ = params.max_page_scale_factor;
invalidate_needs_draw_ |= params.invalidate_needs_draw;
if (need_invalidate_count_ != params.need_invalidate_count) {
@@ -521,15 +526,22 @@ void SynchronousCompositorHost::UpdateState(
client_->DidUpdateContent(this);
}
+ UpdateRootLayerStateOnClient();
+}
+
+void SynchronousCompositorHost::DidBecomeActive() {
+ UpdateRootLayerStateOnClient();
+}
+
+void SynchronousCompositorHost::UpdateRootLayerStateOnClient() {
// Ensure only valid values from compositor are sent to client.
// Compositor has page_scale_factor set to 0 before initialization, so check
// for that case here.
- if (params.page_scale_factor) {
+ if (page_scale_factor_) {
client_->UpdateRootLayerState(
- this, gfx::ScrollOffsetToVector2dF(params.total_scroll_offset),
- gfx::ScrollOffsetToVector2dF(params.max_scroll_offset),
- params.scrollable_size, params.page_scale_factor,
- params.min_page_scale_factor, params.max_page_scale_factor);
+ this, gfx::ScrollOffsetToVector2dF(root_scroll_offset_),
+ gfx::ScrollOffsetToVector2dF(max_scroll_offset_), scrollable_size_,
+ page_scale_factor_, min_page_scale_factor_, max_page_scale_factor_);
}
}
diff --git a/chromium/content/browser/android/synchronous_compositor_host.h b/chromium/content/browser/android/synchronous_compositor_host.h
index 6990380f9c5..3c17c46e4a6 100644
--- a/chromium/content/browser/android/synchronous_compositor_host.h
+++ b/chromium/content/browser/android/synchronous_compositor_host.h
@@ -54,6 +54,7 @@ class SynchronousCompositorHost : public SynchronousCompositor,
uint32_t layer_tree_frame_sink_id,
const std::vector<viz::ReturnedResource>& resources) override;
void SetMemoryPolicy(size_t bytes_limit) override;
+ void DidBecomeActive() override;
void DidChangeRootLayerScrollOffset(
const gfx::ScrollOffset& root_offset) override;
void SynchronouslyZoomBy(float zoom_delta, const gfx::Point& anchor) override;
@@ -102,6 +103,7 @@ class SynchronousCompositorHost : public SynchronousCompositor,
// Whether the synchronous compositor host is ready to
// handle blocking calls.
bool IsReadyForSynchronousCall();
+ void UpdateRootLayerStateOnClient();
RenderWidgetHostViewAndroid* const rwhva_;
SynchronousCompositorClient* const client_;
@@ -129,7 +131,8 @@ class SynchronousCompositorHost : public SynchronousCompositor,
// Indicates begin frames are paused from the browser.
bool begin_frame_paused_ = false;
- // Updated by both renderer and browser.
+ // Updated by both renderer and browser. This is in physical pixel when
+ // use-zoom-for-dsf is enabled, otherwise in dip.
gfx::ScrollOffset root_scroll_offset_;
// Indicates that whether OnComputeScroll is called or overridden. The
@@ -144,6 +147,12 @@ class SynchronousCompositorHost : public SynchronousCompositor,
bool invalidate_needs_draw_;
uint32_t did_activate_pending_tree_count_;
uint32_t frame_metadata_version_ = 0u;
+ // Physical pixel when use-zoom-for-dsf is enabled, otherwise in dip.
+ gfx::ScrollOffset max_scroll_offset_;
+ gfx::SizeF scrollable_size_;
+ float page_scale_factor_ = 0.f;
+ float min_page_scale_factor_ = 0.f;
+ float max_page_scale_factor_ = 0.f;
scoped_refptr<SynchronousCompositorSyncCallBridge> bridge_;
diff --git a/chromium/content/browser/android/tap_disambiguator.cc b/chromium/content/browser/android/tap_disambiguator.cc
deleted file mode 100644
index 875c128481d..00000000000
--- a/chromium/content/browser/android/tap_disambiguator.cc
+++ /dev/null
@@ -1,109 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/android/tap_disambiguator.h"
-
-#include "base/android/jni_android.h"
-#include "base/android/jni_string.h"
-#include "base/android/scoped_java_ref.h"
-#include "content/browser/renderer_host/render_widget_host_view_android.h"
-#include "content/public/browser/web_contents.h"
-#include "jni/TapDisambiguator_jni.h"
-#include "ui/gfx/android/java_bitmap.h"
-
-using base::android::AttachCurrentThread;
-using base::android::ConvertUTF8ToJavaString;
-using base::android::JavaParamRef;
-using base::android::ScopedJavaLocalRef;
-
-namespace content {
-
-namespace {
-
-ScopedJavaLocalRef<jobject> JNI_TapDisambiguator_CreateJavaRect(
- JNIEnv* env,
- const gfx::Rect& rect) {
- return ScopedJavaLocalRef<jobject>(Java_TapDisambiguator_createRect(
- env, rect.x(), rect.y(), rect.right(), rect.bottom()));
-}
-
-} // namespace
-
-jlong JNI_TapDisambiguator_Init(JNIEnv* env,
- const JavaParamRef<jobject>& obj,
- const JavaParamRef<jobject>& jweb_contents) {
- WebContents* web_contents = WebContents::FromJavaWebContents(jweb_contents);
- DCHECK(web_contents);
-
- // Owns itself and gets destroyed when |WebContentsDestroyed| is called.
- auto* tap_disambiguator = new TapDisambiguator(env, obj, web_contents);
- tap_disambiguator->Initialize();
- return reinterpret_cast<intptr_t>(tap_disambiguator);
-}
-
-TapDisambiguator::TapDisambiguator(JNIEnv* env,
- const JavaParamRef<jobject>& obj,
- WebContents* web_contents)
- : RenderWidgetHostConnector(web_contents), rwhva_(nullptr) {
- java_obj_ = JavaObjectWeakGlobalRef(env, obj);
-}
-
-TapDisambiguator::~TapDisambiguator() {
- JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jobject> obj = java_obj_.get(env);
- if (!obj.is_null())
- Java_TapDisambiguator_destroy(env, obj);
-}
-
-void TapDisambiguator::UpdateRenderProcessConnection(
- RenderWidgetHostViewAndroid* old_rwhva,
- RenderWidgetHostViewAndroid* new_rwhva) {
- if (old_rwhva)
- old_rwhva->set_tap_disambiguator(nullptr);
- if (new_rwhva)
- new_rwhva->set_tap_disambiguator(this);
- rwhva_ = new_rwhva;
-}
-
-void TapDisambiguator::ShowPopup(const gfx::Rect& rect_pixels,
- const SkBitmap& zoomed_bitmap) {
- JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jobject> obj = java_obj_.get(env);
- if (obj.is_null())
- return;
-
- ScopedJavaLocalRef<jobject> rect_object(
- JNI_TapDisambiguator_CreateJavaRect(env, rect_pixels));
-
- ScopedJavaLocalRef<jobject> java_bitmap =
- gfx::ConvertToJavaBitmap(&zoomed_bitmap);
- DCHECK(!java_bitmap.is_null());
-
- Java_TapDisambiguator_showPopup(env, obj, rect_object, java_bitmap);
-}
-
-void TapDisambiguator::HidePopup() {
- JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jobject> obj = java_obj_.get(env);
- if (obj.is_null())
- return;
- Java_TapDisambiguator_hidePopup(env, obj);
-}
-
-void TapDisambiguator::ResolveTapDisambiguation(
- JNIEnv* env,
- const JavaParamRef<jobject>& obj,
- jlong time_ms,
- jfloat x,
- jfloat y,
- jboolean is_long_press) {
- if (!rwhva_)
- return;
-
- float dip_scale = rwhva_->GetNativeView()->GetDipScale();
- rwhva_->ResolveTapDisambiguation(
- time_ms / 1000, gfx::Point(x / dip_scale, y / dip_scale), is_long_press);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/android/tap_disambiguator.h b/chromium/content/browser/android/tap_disambiguator.h
deleted file mode 100644
index 849c5b7803e..00000000000
--- a/chromium/content/browser/android/tap_disambiguator.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_ANDROID_TAP_DISAMBIGUATOR_H_
-#define CONTENT_BROWSER_ANDROID_TAP_DISAMBIGUATOR_H_
-
-#include <jni.h>
-
-#include "base/android/jni_weak_ref.h"
-#include "content/browser/android/render_widget_host_connector.h"
-#include "ui/gfx/geometry/rect_f.h"
-
-namespace content {
-
-class RenderWidgetHostViewAndroid;
-
-class TapDisambiguator : public RenderWidgetHostConnector {
- public:
- TapDisambiguator(JNIEnv* env,
- const base::android::JavaParamRef<jobject>& obj,
- WebContents* web_contents);
-
- // RendetWidgetHostConnector implementation.
- void UpdateRenderProcessConnection(
- RenderWidgetHostViewAndroid* old_rwhva,
- RenderWidgetHostViewAndroid* new_rhwva) override;
-
- // Shows the disambiguation popup
- // |rect_pixels| --> window coordinates which |zoomed_bitmap| represents
- // |zoomed_bitmap| --> magnified image of potential touch targets
- void ResolveTapDisambiguation(JNIEnv* env,
- const base::android::JavaParamRef<jobject>& obj,
- jlong time_ms,
- jfloat x,
- jfloat y,
- jboolean is_long_press);
-
- // Called from native -> java
-
- // Shows the disambiguator popup
- // |rect_pixels| --> window coordinates which |zoomed_bitmap| represents
- // |zoomed_bitmap| --> magnified image of potential touch targets
- void ShowPopup(const gfx::Rect& rect_pixels, const SkBitmap& zoomed_bitmap);
- void HidePopup();
-
- private:
- ~TapDisambiguator() override;
-
- // Current RenderWidgetHostView connected to this instance. Can be null.
- RenderWidgetHostViewAndroid* rwhva_;
- JavaObjectWeakGlobalRef java_obj_;
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_ANDROID_TAP_DISAMBIGUATOR_H_
diff --git a/chromium/content/browser/appcache/appcache.cc b/chromium/content/browser/appcache/appcache.cc
index 2e1a8046642..5390894d2ed 100644
--- a/chromium/content/browser/appcache/appcache.cc
+++ b/chromium/content/browser/appcache/appcache.cc
@@ -85,8 +85,9 @@ const AppCacheEntry* AppCache::GetEntryAndUrlWithResponseId(
return nullptr;
}
-GURL AppCache::GetNamespaceEntryUrl(const AppCacheNamespaceVector& namespaces,
- const GURL& namespace_url) const {
+GURL AppCache::GetNamespaceEntryUrl(
+ const std::vector<AppCacheNamespace>& namespaces,
+ const GURL& namespace_url) const {
size_t count = namespaces.size();
for (size_t i = 0; i < count; ++i) {
if (namespaces[i].namespace_url == namespace_url)
@@ -262,8 +263,8 @@ bool AppCache::FindResponseForRequest(const GURL& url,
return *found_network_namespace;
}
-
-void AppCache::ToResourceInfoVector(AppCacheResourceInfoVector* infos) const {
+void AppCache::ToResourceInfoVector(
+ std::vector<AppCacheResourceInfo>* infos) const {
DCHECK(infos && infos->empty());
for (const auto& pair : entries_) {
infos->push_back(AppCacheResourceInfo());
@@ -282,7 +283,7 @@ void AppCache::ToResourceInfoVector(AppCacheResourceInfoVector* infos) const {
// static
const AppCacheNamespace* AppCache::FindNamespace(
- const AppCacheNamespaceVector& namespaces,
+ const std::vector<AppCacheNamespace>& namespaces,
const GURL& url) {
size_t count = namespaces.size();
for (size_t i = 0; i < count; ++i) {
diff --git a/chromium/content/browser/appcache/appcache.h b/chromium/content/browser/appcache/appcache.h
index f468b5dea18..8e21cf3e71c 100644
--- a/chromium/content/browser/appcache/appcache.h
+++ b/chromium/content/browser/appcache/appcache.h
@@ -130,10 +130,10 @@ class CONTENT_EXPORT AppCache
bool* found_network_namespace);
// Populates the 'infos' vector with an element per entry in the appcache.
- void ToResourceInfoVector(AppCacheResourceInfoVector* infos) const;
+ void ToResourceInfoVector(std::vector<AppCacheResourceInfo>* infos) const;
static const AppCacheNamespace* FindNamespace(
- const AppCacheNamespaceVector& namespaces,
+ const std::vector<AppCacheNamespace>& namespaces,
const GURL& url);
private:
@@ -160,7 +160,7 @@ class CONTENT_EXPORT AppCache
return FindNamespace(online_whitelist_namespaces_, url) != nullptr;
}
- GURL GetNamespaceEntryUrl(const AppCacheNamespaceVector& namespaces,
+ GURL GetNamespaceEntryUrl(const std::vector<AppCacheNamespace>& namespaces,
const GURL& namespace_url) const;
// Use AppCacheHost::Associate*Cache() to manipulate host association.
@@ -175,9 +175,9 @@ class CONTENT_EXPORT AppCache
EntryMap entries_; // contains entries of all types
- AppCacheNamespaceVector intercept_namespaces_;
- AppCacheNamespaceVector fallback_namespaces_;
- AppCacheNamespaceVector online_whitelist_namespaces_;
+ std::vector<AppCacheNamespace> intercept_namespaces_;
+ std::vector<AppCacheNamespace> fallback_namespaces_;
+ std::vector<AppCacheNamespace> online_whitelist_namespaces_;
bool online_whitelist_all_;
bool is_complete_;
diff --git a/chromium/content/browser/appcache/appcache_database.cc b/chromium/content/browser/appcache/appcache_database.cc
index 0f747557abb..e3d373be53a 100644
--- a/chromium/content/browser/appcache/appcache_database.cc
+++ b/chromium/content/browser/appcache/appcache_database.cc
@@ -13,7 +13,7 @@
#include "base/strings/utf_string_conversions.h"
#include "content/browser/appcache/appcache_entry.h"
#include "content/browser/appcache/appcache_histograms.h"
-#include "sql/connection.h"
+#include "sql/database.h"
#include "sql/error_delegate_util.h"
#include "sql/meta_table.h"
#include "sql/statement.h"
@@ -156,14 +156,14 @@ const IndexInfo kIndexes[] = {
const int kTableCount = arraysize(kTables);
const int kIndexCount = arraysize(kIndexes);
-bool CreateTable(sql::Connection* db, const TableInfo& info) {
+bool CreateTable(sql::Database* db, const TableInfo& info) {
std::string sql("CREATE TABLE ");
sql += info.table_name;
sql += info.columns;
return db->Execute(sql.c_str());
}
-bool CreateIndex(sql::Connection* db, const IndexInfo& info) {
+bool CreateIndex(sql::Database* db, const IndexInfo& info) {
std::string sql;
if (info.unique)
sql += "CREATE UNIQUE INDEX ";
@@ -1042,7 +1042,7 @@ bool AppCacheDatabase::LazyOpen(bool create_if_needed) {
return false;
}
- db_.reset(new sql::Connection);
+ db_.reset(new sql::Database);
meta_table_.reset(new sql::MetaTable);
db_->set_histogram_tag("AppCache");
diff --git a/chromium/content/browser/appcache/appcache_database.h b/chromium/content/browser/appcache/appcache_database.h
index 164f6b58772..fe3e144e8ca 100644
--- a/chromium/content/browser/appcache/appcache_database.h
+++ b/chromium/content/browser/appcache/appcache_database.h
@@ -23,7 +23,7 @@
#include "url/origin.h"
namespace sql {
-class Connection;
+class Database;
class MetaTable;
class Statement;
}
@@ -190,7 +190,7 @@ class CONTENT_EXPORT AppCacheDatabase {
bool DeleteDeletableResponseIds(const std::vector<int64_t>& response_ids);
// So our callers can wrap operations in transactions.
- sql::Connection* db_connection() {
+ sql::Database* db_connection() {
LazyOpen(true);
return db_.get();
}
@@ -234,7 +234,7 @@ class CONTENT_EXPORT AppCacheDatabase {
void OnDatabaseError(int err, sql::Statement* stmt);
base::FilePath db_file_path_;
- std::unique_ptr<sql::Connection> db_;
+ std::unique_ptr<sql::Database> db_;
std::unique_ptr<sql::MetaTable> meta_table_;
std::map<int64_t, base::Time> lazy_last_access_times_;
bool is_disabled_;
diff --git a/chromium/content/browser/appcache/appcache_database_unittest.cc b/chromium/content/browser/appcache/appcache_database_unittest.cc
index 7f72b4fe59c..53b5e2e317f 100644
--- a/chromium/content/browser/appcache/appcache_database_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_database_unittest.cc
@@ -13,7 +13,7 @@
#include "base/strings/stringprintf.h"
#include "content/browser/appcache/appcache_database.h"
#include "content/browser/appcache/appcache_entry.h"
-#include "sql/connection.h"
+#include "sql/database.h"
#include "sql/meta_table.h"
#include "sql/statement.h"
#include "sql/test/scoped_error_expecter.h"
@@ -80,7 +80,7 @@ TEST(AppCacheDatabaseTest, ReCreate) {
}
#ifdef NDEBUG
-// Only run in release builds because sql::Connection and familiy
+// Only run in release builds because sql::Database and familiy
// crank up DLOG(FATAL)'ness and this test presents it with
// intentionally bad data which causes debug builds to exit instead
// of run to completion. In release builds, errors the are delivered
@@ -961,7 +961,7 @@ TEST(AppCacheDatabaseTest, UpgradeSchema4to7) {
const int kTableCount4 = arraysize(kTables4);
const int kIndexCount4 = arraysize(kIndexes4);
- sql::Connection connection;
+ sql::Database connection;
EXPECT_TRUE(connection.Open(kDbFile));
sql::Transaction transaction(&connection);
@@ -1212,7 +1212,7 @@ TEST(AppCacheDatabaseTest, UpgradeSchema5or6to7) {
const int kTableCount5 = arraysize(kTables5);
const int kIndexCount5 = arraysize(kIndexes5);
- sql::Connection connection;
+ sql::Database connection;
EXPECT_TRUE(connection.Open(kDbFile));
sql::Transaction transaction(&connection);
diff --git a/chromium/content/browser/appcache/appcache_disk_cache.cc b/chromium/content/browser/appcache/appcache_disk_cache.cc
index 8c28d1862d7..c7018934cb2 100644
--- a/chromium/content/browser/appcache/appcache_disk_cache.cc
+++ b/chromium/content/browser/appcache/appcache_disk_cache.cc
@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
+#include "base/callback_helpers.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
@@ -16,6 +17,7 @@
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "net/base/cache_type.h"
+#include "net/base/completion_repeating_callback.h"
#include "net/base/net_errors.h"
namespace content {
@@ -65,27 +67,28 @@ class AppCacheDiskCache::EntryImpl : public Entry {
int64_t offset,
net::IOBuffer* buf,
int buf_len,
- const net::CompletionCallback& callback) override {
+ net::CompletionOnceCallback callback) override {
if (offset < 0 || offset > std::numeric_limits<int32_t>::max())
return net::ERR_INVALID_ARGUMENT;
if (!disk_cache_entry_)
return net::ERR_ABORTED;
- return disk_cache_entry_->ReadData(
- index, static_cast<int>(offset), buf, buf_len, callback);
+ return disk_cache_entry_->ReadData(index, static_cast<int>(offset), buf,
+ buf_len, std::move(callback));
}
int Write(int index,
int64_t offset,
net::IOBuffer* buf,
int buf_len,
- const net::CompletionCallback& callback) override {
+ net::CompletionOnceCallback callback) override {
if (offset < 0 || offset > std::numeric_limits<int32_t>::max())
return net::ERR_INVALID_ARGUMENT;
if (!disk_cache_entry_)
return net::ERR_ABORTED;
const bool kTruncate = true;
- return disk_cache_entry_->WriteData(
- index, static_cast<int>(offset), buf, buf_len, callback, kTruncate);
+ return disk_cache_entry_->WriteData(index, static_cast<int>(offset), buf,
+ buf_len, std::move(callback),
+ kTruncate);
}
int64_t GetSize(int index) override {
@@ -122,35 +125,35 @@ class AppCacheDiskCache::ActiveCall
static int CreateEntry(const base::WeakPtr<AppCacheDiskCache>& owner,
int64_t key,
Entry** entry,
- const net::CompletionCallback& callback) {
+ net::CompletionOnceCallback callback) {
scoped_refptr<ActiveCall> active_call(
- new ActiveCall(owner, entry, callback));
+ new ActiveCall(owner, entry, std::move(callback)));
int rv = owner->disk_cache()->CreateEntry(
base::Int64ToString(key), net::HIGHEST, &active_call->entry_ptr_,
- base::Bind(&ActiveCall::OnAsyncCompletion, active_call));
+ base::BindOnce(&ActiveCall::OnAsyncCompletion, active_call));
return active_call->HandleImmediateReturnValue(rv);
}
static int OpenEntry(const base::WeakPtr<AppCacheDiskCache>& owner,
int64_t key,
Entry** entry,
- const net::CompletionCallback& callback) {
+ net::CompletionOnceCallback callback) {
scoped_refptr<ActiveCall> active_call(
- new ActiveCall(owner, entry, callback));
+ new ActiveCall(owner, entry, std::move(callback)));
int rv = owner->disk_cache()->OpenEntry(
base::Int64ToString(key), net::HIGHEST, &active_call->entry_ptr_,
- base::Bind(&ActiveCall::OnAsyncCompletion, active_call));
+ base::BindOnce(&ActiveCall::OnAsyncCompletion, active_call));
return active_call->HandleImmediateReturnValue(rv);
}
static int DoomEntry(const base::WeakPtr<AppCacheDiskCache>& owner,
int64_t key,
- const net::CompletionCallback& callback) {
+ net::CompletionOnceCallback callback) {
scoped_refptr<ActiveCall> active_call(
- new ActiveCall(owner, nullptr, callback));
+ new ActiveCall(owner, nullptr, std::move(callback)));
int rv = owner->disk_cache()->DoomEntry(
base::Int64ToString(key), net::HIGHEST,
- base::Bind(&ActiveCall::OnAsyncCompletion, active_call));
+ base::BindOnce(&ActiveCall::OnAsyncCompletion, active_call));
return active_call->HandleImmediateReturnValue(rv);
}
@@ -159,10 +162,10 @@ class AppCacheDiskCache::ActiveCall
ActiveCall(const base::WeakPtr<AppCacheDiskCache>& owner,
Entry** entry,
- const net::CompletionCallback& callback)
+ net::CompletionOnceCallback callback)
: owner_(owner),
entry_(entry),
- callback_(callback),
+ callback_(std::move(callback)),
entry_ptr_(nullptr) {
DCHECK(owner_);
}
@@ -192,12 +195,12 @@ class AppCacheDiskCache::ActiveCall
rv = net::ERR_ABORTED;
}
}
- callback_.Run(rv);
+ std::move(callback_).Run(rv);
}
base::WeakPtr<AppCacheDiskCache> owner_;
Entry** entry_;
- net::CompletionCallback callback_;
+ net::CompletionOnceCallback callback_;
disk_cache::Entry* entry_ptr_;
};
@@ -219,15 +222,16 @@ int AppCacheDiskCache::InitWithDiskBackend(
int disk_cache_size,
bool force,
base::OnceClosure post_cleanup_callback,
- const net::CompletionCallback& callback) {
+ net::CompletionOnceCallback callback) {
return Init(net::APP_CACHE, disk_cache_directory, disk_cache_size, force,
- std::move(post_cleanup_callback), callback);
+ std::move(post_cleanup_callback), std::move(callback));
}
int AppCacheDiskCache::InitWithMemBackend(
- int mem_cache_size, const net::CompletionCallback& callback) {
+ int mem_cache_size,
+ net::CompletionOnceCallback callback) {
return Init(net::MEMORY_CACHE, base::FilePath(), mem_cache_size, false,
- base::OnceClosure(), callback);
+ base::OnceClosure(), std::move(callback));
}
void AppCacheDiskCache::Disable() {
@@ -254,59 +258,63 @@ void AppCacheDiskCache::Disable() {
int AppCacheDiskCache::CreateEntry(int64_t key,
Entry** entry,
- const net::CompletionCallback& callback) {
+ net::CompletionOnceCallback callback) {
DCHECK(entry);
DCHECK(!callback.is_null());
if (is_disabled_)
return net::ERR_ABORTED;
if (is_initializing_or_waiting_to_initialize()) {
- pending_calls_.push_back(PendingCall(CREATE, key, entry, callback));
+ pending_calls_.push_back(
+ PendingCall(CREATE, key, entry, std::move(callback)));
return net::ERR_IO_PENDING;
}
if (!disk_cache_)
return net::ERR_FAILED;
- return ActiveCall::CreateEntry(
- weak_factory_.GetWeakPtr(), key, entry, callback);
+ return ActiveCall::CreateEntry(weak_factory_.GetWeakPtr(), key, entry,
+ std::move(callback));
}
int AppCacheDiskCache::OpenEntry(int64_t key,
Entry** entry,
- const net::CompletionCallback& callback) {
+ net::CompletionOnceCallback callback) {
DCHECK(entry);
DCHECK(!callback.is_null());
if (is_disabled_)
return net::ERR_ABORTED;
if (is_initializing_or_waiting_to_initialize()) {
- pending_calls_.push_back(PendingCall(OPEN, key, entry, callback));
+ pending_calls_.push_back(
+ PendingCall(OPEN, key, entry, std::move(callback)));
return net::ERR_IO_PENDING;
}
if (!disk_cache_)
return net::ERR_FAILED;
- return ActiveCall::OpenEntry(
- weak_factory_.GetWeakPtr(), key, entry, callback);
+ return ActiveCall::OpenEntry(weak_factory_.GetWeakPtr(), key, entry,
+ std::move(callback));
}
int AppCacheDiskCache::DoomEntry(int64_t key,
- const net::CompletionCallback& callback) {
+ net::CompletionOnceCallback callback) {
DCHECK(!callback.is_null());
if (is_disabled_)
return net::ERR_ABORTED;
if (is_initializing_or_waiting_to_initialize()) {
- pending_calls_.push_back(PendingCall(DOOM, key, nullptr, callback));
+ pending_calls_.push_back(
+ PendingCall(DOOM, key, nullptr, std::move(callback)));
return net::ERR_IO_PENDING;
}
if (!disk_cache_)
return net::ERR_FAILED;
- return ActiveCall::DoomEntry(weak_factory_.GetWeakPtr(), key, callback);
+ return ActiveCall::DoomEntry(weak_factory_.GetWeakPtr(), key,
+ std::move(callback));
}
AppCacheDiskCache::AppCacheDiskCache(bool use_simple_cache)
@@ -323,10 +331,13 @@ AppCacheDiskCache::PendingCall::PendingCall(
PendingCallType call_type,
int64_t key,
Entry** entry,
- const net::CompletionCallback& callback)
- : call_type(call_type), key(key), entry(entry), callback(callback) {}
+ net::CompletionOnceCallback callback)
+ : call_type(call_type),
+ key(key),
+ entry(entry),
+ callback(std::move(callback)) {}
-AppCacheDiskCache::PendingCall::PendingCall(const PendingCall& other) = default;
+AppCacheDiskCache::PendingCall::PendingCall(PendingCall&& other) = default;
AppCacheDiskCache::PendingCall::~PendingCall() {}
@@ -335,7 +346,7 @@ int AppCacheDiskCache::Init(net::CacheType cache_type,
int cache_size,
bool force,
base::OnceClosure post_cleanup_callback,
- const net::CompletionCallback& callback) {
+ net::CompletionOnceCallback callback) {
DCHECK(!is_initializing_or_waiting_to_initialize() && !disk_cache_.get());
is_disabled_ = false;
create_backend_callback_ = new CreateBackendCallbackShim(this);
@@ -347,10 +358,10 @@ int AppCacheDiskCache::Init(net::CacheType cache_type,
cache_directory, cache_size, force, nullptr,
&(create_backend_callback_->backend_ptr_),
std::move(post_cleanup_callback),
- base::Bind(&CreateBackendCallbackShim::Callback,
- create_backend_callback_));
+ base::BindOnce(&CreateBackendCallbackShim::Callback,
+ create_backend_callback_));
if (rv == net::ERR_IO_PENDING)
- init_callback_ = callback;
+ init_callback_ = std::move(callback);
else
OnCreateBackendComplete(rv);
return rv;
@@ -364,29 +375,31 @@ void AppCacheDiskCache::OnCreateBackendComplete(int rv) {
// Invoke our clients callback function.
if (!init_callback_.is_null()) {
- init_callback_.Run(rv);
- init_callback_.Reset();
+ std::move(init_callback_).Run(rv);
}
// Service pending calls that were queued up while we were initializing.
- for (const auto& call : pending_calls_) {
+ for (auto& call : pending_calls_) {
+ // This is safe, because the callback will only be called once.
+ net::CompletionRepeatingCallback copyable_callback =
+ base::AdaptCallbackForRepeating(std::move(call.callback));
rv = net::ERR_FAILED;
switch (call.call_type) {
case CREATE:
- rv = CreateEntry(call.key, call.entry, call.callback);
+ rv = CreateEntry(call.key, call.entry, copyable_callback);
break;
case OPEN:
- rv = OpenEntry(call.key, call.entry, call.callback);
+ rv = OpenEntry(call.key, call.entry, copyable_callback);
break;
case DOOM:
- rv = DoomEntry(call.key, call.callback);
+ rv = DoomEntry(call.key, copyable_callback);
break;
default:
NOTREACHED();
break;
}
if (rv != net::ERR_IO_PENDING)
- call.callback.Run(rv);
+ copyable_callback.Run(rv);
}
pending_calls_.clear();
}
diff --git a/chromium/content/browser/appcache/appcache_disk_cache.h b/chromium/content/browser/appcache/appcache_disk_cache.h
index 5eba6053397..73bccf9d2f9 100644
--- a/chromium/content/browser/appcache/appcache_disk_cache.h
+++ b/chromium/content/browser/appcache/appcache_disk_cache.h
@@ -15,6 +15,7 @@
#include "base/memory/ref_counted.h"
#include "content/browser/appcache/appcache_response.h"
#include "content/common/content_export.h"
+#include "net/base/completion_once_callback.h"
#include "net/disk_cache/disk_cache.h"
namespace content {
@@ -32,23 +33,23 @@ class CONTENT_EXPORT AppCacheDiskCache
int disk_cache_size,
bool force,
base::OnceClosure post_cleanup_callback,
- const net::CompletionCallback& callback);
+ net::CompletionOnceCallback callback);
// Initializes the object to use memory only storage.
// This is used for Chrome's incognito browsing.
int InitWithMemBackend(int disk_cache_size,
- const net::CompletionCallback& callback);
+ net::CompletionOnceCallback callback);
void Disable();
bool is_disabled() const { return is_disabled_; }
int CreateEntry(int64_t key,
Entry** entry,
- const net::CompletionCallback& callback) override;
+ net::CompletionOnceCallback callback) override;
int OpenEntry(int64_t key,
Entry** entry,
- const net::CompletionCallback& callback) override;
- int DoomEntry(int64_t key, const net::CompletionCallback& callback) override;
+ net::CompletionOnceCallback callback) override;
+ int DoomEntry(int64_t key, net::CompletionOnceCallback callback) override;
void set_is_waiting_to_initialize(bool is_waiting_to_initialize) {
is_waiting_to_initialize_ = is_waiting_to_initialize;
@@ -73,21 +74,19 @@ class CONTENT_EXPORT AppCacheDiskCache
DOOM
};
struct PendingCall {
- PendingCallType call_type;
- int64_t key;
- Entry** entry;
- net::CompletionCallback callback;
-
PendingCall();
-
PendingCall(PendingCallType call_type,
int64_t key,
Entry** entry,
- const net::CompletionCallback& callback);
-
- PendingCall(const PendingCall& other);
+ net::CompletionOnceCallback callback);
+ PendingCall(PendingCall&& other);
~PendingCall();
+
+ PendingCallType call_type;
+ int64_t key;
+ Entry** entry;
+ net::CompletionOnceCallback callback;
};
using PendingCalls = std::vector<PendingCall>;
@@ -104,7 +103,7 @@ class CONTENT_EXPORT AppCacheDiskCache
int cache_size,
bool force,
base::OnceClosure post_cleanup_callback,
- const net::CompletionCallback& callback);
+ net::CompletionOnceCallback callback);
void OnCreateBackendComplete(int rv);
void AddOpenEntry(EntryImpl* entry) { open_entries_.insert(entry); }
void RemoveOpenEntry(EntryImpl* entry) { open_entries_.erase(entry); }
@@ -112,7 +111,7 @@ class CONTENT_EXPORT AppCacheDiskCache
bool use_simple_cache_;
bool is_disabled_;
bool is_waiting_to_initialize_;
- net::CompletionCallback init_callback_;
+ net::CompletionOnceCallback init_callback_;
scoped_refptr<CreateBackendCallbackShim> create_backend_callback_;
PendingCalls pending_calls_;
OpenEntries open_entries_;
diff --git a/chromium/content/browser/appcache/appcache_disk_cache_unittest.cc b/chromium/content/browser/appcache/appcache_disk_cache_unittest.cc
index 321ad52d4f1..f6e4cf492d9 100644
--- a/chromium/content/browser/appcache/appcache_disk_cache_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_disk_cache_unittest.cc
@@ -10,6 +10,7 @@
#include "base/single_thread_task_runner.h"
#include "base/test/scoped_task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "net/base/completion_repeating_callback.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/base/test_completion_callback.h"
@@ -24,9 +25,8 @@ class AppCacheDiskCacheTest : public testing::Test {
void SetUp() override {
ASSERT_TRUE(directory_.CreateUniqueTempDir());
- completion_callback_ = base::Bind(
- &AppCacheDiskCacheTest::OnComplete,
- base::Unretained(this));
+ completion_callback_ = base::BindRepeating(
+ &AppCacheDiskCacheTest::OnComplete, base::Unretained(this));
}
void TearDown() override { scoped_task_environment_.RunUntilIdle(); }
@@ -42,7 +42,7 @@ class AppCacheDiskCacheTest : public testing::Test {
base::test::ScopedTaskEnvironment scoped_task_environment_;
base::ScopedTempDir directory_;
- net::CompletionCallback completion_callback_;
+ net::CompletionRepeatingCallback completion_callback_;
std::vector<int> completion_results_;
static const int k10MBytes = 10 * 1024 * 1024;
diff --git a/chromium/content/browser/appcache/appcache_dispatcher_host.cc b/chromium/content/browser/appcache/appcache_dispatcher_host.cc
index 966ab0e1271..479fddbd61b 100644
--- a/chromium/content/browser/appcache/appcache_dispatcher_host.cc
+++ b/chromium/content/browser/appcache/appcache_dispatcher_host.cc
@@ -89,7 +89,7 @@ void AppCacheDispatcherHost::SelectCache(int32_t host_id,
mojo::ReportBadMessage("ACDH_SELECT_CACHE");
}
} else {
- frontend_proxy_.OnCacheSelected(host_id, std::move(AppCacheInfo()));
+ frontend_proxy_.OnCacheSelected(host_id, AppCacheInfo());
}
}
@@ -99,7 +99,7 @@ void AppCacheDispatcherHost::SelectCacheForSharedWorker(int32_t host_id,
if (!backend_impl_.SelectCacheForSharedWorker(host_id, appcache_id))
mojo::ReportBadMessage("ACDH_SELECT_CACHE_FOR_SHARED_WORKER");
} else {
- frontend_proxy_.OnCacheSelected(host_id, std::move(AppCacheInfo()));
+ frontend_proxy_.OnCacheSelected(host_id, AppCacheInfo());
}
}
diff --git a/chromium/content/browser/appcache/appcache_group.cc b/chromium/content/browser/appcache/appcache_group.cc
index 85e6be0e7e7..6a83480f298 100644
--- a/chromium/content/browser/appcache/appcache_group.cc
+++ b/chromium/content/browser/appcache/appcache_group.cc
@@ -114,9 +114,9 @@ void AppCacheGroup::AddCache(AppCache* complete_cache) {
void AppCacheGroup::RemoveCache(AppCache* cache) {
DCHECK(cache->associated_hosts().empty());
if (cache == newest_complete_cache_) {
- CancelUpdate();
AppCache* tmp_cache = newest_complete_cache_;
newest_complete_cache_ = nullptr;
+ CancelUpdate();
tmp_cache->set_owning_group(nullptr); // may cause this group to be deleted
} else {
scoped_refptr<AppCacheGroup> protect(this);
@@ -227,7 +227,7 @@ void AppCacheGroup::RunQueuedUpdates() {
// static
bool AppCacheGroup::FindObserver(
const UpdateObserver* find_me,
- const base::ObserverList<UpdateObserver>& observer_list) {
+ const base::ObserverList<UpdateObserver>::Unchecked& observer_list) {
return observer_list.HasObserver(find_me);
}
diff --git a/chromium/content/browser/appcache/appcache_group.h b/chromium/content/browser/appcache/appcache_group.h
index c119f59274d..9d20a731566 100644
--- a/chromium/content/browser/appcache/appcache_group.h
+++ b/chromium/content/browser/appcache/appcache_group.h
@@ -145,7 +145,7 @@ class CONTENT_EXPORT AppCacheGroup
void RunQueuedUpdates();
static bool FindObserver(
const UpdateObserver* find_me,
- const base::ObserverList<UpdateObserver>& observer_list);
+ const base::ObserverList<UpdateObserver>::Unchecked& observer_list);
void ScheduleUpdateRestart(int delay_ms);
void HostDestructionImminent(AppCacheHost* host);
@@ -179,11 +179,11 @@ class CONTENT_EXPORT AppCacheGroup
AppCacheStorage* storage_;
// List of objects observing this group.
- base::ObserverList<UpdateObserver> observers_;
+ base::ObserverList<UpdateObserver>::Unchecked observers_;
// Updates that have been queued for the next run.
QueuedUpdates queued_updates_;
- base::ObserverList<UpdateObserver> queued_observers_;
+ base::ObserverList<UpdateObserver>::Unchecked queued_observers_;
base::CancelableClosure restart_update_task_;
std::unique_ptr<HostObserver> host_observer_;
diff --git a/chromium/content/browser/appcache/appcache_histograms.cc b/chromium/content/browser/appcache/appcache_histograms.cc
index 6027c8c650a..110ffdf5261 100644
--- a/chromium/content/browser/appcache/appcache_histograms.cc
+++ b/chromium/content/browser/appcache/appcache_histograms.cc
@@ -132,21 +132,6 @@ void AppCacheHistograms::AddCompletionRunTimeSample(
UMA_HISTOGRAM_TIMES("appcache.CompletionRunTime", duration);
}
-void AppCacheHistograms::AddNetworkJobStartDelaySample(
- const base::TimeDelta& duration) {
- UMA_HISTOGRAM_TIMES("appcache.JobStartDelay.Network", duration);
-}
-
-void AppCacheHistograms::AddErrorJobStartDelaySample(
- const base::TimeDelta& duration) {
- UMA_HISTOGRAM_TIMES("appcache.JobStartDelay.Error", duration);
-}
-
-void AppCacheHistograms::AddAppCacheJobStartDelaySample(
- const base::TimeDelta& duration) {
- UMA_HISTOGRAM_TIMES("appcache.JobStartDelay.AppCache", duration);
-}
-
void AppCacheHistograms::AddMissingManifestEntrySample() {
UMA_HISTOGRAM_BOOLEAN("appcache.MissingManifestEntry", true);
}
diff --git a/chromium/content/browser/appcache/appcache_histograms.h b/chromium/content/browser/appcache/appcache_histograms.h
index 043d6d9a4fc..6414d9f3edc 100644
--- a/chromium/content/browser/appcache/appcache_histograms.h
+++ b/chromium/content/browser/appcache/appcache_histograms.h
@@ -46,9 +46,6 @@ class AppCacheHistograms {
static void AddTaskRunTimeSample(const base::TimeDelta& duration);
static void AddCompletionQueueTimeSample(const base::TimeDelta& duration);
static void AddCompletionRunTimeSample(const base::TimeDelta& duration);
- static void AddNetworkJobStartDelaySample(const base::TimeDelta& duration);
- static void AddErrorJobStartDelaySample(const base::TimeDelta& duration);
- static void AddAppCacheJobStartDelaySample(const base::TimeDelta& duration);
static void AddMissingManifestEntrySample();
enum MissingManifestCallsiteType {
diff --git a/chromium/content/browser/appcache/appcache_host.cc b/chromium/content/browser/appcache/appcache_host.cc
index 2b27d83d316..f82d1f76585 100644
--- a/chromium/content/browser/appcache/appcache_host.cc
+++ b/chromium/content/browser/appcache/appcache_host.cc
@@ -4,6 +4,8 @@
#include "content/browser/appcache/appcache_host.h"
+#include <vector>
+
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/strings/string_util.h"
@@ -24,29 +26,31 @@ namespace content {
namespace {
-void FillCacheInfo(const AppCache* cache,
- const GURL& manifest_url,
- AppCacheStatus status, AppCacheInfo* info) {
- info->manifest_url = manifest_url;
- info->status = status;
+AppCacheInfo CreateCacheInfo(const AppCache* cache,
+ const GURL& manifest_url,
+ AppCacheStatus status) {
+ AppCacheInfo info;
+ info.manifest_url = manifest_url;
+ info.status = status;
if (!cache)
- return;
+ return info;
- info->cache_id = cache->cache_id();
+ info.cache_id = cache->cache_id();
if (!cache->is_complete())
- return;
+ return info;
DCHECK(cache->owning_group());
- info->is_complete = true;
- info->group_id = cache->owning_group()->group_id();
- info->last_update_time = cache->update_time();
- info->creation_time = cache->owning_group()->creation_time();
- info->size = cache->cache_size();
+ info.is_complete = true;
+ info.group_id = cache->owning_group()->group_id();
+ info.last_update_time = cache->update_time();
+ info.creation_time = cache->owning_group()->creation_time();
+ info.size = cache->cache_size();
+ return info;
}
-} // Anonymous namespace
+} // namespace
AppCacheHost::AppCacheHost(int host_id,
AppCacheFrontend* frontend,
@@ -317,7 +321,7 @@ std::unique_ptr<AppCacheRequestHandler> AppCacheHost::CreateRequestHandler(
}
void AppCacheHost::GetResourceList(
- AppCacheResourceInfoVector* resource_infos) {
+ std::vector<AppCacheResourceInfo>* resource_infos) {
if (associated_cache_.get() && associated_cache_->is_complete())
associated_cache_->ToResourceInfoVector(resource_infos);
}
@@ -463,9 +467,8 @@ void AppCacheHost::OnUpdateComplete(AppCacheGroup* group) {
if (associated_cache_info_pending_ && associated_cache_.get() &&
associated_cache_->is_complete()) {
- AppCacheInfo info;
- FillCacheInfo(
- associated_cache_.get(), preferred_manifest_url_, GetStatus(), &info);
+ AppCacheInfo info = CreateCacheInfo(associated_cache_.get(),
+ preferred_manifest_url_, GetStatus());
associated_cache_info_pending_ = false;
// In the network service world, we need to pass the URLLoaderFactory
// instance to the renderer which it can use to request subresources.
@@ -562,11 +565,10 @@ void AppCacheHost::AssociateCacheHelper(AppCache* cache,
associated_cache_ = cache;
SetSwappableCache(cache ? cache->owning_group() : nullptr);
associated_cache_info_pending_ = cache && !cache->is_complete();
- AppCacheInfo info;
if (cache)
cache->AssociateHost(this);
- FillCacheInfo(cache, manifest_url, GetStatus(), &info);
+ AppCacheInfo info = CreateCacheInfo(cache, manifest_url, GetStatus());
// In the network service world, we need to pass the URLLoaderFactory
// instance to the renderer which it can use to request subresources.
// This ensures that they can be served out of the AppCache.
diff --git a/chromium/content/browser/appcache/appcache_host.h b/chromium/content/browser/appcache/appcache_host.h
index e5d29763fda..ee149def125 100644
--- a/chromium/content/browser/appcache/appcache_host.h
+++ b/chromium/content/browser/appcache/appcache_host.h
@@ -340,7 +340,7 @@ class CONTENT_EXPORT AppCacheHost
bool associated_cache_info_pending_;
// List of objects observing us.
- base::ObserverList<Observer> observers_;
+ base::ObserverList<Observer>::Unchecked observers_;
// Used to inform the QuotaManager of what origins are currently in use.
url::Origin origin_in_use_;
diff --git a/chromium/content/browser/appcache/appcache_host_unittest.cc b/chromium/content/browser/appcache/appcache_host_unittest.cc
index 85c35283e29..64f9bcfec8d 100644
--- a/chromium/content/browser/appcache/appcache_host_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_host_unittest.cc
@@ -180,8 +180,8 @@ TEST_F(AppCacheHostTest, Basic) {
}
TEST_F(AppCacheHostTest, SelectNoCache) {
- scoped_refptr<MockQuotaManagerProxy> mock_quota_proxy(
- new MockQuotaManagerProxy);
+ scoped_refptr<MockQuotaManagerProxy> mock_quota_proxy =
+ base::MakeRefCounted<MockQuotaManagerProxy>();
service_.set_quota_manager_proxy(mock_quota_proxy.get());
// Reset our mock frontend
@@ -255,7 +255,8 @@ TEST_F(AppCacheHostTest, ForeignFallbackEntry) {
// Precondition, a cache with a fallback entry that is not marked as foreign.
const int kCacheId = 22;
const GURL kFallbackURL("http://origin/fallback_resource");
- scoped_refptr<AppCache> cache = new AppCache(service_.storage(), kCacheId);
+ scoped_refptr<AppCache> cache =
+ base::MakeRefCounted<AppCache>(service_.storage(), kCacheId);
cache->AddEntry(kFallbackURL, AppCacheEntry(AppCacheEntry::FALLBACK));
AppCacheHost host(1, &mock_frontend_, &service_);
@@ -341,20 +342,22 @@ TEST_F(AppCacheHostTest, SetSwappableCache) {
host.SetSwappableCache(nullptr);
EXPECT_FALSE(host.swappable_cache_.get());
- scoped_refptr<AppCacheGroup> group1(new AppCacheGroup(
- service_.storage(), GURL(), service_.storage()->NewGroupId()));
+ const GURL kGroup1ManifestUrl("http://bar.com");
+ scoped_refptr<AppCacheGroup> group1 = base::MakeRefCounted<AppCacheGroup>(
+ service_.storage(), kGroup1ManifestUrl, service_.storage()->NewGroupId());
host.SetSwappableCache(group1.get());
EXPECT_FALSE(host.swappable_cache_.get());
- AppCache* cache1 = new AppCache(service_.storage(), 111);
+ scoped_refptr<AppCache> cache1 =
+ base::MakeRefCounted<AppCache>(service_.storage(), 111);
cache1->set_complete(true);
- group1->AddCache(cache1);
+ group1->AddCache(cache1.get());
host.SetSwappableCache(group1.get());
EXPECT_EQ(cache1, host.swappable_cache_.get());
mock_frontend_.last_host_id_ = -222; // to verify we received OnCacheSelected
- host.AssociateCompleteCache(cache1);
+ host.AssociateCompleteCache(cache1.get());
EXPECT_FALSE(host.swappable_cache_.get()); // was same as associated cache
EXPECT_EQ(AppCacheStatus::APPCACHE_STATUS_IDLE, host.GetStatus());
// verify OnCacheSelected was called
@@ -362,41 +365,52 @@ TEST_F(AppCacheHostTest, SetSwappableCache) {
EXPECT_EQ(cache1->cache_id(), mock_frontend_.last_cache_id_);
EXPECT_EQ(AppCacheStatus::APPCACHE_STATUS_IDLE, mock_frontend_.last_status_);
- AppCache* cache2 = new AppCache(service_.storage(), 222);
+ scoped_refptr<AppCache> cache2 =
+ base::MakeRefCounted<AppCache>(service_.storage(), 222);
cache2->set_complete(true);
- group1->AddCache(cache2);
- EXPECT_EQ(cache2, host.swappable_cache_.get()); // updated to newest
-
- scoped_refptr<AppCacheGroup> group2(
- new AppCacheGroup(service_.storage(), GURL("http://foo.com"),
- service_.storage()->NewGroupId()));
- AppCache* cache3 = new AppCache(service_.storage(), 333);
+ group1->AddCache(cache2.get());
+ EXPECT_EQ(cache2.get(), host.swappable_cache_.get()); // updated to newest
+
+ const GURL kGroup2ManifestUrl("http://foo.com/");
+ scoped_refptr<AppCacheGroup> group2 = base::MakeRefCounted<AppCacheGroup>(
+ service_.storage(), kGroup2ManifestUrl, service_.storage()->NewGroupId());
+ scoped_refptr<AppCache> cache3 =
+ base::MakeRefCounted<AppCache>(service_.storage(), 333);
cache3->set_complete(true);
- group2->AddCache(cache3);
+ group2->AddCache(cache3.get());
- AppCache* cache4 = new AppCache(service_.storage(), 444);
+ scoped_refptr<AppCache> cache4 =
+ base::MakeRefCounted<AppCache>(service_.storage(), 444);
cache4->set_complete(true);
- group2->AddCache(cache4);
- EXPECT_EQ(cache2, host.swappable_cache_.get()); // unchanged
+ group2->AddCache(cache4.get());
+ EXPECT_EQ(cache2.get(), host.swappable_cache_.get()); // unchanged
- host.AssociateCompleteCache(cache3);
- EXPECT_EQ(cache4, host.swappable_cache_.get()); // newest cache in group2
+ cache1.reset();
+ cache2.reset();
+
+ host.AssociateCompleteCache(cache3.get());
+ EXPECT_EQ(cache4.get(),
+ host.swappable_cache_.get()); // newest cache in group2
EXPECT_FALSE(group1->HasCache()); // both caches in group1 have refcount 0
- host.AssociateNoCache(GURL());
+ cache3.reset();
+ cache4.reset();
+
+ host.AssociateNoCache(kGroup1ManifestUrl);
EXPECT_FALSE(host.swappable_cache_.get());
EXPECT_FALSE(group2->HasCache()); // both caches in group2 have refcount 0
// Host adds reference to newest cache when an update is complete.
- AppCache* cache5 = new AppCache(service_.storage(), 555);
+ scoped_refptr<AppCache> cache5 =
+ base::MakeRefCounted<AppCache>(service_.storage(), 555);
cache5->set_complete(true);
- group2->AddCache(cache5);
+ group2->AddCache(cache5.get());
host.group_being_updated_ = group2;
host.OnUpdateComplete(group2.get());
EXPECT_FALSE(host.group_being_updated_.get());
- EXPECT_EQ(cache5, host.swappable_cache_.get());
+ EXPECT_EQ(cache5.get(), host.swappable_cache_.get());
- group2->RemoveCache(cache5);
+ group2->RemoveCache(cache5.get());
EXPECT_FALSE(group2->HasCache());
host.group_being_updated_ = group2;
host.OnUpdateComplete(group2.get());
@@ -405,8 +419,8 @@ TEST_F(AppCacheHostTest, SetSwappableCache) {
}
TEST_F(AppCacheHostTest, SelectCacheAllowed) {
- scoped_refptr<MockQuotaManagerProxy> mock_quota_proxy(
- new MockQuotaManagerProxy);
+ scoped_refptr<MockQuotaManagerProxy> mock_quota_proxy =
+ base::MakeRefCounted<MockQuotaManagerProxy>();
MockAppCachePolicy mock_appcache_policy;
mock_appcache_policy.can_create_return_value_ = true;
service_.set_quota_manager_proxy(mock_quota_proxy.get());
@@ -446,8 +460,8 @@ TEST_F(AppCacheHostTest, SelectCacheAllowed) {
}
TEST_F(AppCacheHostTest, SelectCacheBlocked) {
- scoped_refptr<MockQuotaManagerProxy> mock_quota_proxy(
- new MockQuotaManagerProxy);
+ scoped_refptr<MockQuotaManagerProxy> mock_quota_proxy =
+ base::MakeRefCounted<MockQuotaManagerProxy>();
MockAppCachePolicy mock_appcache_policy;
mock_appcache_policy.can_create_return_value_ = false;
service_.set_quota_manager_proxy(mock_quota_proxy.get());
diff --git a/chromium/content/browser/appcache/appcache_internals_ui.cc b/chromium/content/browser/appcache/appcache_internals_ui.cc
index f33713440f4..d95dcaf3494 100644
--- a/chromium/content/browser/appcache/appcache_internals_ui.cc
+++ b/chromium/content/browser/appcache/appcache_internals_ui.cc
@@ -127,7 +127,7 @@ GetDictionaryValueForAppCacheResourceInfo(
}
std::unique_ptr<base::ListValue> GetListValueForAppCacheResourceInfoVector(
- AppCacheResourceInfoVector* resource_info_vector) {
+ std::vector<AppCacheResourceInfo>* resource_info_vector) {
std::unique_ptr<base::ListValue> list(new base::ListValue);
for (const AppCacheResourceInfo& res_info : *resource_info_vector)
list->Append(GetDictionaryValueForAppCacheResourceInfo(res_info));
@@ -238,9 +238,9 @@ void AppCacheInternalsUI::Proxy::RequestAppCacheDetails(
void AppCacheInternalsUI::Proxy::OnGroupLoaded(AppCacheGroup* appcache_group,
const GURL& manifest_gurl) {
- std::unique_ptr<AppCacheResourceInfoVector> resource_info_vector;
+ std::unique_ptr<std::vector<AppCacheResourceInfo>> resource_info_vector;
if (appcache_group && appcache_group->newest_complete_cache()) {
- resource_info_vector.reset(new AppCacheResourceInfoVector);
+ resource_info_vector.reset(new std::vector<AppCacheResourceInfo>);
appcache_group->newest_complete_cache()->ToResourceInfoVector(
resource_info_vector.get());
std::sort(resource_info_vector->begin(), resource_info_vector->end(),
@@ -445,7 +445,7 @@ void AppCacheInternalsUI::OnAppCacheInfoDeleted(
void AppCacheInternalsUI::OnAppCacheDetailsReady(
const base::FilePath& partition_path,
const std::string& manifest_url,
- std::unique_ptr<AppCacheResourceInfoVector> resource_info_vector) {
+ std::unique_ptr<std::vector<AppCacheResourceInfo>> resource_info_vector) {
if (resource_info_vector) {
web_ui()->CallJavascriptFunctionUnsafe(
kFunctionOnAppCacheDetailsReady, base::Value(manifest_url),
@@ -464,25 +464,22 @@ void AppCacheInternalsUI::OnFileDetailsReady(
scoped_refptr<net::IOBuffer> response_data,
int data_length) {
std::string headers;
- if (response_info->http_response_info()) {
- headers.append("<hr><pre>");
- headers.append(net::EscapeForHTML(
- response_info->http_response_info()->headers->GetStatusLine()));
+ headers.append("<hr><pre>");
+ headers.append(net::EscapeForHTML(
+ response_info->http_response_info().headers->GetStatusLine()));
+ headers.push_back('\n');
+
+ size_t iter = 0;
+ std::string name, value;
+ while (response_info->http_response_info().headers->EnumerateHeaderLines(
+ &iter, &name, &value)) {
+ headers.append(net::EscapeForHTML(name));
+ headers.append(": ");
+ headers.append(net::EscapeForHTML(value));
headers.push_back('\n');
-
- size_t iter = 0;
- std::string name, value;
- while (response_info->http_response_info()->headers->EnumerateHeaderLines(
- &iter, &name, &value)) {
- headers.append(net::EscapeForHTML(name));
- headers.append(": ");
- headers.append(net::EscapeForHTML(value));
- headers.push_back('\n');
- }
- headers.append("</pre>");
- } else {
- headers.append("Failed to read response headers. <br>");
}
+ headers.append("</pre>");
+
std::string hex_dump = base::StringPrintf(
"<hr><pre> Showing %d of %d bytes\n\n", static_cast<int>(data_length),
static_cast<int>(response_info->response_data_size()));
diff --git a/chromium/content/browser/appcache/appcache_internals_ui.h b/chromium/content/browser/appcache/appcache_internals_ui.h
index 5fdf4a308c4..930361f0957 100644
--- a/chromium/content/browser/appcache/appcache_internals_ui.h
+++ b/chromium/content/browser/appcache/appcache_internals_ui.h
@@ -9,6 +9,7 @@
#include <list>
#include <memory>
+#include <vector>
#include "base/macros.h"
#include "base/memory/ref_counted.h"
@@ -108,7 +109,7 @@ class AppCacheInternalsUI : public WebUIController {
void OnAppCacheDetailsReady(
const base::FilePath& partition_path,
const std::string& manifest_url,
- std::unique_ptr<AppCacheResourceInfoVector> resource_info_vector);
+ std::unique_ptr<std::vector<AppCacheResourceInfo>> resource_info_vector);
void OnFileDetailsReady(const Proxy::ResponseEnquiry& response_enquiry,
scoped_refptr<AppCacheResponseInfo> response_info,
scoped_refptr<net::IOBuffer> response_data,
diff --git a/chromium/content/browser/appcache/appcache_job.cc b/chromium/content/browser/appcache/appcache_job.cc
index 24312c7de5b..20fcaed3a65 100644
--- a/chromium/content/browser/appcache/appcache_job.cc
+++ b/chromium/content/browser/appcache/appcache_job.cc
@@ -84,8 +84,8 @@ void AppCacheJob::SetupRangeResponse() {
// Make a copy of the full response headers and fix them up
// for the range we'll be returning.
- range_response_info_.reset(
- new net::HttpResponseInfo(*info_->http_response_info()));
+ range_response_info_ =
+ std::make_unique<net::HttpResponseInfo>(info_->http_response_info());
net::HttpResponseHeaders* headers = range_response_info_->headers.get();
headers->UpdateWithNewRange(range_requested_, resource_size,
true /* replace status line */);
diff --git a/chromium/content/browser/appcache/appcache_manifest_parser.h b/chromium/content/browser/appcache/appcache_manifest_parser.h
index 75f7fe8356c..016655b25e9 100644
--- a/chromium/content/browser/appcache/appcache_manifest_parser.h
+++ b/chromium/content/browser/appcache/appcache_manifest_parser.h
@@ -48,9 +48,9 @@ struct CONTENT_EXPORT AppCacheManifest {
~AppCacheManifest();
base::hash_set<std::string> explicit_urls;
- AppCacheNamespaceVector intercept_namespaces;
- AppCacheNamespaceVector fallback_namespaces;
- AppCacheNamespaceVector online_whitelist_namespaces;
+ std::vector<AppCacheNamespace> intercept_namespaces;
+ std::vector<AppCacheNamespace> fallback_namespaces;
+ std::vector<AppCacheNamespace> online_whitelist_namespaces;
bool online_whitelist_all = false;
bool did_ignore_intercept_namespaces = false;
bool did_ignore_fallback_namespaces = false;
diff --git a/chromium/content/browser/appcache/appcache_manifest_parser_unittest.cc b/chromium/content/browser/appcache/appcache_manifest_parser_unittest.cc
index caa0264b770..5ca2d3ac9e1 100644
--- a/chromium/content/browser/appcache/appcache_manifest_parser_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_manifest_parser_unittest.cc
@@ -5,6 +5,7 @@
#include <stddef.h>
#include <string>
+#include <vector>
#include "base/macros.h"
#include "content/browser/appcache/appcache_manifest_parser.h"
@@ -174,7 +175,8 @@ TEST(AppCacheManifestParserTest, WhitelistUrls) {
EXPECT_FALSE(manifest.did_ignore_intercept_namespaces);
EXPECT_FALSE(manifest.did_ignore_fallback_namespaces);
- const AppCacheNamespaceVector& online = manifest.online_whitelist_namespaces;
+ const std::vector<AppCacheNamespace>& online =
+ manifest.online_whitelist_namespaces;
const size_t kExpected = 6;
ASSERT_EQ(kExpected, online.size());
EXPECT_EQ(APPCACHE_NETWORK_NAMESPACE, online[0].type);
@@ -223,7 +225,8 @@ TEST(AppCacheManifestParserTest, FallbackUrls) {
EXPECT_FALSE(manifest.did_ignore_intercept_namespaces);
EXPECT_FALSE(manifest.did_ignore_fallback_namespaces);
- const AppCacheNamespaceVector& fallbacks = manifest.fallback_namespaces;
+ const std::vector<AppCacheNamespace>& fallbacks =
+ manifest.fallback_namespaces;
const size_t kExpected = 5;
ASSERT_EQ(kExpected, fallbacks.size());
EXPECT_EQ(APPCACHE_FALLBACK_NAMESPACE, fallbacks[0].type);
@@ -281,7 +284,8 @@ TEST(AppCacheManifestParserTest, FallbackUrlsWithPort) {
EXPECT_TRUE(manifest.online_whitelist_namespaces.empty());
EXPECT_FALSE(manifest.online_whitelist_all);
- const AppCacheNamespaceVector& fallbacks = manifest.fallback_namespaces;
+ const std::vector<AppCacheNamespace>& fallbacks =
+ manifest.fallback_namespaces;
const size_t kExpected = 3;
ASSERT_EQ(kExpected, fallbacks.size());
EXPECT_EQ(APPCACHE_FALLBACK_NAMESPACE, fallbacks[0].type);
@@ -334,7 +338,8 @@ TEST(AppCacheManifestParserTest, InterceptUrls) {
EXPECT_FALSE(manifest.did_ignore_intercept_namespaces);
EXPECT_FALSE(manifest.did_ignore_fallback_namespaces);
- const AppCacheNamespaceVector& intercepts = manifest.intercept_namespaces;
+ const std::vector<AppCacheNamespace>& intercepts =
+ manifest.intercept_namespaces;
const size_t kExpected = 3;
ASSERT_EQ(kExpected, intercepts.size());
EXPECT_EQ(APPCACHE_INTERCEPT_NAMESPACE, intercepts[0].type);
@@ -401,7 +406,8 @@ TEST(AppCacheManifestParserTest, ComboUrls) {
EXPECT_TRUE(urls.find("http://combo.com:99/explicit-2") != urls.end());
EXPECT_TRUE(urls.find("http://www.diff.com/explicit-3") != urls.end());
- const AppCacheNamespaceVector& online = manifest.online_whitelist_namespaces;
+ const std::vector<AppCacheNamespace>& online =
+ manifest.online_whitelist_namespaces;
expected = 4;
ASSERT_EQ(expected, online.size());
EXPECT_EQ(GURL("http://combo.com/whitelist-1"),
@@ -413,7 +419,8 @@ TEST(AppCacheManifestParserTest, ComboUrls) {
EXPECT_EQ(GURL("http://combo.com:99/whitelist-4"),
online[3].namespace_url);
- const AppCacheNamespaceVector& fallbacks = manifest.fallback_namespaces;
+ const std::vector<AppCacheNamespace>& fallbacks =
+ manifest.fallback_namespaces;
expected = 2;
ASSERT_EQ(expected, fallbacks.size());
EXPECT_EQ(APPCACHE_FALLBACK_NAMESPACE, fallbacks[0].type);
diff --git a/chromium/content/browser/appcache/appcache_quota_client.cc b/chromium/content/browser/appcache/appcache_quota_client.cc
index 378bb0efe92..c9266e4e7b9 100644
--- a/chromium/content/browser/appcache/appcache_quota_client.cc
+++ b/chromium/content/browser/appcache/appcache_quota_client.cc
@@ -7,6 +7,7 @@
#include <algorithm>
#include <map>
#include <set>
+#include <utility>
#include "base/bind.h"
#include "base/bind_helpers.h"
@@ -207,15 +208,16 @@ const AppCacheStorage::UsageMap* AppCacheQuotaClient::GetUsageMap() {
return service_->storage()->usage_map();
}
-net::CancelableCompletionCallback*
+net::CancelableCompletionRepeatingCallback*
AppCacheQuotaClient::GetServiceDeleteCallback() {
- // Lazily created due to CancelableCompletionCallback's threading
- // restrictions, there is no way to detach from the thread created on.
+ // Lazily created due to base::CancelableCallback's threading restrictions,
+ // there is no way to detach from the thread created on.
if (!service_delete_callback_) {
- service_delete_callback_.reset(
- new net::CancelableCompletionCallback(
- base::Bind(&AppCacheQuotaClient::DidDeleteAppCachesForOrigin,
- base::Unretained(this))));
+ service_delete_callback_ =
+ std::make_unique<net::CancelableCompletionRepeatingCallback>(
+ base::BindRepeating(
+ &AppCacheQuotaClient::DidDeleteAppCachesForOrigin,
+ base::Unretained(this)));
}
return service_delete_callback_.get();
}
diff --git a/chromium/content/browser/appcache/appcache_quota_client.h b/chromium/content/browser/appcache/appcache_quota_client.h
index d40424dcea3..a5dc1e63064 100644
--- a/chromium/content/browser/appcache/appcache_quota_client.h
+++ b/chromium/content/browser/appcache/appcache_quota_client.h
@@ -14,7 +14,7 @@
#include "base/memory/ref_counted.h"
#include "content/browser/appcache/appcache_storage.h"
#include "content/common/content_export.h"
-#include "net/base/completion_callback.h"
+#include "net/base/completion_repeating_callback.h"
#include "storage/browser/quota/quota_client.h"
#include "storage/browser/quota/quota_task.h"
#include "third_party/blink/public/mojom/quota/quota_types.mojom.h"
@@ -67,7 +67,7 @@ class AppCacheQuotaClient : public storage::QuotaClient {
void ProcessPendingRequests();
void DeletePendingRequests();
const AppCacheStorage::UsageMap* GetUsageMap();
- net::CancelableCompletionCallback* GetServiceDeleteCallback();
+ net::CancelableCompletionRepeatingCallback* GetServiceDeleteCallback();
// For use by appcache internals during initialization and shutdown.
CONTENT_EXPORT void NotifyAppCacheReady();
@@ -81,7 +81,8 @@ class AppCacheQuotaClient : public storage::QuotaClient {
// And once it's ready, we can only handle one delete request at a time,
// so we queue up additional requests while one is in already in progress.
DeletionCallback current_delete_request_callback_;
- std::unique_ptr<net::CancelableCompletionCallback> service_delete_callback_;
+ std::unique_ptr<net::CancelableCompletionRepeatingCallback>
+ service_delete_callback_;
AppCacheServiceImpl* service_;
bool appcache_is_ready_;
diff --git a/chromium/content/browser/appcache/appcache_request_handler.cc b/chromium/content/browser/appcache/appcache_request_handler.cc
index 7f291f904b0..459c79ab482 100644
--- a/chromium/content/browser/appcache/appcache_request_handler.cc
+++ b/chromium/content/browser/appcache/appcache_request_handler.cc
@@ -222,17 +222,17 @@ void AppCacheRequestHandler::GetExtraResponseInfo(int64_t* cache_id,
// static
std::unique_ptr<AppCacheRequestHandler>
-AppCacheRequestHandler::InitializeForNavigationNetworkService(
+AppCacheRequestHandler::InitializeForMainResourceNetworkService(
const network::ResourceRequest& request,
- AppCacheNavigationHandleCore* appcache_handle_core,
+ base::WeakPtr<AppCacheHost> appcache_host,
scoped_refptr<network::SharedURLLoaderFactory> network_loader_factory) {
std::unique_ptr<AppCacheRequestHandler> handler =
- appcache_handle_core->host()->CreateRequestHandler(
+ appcache_host->CreateRequestHandler(
AppCacheURLLoaderRequest::Create(request),
static_cast<ResourceType>(request.resource_type),
request.should_reset_appcache);
handler->network_loader_factory_ = std::move(network_loader_factory);
- handler->appcache_host_ = appcache_handle_core->host()->GetWeakPtr();
+ handler->appcache_host_ = std::move(appcache_host);
return handler;
}
@@ -403,8 +403,8 @@ void AppCacheRequestHandler::OnMainResponseFound(
}
if (should_reset_appcache_ && !manifest_url.is_empty()) {
- host_->service()->DeleteAppCacheGroup(
- manifest_url, net::CompletionCallback());
+ host_->service()->DeleteAppCacheGroup(manifest_url,
+ net::CompletionOnceCallback());
DeliverNetworkResponse();
return;
}
@@ -546,13 +546,21 @@ void AppCacheRequestHandler::OnCacheSelectionComplete(AppCacheHost* host) {
}
void AppCacheRequestHandler::MaybeCreateLoader(
- const network::ResourceRequest& resource_request,
+ const network::ResourceRequest& tentative_resource_request,
ResourceContext* resource_context,
- LoaderCallback callback) {
+ LoaderCallback callback,
+ FallbackCallback fallback_callback) {
loader_callback_ =
base::BindOnce(&AppCacheRequestHandler::RunLoaderCallbackForMainResource,
weak_factory_.GetWeakPtr(), std::move(callback));
- request_->AsURLLoaderRequest()->set_request(resource_request);
+
+ // TODO(crbug.com/876531): Figure out how AppCache interception should
+ // interact with URLLoaderThrottles. It might be incorrect to store
+ // |tentative_resource_request| here, since throttles can rewrite headers
+ // between now and when the request handler passed to |loader_callback_| is
+ // invoked.
+ request_->AsURLLoaderRequest()->set_request(tentative_resource_request);
+
MaybeLoadResource(nullptr);
// If a job is created, the job assumes ownership of the callback and
// the responsibility to call it. If no job is created, we call it with
@@ -572,16 +580,19 @@ bool AppCacheRequestHandler::MaybeCreateLoaderForResponse(
// a loader to start.
bool was_called = false;
loader_callback_ = base::BindOnce(
- [](network::mojom::URLLoaderPtr* loader,
+ [](const network::ResourceRequest& resource_request,
+ network::mojom::URLLoaderPtr* loader,
network::mojom::URLLoaderClientRequest* client_request,
bool* was_called,
SingleRequestURLLoaderFactory::RequestHandler handler) {
*was_called = true;
network::mojom::URLLoaderClientPtr client;
*client_request = mojo::MakeRequest(&client);
- std::move(handler).Run(mojo::MakeRequest(loader), std::move(client));
+ std::move(handler).Run(resource_request, mojo::MakeRequest(loader),
+ std::move(client));
},
- loader, client_request, &was_called);
+ *(request_->AsURLLoaderRequest()->GetResourceRequest()), loader,
+ client_request, &was_called);
request_->AsURLLoaderRequest()->set_response(response);
if (!MaybeLoadFallbackForResponse(nullptr)) {
DCHECK(!was_called);
@@ -612,9 +623,13 @@ void AppCacheRequestHandler::MaybeCreateSubresourceLoader(
LoaderCallback loader_callback) {
DCHECK(!job_);
DCHECK(!is_main_resource());
+ // AppCache doesn't use the fallback_callback.
+ FallbackCallback fallback_callback = base::DoNothing();
+
// Subresource loads start out just like a main resource loads, but they go
// down different branches along the way to completion.
- MaybeCreateLoader(resource_request, nullptr, std::move(loader_callback));
+ MaybeCreateLoader(resource_request, nullptr, std::move(loader_callback),
+ std::move(fallback_callback));
}
void AppCacheRequestHandler::MaybeFallbackForSubresourceResponse(
diff --git a/chromium/content/browser/appcache/appcache_request_handler.h b/chromium/content/browser/appcache/appcache_request_handler.h
index b8b82668b0e..57362f43c43 100644
--- a/chromium/content/browser/appcache/appcache_request_handler.h
+++ b/chromium/content/browser/appcache/appcache_request_handler.h
@@ -33,7 +33,6 @@ struct ResourceResponseHead;
namespace content {
class AppCacheJob;
-class AppCacheNavigationHandleCore;
class AppCacheSubresourceURLFactory;
class AppCacheRequest;
class AppCacheRequestHandlerTest;
@@ -75,9 +74,11 @@ class CONTENT_EXPORT AppCacheRequestHandler
// MaybeLoadResource and MaybeLoadFallbackForResponse.
// Eventually one of the Deliver*Response() methods is called and the
// LoaderCallback is invoked.
- void MaybeCreateLoader(const network::ResourceRequest& resource_request,
- ResourceContext* resource_context,
- LoaderCallback callback) override;
+ void MaybeCreateLoader(
+ const network::ResourceRequest& tentative_resource_request,
+ ResourceContext* resource_context,
+ LoaderCallback callback,
+ FallbackCallback fallback_callback) override;
// MaybeCreateLoaderForResponse always returns synchronously.
bool MaybeCreateLoaderForResponse(
const network::ResourceResponseHead& response,
@@ -106,9 +107,9 @@ class CONTENT_EXPORT AppCacheRequestHandler
LoaderCallback callback);
static std::unique_ptr<AppCacheRequestHandler>
- InitializeForNavigationNetworkService(
+ InitializeForMainResourceNetworkService(
const network::ResourceRequest& request,
- AppCacheNavigationHandleCore* appcache_handle_core,
+ base::WeakPtr<AppCacheHost> appcache_host,
scoped_refptr<network::SharedURLLoaderFactory> network_loader_factory);
static bool IsMainResourceType(ResourceType type) {
diff --git a/chromium/content/browser/appcache/appcache_response.cc b/chromium/content/browser/appcache/appcache_response.cc
index dd47432bcb6..15bb71504fb 100644
--- a/chromium/content/browser/appcache/appcache_response.cc
+++ b/chromium/content/browser/appcache/appcache_response.cc
@@ -6,6 +6,8 @@
#include <stddef.h>
+#include <utility>
+
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/compiler_specific.h"
@@ -17,7 +19,7 @@
#include "base/strings/string_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/appcache/appcache_storage.h"
-#include "net/base/completion_callback.h"
+#include "net/base/completion_once_callback.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "storage/common/storage_histograms.h"
@@ -29,20 +31,19 @@ namespace {
// Disk cache entry data indices.
enum { kResponseInfoIndex, kResponseContentIndex, kResponseMetadataIndex };
-// An IOBuffer that wraps a pickle's data. Ownership of the
-// pickle is transfered to the WrappedPickleIOBuffer object.
+// An IOBuffer that wraps a pickle's data.
class WrappedPickleIOBuffer : public net::WrappedIOBuffer {
public:
- explicit WrappedPickleIOBuffer(const base::Pickle* pickle)
+ explicit WrappedPickleIOBuffer(std::unique_ptr<const base::Pickle> pickle)
: net::WrappedIOBuffer(reinterpret_cast<const char*>(pickle->data())),
- pickle_(pickle) {
- DCHECK(pickle->data());
+ pickle_(std::move(pickle)) {
+ DCHECK(pickle_->data());
}
private:
- ~WrappedPickleIOBuffer() override {}
+ ~WrappedPickleIOBuffer() override = default;
- std::unique_ptr<const base::Pickle> pickle_;
+ const std::unique_ptr<const base::Pickle> pickle_;
};
} // anon namespace
@@ -50,17 +51,18 @@ class WrappedPickleIOBuffer : public net::WrappedIOBuffer {
// AppCacheResponseInfo ----------------------------------------------
-AppCacheResponseInfo::AppCacheResponseInfo(AppCacheStorage* storage,
- const GURL& manifest_url,
- int64_t response_id,
- net::HttpResponseInfo* http_info,
- int64_t response_data_size)
+AppCacheResponseInfo::AppCacheResponseInfo(
+ AppCacheStorage* storage,
+ const GURL& manifest_url,
+ int64_t response_id,
+ std::unique_ptr<net::HttpResponseInfo> http_info,
+ int64_t response_data_size)
: manifest_url_(manifest_url),
response_id_(response_id),
- http_response_info_(http_info),
+ http_response_info_(std::move(http_info)),
response_data_size_(response_data_size),
storage_(storage) {
- DCHECK(http_info);
+ DCHECK(http_response_info_);
DCHECK(response_id != kAppCacheNoResponseId);
storage_->working_set()->AddResponseInfo(this);
}
@@ -74,10 +76,11 @@ AppCacheResponseInfo::~AppCacheResponseInfo() {
HttpResponseInfoIOBuffer::HttpResponseInfoIOBuffer()
: response_data_size(kUnkownResponseDataSize) {}
-HttpResponseInfoIOBuffer::HttpResponseInfoIOBuffer(net::HttpResponseInfo* info)
- : http_info(info), response_data_size(kUnkownResponseDataSize) {}
+HttpResponseInfoIOBuffer::HttpResponseInfoIOBuffer(
+ std::unique_ptr<net::HttpResponseInfo> info)
+ : http_info(std::move(info)), response_data_size(kUnkownResponseDataSize) {}
-HttpResponseInfoIOBuffer::~HttpResponseInfoIOBuffer() {}
+HttpResponseInfoIOBuffer::~HttpResponseInfoIOBuffer() = default;
// AppCacheDiskCacheInterface ----------------------------------------
@@ -95,12 +98,11 @@ AppCacheDiskCacheInterface::~AppCacheDiskCacheInterface() {}
AppCacheResponseIO::AppCacheResponseIO(
int64_t response_id,
- const base::WeakPtr<AppCacheDiskCacheInterface>& disk_cache)
+ base::WeakPtr<AppCacheDiskCacheInterface> disk_cache)
: response_id_(response_id),
- disk_cache_(disk_cache),
+ disk_cache_(std::move(disk_cache)),
entry_(nullptr),
- buffer_len_(0),
- weak_factory_(this) {}
+ buffer_len_(0) {}
AppCacheResponseIO::~AppCacheResponseIO() {
if (entry_)
@@ -109,8 +111,8 @@ AppCacheResponseIO::~AppCacheResponseIO() {
void AppCacheResponseIO::ScheduleIOCompletionCallback(int result) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(&AppCacheResponseIO::OnIOComplete,
- weak_factory_.GetWeakPtr(), result));
+ FROM_HERE,
+ base::BindOnce(&AppCacheResponseIO::OnIOComplete, GetWeakPtr(), result));
}
void AppCacheResponseIO::InvokeUserCompletionCallback(int result) {
@@ -128,8 +130,7 @@ void AppCacheResponseIO::ReadRaw(int index, int offset,
DCHECK(entry_);
int rv = entry_->Read(
index, offset, buf, buf_len,
- base::Bind(&AppCacheResponseIO::OnRawIOComplete,
- weak_factory_.GetWeakPtr()));
+ base::BindOnce(&AppCacheResponseIO::OnRawIOComplete, GetWeakPtr()));
if (rv != net::ERR_IO_PENDING)
ScheduleIOCompletionCallback(rv);
}
@@ -139,8 +140,7 @@ void AppCacheResponseIO::WriteRaw(int index, int offset,
DCHECK(entry_);
int rv = entry_->Write(
index, offset, buf, buf_len,
- base::Bind(&AppCacheResponseIO::OnRawIOComplete,
- weak_factory_.GetWeakPtr()));
+ base::BindOnce(&AppCacheResponseIO::OnRawIOComplete, GetWeakPtr()));
if (rv != net::ERR_IO_PENDING)
ScheduleIOCompletionCallback(rv);
}
@@ -159,28 +159,34 @@ void AppCacheResponseIO::OpenEntryIfNeeded() {
rv = net::ERR_FAILED;
} else {
entry_ptr = new AppCacheDiskCacheInterface::Entry*;
- open_callback_ =
- base::Bind(&AppCacheResponseIO::OpenEntryCallback,
- weak_factory_.GetWeakPtr(), base::Owned(entry_ptr));
- rv = disk_cache_->OpenEntry(response_id_, entry_ptr, open_callback_);
+ rv = disk_cache_->OpenEntry(
+ response_id_, entry_ptr,
+ base::BindOnce(&AppCacheResponseIO::OpenEntryCallback, GetWeakPtr(),
+ entry_ptr));
}
if (rv != net::ERR_IO_PENDING)
- OpenEntryCallback(entry_ptr, rv);
+ OpenEntryCallback(GetWeakPtr(), entry_ptr, rv);
}
+// static
void AppCacheResponseIO::OpenEntryCallback(
- AppCacheDiskCacheInterface::Entry** entry, int rv) {
- DCHECK(info_buffer_.get() || buffer_.get());
+ base::WeakPtr<AppCacheResponseIO> response,
+ AppCacheDiskCacheInterface::Entry** entry,
+ int rv) {
+ if (!response) {
+ delete entry;
+ return;
+ }
- if (!open_callback_.is_null()) {
- if (rv == net::OK) {
- DCHECK(entry);
- entry_ = *entry;
- }
- open_callback_.Reset();
+ DCHECK(response->info_buffer_.get() || response->buffer_.get());
+
+ if (!response->entry_ && rv == net::OK) {
+ DCHECK(entry);
+ response->entry_ = *entry;
}
- OnOpenEntryComplete();
+ delete entry;
+ response->OnOpenEntryComplete();
}
@@ -188,16 +194,15 @@ void AppCacheResponseIO::OpenEntryCallback(
AppCacheResponseReader::AppCacheResponseReader(
int64_t response_id,
- const base::WeakPtr<AppCacheDiskCacheInterface>& disk_cache)
- : AppCacheResponseIO(response_id, disk_cache),
+ base::WeakPtr<AppCacheDiskCacheInterface> disk_cache)
+ : AppCacheResponseIO(response_id, std::move(disk_cache)),
range_offset_(0),
range_length_(std::numeric_limits<int32_t>::max()),
read_position_(0),
reading_metadata_size_(0),
weak_factory_(this) {}
-AppCacheResponseReader::~AppCacheResponseReader() {
-}
+AppCacheResponseReader::~AppCacheResponseReader() = default;
void AppCacheResponseReader::ReadInfo(HttpResponseInfoIOBuffer* info_buf,
OnceCompletionCallback callback) {
@@ -312,20 +317,23 @@ void AppCacheResponseReader::OnOpenEntryComplete() {
ContinueReadData();
}
+base::WeakPtr<AppCacheResponseIO> AppCacheResponseReader::GetWeakPtr() {
+ return weak_factory_.GetWeakPtr();
+}
+
// AppCacheResponseWriter ----------------------------------------------
AppCacheResponseWriter::AppCacheResponseWriter(
int64_t response_id,
- const base::WeakPtr<AppCacheDiskCacheInterface>& disk_cache)
- : AppCacheResponseIO(response_id, disk_cache),
+ base::WeakPtr<AppCacheDiskCacheInterface> disk_cache)
+ : AppCacheResponseIO(response_id, std::move(disk_cache)),
info_size_(0),
write_position_(0),
write_amount_(0),
creation_phase_(INITIAL_ATTEMPT),
weak_factory_(this) {}
-AppCacheResponseWriter::~AppCacheResponseWriter() {
-}
+AppCacheResponseWriter::~AppCacheResponseWriter() = default;
void AppCacheResponseWriter::WriteInfo(HttpResponseInfoIOBuffer* info_buf,
OnceCompletionCallback callback) {
@@ -350,10 +358,11 @@ void AppCacheResponseWriter::ContinueWriteInfo() {
const bool kSkipTransientHeaders = true;
const bool kTruncated = false;
- base::Pickle* pickle = new base::Pickle;
- info_buffer_->http_info->Persist(pickle, kSkipTransientHeaders, kTruncated);
+ std::unique_ptr<base::Pickle> pickle = std::make_unique<base::Pickle>();
+ info_buffer_->http_info->Persist(pickle.get(), kSkipTransientHeaders,
+ kTruncated);
write_amount_ = static_cast<int>(pickle->size());
- buffer_ = new WrappedPickleIOBuffer(pickle); // takes ownership of pickle
+ buffer_ = base::MakeRefCounted<WrappedPickleIOBuffer>(std::move(pickle));
WriteRaw(kResponseInfoIndex, 0, buffer_.get(), write_amount_);
}
@@ -408,73 +417,94 @@ void AppCacheResponseWriter::CreateEntryIfNeededAndContinue() {
} else {
creation_phase_ = INITIAL_ATTEMPT;
entry_ptr = new AppCacheDiskCacheInterface::Entry*;
- create_callback_ =
- base::Bind(&AppCacheResponseWriter::OnCreateEntryComplete,
- weak_factory_.GetWeakPtr(), base::Owned(entry_ptr));
- rv = disk_cache_->CreateEntry(response_id_, entry_ptr, create_callback_);
+ rv = disk_cache_->CreateEntry(
+ response_id_, entry_ptr,
+ base::BindOnce(&AppCacheResponseWriter::OnCreateEntryComplete,
+ weak_factory_.GetWeakPtr(), entry_ptr));
}
if (rv != net::ERR_IO_PENDING)
- OnCreateEntryComplete(entry_ptr, rv);
+ OnCreateEntryComplete(weak_factory_.GetWeakPtr(), entry_ptr, rv);
}
+// static
void AppCacheResponseWriter::OnCreateEntryComplete(
- AppCacheDiskCacheInterface::Entry** entry, int rv) {
- DCHECK(info_buffer_.get() || buffer_.get());
+ base::WeakPtr<AppCacheResponseWriter> writer,
+ AppCacheDiskCacheInterface::Entry** entry,
+ int rv) {
+ if (!writer) {
+ if (entry) {
+ delete entry;
+ }
+ return;
+ }
- if (!disk_cache_) {
- ScheduleIOCompletionCallback(net::ERR_FAILED);
+ DCHECK(writer->info_buffer_.get() || writer->buffer_.get());
+
+ if (!writer->disk_cache_) {
+ if (entry) {
+ delete entry;
+ }
+ writer->ScheduleIOCompletionCallback(net::ERR_FAILED);
return;
- } else if (creation_phase_ == INITIAL_ATTEMPT) {
+ } else if (writer->creation_phase_ == INITIAL_ATTEMPT) {
if (rv != net::OK) {
// We may try to overwrite existing entries.
- creation_phase_ = DOOM_EXISTING;
- rv = disk_cache_->DoomEntry(response_id_, create_callback_);
+ delete entry;
+ writer->creation_phase_ = DOOM_EXISTING;
+ rv = writer->disk_cache_->DoomEntry(
+ writer->response_id_,
+ base::BindOnce(&AppCacheResponseWriter::OnCreateEntryComplete, writer,
+ nullptr));
if (rv != net::ERR_IO_PENDING)
- OnCreateEntryComplete(nullptr, rv);
+ OnCreateEntryComplete(writer, nullptr, rv);
return;
}
- } else if (creation_phase_ == DOOM_EXISTING) {
- creation_phase_ = SECOND_ATTEMPT;
+ } else if (writer->creation_phase_ == DOOM_EXISTING) {
+ DCHECK_EQ(nullptr, entry);
+ writer->creation_phase_ = SECOND_ATTEMPT;
AppCacheDiskCacheInterface::Entry** entry_ptr =
new AppCacheDiskCacheInterface::Entry*;
- create_callback_ =
- base::Bind(&AppCacheResponseWriter::OnCreateEntryComplete,
- weak_factory_.GetWeakPtr(), base::Owned(entry_ptr));
- rv = disk_cache_->CreateEntry(response_id_, entry_ptr, create_callback_);
+ rv = writer->disk_cache_->CreateEntry(
+ writer->response_id_, entry_ptr,
+ base::BindOnce(&AppCacheResponseWriter::OnCreateEntryComplete, writer,
+ entry_ptr));
if (rv != net::ERR_IO_PENDING)
- OnCreateEntryComplete(entry_ptr, rv);
+ OnCreateEntryComplete(writer, entry_ptr, rv);
return;
}
- if (!create_callback_.is_null()) {
- if (rv == net::OK)
- entry_ = *entry;
-
- create_callback_.Reset();
+ if (!writer->entry_ && rv == net::OK) {
+ DCHECK(entry);
+ writer->entry_ = *entry;
}
- if (info_buffer_.get())
- ContinueWriteInfo();
+ delete entry;
+
+ if (writer->info_buffer_.get())
+ writer->ContinueWriteInfo();
else
- ContinueWriteData();
+ writer->ContinueWriteData();
+}
+
+base::WeakPtr<AppCacheResponseIO> AppCacheResponseWriter::GetWeakPtr() {
+ return weak_factory_.GetWeakPtr();
}
// AppCacheResponseMetadataWriter ----------------------------------------------
AppCacheResponseMetadataWriter::AppCacheResponseMetadataWriter(
int64_t response_id,
- const base::WeakPtr<AppCacheDiskCacheInterface>& disk_cache)
- : AppCacheResponseIO(response_id, disk_cache),
+ base::WeakPtr<AppCacheDiskCacheInterface> disk_cache)
+ : AppCacheResponseIO(response_id, std::move(disk_cache)),
write_amount_(0),
weak_factory_(this) {}
-AppCacheResponseMetadataWriter::~AppCacheResponseMetadataWriter() {
-}
+AppCacheResponseMetadataWriter::~AppCacheResponseMetadataWriter() = default;
void AppCacheResponseMetadataWriter::WriteMetadata(
net::IOBuffer* buf,
int buf_len,
- const net::CompletionCallback& callback) {
+ net::CompletionOnceCallback callback) {
DCHECK(!callback.is_null());
DCHECK(!IsIOPending());
DCHECK(buf);
@@ -483,7 +513,7 @@ void AppCacheResponseMetadataWriter::WriteMetadata(
buffer_ = buf;
write_amount_ = buf_len;
- callback_ = callback; // cleared on completion
+ callback_ = std::move(callback); // cleared on completion
OpenEntryIfNeeded();
}
@@ -503,4 +533,8 @@ void AppCacheResponseMetadataWriter::OnIOComplete(int result) {
// Note: |this| may have been deleted by the completion callback.
}
+base::WeakPtr<AppCacheResponseIO> AppCacheResponseMetadataWriter::GetWeakPtr() {
+ return weak_factory_.GetWeakPtr();
+}
+
} // namespace content
diff --git a/chromium/content/browser/appcache/appcache_response.h b/chromium/content/browser/appcache/appcache_response.h
index fb85715d141..de0663e162e 100644
--- a/chromium/content/browser/appcache/appcache_response.h
+++ b/chromium/content/browser/appcache/appcache_response.h
@@ -14,7 +14,7 @@
#include "base/memory/weak_ptr.h"
#include "content/common/appcache_interfaces.h"
#include "content/common/content_export.h"
-#include "net/base/completion_callback.h"
+#include "net/base/completion_once_callback.h"
#include "net/http/http_response_info.h"
#include "url/gurl.h"
@@ -35,29 +35,28 @@ using OnceCompletionCallback = base::OnceCallback<void(int)>;
class CONTENT_EXPORT AppCacheResponseInfo
: public base::RefCounted<AppCacheResponseInfo> {
public:
- // AppCacheResponseInfo takes ownership of the http_info.
AppCacheResponseInfo(AppCacheStorage* storage,
const GURL& manifest_url,
int64_t response_id,
- net::HttpResponseInfo* http_info,
+ std::unique_ptr<net::HttpResponseInfo> http_info,
int64_t response_data_size);
const GURL& manifest_url() const { return manifest_url_; }
int64_t response_id() const { return response_id_; }
- const net::HttpResponseInfo* http_response_info() const {
- return http_response_info_.get();
+ const net::HttpResponseInfo& http_response_info() const {
+ return *http_response_info_;
}
int64_t response_data_size() const { return response_data_size_; }
private:
friend class base::RefCounted<AppCacheResponseInfo>;
- virtual ~AppCacheResponseInfo();
+ ~AppCacheResponseInfo();
const GURL manifest_url_;
const int64_t response_id_;
const std::unique_ptr<net::HttpResponseInfo> http_response_info_;
const int64_t response_data_size_;
- AppCacheStorage* storage_;
+ AppCacheStorage* const storage_;
};
// A refcounted wrapper for HttpResponseInfo so we can apply the
@@ -68,11 +67,12 @@ struct CONTENT_EXPORT HttpResponseInfoIOBuffer
int response_data_size;
HttpResponseInfoIOBuffer();
- explicit HttpResponseInfoIOBuffer(net::HttpResponseInfo* info);
+ explicit HttpResponseInfoIOBuffer(
+ std::unique_ptr<net::HttpResponseInfo> info);
- protected:
+ private:
friend class base::RefCountedThreadSafe<HttpResponseInfoIOBuffer>;
- virtual ~HttpResponseInfoIOBuffer();
+ ~HttpResponseInfoIOBuffer();
};
// Low level storage API used by the response reader and writer.
@@ -84,16 +84,16 @@ class CONTENT_EXPORT AppCacheDiskCacheInterface {
int64_t offset,
net::IOBuffer* buf,
int buf_len,
- const net::CompletionCallback& callback) = 0;
+ net::CompletionOnceCallback callback) = 0;
virtual int Write(int index,
int64_t offset,
net::IOBuffer* buf,
int buf_len,
- const net::CompletionCallback& callback) = 0;
+ net::CompletionOnceCallback callback) = 0;
virtual int64_t GetSize(int index) = 0;
virtual void Close() = 0;
protected:
- virtual ~Entry() {}
+ virtual ~Entry() = default;
};
// The uma_name pointer must remain valid for the life of the object.
@@ -101,12 +101,11 @@ class CONTENT_EXPORT AppCacheDiskCacheInterface {
virtual int CreateEntry(int64_t key,
Entry** entry,
- const net::CompletionCallback& callback) = 0;
+ net::CompletionOnceCallback callback) = 0;
virtual int OpenEntry(int64_t key,
Entry** entry,
- const net::CompletionCallback& callback) = 0;
- virtual int DoomEntry(int64_t key,
- const net::CompletionCallback& callback) = 0;
+ net::CompletionOnceCallback callback) = 0;
+ virtual int DoomEntry(int64_t key, net::CompletionOnceCallback callback) = 0;
const char* uma_name() const { return uma_name_; }
base::WeakPtr<AppCacheDiskCacheInterface> GetWeakPtr();
@@ -125,20 +124,23 @@ class CONTENT_EXPORT AppCacheResponseIO {
int64_t response_id() const { return response_id_; }
protected:
- AppCacheResponseIO(
- int64_t response_id,
- const base::WeakPtr<AppCacheDiskCacheInterface>& disk_cache);
+ AppCacheResponseIO(int64_t response_id,
+ base::WeakPtr<AppCacheDiskCacheInterface> disk_cache);
virtual void OnIOComplete(int result) = 0;
virtual void OnOpenEntryComplete() {}
- bool IsIOPending() { return !callback_.is_null(); }
+ bool IsIOPending() const { return !callback_.is_null(); }
void ScheduleIOCompletionCallback(int result);
void InvokeUserCompletionCallback(int result);
void ReadRaw(int index, int offset, net::IOBuffer* buf, int buf_len);
void WriteRaw(int index, int offset, net::IOBuffer* buf, int buf_len);
void OpenEntryIfNeeded();
+ // Methods in this class use weak pointers. The weak pointer factories must be
+ // defined in the subclasses, to avoid use-after-free situations.
+ virtual base::WeakPtr<AppCacheResponseIO> GetWeakPtr() = 0;
+
const int64_t response_id_;
base::WeakPtr<AppCacheDiskCacheInterface> disk_cache_;
AppCacheDiskCacheInterface::Entry* entry_;
@@ -146,20 +148,20 @@ class CONTENT_EXPORT AppCacheResponseIO {
scoped_refptr<net::IOBuffer> buffer_;
int buffer_len_;
OnceCompletionCallback callback_;
- net::CompletionCallback open_callback_;
- base::WeakPtrFactory<AppCacheResponseIO> weak_factory_;
+ net::CompletionOnceCallback open_callback_;
private:
void OnRawIOComplete(int result);
- void OpenEntryCallback(AppCacheDiskCacheInterface::Entry** entry, int rv);
+ static void OpenEntryCallback(base::WeakPtr<AppCacheResponseIO> response,
+ AppCacheDiskCacheInterface::Entry** entry,
+ int rv);
};
// Reads existing response data from storage. If the object is deleted
// and there is a read in progress, the implementation will return
// immediately but will take care of any side effect of cancelling the
// operation. In other words, instances are safe to delete at will.
-class CONTENT_EXPORT AppCacheResponseReader
- : public AppCacheResponseIO {
+class CONTENT_EXPORT AppCacheResponseReader : public AppCacheResponseIO {
public:
~AppCacheResponseReader() override;
@@ -201,12 +203,13 @@ class CONTENT_EXPORT AppCacheResponseReader
friend class content::MockAppCacheStorage;
// Should only be constructed by the storage class and derivatives.
- AppCacheResponseReader(
- int64_t response_id,
- const base::WeakPtr<AppCacheDiskCacheInterface>& disk_cache);
+ AppCacheResponseReader(int64_t response_id,
+ base::WeakPtr<AppCacheDiskCacheInterface> disk_cache);
void OnIOComplete(int result) override;
void OnOpenEntryComplete() override;
+ base::WeakPtr<AppCacheResponseIO> GetWeakPtr() override;
+
void ContinueReadInfo();
void ContinueReadData();
@@ -214,6 +217,7 @@ class CONTENT_EXPORT AppCacheResponseReader
int range_length_;
int read_position_;
int reading_metadata_size_;
+
base::WeakPtrFactory<AppCacheResponseReader> weak_factory_;
};
@@ -221,8 +225,7 @@ class CONTENT_EXPORT AppCacheResponseReader
// and there is a write in progress, the implementation will return
// immediately but will take care of any side effect of cancelling the
// operation. In other words, instances are safe to delete at will.
-class CONTENT_EXPORT AppCacheResponseWriter
- : public AppCacheResponseIO {
+class CONTENT_EXPORT AppCacheResponseWriter : public AppCacheResponseIO {
public:
~AppCacheResponseWriter() override;
@@ -258,9 +261,8 @@ class CONTENT_EXPORT AppCacheResponseWriter
protected:
// Should only be constructed by the storage class and derivatives.
- AppCacheResponseWriter(
- int64_t response_id,
- const base::WeakPtr<AppCacheDiskCacheInterface>& disk_cache);
+ AppCacheResponseWriter(int64_t response_id,
+ base::WeakPtr<AppCacheDiskCacheInterface> disk_cache);
private:
friend class AppCacheStorageImpl;
@@ -274,16 +276,20 @@ class CONTENT_EXPORT AppCacheResponseWriter
};
void OnIOComplete(int result) override;
+ base::WeakPtr<AppCacheResponseIO> GetWeakPtr() override;
+
void ContinueWriteInfo();
void ContinueWriteData();
void CreateEntryIfNeededAndContinue();
- void OnCreateEntryComplete(AppCacheDiskCacheInterface::Entry** entry, int rv);
+ static void OnCreateEntryComplete(
+ base::WeakPtr<AppCacheResponseWriter> writer,
+ AppCacheDiskCacheInterface::Entry** entry,
+ int rv);
int info_size_;
int write_position_;
int write_amount_;
CreationPhase creation_phase_;
- net::CompletionCallback create_callback_;
base::WeakPtrFactory<AppCacheResponseWriter> weak_factory_;
};
@@ -307,7 +313,7 @@ class CONTENT_EXPORT AppCacheResponseMetadataWriter
// progress.
void WriteMetadata(net::IOBuffer* buf,
int buf_len,
- const net::CompletionCallback& callback);
+ net::CompletionOnceCallback callback);
// Returns true if there is a write pending.
bool IsWritePending() { return IsIOPending(); }
@@ -319,11 +325,12 @@ class CONTENT_EXPORT AppCacheResponseMetadataWriter
// Should only be constructed by the storage class and derivatives.
AppCacheResponseMetadataWriter(
int64_t response_id,
- const base::WeakPtr<AppCacheDiskCacheInterface>& disk_cache);
+ base::WeakPtr<AppCacheDiskCacheInterface> disk_cache);
private:
void OnIOComplete(int result) override;
void OnOpenEntryComplete() override;
+ base::WeakPtr<AppCacheResponseIO> GetWeakPtr() override;
int write_amount_;
base::WeakPtrFactory<AppCacheResponseMetadataWriter> weak_factory_;
diff --git a/chromium/content/browser/appcache/appcache_response_unittest.cc b/chromium/content/browser/appcache/appcache_response_unittest.cc
index d0c91629877..799c9133b52 100644
--- a/chromium/content/browser/appcache/appcache_response_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_response_unittest.cc
@@ -177,19 +177,21 @@ class AppCacheResponseTest : public testing::Test {
int basic_response_size() { return 5; } // should match kHttpBody above
- void WriteResponse(net::HttpResponseInfo* head,
- IOBuffer* body, int body_len) {
+ void WriteResponse(std::unique_ptr<net::HttpResponseInfo> head,
+ IOBuffer* body,
+ int body_len) {
DCHECK(body);
scoped_refptr<IOBuffer> body_ref(body);
PushNextTask(base::BindOnce(&AppCacheResponseTest::WriteResponseBody,
base::Unretained(this), body_ref, body_len));
- WriteResponseHead(head);
+ WriteResponseHead(std::move(head));
}
- void WriteResponseHead(net::HttpResponseInfo* head) {
+ void WriteResponseHead(std::unique_ptr<net::HttpResponseInfo> head) {
EXPECT_FALSE(writer_->IsWritePending());
- expected_write_result_ = GetHttpResponseInfoSize(head);
- write_info_buffer_ = new HttpResponseInfoIOBuffer(head);
+ expected_write_result_ = GetHttpResponseInfoSize(*head);
+ write_info_buffer_ =
+ base::MakeRefCounted<HttpResponseInfoIOBuffer>(std::move(head));
writer_->WriteInfo(
write_info_buffer_.get(),
base::BindOnce(&AppCacheResponseTest::OnWriteInfoComplete,
@@ -198,7 +200,7 @@ class AppCacheResponseTest : public testing::Test {
void WriteResponseBody(scoped_refptr<IOBuffer> io_buffer, int buf_len) {
EXPECT_FALSE(writer_->IsWritePending());
- write_buffer_ = io_buffer;
+ write_buffer_ = std::move(io_buffer);
expected_write_result_ = buf_len;
writer_->WriteData(write_buffer_.get(), buf_len,
base::BindOnce(&AppCacheResponseTest::OnWriteComplete,
@@ -268,36 +270,36 @@ class AppCacheResponseTest : public testing::Test {
// Helpers to work with HttpResponseInfo objects
- net::HttpResponseInfo* MakeHttpResponseInfo(const std::string& raw_headers) {
- net::HttpResponseInfo* info = new net::HttpResponseInfo;
+ std::unique_ptr<net::HttpResponseInfo> MakeHttpResponseInfo(
+ const std::string& raw_headers) {
+ std::unique_ptr<net::HttpResponseInfo> info =
+ std::make_unique<net::HttpResponseInfo>();
info->request_time = base::Time::Now();
info->response_time = base::Time::Now();
info->was_cached = false;
- info->headers = new net::HttpResponseHeaders(raw_headers);
+ info->headers = base::MakeRefCounted<net::HttpResponseHeaders>(raw_headers);
return info;
}
- int GetHttpResponseInfoSize(const net::HttpResponseInfo* info) {
- base::Pickle pickle;
- return PickleHttpResonseInfo(&pickle, info);
+ int GetHttpResponseInfoSize(const net::HttpResponseInfo& info) {
+ base::Pickle pickle = PickleHttpResonseInfo(info);
+ return pickle.size();
}
- bool CompareHttpResponseInfos(const net::HttpResponseInfo* info1,
- const net::HttpResponseInfo* info2) {
- base::Pickle pickle1;
- base::Pickle pickle2;
- PickleHttpResonseInfo(&pickle1, info1);
- PickleHttpResonseInfo(&pickle2, info2);
+ bool CompareHttpResponseInfos(const net::HttpResponseInfo& info1,
+ const net::HttpResponseInfo& info2) {
+ base::Pickle pickle1 = PickleHttpResonseInfo(info1);
+ base::Pickle pickle2 = PickleHttpResonseInfo(info2);
return (pickle1.size() == pickle2.size()) &&
(0 == memcmp(pickle1.data(), pickle2.data(), pickle1.size()));
}
- int PickleHttpResonseInfo(base::Pickle* pickle,
- const net::HttpResponseInfo* info) {
+ base::Pickle PickleHttpResonseInfo(const net::HttpResponseInfo& info) {
const bool kSkipTransientHeaders = true;
const bool kTruncated = false;
- info->Persist(pickle, kSkipTransientHeaders, kTruncated);
- return pickle->size();
+ base::Pickle pickle;
+ info.Persist(&pickle, kSkipTransientHeaders, kTruncated);
+ return pickle;
}
// Helpers to fill and verify blocks of memory with a value
@@ -398,7 +400,7 @@ class AppCacheResponseTest : public testing::Test {
EXPECT_EQ(written_response_id_, storage_delegate_->loaded_info_id_);
EXPECT_TRUE(storage_delegate_->loaded_info_.get());
EXPECT_TRUE(CompareHttpResponseInfos(
- write_info_buffer_->http_info.get(),
+ *write_info_buffer_->http_info,
storage_delegate_->loaded_info_->http_response_info()));
EXPECT_EQ(basic_response_size(),
storage_delegate_->loaded_info_->response_data_size());
@@ -469,20 +471,18 @@ class AppCacheResponseTest : public testing::Test {
void Metadata_VerifyMetadata(const char* metadata) {
EXPECT_EQ(written_response_id_, storage_delegate_->loaded_info_id_);
EXPECT_TRUE(storage_delegate_->loaded_info_.get());
- const net::HttpResponseInfo* read_head =
+ const net::HttpResponseInfo& read_head =
storage_delegate_->loaded_info_->http_response_info();
- EXPECT_TRUE(read_head);
const int metadata_size = strlen(metadata);
if (metadata_size) {
- EXPECT_TRUE(read_head->metadata.get());
- EXPECT_EQ(metadata_size, read_head->metadata->size());
- EXPECT_EQ(0,
- memcmp(metadata, read_head->metadata->data(), metadata_size));
+ EXPECT_TRUE(read_head.metadata.get());
+ EXPECT_EQ(metadata_size, read_head.metadata->size());
+ EXPECT_EQ(0, memcmp(metadata, read_head.metadata->data(), metadata_size));
} else {
- EXPECT_FALSE(read_head->metadata.get());
+ EXPECT_FALSE(read_head.metadata.get());
}
EXPECT_TRUE(CompareHttpResponseInfos(
- write_info_buffer_->http_info.get(),
+ *write_info_buffer_->http_info,
storage_delegate_->loaded_info_->http_response_info()));
EXPECT_EQ(basic_response_size(),
storage_delegate_->loaded_info_->response_data_size());
@@ -494,9 +494,10 @@ class AppCacheResponseTest : public testing::Test {
void AmountWritten() {
static const char kHttpHeaders[] = "HTTP/1.0 200 OK\0\0";
std::string raw_headers(kHttpHeaders, arraysize(kHttpHeaders));
- net::HttpResponseInfo* head = MakeHttpResponseInfo(raw_headers);
+ std::unique_ptr<net::HttpResponseInfo> head =
+ MakeHttpResponseInfo(raw_headers);
int expected_amount_written =
- GetHttpResponseInfoSize(head) + kNumBlocks * kBlockSize;
+ GetHttpResponseInfoSize(*head) + kNumBlocks * kBlockSize;
// Push tasks in reverse order.
PushNextTask(base::BindOnce(&AppCacheResponseTest::Verify_AmountWritten,
@@ -507,7 +508,7 @@ class AppCacheResponseTest : public testing::Test {
base::Unretained(this), kNumBlocks - i));
}
PushNextTask(base::BindOnce(&AppCacheResponseTest::WriteResponseHead,
- base::Unretained(this), head));
+ base::Unretained(this), std::move(head)));
writer_.reset(service_->storage()->CreateResponseWriter(GURL()));
written_response_id_ = writer_->response_id();
diff --git a/chromium/content/browser/appcache/appcache_service_impl.cc b/chromium/content/browser/appcache/appcache_service_impl.cc
index 763140468ee..513eef22af8 100644
--- a/chromium/content/browser/appcache/appcache_service_impl.cc
+++ b/chromium/content/browser/appcache/appcache_service_impl.cc
@@ -14,7 +14,7 @@
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/single_thread_task_runner.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "content/browser/appcache/appcache.h"
#include "content/browser/appcache/appcache_backend_impl.h"
@@ -25,28 +25,18 @@
#include "content/browser/appcache/appcache_response.h"
#include "content/browser/appcache/appcache_service_impl.h"
#include "content/browser/appcache/appcache_storage_impl.h"
-#include "net/base/completion_callback.h"
#include "net/base/io_buffer.h"
#include "storage/browser/quota/special_storage_policy.h"
namespace content {
-namespace {
+AppCacheInfoCollection::AppCacheInfoCollection() = default;
-void DeferredCallback(OnceCompletionCallback callback, int rv) {
- std::move(callback).Run(rv);
-}
-
-} // namespace
-
-AppCacheInfoCollection::AppCacheInfoCollection() {}
-
-AppCacheInfoCollection::~AppCacheInfoCollection() {}
+AppCacheInfoCollection::~AppCacheInfoCollection() = default;
// AsyncHelper -------
-class AppCacheServiceImpl::AsyncHelper
- : public AppCacheStorage::Delegate {
+class AppCacheServiceImpl::AsyncHelper : public AppCacheStorage::Delegate {
public:
AsyncHelper(AppCacheServiceImpl* service, OnceCompletionCallback callback)
: service_(service), callback_(std::move(callback)) {
@@ -65,13 +55,12 @@ class AppCacheServiceImpl::AsyncHelper
protected:
void CallCallback(int rv) {
- if (!callback_.is_null()) {
+ if (callback_) {
// Defer to guarantee async completion.
base::SequencedTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::BindOnce(&DeferredCallback, std::move(callback_), rv));
+ FROM_HERE, base::BindOnce(std::move(callback_), rv));
}
- callback_.Reset();
+ DCHECK(!callback_);
}
AppCacheServiceImpl* service_;
@@ -90,11 +79,11 @@ void AppCacheServiceImpl::AsyncHelper::Cancel() {
class AppCacheServiceImpl::DeleteHelper : public AsyncHelper {
public:
- DeleteHelper(
- AppCacheServiceImpl* service, const GURL& manifest_url,
- const net::CompletionCallback& callback)
- : AsyncHelper(service, callback), manifest_url_(manifest_url) {
- }
+ DeleteHelper(AppCacheServiceImpl* service,
+ const GURL& manifest_url,
+ net::CompletionOnceCallback callback)
+ : AsyncHelper(service, std::move(callback)),
+ manifest_url_(manifest_url) {}
void Start() override {
service_->storage()->LoadOrCreateGroup(manifest_url_, this);
@@ -137,8 +126,8 @@ class AppCacheServiceImpl::DeleteOriginHelper : public AsyncHelper {
public:
DeleteOriginHelper(AppCacheServiceImpl* service,
const url::Origin& origin,
- const net::CompletionCallback& callback)
- : AsyncHelper(service, callback),
+ net::CompletionOnceCallback callback)
+ : AsyncHelper(service, std::move(callback)),
origin_(origin),
num_caches_to_delete_(0),
successes_(0),
@@ -261,7 +250,7 @@ class AppCacheServiceImpl::CheckResponseHelper : AsyncHelper {
const GURL& manifest_url,
int64_t cache_id,
int64_t response_id)
- : AsyncHelper(service, net::CompletionCallback()),
+ : AsyncHelper(service, net::CompletionOnceCallback()),
manifest_url_(manifest_url),
cache_id_(cache_id),
response_id_(response_id),
@@ -320,7 +309,8 @@ void AppCacheServiceImpl::CheckResponseHelper::OnGroupLoaded(
if (cache_->cache_id() == cache_id_) {
AppCacheHistograms::CountCheckResponseResult(
AppCacheHistograms::ENTRY_NOT_FOUND);
- service_->DeleteAppCacheGroup(manifest_url_, net::CompletionCallback());
+ service_->DeleteAppCacheGroup(manifest_url_,
+ net::CompletionOnceCallback());
} else {
AppCacheHistograms::CountCheckResponseResult(
AppCacheHistograms::RESPONSE_OUT_OF_DATE);
@@ -344,7 +334,7 @@ void AppCacheServiceImpl::CheckResponseHelper::OnReadInfoComplete(int result) {
if (result < 0) {
AppCacheHistograms::CountCheckResponseResult(
AppCacheHistograms::READ_HEADERS_ERROR);
- service_->DeleteAppCacheGroup(manifest_url_, net::CompletionCallback());
+ service_->DeleteAppCacheGroup(manifest_url_, net::CompletionOnceCallback());
delete this;
return;
}
@@ -380,7 +370,7 @@ void AppCacheServiceImpl::CheckResponseHelper::OnReadDataComplete(int result) {
AppCacheHistograms::CountCheckResponseResult(check_result);
if (check_result != AppCacheHistograms::RESPONSE_OK)
- service_->DeleteAppCacheGroup(manifest_url_, net::CompletionCallback());
+ service_->DeleteAppCacheGroup(manifest_url_, net::CompletionOnceCallback());
delete this;
}
@@ -442,9 +432,9 @@ void AppCacheServiceImpl::ScheduleReinitialize() {
// leave the appcache disabled for an indefinite period of time. Some
// users never shutdown the browser.
- const base::TimeDelta kZeroDelta;
- const base::TimeDelta kOneHour(base::TimeDelta::FromHours(1));
- const base::TimeDelta k30Seconds(base::TimeDelta::FromSeconds(30));
+ constexpr base::TimeDelta kZeroDelta;
+ constexpr base::TimeDelta kOneHour = base::TimeDelta::FromHours(1);
+ constexpr base::TimeDelta kThirtySeconds = base::TimeDelta::FromSeconds(30);
// If the system managed to stay up for long enough, reset the
// delay so a new failure won't incur a long wait to get going again.
@@ -456,7 +446,7 @@ void AppCacheServiceImpl::ScheduleReinitialize() {
this, &AppCacheServiceImpl::Reinitialize);
// Adjust the delay for next time.
- base::TimeDelta increment = std::max(k30Seconds, next_reinit_delay_);
+ base::TimeDelta increment = std::max(kThirtySeconds, next_reinit_delay_);
next_reinit_delay_ = std::min(next_reinit_delay_ + increment, kOneHour);
}
@@ -484,15 +474,17 @@ void AppCacheServiceImpl::GetAllAppCacheInfo(AppCacheInfoCollection* collection,
void AppCacheServiceImpl::DeleteAppCacheGroup(
const GURL& manifest_url,
- const net::CompletionCallback& callback) {
- DeleteHelper* helper = new DeleteHelper(this, manifest_url, callback);
+ net::CompletionOnceCallback callback) {
+ DeleteHelper* helper =
+ new DeleteHelper(this, manifest_url, std::move(callback));
helper->Start();
}
void AppCacheServiceImpl::DeleteAppCachesForOrigin(
const url::Origin& origin,
- const net::CompletionCallback& callback) {
- DeleteOriginHelper* helper = new DeleteOriginHelper(this, origin, callback);
+ net::CompletionOnceCallback callback) {
+ DeleteOriginHelper* helper =
+ new DeleteOriginHelper(this, origin, std::move(callback));
helper->Start();
}
@@ -512,8 +504,7 @@ void AppCacheServiceImpl::set_special_storage_policy(
void AppCacheServiceImpl::RegisterBackend(
AppCacheBackendImpl* backend_impl) {
DCHECK(backends_.find(backend_impl->process_id()) == backends_.end());
- backends_.insert(
- BackendMap::value_type(backend_impl->process_id(), backend_impl));
+ backends_.insert({backend_impl->process_id(), backend_impl});
}
void AppCacheServiceImpl::UnregisterBackend(
diff --git a/chromium/content/browser/appcache/appcache_service_impl.h b/chromium/content/browser/appcache/appcache_service_impl.h
index bf6fabe30ff..d83fc409e17 100644
--- a/chromium/content/browser/appcache/appcache_service_impl.h
+++ b/chromium/content/browser/appcache/appcache_service_impl.h
@@ -21,7 +21,7 @@
#include "content/common/appcache_interfaces.h"
#include "content/common/content_export.h"
#include "content/public/browser/appcache_service.h"
-#include "net/base/completion_callback.h"
+#include "net/base/completion_once_callback.h"
#include "net/base/net_errors.h"
#include "storage/browser/quota/quota_manager_proxy.h"
@@ -65,8 +65,7 @@ class CONTENT_EXPORT AppCacheStorageReference
// Class that manages the application cache service. Sends notifications
// to many frontends. One instance per user-profile. Each instance has
// exclusive access to its cache_directory on disk.
-class CONTENT_EXPORT AppCacheServiceImpl
- : public AppCacheService {
+class CONTENT_EXPORT AppCacheServiceImpl : public AppCacheService {
public:
class CONTENT_EXPORT Observer {
@@ -105,14 +104,13 @@ class CONTENT_EXPORT AppCacheServiceImpl
void GetAllAppCacheInfo(AppCacheInfoCollection* collection,
OnceCompletionCallback callback) override;
void DeleteAppCacheGroup(const GURL& manifest_url,
- const net::CompletionCallback& callback) override;
+ net::CompletionOnceCallback callback) override;
// Deletes all appcaches for the origin, 'callback' is invoked upon
// completion. This method always completes asynchronously.
// (virtual for unit testing)
- virtual void DeleteAppCachesForOrigin(
- const url::Origin& origin,
- const net::CompletionCallback& callback);
+ virtual void DeleteAppCachesForOrigin(const url::Origin& origin,
+ net::CompletionOnceCallback callback);
// Checks the integrity of 'response_id' by reading the headers and data.
// If it cannot be read, the cache group for 'manifest_url' is deleted.
@@ -155,8 +153,8 @@ class CONTENT_EXPORT AppCacheServiceImpl
void RegisterBackend(AppCacheBackendImpl* backend_impl);
virtual void UnregisterBackend(AppCacheBackendImpl* backend_impl);
AppCacheBackendImpl* GetBackend(int id) const {
- BackendMap::const_iterator it = backends_.find(id);
- return (it != backends_.end()) ? it->second : NULL;
+ auto it = backends_.find(id);
+ return (it != backends_.end()) ? it->second : nullptr;
}
AppCacheStorage* storage() const { return storage_.get(); }
@@ -193,10 +191,6 @@ class CONTENT_EXPORT AppCacheServiceImpl
class GetInfoHelper;
class CheckResponseHelper;
- using PendingAsyncHelpers =
- std::map<AsyncHelper*, std::unique_ptr<AsyncHelper>>;
- using BackendMap = std::map<int, AppCacheBackendImpl*>;
-
void Reinitialize();
base::FilePath cache_directory_;
@@ -206,8 +200,9 @@ class CONTENT_EXPORT AppCacheServiceImpl
std::unique_ptr<AppCacheStorage> storage_;
scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy_;
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy_;
- PendingAsyncHelpers pending_helpers_;
- BackendMap backends_; // One 'backend' per child process.
+ std::map<AsyncHelper*, std::unique_ptr<AsyncHelper>> pending_helpers_;
+ // One 'backend' per child process.
+ std::map<int, AppCacheBackendImpl*> backends_;
// Context for use during cache updates.
net::URLRequestContext* request_context_;
// If true, nothing (not even session-only data) should be deleted on exit.
@@ -215,7 +210,7 @@ class CONTENT_EXPORT AppCacheServiceImpl
base::Time last_reinit_time_;
base::TimeDelta next_reinit_delay_;
base::OneShotTimer reinit_timer_;
- base::ObserverList<Observer> observers_;
+ base::ObserverList<Observer>::Unchecked observers_;
// In the network service world contains the pointer to the
// URLLoaderFactoryGetter instance which is used to get to the network
diff --git a/chromium/content/browser/appcache/appcache_service_unittest.cc b/chromium/content/browser/appcache/appcache_service_unittest.cc
index 6d0d46cbc5c..50a7421ae9c 100644
--- a/chromium/content/browser/appcache/appcache_service_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_service_unittest.cc
@@ -18,7 +18,7 @@
#include "content/browser/appcache/appcache_response.h"
#include "content/browser/appcache/appcache_service_impl.h"
#include "content/browser/appcache/mock_appcache_storage.h"
-#include "net/base/completion_callback.h"
+#include "net/base/completion_once_callback.h"
#include "net/base/io_buffer.h"
#include "net/http/http_response_headers.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -101,10 +101,7 @@ class AppCacheServiceImplTest : public testing::Test {
kManifestUrl(kOriginURL.Resolve("manifest")),
service_(new AppCacheServiceImpl(nullptr)),
delete_result_(net::OK),
- delete_completion_count_(0),
- deletion_callback_(
- base::Bind(&AppCacheServiceImplTest::OnDeleteAppCachesComplete,
- base::Unretained(this))) {
+ delete_completion_count_(0) {
// Setup to use mock storage.
service_->storage_.reset(new MockAppCacheStorage(service_.get()));
}
@@ -183,6 +180,11 @@ class AppCacheServiceImplTest : public testing::Test {
return pickle->size();
}
+ net::CompletionOnceCallback deletion_callback() {
+ return base::BindOnce(&AppCacheServiceImplTest::OnDeleteAppCachesComplete,
+ base::Unretained(this));
+ }
+
const GURL kOriginURL;
const url::Origin kOrigin;
const GURL kManifestUrl;
@@ -191,12 +193,11 @@ class AppCacheServiceImplTest : public testing::Test {
std::unique_ptr<AppCacheServiceImpl> service_;
int delete_result_;
int delete_completion_count_;
- net::CompletionCallback deletion_callback_;
};
TEST_F(AppCacheServiceImplTest, DeleteAppCachesForOrigin) {
// Without giving mock storage simiulated info, should fail.
- service_->DeleteAppCachesForOrigin(kOrigin, deletion_callback_);
+ service_->DeleteAppCachesForOrigin(kOrigin, deletion_callback());
EXPECT_EQ(0, delete_completion_count_);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1, delete_completion_count_);
@@ -205,7 +206,7 @@ TEST_F(AppCacheServiceImplTest, DeleteAppCachesForOrigin) {
// Should succeed given an empty info collection.
mock_storage()->SimulateGetAllInfo(new content::AppCacheInfoCollection);
- service_->DeleteAppCachesForOrigin(kOrigin, deletion_callback_);
+ service_->DeleteAppCachesForOrigin(kOrigin, deletion_callback());
EXPECT_EQ(0, delete_completion_count_);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1, delete_completion_count_);
@@ -227,7 +228,7 @@ TEST_F(AppCacheServiceImplTest, DeleteAppCachesForOrigin) {
info_vector.push_back(mock_manifest_3);
info->infos_by_origin[kOrigin] = info_vector;
mock_storage()->SimulateGetAllInfo(info.get());
- service_->DeleteAppCachesForOrigin(kOrigin, deletion_callback_);
+ service_->DeleteAppCachesForOrigin(kOrigin, deletion_callback());
EXPECT_EQ(0, delete_completion_count_);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1, delete_completion_count_);
@@ -238,7 +239,7 @@ TEST_F(AppCacheServiceImplTest, DeleteAppCachesForOrigin) {
info->infos_by_origin[kOrigin] = info_vector;
mock_storage()->SimulateGetAllInfo(info.get());
mock_storage()->SimulateMakeGroupObsoleteFailure();
- service_->DeleteAppCachesForOrigin(kOrigin, deletion_callback_);
+ service_->DeleteAppCachesForOrigin(kOrigin, deletion_callback());
EXPECT_EQ(0, delete_completion_count_);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1, delete_completion_count_);
@@ -247,7 +248,7 @@ TEST_F(AppCacheServiceImplTest, DeleteAppCachesForOrigin) {
// Should complete with abort error if the service is deleted
// prior to a delete completion.
- service_->DeleteAppCachesForOrigin(kOrigin, deletion_callback_);
+ service_->DeleteAppCachesForOrigin(kOrigin, deletion_callback());
EXPECT_EQ(0, delete_completion_count_);
service_.reset(); // kill it
EXPECT_EQ(1, delete_completion_count_);
diff --git a/chromium/content/browser/appcache/appcache_storage.cc b/chromium/content/browser/appcache/appcache_storage.cc
index e4394e252df..3be839ed241 100644
--- a/chromium/content/browser/appcache/appcache_storage.cc
+++ b/chromium/content/browser/appcache/appcache_storage.cc
@@ -4,6 +4,8 @@
#include "content/browser/appcache/appcache_storage.h"
+#include <utility>
+
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/memory/ptr_util.h"
@@ -71,9 +73,8 @@ void AppCacheStorage::ResponseInfoLoadTask::OnReadComplete(int result) {
scoped_refptr<AppCacheResponseInfo> info;
if (result >= 0) {
- info = new AppCacheResponseInfo(storage_, manifest_url_,
- response_id_,
- info_buffer_->http_info.release(),
+ info = new AppCacheResponseInfo(storage_, manifest_url_, response_id_,
+ std::move(info_buffer_->http_info),
info_buffer_->response_data_size);
}
FOR_EACH_DELEGATE(delegates_, OnResponseInfoLoaded(info.get(), response_id_));
diff --git a/chromium/content/browser/appcache/appcache_storage.h b/chromium/content/browser/appcache/appcache_storage.h
index 2bf62b2c41f..5e49a2760a2 100644
--- a/chromium/content/browser/appcache/appcache_storage.h
+++ b/chromium/content/browser/appcache/appcache_storage.h
@@ -18,7 +18,6 @@
#include "base/memory/weak_ptr.h"
#include "content/browser/appcache/appcache_working_set.h"
#include "content/common/content_export.h"
-#include "net/base/completion_callback.h"
#include "url/origin.h"
class GURL;
diff --git a/chromium/content/browser/appcache/appcache_storage_impl.cc b/chromium/content/browser/appcache/appcache_storage_impl.cc
index b7003845da0..7ca367b82d4 100644
--- a/chromium/content/browser/appcache/appcache_storage_impl.cc
+++ b/chromium/content/browser/appcache/appcache_storage_impl.cc
@@ -35,7 +35,7 @@
#include "content/public/common/content_switches.h"
#include "net/base/cache_type.h"
#include "net/base/net_errors.h"
-#include "sql/connection.h"
+#include "sql/database.h"
#include "sql/transaction.h"
#include "storage/browser/quota/quota_client.h"
#include "storage/browser/quota/quota_manager.h"
@@ -44,17 +44,20 @@
namespace content {
-const int kMB = 1024 * 1024;
+namespace {
+
+constexpr const int kMB = 1024 * 1024;
// Hard coded default when not using quota management.
-static const int kDefaultQuota = 5 * kMB;
+constexpr const int kDefaultQuota = 5 * kMB;
-static const int kMaxAppCacheDiskCacheSize = 250 * kMB;
-static const int kMaxAppCacheMemDiskCacheSize = 10 * kMB;
-static const base::FilePath::CharType kDiskCacheDirectoryName[] =
- FILE_PATH_LITERAL("Cache");
+constexpr const int kMaxAppCacheDiskCacheSize = 250 * kMB;
+constexpr const int kMaxAppCacheMemDiskCacheSize = 10 * kMB;
-namespace {
+constexpr base::FilePath::CharType kDiskCacheDirectoryName[] =
+ FILE_PATH_LITERAL("Cache");
+constexpr base::FilePath::CharType kAppCacheDatabaseName[] =
+ FILE_PATH_LITERAL("Index");
// Helpers for clearing data from the AppCacheDatabase.
bool DeleteGroupAndRelatedRecords(
@@ -107,7 +110,7 @@ void AppCacheStorageImpl::ClearSessionOnlyOrigins(
if (origins.empty())
return; // nothing to delete
- sql::Connection* connection = database->db_connection();
+ sql::Database* connection = database->db_connection();
if (!connection) {
NOTREACHED() << "Missing database connection.";
return;
@@ -701,7 +704,7 @@ void AppCacheStorageImpl::StoreGroupAndCacheTask::OnQuotaCallback(
void AppCacheStorageImpl::StoreGroupAndCacheTask::Run() {
DCHECK(!success_);
- sql::Connection* connection = database_->db_connection();
+ sql::Database* connection = database_->db_connection();
if (!connection)
return;
@@ -872,7 +875,7 @@ class NetworkNamespaceHelper {
bool IsInNetworkNamespace(const GURL& url, int64_t cache_id) {
std::pair<WhiteListMap::iterator, bool> result = namespaces_map_.insert(
- WhiteListMap::value_type(cache_id, AppCacheNamespaceVector()));
+ WhiteListMap::value_type(cache_id, std::vector<AppCacheNamespace>()));
if (result.second)
GetOnlineWhiteListForCache(cache_id, &result.first->second);
return AppCache::FindNamespace(result.first->second, url) != nullptr;
@@ -880,7 +883,7 @@ class NetworkNamespaceHelper {
private:
void GetOnlineWhiteListForCache(int64_t cache_id,
- AppCacheNamespaceVector* namespaces) {
+ std::vector<AppCacheNamespace>* namespaces) {
DCHECK(namespaces && namespaces->empty());
using WhiteListVector =
std::vector<AppCacheDatabase::OnlineWhiteListRecord>;
@@ -896,7 +899,7 @@ class NetworkNamespaceHelper {
}
// Key is cache id
- using WhiteListMap = std::map<int64_t, AppCacheNamespaceVector>;
+ using WhiteListMap = std::map<int64_t, std::vector<AppCacheNamespace>>;
WhiteListMap namespaces_map_;
AppCacheDatabase* database_;
};
@@ -1185,7 +1188,7 @@ AppCacheStorageImpl::MakeGroupObsoleteTask::MakeGroupObsoleteTask(
void AppCacheStorageImpl::MakeGroupObsoleteTask::Run() {
DCHECK(!success_);
- sql::Connection* connection = database_->db_connection();
+ sql::Database* connection = database_->db_connection();
if (!connection)
return;
@@ -1975,8 +1978,8 @@ void AppCacheStorageImpl::LazilyCommitLastAccessTimes() {
const base::TimeDelta kDelay = base::TimeDelta::FromMinutes(5);
lazy_commit_timer_.Start(
FROM_HERE, kDelay,
- base::Bind(&AppCacheStorageImpl::OnLazyCommitTimer,
- weak_factory_.GetWeakPtr()));
+ base::BindOnce(&AppCacheStorageImpl::OnLazyCommitTimer,
+ weak_factory_.GetWeakPtr()));
}
void AppCacheStorageImpl::OnLazyCommitTimer() {
diff --git a/chromium/content/browser/appcache/appcache_storage_unittest.cc b/chromium/content/browser/appcache/appcache_storage_unittest.cc
index 961299a6eaa..b3ebc6a12e5 100644
--- a/chromium/content/browser/appcache/appcache_storage_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_storage_unittest.cc
@@ -29,7 +29,8 @@ class AppCacheStorageTest : public testing::Test {
TEST_F(AppCacheStorageTest, AddRemoveCache) {
MockAppCacheService service;
- scoped_refptr<AppCache> cache(new AppCache(service.storage(), 111));
+ scoped_refptr<AppCache> cache =
+ base::MakeRefCounted<AppCache>(service.storage(), 111);
EXPECT_EQ(cache.get(),
service.storage()->working_set()->GetCache(111));
@@ -45,14 +46,16 @@ TEST_F(AppCacheStorageTest, AddRemoveCache) {
TEST_F(AppCacheStorageTest, AddRemoveGroup) {
MockAppCacheService service;
- scoped_refptr<AppCacheGroup> group(
- new AppCacheGroup(service.storage(), GURL(), 111));
+ const GURL kManifestUrl("http://origin/");
+ scoped_refptr<AppCacheGroup> group =
+ base::MakeRefCounted<AppCacheGroup>(service.storage(), kManifestUrl, 111);
- EXPECT_EQ(group.get(), service.storage()->working_set()->GetGroup(GURL()));
+ EXPECT_EQ(group.get(),
+ service.storage()->working_set()->GetGroup(kManifestUrl));
service.storage()->working_set()->RemoveGroup(group.get());
- EXPECT_TRUE(!service.storage()->working_set()->GetGroup(GURL()));
+ EXPECT_TRUE(!service.storage()->working_set()->GetGroup(kManifestUrl));
// Removing non-existing group from service should not fail.
MockAppCacheService dummy;
@@ -61,10 +64,11 @@ TEST_F(AppCacheStorageTest, AddRemoveGroup) {
TEST_F(AppCacheStorageTest, AddRemoveResponseInfo) {
MockAppCacheService service;
- scoped_refptr<AppCacheResponseInfo> info(
- new AppCacheResponseInfo(service.storage(), GURL(),
- 111, new net::HttpResponseInfo,
- kUnkownResponseDataSize));
+ const GURL kManifestUrl("http://origin/");
+ scoped_refptr<AppCacheResponseInfo> info =
+ base::MakeRefCounted<AppCacheResponseInfo>(
+ service.storage(), kManifestUrl, 111,
+ std::make_unique<net::HttpResponseInfo>(), kUnkownResponseDataSize);
EXPECT_EQ(info.get(),
service.storage()->working_set()->GetResponseInfo(111));
@@ -121,8 +125,8 @@ TEST_F(AppCacheStorageTest, UsageMap) {
const url::Origin kOrigin2(url::Origin::Create(GURL("http://origin2/")));
MockAppCacheService service;
- scoped_refptr<MockQuotaManagerProxy> mock_proxy(
- new MockQuotaManagerProxy(nullptr, nullptr));
+ scoped_refptr<MockQuotaManagerProxy> mock_proxy =
+ base::MakeRefCounted<MockQuotaManagerProxy>(nullptr, nullptr);
service.set_quota_manager_proxy(mock_proxy.get());
service.storage()->UpdateUsageMapAndNotify(kOrigin, 0);
diff --git a/chromium/content/browser/appcache/appcache_subresource_url_factory.cc b/chromium/content/browser/appcache/appcache_subresource_url_factory.cc
index 08336328e4e..c3f75f9d9a1 100644
--- a/chromium/content/browser/appcache/appcache_subresource_url_factory.cc
+++ b/chromium/content/browser/appcache/appcache_subresource_url_factory.cc
@@ -108,7 +108,7 @@ class SubresourceLoader : public network::mojom::URLLoader,
network::mojom::URLLoaderClientPtr client_ptr;
local_client_binding_.Bind(mojo::MakeRequest(&client_ptr));
- std::move(handler).Run(mojo::MakeRequest(&appcache_loader_),
+ std::move(handler).Run(request_, mojo::MakeRequest(&appcache_loader_),
std::move(client_ptr));
}
diff --git a/chromium/content/browser/appcache/appcache_unittest.cc b/chromium/content/browser/appcache/appcache_unittest.cc
index 5fb6ea92bea..67c8b01e9a8 100644
--- a/chromium/content/browser/appcache/appcache_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_unittest.cc
@@ -5,6 +5,8 @@
#include <stddef.h>
#include <stdint.h>
+#include <vector>
+
#include "base/test/scoped_task_environment.h"
#include "content/browser/appcache/appcache.h"
#include "content/browser/appcache/appcache_host.h"
@@ -136,7 +138,7 @@ TEST_F(AppCacheTest, InitializeWithManifest) {
EXPECT_EQ(GURL("http://fb1.com"), fallbacks[0].namespace_url);
EXPECT_EQ(GURL("http://fbone.com"), fallbacks[0].target_url);
EXPECT_TRUE(fallbacks[0].is_pattern);
- const AppCacheNamespaceVector& whitelist =
+ const std::vector<AppCacheNamespace>& whitelist =
cache->online_whitelist_namespaces_;
expected = 2;
EXPECT_EQ(expected, whitelist.size());
diff --git a/chromium/content/browser/appcache/appcache_update_job.cc b/chromium/content/browser/appcache/appcache_update_job.cc
index a6d641667cb..32be530befe 100644
--- a/chromium/content/browser/appcache/appcache_update_job.cc
+++ b/chromium/content/browser/appcache/appcache_update_job.cc
@@ -688,8 +688,9 @@ void AppCacheUpdateJob::HandleManifestRefetchCompleted(URLFetcher* fetcher,
StoreGroupAndCache();
} else {
manifest_response_writer_.reset(CreateResponseWriter());
- scoped_refptr<HttpResponseInfoIOBuffer> io_buffer(
- new HttpResponseInfoIOBuffer(manifest_response_info_.release()));
+ scoped_refptr<HttpResponseInfoIOBuffer> io_buffer =
+ base::MakeRefCounted<HttpResponseInfoIOBuffer>(
+ std::move(manifest_response_info_));
manifest_response_writer_->WriteInfo(
io_buffer.get(),
base::BindOnce(&AppCacheUpdateJob::OnManifestInfoWriteComplete,
@@ -893,7 +894,8 @@ void AppCacheUpdateJob::CheckIfManifestChanged() {
GURL(), 0, false /*is_cross_origin*/),
DB_ERROR, GURL());
AppCacheHistograms::AddMissingManifestEntrySample();
- service->DeleteAppCacheGroup(manifest_url_, net::CompletionCallback());
+ service->DeleteAppCacheGroup(manifest_url_,
+ net::CompletionOnceCallback());
}
return;
}
@@ -989,8 +991,8 @@ void AppCacheUpdateJob::FetchUrls() {
DCHECK(existing_entry->response_id() ==
url_to_fetch.existing_response_info->response_id());
fetcher->set_existing_response_headers(
- url_to_fetch.existing_response_info->http_response_info()->headers
- .get());
+ url_to_fetch.existing_response_info->http_response_info()
+ .headers.get());
fetcher->set_existing_entry(*existing_entry);
}
fetcher->Start();
@@ -1167,7 +1169,7 @@ void AppCacheUpdateJob::OnResponseInfoLoaded(
AppCacheResponseInfo* response_info,
int64_t response_id) {
const net::HttpResponseInfo* http_info =
- response_info ? response_info->http_response_info() : nullptr;
+ response_info ? &response_info->http_response_info() : nullptr;
// Needed response info for a manifest fetch request.
if (internal_state_ == FETCH_MANIFEST) {
diff --git a/chromium/content/browser/appcache/appcache_update_job.h b/chromium/content/browser/appcache/appcache_update_job.h
index 262da887387..79eabef47b1 100644
--- a/chromium/content/browser/appcache/appcache_update_job.h
+++ b/chromium/content/browser/appcache/appcache_update_job.h
@@ -26,7 +26,6 @@
#include "content/browser/appcache/appcache_storage.h"
#include "content/common/appcache_interfaces.h"
#include "content/common/content_export.h"
-#include "net/base/completion_callback.h"
#include "net/http/http_response_headers.h"
#include "net/url_request/url_request.h"
#include "url/gurl.h"
diff --git a/chromium/content/browser/appcache/appcache_update_job_unittest.cc b/chromium/content/browser/appcache/appcache_update_job_unittest.cc
index d801ffce9a4..6cb4ce06c35 100644
--- a/chromium/content/browser/appcache/appcache_update_job_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_update_job_unittest.cc
@@ -7,6 +7,7 @@
#include <stddef.h>
#include <stdint.h>
+#include <memory>
#include <utility>
#include "base/bind.h"
@@ -1388,14 +1389,17 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
"HTTP/1.1 200 OK\0"
"Cache-Control: max-age=8675309\0"
"\0";
- net::HttpResponseHeaders* headers =
- new net::HttpResponseHeaders(std::string(data, arraysize(data)));
- net::HttpResponseInfo* response_info = new net::HttpResponseInfo();
+ scoped_refptr<net::HttpResponseHeaders> headers =
+ base::MakeRefCounted<net::HttpResponseHeaders>(
+ std::string(data, base::size(data)));
+ std::unique_ptr<net::HttpResponseInfo> response_info =
+ std::make_unique<net::HttpResponseInfo>();
response_info->request_time = base::Time::Now();
response_info->response_time = base::Time::Now();
- response_info->headers = headers; // adds ref to headers
- scoped_refptr<HttpResponseInfoIOBuffer> io_buffer(
- new HttpResponseInfoIOBuffer(response_info)); // adds ref to info
+ response_info->headers = std::move(headers);
+ scoped_refptr<HttpResponseInfoIOBuffer> io_buffer =
+ base::MakeRefCounted<HttpResponseInfoIOBuffer>(
+ std::move(response_info));
response_writer_->WriteInfo(
io_buffer.get(),
base::BindOnce(
@@ -1451,14 +1455,17 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
"HTTP/1.1 200 OK\0"
"Expires: Thu, 01 Dec 1994 16:00:00 GMT\0"
"\0";
- net::HttpResponseHeaders* headers =
- new net::HttpResponseHeaders(std::string(data, arraysize(data)));
- net::HttpResponseInfo* response_info = new net::HttpResponseInfo();
+ scoped_refptr<net::HttpResponseHeaders> headers =
+ base::MakeRefCounted<net::HttpResponseHeaders>(
+ std::string(data, base::size(data)));
+ std::unique_ptr<net::HttpResponseInfo> response_info =
+ std::make_unique<net::HttpResponseInfo>();
response_info->request_time = base::Time::Now();
response_info->response_time = base::Time::Now();
- response_info->headers = headers; // adds ref to headers
- scoped_refptr<HttpResponseInfoIOBuffer> io_buffer(
- new HttpResponseInfoIOBuffer(response_info)); // adds ref to info
+ response_info->headers = std::move(headers);
+ scoped_refptr<HttpResponseInfoIOBuffer> io_buffer =
+ base::MakeRefCounted<HttpResponseInfoIOBuffer>(
+ std::move(response_info));
response_writer_->WriteInfo(
io_buffer.get(),
base::BindOnce(
@@ -1514,14 +1521,17 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
"Cache-Control: max-age=8675309\0"
"Vary: blah\0"
"\0";
- net::HttpResponseHeaders* headers =
- new net::HttpResponseHeaders(std::string(data, arraysize(data)));
- net::HttpResponseInfo* response_info = new net::HttpResponseInfo();
+ scoped_refptr<net::HttpResponseHeaders> headers =
+ base::MakeRefCounted<net::HttpResponseHeaders>(
+ std::string(data, base::size(data)));
+ std::unique_ptr<net::HttpResponseInfo> response_info =
+ std::make_unique<net::HttpResponseInfo>();
response_info->request_time = base::Time::Now();
response_info->response_time = base::Time::Now();
- response_info->headers = headers; // adds ref to headers
- scoped_refptr<HttpResponseInfoIOBuffer> io_buffer(
- new HttpResponseInfoIOBuffer(response_info)); // adds ref to info
+ response_info->headers = std::move(headers);
+ scoped_refptr<HttpResponseInfoIOBuffer> io_buffer =
+ base::MakeRefCounted<HttpResponseInfoIOBuffer>(
+ std::move(response_info));
response_writer_->WriteInfo(
io_buffer.get(),
base::BindOnce(
@@ -1581,14 +1591,17 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
"Cache-Control: max-age=8675309\0"
"Vary: origin, accept-encoding\0"
"\0";
- net::HttpResponseHeaders* headers =
- new net::HttpResponseHeaders(std::string(data, arraysize(data)));
- net::HttpResponseInfo* response_info = new net::HttpResponseInfo();
+ scoped_refptr<net::HttpResponseHeaders> headers =
+ base::MakeRefCounted<net::HttpResponseHeaders>(
+ std::string(data, base::size(data)));
+ std::unique_ptr<net::HttpResponseInfo> response_info =
+ std::make_unique<net::HttpResponseInfo>();
response_info->request_time = base::Time::Now();
response_info->response_time = base::Time::Now();
- response_info->headers = headers; // adds ref to headers
- scoped_refptr<HttpResponseInfoIOBuffer> io_buffer(
- new HttpResponseInfoIOBuffer(response_info)); // adds ref to info
+ response_info->headers = std::move(headers);
+ scoped_refptr<HttpResponseInfoIOBuffer> io_buffer =
+ base::MakeRefCounted<HttpResponseInfoIOBuffer>(
+ std::move(response_info));
response_writer_->WriteInfo(
io_buffer.get(),
base::BindOnce(
@@ -3204,12 +3217,15 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
"HTTP/1.1 200 OK\0"
"Last-Modified: Sat, 29 Oct 1994 19:43:31 GMT\0"
"\0";
- net::HttpResponseHeaders* headers =
- new net::HttpResponseHeaders(std::string(data, arraysize(data)));
- net::HttpResponseInfo* response_info = new net::HttpResponseInfo();
- response_info->headers = headers; // adds ref to headers
- scoped_refptr<HttpResponseInfoIOBuffer> io_buffer(
- new HttpResponseInfoIOBuffer(response_info)); // adds ref to info
+ scoped_refptr<net::HttpResponseHeaders> headers =
+ base::MakeRefCounted<net::HttpResponseHeaders>(
+ std::string(data, base::size(data)));
+ std::unique_ptr<net::HttpResponseInfo> response_info =
+ std::make_unique<net::HttpResponseInfo>();
+ response_info->headers = std::move(headers);
+ scoped_refptr<HttpResponseInfoIOBuffer> io_buffer =
+ base::MakeRefCounted<HttpResponseInfoIOBuffer>(
+ std::move(response_info));
response_writer_->WriteInfo(
io_buffer.get(),
base::BindOnce(
@@ -3274,12 +3290,15 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
"HTTP/1.1 200 OK\0"
"ETag: \"LadeDade\"\0"
"\0";
- net::HttpResponseHeaders* headers =
- new net::HttpResponseHeaders(std::string(data, arraysize(data)));
- net::HttpResponseInfo* response_info = new net::HttpResponseInfo();
- response_info->headers = headers; // adds ref to headers
- scoped_refptr<HttpResponseInfoIOBuffer> io_buffer(
- new HttpResponseInfoIOBuffer(response_info)); // adds ref to info
+ scoped_refptr<net::HttpResponseHeaders> headers =
+ base::MakeRefCounted<net::HttpResponseHeaders>(
+ std::string(data, base::size(data)));
+ std::unique_ptr<net::HttpResponseInfo> response_info =
+ std::make_unique<net::HttpResponseInfo>();
+ response_info->headers = std::move(headers);
+ scoped_refptr<HttpResponseInfoIOBuffer> io_buffer =
+ base::MakeRefCounted<HttpResponseInfoIOBuffer>(
+ std::move(response_info));
response_writer_->WriteInfo(
io_buffer.get(),
base::BindOnce(
@@ -3532,11 +3551,12 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
const GURL& manifest_url,
int64_t response_id,
const std::string& raw_headers) {
- net::HttpResponseInfo* http_info = new net::HttpResponseInfo();
+ std::unique_ptr<net::HttpResponseInfo> http_info =
+ std::make_unique<net::HttpResponseInfo>();
http_info->headers = new net::HttpResponseHeaders(raw_headers);
scoped_refptr<AppCacheResponseInfo> info(
- new AppCacheResponseInfo(service_->storage(), manifest_url,
- response_id, http_info, 0));
+ new AppCacheResponseInfo(service_->storage(), manifest_url, response_id,
+ std::move(http_info), 0));
response_infos_.push_back(info);
return info.get();
}
diff --git a/chromium/content/browser/appcache/appcache_update_url_fetcher.cc b/chromium/content/browser/appcache/appcache_update_url_fetcher.cc
index f364e70cf9a..e9652f899a3 100644
--- a/chromium/content/browser/appcache/appcache_update_url_fetcher.cc
+++ b/chromium/content/browser/appcache/appcache_update_url_fetcher.cc
@@ -107,9 +107,10 @@ void AppCacheUpdateJob::URLFetcher::OnResponseStarted(int net_error) {
// completion before reading any response data.
if (fetch_type_ == URL_FETCH || fetch_type_ == MASTER_ENTRY_FETCH) {
response_writer_.reset(job_->CreateResponseWriter());
- scoped_refptr<HttpResponseInfoIOBuffer> io_buffer(
- new HttpResponseInfoIOBuffer(
- new net::HttpResponseInfo(request_->GetResponseInfo())));
+ scoped_refptr<HttpResponseInfoIOBuffer> io_buffer =
+ base::MakeRefCounted<HttpResponseInfoIOBuffer>(
+ std::make_unique<net::HttpResponseInfo>(
+ request_->GetResponseInfo()));
response_writer_->WriteInfo(
io_buffer.get(),
base::BindOnce(&URLFetcher::OnWriteComplete, base::Unretained(this)));
diff --git a/chromium/content/browser/appcache/appcache_url_loader_job.cc b/chromium/content/browser/appcache/appcache_url_loader_job.cc
index 1455c9f3f23..e4245c4861f 100644
--- a/chromium/content/browser/appcache/appcache_url_loader_job.cc
+++ b/chromium/content/browser/appcache/appcache_url_loader_job.cc
@@ -44,9 +44,6 @@ void AppCacheURLLoaderJob::DeliverAppCachedResponse(const GURL& manifest_url,
load_timing_info_.request_start_time = base::Time::Now();
load_timing_info_.request_start = base::TimeTicks::Now();
- AppCacheHistograms::AddAppCacheJobStartDelaySample(base::TimeTicks::Now() -
- start_time_tick_);
-
manifest_url_ = manifest_url;
cache_id_ = cache_id;
entry_ = entry;
@@ -66,16 +63,11 @@ void AppCacheURLLoaderJob::DeliverNetworkResponse() {
if (AppCacheRequestHandler::IsRunningInTests())
return;
- AppCacheHistograms::AddNetworkJobStartDelaySample(base::TimeTicks::Now() -
- start_time_tick_);
-
// We signal our caller with an empy callback that it needs to perform
// the network load.
DCHECK(loader_callback_ && !binding_.is_bound());
std::move(loader_callback_).Run({});
- weak_factory_.InvalidateWeakPtrs();
- is_deleting_soon_ = true;
- base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this);
+ DeleteSoon();
}
void AppCacheURLLoaderJob::DeliverErrorResponse() {
@@ -87,10 +79,18 @@ void AppCacheURLLoaderJob::DeliverErrorResponse() {
if (loader_callback_)
CallLoaderCallback();
- NotifyCompleted(net::ERR_FAILED);
- AppCacheHistograms::AddErrorJobStartDelaySample(base::TimeTicks::Now() -
- start_time_tick_);
+ if (!client_) {
+ // Although all callsites that lead to construction of AppCacheURLLoaderJob
+ // provide a NavigationLoaderInterceptor::LoaderCallback, some use weak
+ // pointers to bind it. So it's possible that in between the time that
+ // AppCacheURLLoaderJob grabs the response info from storage that the
+ // callback is now empty, which leads to client_ not being initialized.
+ DeleteSoon();
+ return;
+ }
+
+ NotifyCompleted(net::ERR_FAILED);
}
AppCacheURLLoaderJob* AppCacheURLLoaderJob::AsURLLoaderJob() {
@@ -129,13 +129,18 @@ void AppCacheURLLoaderJob::DeleteIfNeeded() {
delete this;
}
-void AppCacheURLLoaderJob::Start(network::mojom::URLLoaderRequest request,
- network::mojom::URLLoaderClientPtr client) {
+void AppCacheURLLoaderJob::Start(
+ const network::ResourceRequest& /* resource_request */,
+ network::mojom::URLLoaderRequest request,
+ network::mojom::URLLoaderClientPtr client) {
+ // TODO(crbug.com/876531): Figure out how AppCache interception should
+ // interact with URLLoaderThrottles. It might be incorrect to ignore
+ // |resource_request| here, since it's the current request after throttles.
DCHECK(!binding_.is_bound());
binding_.Bind(std::move(request));
client_ = std::move(client);
- binding_.set_connection_error_handler(base::BindOnce(
- &AppCacheURLLoaderJob::OnConnectionError, GetDerivedWeakPtr()));
+ binding_.set_connection_error_handler(
+ base::BindOnce(&AppCacheURLLoaderJob::DeleteSoon, GetDerivedWeakPtr()));
}
AppCacheURLLoaderJob::AppCacheURLLoaderJob(
@@ -178,6 +183,12 @@ void AppCacheURLLoaderJob::OnResponseInfoLoaded(
if (loader_callback_)
CallLoaderCallback();
+ if (!client_) {
+ // See comment in DeliverErrorResponse.
+ DeleteSoon();
+ return;
+ }
+
info_ = response_info;
reader_.reset(
storage_->CreateResponseReader(manifest_url_, entry_.response_id()));
@@ -248,7 +259,7 @@ void AppCacheURLLoaderJob::OnResponseBodyStreamReady(MojoResult result) {
ReadMore();
}
-void AppCacheURLLoaderJob::OnConnectionError() {
+void AppCacheURLLoaderJob::DeleteSoon() {
if (storage_.get())
storage_->CancelDelegateCallbacks(this);
weak_factory_.InvalidateWeakPtrs();
@@ -257,36 +268,34 @@ void AppCacheURLLoaderJob::OnConnectionError() {
}
void AppCacheURLLoaderJob::SendResponseInfo() {
- DCHECK(client_);
// If this is null it means the response information was sent to the client.
if (!data_pipe_.consumer_handle.is_valid())
return;
- const net::HttpResponseInfo* http_info = is_range_request()
- ? range_response_info_.get()
- : info_->http_response_info();
+ const net::HttpResponseInfo& http_info =
+ is_range_request() ? *range_response_info_ : info_->http_response_info();
network::ResourceResponseHead response_head;
- response_head.headers = http_info->headers;
+ response_head.headers = http_info.headers;
response_head.appcache_id = cache_id_;
response_head.appcache_manifest_url = manifest_url_;
- http_info->headers->GetMimeType(&response_head.mime_type);
- http_info->headers->GetCharset(&response_head.charset);
+ http_info.headers->GetMimeType(&response_head.mime_type);
+ http_info.headers->GetCharset(&response_head.charset);
// TODO(ananta)
// Verify if the times sent here are correct.
- response_head.request_time = http_info->request_time;
- response_head.response_time = http_info->response_time;
+ response_head.request_time = http_info.request_time;
+ response_head.response_time = http_info.response_time;
response_head.content_length =
is_range_request() ? range_response_info_->headers->GetContentLength()
: info_->response_data_size();
- response_head.connection_info = http_info->connection_info;
- response_head.socket_address = http_info->socket_address;
- response_head.was_fetched_via_spdy = http_info->was_fetched_via_spdy;
- response_head.was_alpn_negotiated = http_info->was_alpn_negotiated;
- response_head.alpn_negotiated_protocol = http_info->alpn_negotiated_protocol;
- if (http_info->ssl_info.cert)
- response_head.ssl_info = http_info->ssl_info;
+ response_head.connection_info = http_info.connection_info;
+ response_head.socket_address = http_info.socket_address;
+ response_head.was_fetched_via_spdy = http_info.was_fetched_via_spdy;
+ response_head.was_alpn_negotiated = http_info.was_alpn_negotiated;
+ response_head.alpn_negotiated_protocol = http_info.alpn_negotiated_protocol;
+ if (http_info.ssl_info.cert)
+ response_head.ssl_info = http_info.ssl_info;
response_head.load_timing = load_timing_info_;
client_->OnReceiveResponse(response_head);
@@ -334,7 +343,7 @@ void AppCacheURLLoaderJob::NotifyCompleted(int error_code) {
if (!error_code) {
const net::HttpResponseInfo* http_info =
is_range_request() ? range_response_info_.get()
- : (info_ ? info_->http_response_info() : nullptr);
+ : (info_ ? &info_->http_response_info() : nullptr);
status.exists_in_cache = http_info->was_cached;
status.completion_time = base::TimeTicks::Now();
status.encoded_body_length =
diff --git a/chromium/content/browser/appcache/appcache_url_loader_job.h b/chromium/content/browser/appcache/appcache_url_loader_job.h
index 1cc9ae22816..93767a7ca5f 100644
--- a/chromium/content/browser/appcache/appcache_url_loader_job.h
+++ b/chromium/content/browser/appcache/appcache_url_loader_job.h
@@ -39,7 +39,8 @@ class CONTENT_EXPORT AppCacheURLLoaderJob : public AppCacheJob,
~AppCacheURLLoaderJob() override;
// Sets up the bindings.
- void Start(network::mojom::URLLoaderRequest request,
+ void Start(const network::ResourceRequest& resource_request,
+ network::mojom::URLLoaderRequest request,
network::mojom::URLLoaderClientPtr client);
// AppCacheJob overrides.
@@ -89,8 +90,9 @@ class CONTENT_EXPORT AppCacheURLLoaderJob : public AppCacheJob,
// Callback invoked when the data pipe can be written to.
void OnResponseBodyStreamReady(MojoResult result);
- // Mojo binding error handler.
- void OnConnectionError();
+ // Schedules a task to delete self with some clean-ups. This is also used as
+ // a mojo binding error handler.
+ void DeleteSoon();
void SendResponseInfo();
void ReadMore();
diff --git a/chromium/content/browser/appcache/appcache_url_loader_request.cc b/chromium/content/browser/appcache/appcache_url_loader_request.cc
index 03e37c05688..75bd7798eec 100644
--- a/chromium/content/browser/appcache/appcache_url_loader_request.cc
+++ b/chromium/content/browser/appcache/appcache_url_loader_request.cc
@@ -84,6 +84,7 @@ void AppCacheURLLoaderRequest::UpdateWithRedirectInfo(
request_.url = redirect_info.new_url;
request_.method = redirect_info.new_method;
request_.referrer = GURL(redirect_info.new_referrer);
+ request_.referrer_policy = redirect_info.new_referrer_policy;
request_.site_for_cookies = redirect_info.new_site_for_cookies;
}
diff --git a/chromium/content/browser/appcache/appcache_url_request_job.cc b/chromium/content/browser/appcache/appcache_url_request_job.cc
index 70fd5664338..d0c16f3b250 100644
--- a/chromium/content/browser/appcache/appcache_url_request_job.cc
+++ b/chromium/content/browser/appcache/appcache_url_request_job.cc
@@ -138,8 +138,6 @@ void AppCacheURLRequestJob::BeginDelivery() {
switch (delivery_type_) {
case NETWORK_DELIVERY:
- AppCacheHistograms::AddNetworkJobStartDelaySample(
- base::TimeTicks::Now() - start_time_tick_);
// To fallthru to the network, we restart the request which will
// cause a new job to be created to retrieve the resource from the
// network. Our caller is responsible for arranging to not re-intercept
@@ -148,8 +146,6 @@ void AppCacheURLRequestJob::BeginDelivery() {
break;
case ERROR_DELIVERY:
- AppCacheHistograms::AddErrorJobStartDelaySample(
- base::TimeTicks::Now() - start_time_tick_);
request()->net_log().AddEvent(
net::NetLogEventType::APPCACHE_DELIVERING_ERROR_RESPONSE);
NotifyStartError(net::URLRequestStatus(net::URLRequestStatus::FAILED,
@@ -157,8 +153,6 @@ void AppCacheURLRequestJob::BeginDelivery() {
break;
case APPCACHED_DELIVERY:
- AppCacheHistograms::AddAppCacheJobStartDelaySample(
- base::TimeTicks::Now() - start_time_tick_);
request()->net_log().AddEvent(
is_fallback_
? net::NetLogEventType::APPCACHE_DELIVERING_FALLBACK_RESPONSE
@@ -222,7 +216,7 @@ const net::HttpResponseInfo* AppCacheURLRequestJob::http_info() const {
return nullptr;
if (range_response_info_)
return range_response_info_.get();
- return info_->http_response_info();
+ return &info_->http_response_info();
}
void AppCacheURLRequestJob::OnReadComplete(int result) {
diff --git a/chromium/content/browser/appcache/appcache_url_request_job_unittest.cc b/chromium/content/browser/appcache/appcache_url_request_job_unittest.cc
index f8413977f0e..266c8173551 100644
--- a/chromium/content/browser/appcache/appcache_url_request_job_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_url_request_job_unittest.cc
@@ -337,25 +337,28 @@ class AppCacheURLRequestJobTest : public testing::Test {
// Wrappers to call AppCacheResponseReader/Writer Read and Write methods
void WriteBasicResponse() {
- scoped_refptr<IOBuffer> body(new WrappedIOBuffer(kHttpBasicBody));
+ scoped_refptr<IOBuffer> body =
+ base::MakeRefCounted<WrappedIOBuffer>(kHttpBasicBody);
std::string raw_headers(kHttpBasicHeaders, arraysize(kHttpBasicHeaders));
WriteResponse(
MakeHttpResponseInfo(raw_headers), body.get(), strlen(kHttpBasicBody));
}
- void WriteResponse(net::HttpResponseInfo* head,
- IOBuffer* body, int body_len) {
+ void WriteResponse(std::unique_ptr<net::HttpResponseInfo> head,
+ IOBuffer* body,
+ int body_len) {
DCHECK(body);
scoped_refptr<IOBuffer> body_ref(body);
PushNextTask(base::BindOnce(&AppCacheURLRequestJobTest::WriteResponseBody,
base::Unretained(this), body_ref, body_len));
- WriteResponseHead(head);
+ WriteResponseHead(std::move(head));
}
- void WriteResponseHead(net::HttpResponseInfo* head) {
+ void WriteResponseHead(std::unique_ptr<net::HttpResponseInfo> head) {
EXPECT_FALSE(writer_->IsWritePending());
- expected_write_result_ = GetHttpResponseInfoSize(head);
- write_info_buffer_ = new HttpResponseInfoIOBuffer(head);
+ expected_write_result_ = GetHttpResponseInfoSize(*head);
+ write_info_buffer_ =
+ base::MakeRefCounted<HttpResponseInfoIOBuffer>(std::move(head));
writer_->WriteInfo(
write_info_buffer_.get(),
base::BindOnce(&AppCacheURLRequestJobTest::OnWriteInfoComplete,
@@ -409,36 +412,36 @@ class AppCacheURLRequestJobTest : public testing::Test {
// Helpers to work with HttpResponseInfo objects
- net::HttpResponseInfo* MakeHttpResponseInfo(const std::string& raw_headers) {
- net::HttpResponseInfo* info = new net::HttpResponseInfo;
+ std::unique_ptr<net::HttpResponseInfo> MakeHttpResponseInfo(
+ const std::string& raw_headers) {
+ std::unique_ptr<net::HttpResponseInfo> info =
+ std::make_unique<net::HttpResponseInfo>();
info->request_time = base::Time::Now();
info->response_time = base::Time::Now();
info->was_cached = false;
- info->headers = new net::HttpResponseHeaders(raw_headers);
+ info->headers = base::MakeRefCounted<net::HttpResponseHeaders>(raw_headers);
return info;
}
- int GetHttpResponseInfoSize(const net::HttpResponseInfo* info) {
- base::Pickle pickle;
- return PickleHttpResonseInfo(&pickle, info);
+ int GetHttpResponseInfoSize(const net::HttpResponseInfo& info) {
+ base::Pickle pickle = PickleHttpResonseInfo(info);
+ return pickle.size();
}
- bool CompareHttpResponseInfos(const net::HttpResponseInfo* info1,
- const net::HttpResponseInfo* info2) {
- base::Pickle pickle1;
- base::Pickle pickle2;
- PickleHttpResonseInfo(&pickle1, info1);
- PickleHttpResonseInfo(&pickle2, info2);
+ bool CompareHttpResponseInfos(const net::HttpResponseInfo& info1,
+ const net::HttpResponseInfo& info2) {
+ base::Pickle pickle1 = PickleHttpResonseInfo(info1);
+ base::Pickle pickle2 = PickleHttpResonseInfo(info2);
return (pickle1.size() == pickle2.size()) &&
(0 == memcmp(pickle1.data(), pickle2.data(), pickle1.size()));
}
- int PickleHttpResonseInfo(base::Pickle* pickle,
- const net::HttpResponseInfo* info) {
+ base::Pickle PickleHttpResonseInfo(const net::HttpResponseInfo& info) {
const bool kSkipTransientHeaders = true;
const bool kTruncated = false;
- info->Persist(pickle, kSkipTransientHeaders, kTruncated);
- return pickle->size();
+ base::Pickle pickle;
+ info.Persist(&pickle, kSkipTransientHeaders, kTruncated);
+ return pickle;
}
// Helpers to fill and verify blocks of memory with a value
@@ -665,8 +668,7 @@ class AppCacheURLRequestJobTest : public testing::Test {
void VerifyDeliverSmallAppCachedResponse() {
EXPECT_EQ(net::OK, url_request_delegate_->request_status());
EXPECT_TRUE(CompareHttpResponseInfos(
- write_info_buffer_->http_info.get(),
- &url_request_delegate_->received_info_));
+ *write_info_buffer_->http_info, url_request_delegate_->received_info_));
EXPECT_EQ(5, url_request_delegate_->amount_received_);
EXPECT_EQ(0, memcmp(kHttpBasicBody,
url_request_delegate_->received_data_->data(),
@@ -712,8 +714,7 @@ class AppCacheURLRequestJobTest : public testing::Test {
void VerifyDeliverLargeAppCachedResponse() {
EXPECT_EQ(net::OK, url_request_delegate_->request_status());
EXPECT_TRUE(CompareHttpResponseInfos(
- write_info_buffer_->http_info.get(),
- &url_request_delegate_->received_info_));
+ *write_info_buffer_->http_info, url_request_delegate_->received_info_));
EXPECT_EQ(3072, url_request_delegate_->amount_received_);
char* p = url_request_delegate_->received_data_->data();
for (int i = 0; i < 3; ++i, p += kBlockSize)
diff --git a/chromium/content/browser/appcache/mock_appcache_service.cc b/chromium/content/browser/appcache/mock_appcache_service.cc
index da773f185db..6505950fb3b 100644
--- a/chromium/content/browser/appcache/mock_appcache_service.cc
+++ b/chromium/content/browser/appcache/mock_appcache_service.cc
@@ -4,6 +4,8 @@
#include "content/browser/appcache/mock_appcache_service.h"
+#include <utility>
+
#include "base/bind.h"
#include "base/location.h"
#include "base/single_thread_task_runner.h"
@@ -11,17 +13,16 @@
namespace content {
-static void DeferredCallCallback(
- const net::CompletionCallback& callback, int rv) {
- callback.Run(rv);
+static void DeferredCallCallback(net::CompletionOnceCallback callback, int rv) {
+ std::move(callback).Run(rv);
}
void MockAppCacheService::DeleteAppCachesForOrigin(
const url::Origin& origin,
- const net::CompletionCallback& callback) {
+ net::CompletionOnceCallback callback) {
++delete_called_count_;
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(&DeferredCallCallback, callback,
+ FROM_HERE, base::BindOnce(&DeferredCallCallback, std::move(callback),
mock_delete_appcaches_for_origin_result_));
}
diff --git a/chromium/content/browser/appcache/mock_appcache_service.h b/chromium/content/browser/appcache/mock_appcache_service.h
index 51ac9c76591..322d12fd52c 100644
--- a/chromium/content/browser/appcache/mock_appcache_service.h
+++ b/chromium/content/browser/appcache/mock_appcache_service.h
@@ -24,9 +24,8 @@ class MockAppCacheService : public AppCacheServiceImpl {
// Just returns a canned completion code without actually
// removing groups and caches in our mock storage instance.
- void DeleteAppCachesForOrigin(
- const url::Origin& origin,
- const net::CompletionCallback& callback) override;
+ void DeleteAppCachesForOrigin(const url::Origin& origin,
+ net::CompletionOnceCallback callback) override;
void set_quota_manager_proxy(storage::QuotaManagerProxy* proxy) {
quota_manager_proxy_ = proxy;
diff --git a/chromium/content/browser/appcache/mock_appcache_storage.h b/chromium/content/browser/appcache/mock_appcache_storage.h
index 09a1fbd0722..4823ff0523f 100644
--- a/chromium/content/browser/appcache/mock_appcache_storage.h
+++ b/chromium/content/browser/appcache/mock_appcache_storage.h
@@ -144,7 +144,8 @@ class MockAppCacheStorage : public AppCacheStorage {
if (!disk_cache_) {
const int kMaxCacheSize = 10 * 1024 * 1024;
disk_cache_.reset(new AppCacheDiskCache);
- disk_cache_->InitWithMemBackend(kMaxCacheSize, net::CompletionCallback());
+ disk_cache_->InitWithMemBackend(kMaxCacheSize,
+ net::CompletionOnceCallback());
}
return disk_cache_.get();
}
diff --git a/chromium/content/browser/background_fetch/OWNERS b/chromium/content/browser/background_fetch/OWNERS
index a7cd217e75b..3a617dc86ba 100644
--- a/chromium/content/browser/background_fetch/OWNERS
+++ b/chromium/content/browser/background_fetch/OWNERS
@@ -3,9 +3,10 @@
# //chrome/browser/background_fetch/
# //content/common/background_fetch/
-awdf@chromium.org
peter@chromium.org
delphick@chromium.org
+nator@chromium.org
+rayankans@chromium.org
# TEAM: platform-capabilities@chromium.org
# COMPONENT: Blink>BackgroundFetch
diff --git a/chromium/content/browser/background_fetch/background_fetch.proto b/chromium/content/browser/background_fetch/background_fetch.proto
index c8708770309..d1cef4f3bfd 100644
--- a/chromium/content/browser/background_fetch/background_fetch.proto
+++ b/chromium/content/browser/background_fetch/background_fetch.proto
@@ -11,8 +11,26 @@ package content.proto;
// Stores per-registration (as opposed to per-request) data.
// https://wicg.github.io/background-fetch/#background-fetch-registration
//
-// Next Tag: 7
+// Next Tag: 9
message BackgroundFetchRegistration {
+ enum BackgroundFetchState {
+ PENDING = 0; // Default value.
+ FAILURE = 1;
+ SUCCESS = 2;
+ }
+
+ // This should be kept in sync with blink.mojom.BackgroundFetchFailureReason.
+ enum BackgroundFetchFailureReason {
+ NONE = 0; // Default value.
+ CANCELLED_FROM_UI = 1;
+ CANCELLED_BY_DEVELOPER = 2;
+ BAD_STATUS = 3;
+ FETCH_ERROR = 4;
+ SERVICE_WORKER_UNAVAILABLE = 5;
+ QUOTA_EXCEEDED = 6;
+ TOTAL_DOWNLOAD_SIZE_EXCEEDED = 7;
+ }
+
// See definition of |unique_id| in BackgroundFetchRegistrationId.
optional string unique_id = 1;
@@ -23,6 +41,8 @@ message BackgroundFetchRegistration {
optional uint64 uploaded = 4;
optional uint64 download_total = 5;
optional uint64 downloaded = 6;
+ optional BackgroundFetchState state = 7;
+ optional BackgroundFetchFailureReason failure_reason = 8;
}
// Developer provided options.
@@ -30,6 +50,8 @@ message BackgroundFetchRegistration {
//
// Next Tag: 3
message BackgroundFetchOptions {
+ // The initial title provided by the developer. This can be updated,
+ // and the most recent value is stored in BackgroundFetchUIOptions.
optional string title = 1;
// https://w3c.github.io/manifest/#dom-imageresource
@@ -66,7 +88,7 @@ message BackgroundFetchOptions {
// in memory. This information should be everything needed to reconstruct
// the state of an interrupted background fetch.
//
-// Next Tag: 7
+// Next Tag: 6
message BackgroundFetchMetadata {
optional int64 creation_microseconds_since_unix_epoch = 1;
optional string origin = 2;
@@ -76,10 +98,17 @@ message BackgroundFetchMetadata {
// Number of fetches initiated by the developer.
optional int32 num_fetches = 5;
+}
+
+// All the updateable options that show up in the UI (e.g. notification).
+//
+// Next Tag: 3
+message BackgroundFetchUIOptions {
+ optional string title = 1;
// Raw bytes needed to deserialize into a PNG icon. Only used if the icon
// has a max resolution of 256x256. This means this is at most ~256KB.
- optional bytes icon = 6;
+ optional bytes icon = 2;
}
// A background fetch request that is still in a pending state.
diff --git a/chromium/content/browser/background_fetch/background_fetch_context.cc b/chromium/content/browser/background_fetch/background_fetch_context.cc
index 38bdb10727d..13f6f472b29 100644
--- a/chromium/content/browser/background_fetch/background_fetch_context.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_context.cc
@@ -12,12 +12,16 @@
#include "content/browser/background_fetch/background_fetch_metrics.h"
#include "content/browser/background_fetch/background_fetch_registration_id.h"
#include "content/browser/background_fetch/background_fetch_registration_notifier.h"
+#include "content/browser/background_fetch/background_fetch_request_match_params.h"
#include "content/browser/background_fetch/background_fetch_scheduler.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/public/browser/background_fetch_delegate.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/web_contents.h"
#include "net/url_request/url_request_context_getter.h"
#include "storage/browser/blob/blob_data_handle.h"
+#include "storage/browser/quota/quota_manager_proxy.h"
namespace content {
@@ -25,7 +29,8 @@ BackgroundFetchContext::BackgroundFetchContext(
BrowserContext* browser_context,
const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context,
const scoped_refptr<content::CacheStorageContextImpl>&
- cache_storage_context)
+ cache_storage_context,
+ scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy)
: browser_context_(browser_context),
service_worker_context_(service_worker_context),
event_dispatcher_(service_worker_context),
@@ -38,7 +43,8 @@ BackgroundFetchContext::BackgroundFetchContext(
DCHECK(service_worker_context_);
data_manager_ = std::make_unique<BackgroundFetchDataManager>(
- browser_context_, service_worker_context, cache_storage_context);
+ browser_context_, service_worker_context, cache_storage_context,
+ std::move(quota_manager_proxy));
scheduler_ = std::make_unique<BackgroundFetchScheduler>(data_manager_.get());
delegate_proxy_.SetClickEventDispatcher(base::BindRepeating(
&BackgroundFetchContext::DispatchClickEvent, weak_factory_.GetWeakPtr()));
@@ -72,11 +78,9 @@ void BackgroundFetchContext::DidGetInitializationData(
}
for (auto& data : initialization_data) {
- CreateController(data.registration_id, data.options, data.icon,
- data.ui_title, data.num_completed_requests,
- data.num_requests, data.active_fetch_guids,
- std::make_unique<BackgroundFetchRegistration>(
- std::move(data.registration)));
+ CreateController(data.registration_id, data.registration, data.options,
+ data.icon, data.ui_title, data.num_completed_requests,
+ data.num_requests, std::move(data.active_fetch_requests));
}
}
@@ -104,7 +108,7 @@ void BackgroundFetchContext::GetDeveloperIdsForServiceWorker(
void BackgroundFetchContext::DidGetRegistration(
blink::mojom::BackgroundFetchService::GetRegistrationCallback callback,
blink::mojom::BackgroundFetchError error,
- std::unique_ptr<BackgroundFetchRegistration> registration) {
+ const BackgroundFetchRegistration& registration) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (error != blink::mojom::BackgroundFetchError::NONE) {
@@ -113,13 +117,15 @@ void BackgroundFetchContext::DidGetRegistration(
return;
}
- DCHECK(registration);
+ BackgroundFetchRegistration updated_registration(registration);
+
// The data manager only has the number of bytes from completed downloads, so
// augment this with the number of downloaded bytes from in-progress jobs.
- DCHECK(job_controllers_.count(registration->unique_id));
- registration->downloaded +=
- job_controllers_[registration->unique_id]->GetInProgressDownloadedBytes();
- std::move(callback).Run(error, *registration.get());
+ DCHECK(job_controllers_.count(registration.unique_id));
+ updated_registration.downloaded +=
+ job_controllers_[registration.unique_id]->GetInProgressDownloadedBytes();
+
+ std::move(callback).Run(error, updated_registration);
}
void BackgroundFetchContext::StartFetch(
@@ -127,6 +133,7 @@ void BackgroundFetchContext::StartFetch(
const std::vector<ServiceWorkerFetchRequest>& requests,
const BackgroundFetchOptions& options,
const SkBitmap& icon,
+ RenderFrameHost* render_frame_host,
blink::mojom::BackgroundFetchService::FetchCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -137,11 +144,58 @@ void BackgroundFetchContext::StartFetch(
DCHECK_EQ(0u, fetch_callbacks_.count(registration_id));
fetch_callbacks_[registration_id] = std::move(callback);
- data_manager_->CreateRegistration(
- registration_id, requests, options, icon,
+ // |data_manager| is guaranteed to outlive |this|. |create_registration| is
+ // passed to `DidGetPermission`, which is tied to |weak_factory_|. That means
+ // that if |create_registration| runs, |this| is still alive, as is
+ // |data_manager| (a pointer owned by |this|).
+ auto create_registration = base::BindOnce(
+ &BackgroundFetchDataManager::CreateRegistration,
+ base::Unretained(data_manager_.get()), registration_id, requests, options,
+ icon,
base::BindOnce(&BackgroundFetchContext::DidCreateRegistration,
- weak_factory_.GetWeakPtr(), registration_id, options, icon,
- requests.size()));
+ weak_factory_.GetWeakPtr(), registration_id));
+
+ GetPermissionForOrigin(
+ registration_id.origin(), render_frame_host,
+ base::BindOnce(&BackgroundFetchContext::DidGetPermission,
+ weak_factory_.GetWeakPtr(), std::move(create_registration),
+ registration_id));
+}
+
+void BackgroundFetchContext::GetPermissionForOrigin(
+ const url::Origin& origin,
+ RenderFrameHost* render_frame_host,
+ GetPermissionCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ ResourceRequestInfo::WebContentsGetter wc_getter = base::NullCallback();
+
+ // Permissions need to go through the DownloadRequestLimiter if the fetch
+ // is started from a top-level frame.
+ if (render_frame_host && !render_frame_host->GetParent()) {
+ wc_getter = base::BindRepeating(&WebContents::FromFrameTreeNodeId,
+ render_frame_host->GetFrameTreeNodeId());
+ }
+
+ delegate_proxy_.GetPermissionForOrigin(origin, std::move(wc_getter),
+ std::move(callback));
+}
+
+void BackgroundFetchContext::DidGetPermission(
+ base::OnceClosure permission_closure,
+ const BackgroundFetchRegistrationId& registration_id,
+ bool has_permission) {
+ if (has_permission) {
+ std::move(permission_closure).Run();
+ return;
+ }
+
+ // No permission, the fetch should be rejected.
+ background_fetch::RecordRegistrationCreatedError(
+ blink::mojom::BackgroundFetchError::PERMISSION_DENIED);
+ std::move(fetch_callbacks_[registration_id])
+ .Run(blink::mojom::BackgroundFetchError::PERMISSION_DENIED,
+ base::nullopt);
}
void BackgroundFetchContext::GetIconDisplaySize(
@@ -153,35 +207,25 @@ void BackgroundFetchContext::GetIconDisplaySize(
void BackgroundFetchContext::DidCreateRegistration(
const BackgroundFetchRegistrationId& registration_id,
- const BackgroundFetchOptions& options,
- const SkBitmap& icon,
- size_t num_requests,
blink::mojom::BackgroundFetchError error,
- std::unique_ptr<BackgroundFetchRegistration> registration) {
+ const BackgroundFetchRegistration& registration) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
background_fetch::RecordRegistrationCreatedError(error);
- if (error != blink::mojom::BackgroundFetchError::NONE) {
- DCHECK(fetch_callbacks_.count(registration_id));
- std::move(fetch_callbacks_[registration_id])
- .Run(error, base::nullopt /* BackgroundFetchRegistration */);
- fetch_callbacks_.erase(registration_id);
- return;
- }
- if (hang_registration_creation_for_testing_) {
- // Hang here, to allow time for testing races. For instance, this helps us
- // test the behavior when a service worker gets unregistered before the
- // controller can be created.
+ auto iter = fetch_callbacks_.find(registration_id);
+
+ // The fetch might have been abandoned already if the Service Worker was
+ // unregistered or corrupted while registration was in progress.
+ if (iter == fetch_callbacks_.end())
return;
- }
- DCHECK(registration);
+ if (error == blink::mojom::BackgroundFetchError::NONE)
+ std::move(iter->second).Run(error, registration);
+ else
+ std::move(iter->second).Run(error, base::nullopt /* registration */);
- // Create the BackgroundFetchJobController to do the actual fetching.
- CreateController(registration_id, options, icon, options.title,
- 0u /* num_completed_requests */, num_requests,
- {} /* outstanding_guids */, std::move(registration));
+ fetch_callbacks_.erase(registration_id);
}
void BackgroundFetchContext::AddRegistrationObserver(
@@ -192,7 +236,8 @@ void BackgroundFetchContext::AddRegistrationObserver(
void BackgroundFetchContext::UpdateUI(
const BackgroundFetchRegistrationId& registration_id,
- const std::string& title,
+ const base::Optional<std::string>& title,
+ const base::Optional<SkBitmap>& icon,
blink::mojom::BackgroundFetchService::UpdateUICallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -203,7 +248,7 @@ void BackgroundFetchContext::UpdateUI(
return;
}
- data_manager_->UpdateRegistrationUI(registration_id, title,
+ data_manager_->UpdateRegistrationUI(registration_id, title, icon,
std::move(callback));
}
@@ -212,6 +257,13 @@ void BackgroundFetchContext::OnServiceWorkerDatabaseCorrupted(
AbandonFetches(service_worker_registration_id);
}
+void BackgroundFetchContext::OnQuotaExceeded(
+ const BackgroundFetchRegistrationId& registration_id) {
+ auto job_it = job_controllers_.find(registration_id.unique_id());
+ if (job_it != job_controllers_.end() && job_it->second)
+ job_it->second->Abort(BackgroundFetchReasonToAbort::QUOTA_EXCEEDED);
+}
+
void BackgroundFetchContext::AbandonFetches(
int64_t service_worker_registration_id) {
// Abandon all active fetches associated with this service worker.
@@ -228,6 +280,7 @@ void BackgroundFetchContext::AbandonFetches(
.service_worker_registration_id() ==
service_worker_registration_id) {
DCHECK(saved_iter->second);
+
saved_iter->second->Abort(
BackgroundFetchReasonToAbort::SERVICE_WORKER_UNAVAILABLE);
}
@@ -249,14 +302,38 @@ void BackgroundFetchContext::AbandonFetches(
}
}
+void BackgroundFetchContext::OnRegistrationCreated(
+ const BackgroundFetchRegistrationId& registration_id,
+ const BackgroundFetchRegistration& registration,
+ const BackgroundFetchOptions& options,
+ const SkBitmap& icon,
+ int num_requests) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (hang_registration_creation_for_testing_) {
+ // Hang here, to allow time for testing races. For instance, this helps us
+ // test the behavior when a service worker gets unregistered before the
+ // controller can be created.
+ return;
+ }
+
+ // TODO(peter): When this moves to the BackgroundFetchScheduler, only create
+ // a controller when the background fetch can actually be started.
+
+ CreateController(registration_id, registration, options, icon, options.title,
+ 0u /* num_completed_requests */, num_requests,
+ {} /* active_fetch_requests */);
+}
+
void BackgroundFetchContext::OnUpdatedUI(
const BackgroundFetchRegistrationId& registration_id,
- const std::string& title) {
+ const base::Optional<std::string>& title,
+ const base::Optional<SkBitmap>& icon) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
auto iter = job_controllers_.find(registration_id.unique_id());
if (iter != job_controllers_.end())
- iter->second->UpdateUI(title);
+ iter->second->UpdateUI(title, icon);
}
void BackgroundFetchContext::OnRegistrationDeleted(
@@ -273,18 +350,19 @@ void BackgroundFetchContext::OnStorageWiped() {
void BackgroundFetchContext::CreateController(
const BackgroundFetchRegistrationId& registration_id,
+ const BackgroundFetchRegistration& registration,
const BackgroundFetchOptions& options,
const SkBitmap& icon,
const std::string& ui_title,
size_t num_completed_requests,
size_t num_requests,
- const std::vector<std::string>& outstanding_guids,
- std::unique_ptr<BackgroundFetchRegistration> registration) {
+ std::vector<scoped_refptr<BackgroundFetchRequestInfo>>
+ active_fetch_requests) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
auto controller = std::make_unique<BackgroundFetchJobController>(
- &delegate_proxy_, registration_id, options, icon,
- registration->downloaded, scheduler_.get(),
+ &delegate_proxy_, scheduler_.get(), registration_id, options, icon,
+ registration.downloaded,
// Safe because JobControllers are destroyed before RegistrationNotifier.
base::BindRepeating(&BackgroundFetchRegistrationNotifier::Notify,
base::Unretained(registration_notifier_.get())),
@@ -293,16 +371,10 @@ void BackgroundFetchContext::CreateController(
base::Bind(&background_fetch::RecordSchedulerFinishedError)));
controller->InitializeRequestStatus(num_completed_requests, num_requests,
- outstanding_guids, ui_title);
+ std::move(active_fetch_requests),
+ ui_title);
scheduler_->AddJobController(controller.get());
job_controllers_.emplace(registration_id.unique_id(), std::move(controller));
-
- auto fetch_callback_iter = fetch_callbacks_.find(registration_id);
- if (fetch_callback_iter != fetch_callbacks_.end()) {
- std::move(fetch_callback_iter->second)
- .Run(blink::mojom::BackgroundFetchError::NONE, *registration);
- fetch_callbacks_.erase(fetch_callback_iter);
- }
}
void BackgroundFetchContext::Abort(
@@ -344,34 +416,45 @@ void BackgroundFetchContext::DidMarkForDeletion(
if (error != blink::mojom::BackgroundFetchError::NONE)
return;
+ auto controllers_iter = job_controllers_.find(registration_id.unique_id());
+
if (reason_to_abort == BackgroundFetchReasonToAbort::ABORTED_BY_DEVELOPER) {
- DCHECK(job_controllers_.count(registration_id.unique_id()));
- job_controllers_[registration_id.unique_id()]->Abort(reason_to_abort);
+ DCHECK(controllers_iter != job_controllers_.end());
+ controllers_iter->second->Abort(reason_to_abort);
}
+ auto registration = controllers_iter->second->NewRegistration(
+ blink::mojom::BackgroundFetchState::FAILURE);
switch (reason_to_abort) {
case BackgroundFetchReasonToAbort::ABORTED_BY_DEVELOPER:
case BackgroundFetchReasonToAbort::CANCELLED_FROM_UI:
CleanupRegistration(registration_id, {},
- mojom::BackgroundFetchState::FAILED);
- // TODO(rayankans): Send fetches to the event dispatcher.
+ blink::mojom::BackgroundFetchState::FAILURE);
event_dispatcher_.DispatchBackgroundFetchAbortEvent(
- registration_id, {} /* settled_fetches */, base::DoNothing());
+ registration_id, std::move(registration), base::DoNothing());
return;
case BackgroundFetchReasonToAbort::TOTAL_DOWNLOAD_SIZE_EXCEEDED:
case BackgroundFetchReasonToAbort::SERVICE_WORKER_UNAVAILABLE:
+ case BackgroundFetchReasonToAbort::QUOTA_EXCEEDED:
case BackgroundFetchReasonToAbort::NONE:
// This will send a BackgroundFetchFetched or BackgroundFetchFail event.
+ // We still need this to figure out which event to send.
+ // TODO(crbug.com/699957, crbug.com/874092): Add a method to only return
+ // the information needed to dispatch these events, instead of settled
+ // fetches.
data_manager_->GetSettledFetchesForRegistration(
registration_id,
+ std::make_unique<BackgroundFetchRequestMatchParams>(),
base::BindOnce(&BackgroundFetchContext::DidGetSettledFetches,
- weak_factory_.GetWeakPtr(), registration_id));
+ weak_factory_.GetWeakPtr(), registration_id,
+ std::move(registration)));
return;
}
}
void BackgroundFetchContext::DidGetSettledFetches(
const BackgroundFetchRegistrationId& registration_id,
+ std::unique_ptr<BackgroundFetchRegistration> registration,
blink::mojom::BackgroundFetchError error,
bool background_fetch_succeeded,
std::vector<BackgroundFetchSettledFetch> settled_fetches,
@@ -380,17 +463,26 @@ void BackgroundFetchContext::DidGetSettledFetches(
if (error != blink::mojom::BackgroundFetchError::NONE) {
CleanupRegistration(registration_id, {} /* fetches */,
- mojom::BackgroundFetchState::FAILED,
+ blink::mojom::BackgroundFetchState::FAILURE,
true /* preserve_info_to_dispatch_click_event */);
return;
}
- // The `backgroundfetched` event will be invoked when all requests in the
+ DCHECK(job_controllers_.count(registration_id.unique_id()));
+
+ if (job_controllers_[registration_id.unique_id()]->total_downloads() !=
+ static_cast<int>(settled_fetches.size())) {
+ // Something went wrong, and some information was lost.
+ background_fetch_succeeded = false;
+ }
+
+ // The `backgroundfetchsuccess` event will be invoked when all requests in the
// registration have completed successfully. In all other cases, the
// `backgroundfetchfail` event will be invoked instead.
if (background_fetch_succeeded) {
- event_dispatcher_.DispatchBackgroundFetchedEvent(
- registration_id, std::move(settled_fetches),
+ registration->state = blink::mojom::BackgroundFetchState::SUCCESS;
+ event_dispatcher_.DispatchBackgroundFetchSuccessEvent(
+ registration_id, std::move(registration),
base::BindOnce(
&BackgroundFetchContext::CleanupRegistration,
weak_factory_.GetWeakPtr(), registration_id,
@@ -398,18 +490,20 @@ void BackgroundFetchContext::DidGetSettledFetches(
// |blob_data_handles| to the callback to keep them alive
// until the waitUntil event is resolved.
std::move(blob_data_handles),
- mojom::BackgroundFetchState::SUCCEEDED,
+ blink::mojom::BackgroundFetchState::SUCCESS,
true /* preserve_info_to_dispatch_click_event */));
} else {
+ registration->state = blink::mojom::BackgroundFetchState::FAILURE;
event_dispatcher_.DispatchBackgroundFetchFailEvent(
- registration_id, std::move(settled_fetches),
+ registration_id, std::move(registration),
base::BindOnce(
&BackgroundFetchContext::CleanupRegistration,
weak_factory_.GetWeakPtr(), registration_id,
// The blob uuid is sent as part of |settled_fetches|. Bind
// |blob_data_handles| to the callback to keep them alive
// until the waitUntil event is resolved.
- std::move(blob_data_handles), mojom::BackgroundFetchState::FAILED,
+ std::move(blob_data_handles),
+ blink::mojom::BackgroundFetchState::FAILURE,
true /* preserve_info_to_dispatch_click_event */));
}
}
@@ -417,19 +511,22 @@ void BackgroundFetchContext::DidGetSettledFetches(
void BackgroundFetchContext::CleanupRegistration(
const BackgroundFetchRegistrationId& registration_id,
const std::vector<std::unique_ptr<storage::BlobDataHandle>>& blob_handles,
- mojom::BackgroundFetchState background_fetch_state,
+ blink::mojom::BackgroundFetchState background_fetch_state,
bool preserve_info_to_dispatch_click_event) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
// If we had an active JobController, it is no longer necessary, as the
// notification's UI can no longer be updated after the fetch is aborted, or
- // after the waitUntil promise of the backgroundfetched/backgroundfetchfail
- // event has been resolved. Store the information we want to persist after
- // the controller is gone, in completed_fetches_.
- scheduler_->RemoveJobController(registration_id);
+ // after the waitUntil promise of the
+ // backgroundfetchsuccess/backgroundfetchfail event has been resolved. Store
+ // the information we want to persist after the controller is gone, in
+ // completed_fetches_.
+ auto controllers_iter = job_controllers_.find(registration_id.unique_id());
+ DCHECK(controllers_iter != job_controllers_.end());
if (preserve_info_to_dispatch_click_event) {
- completed_fetches_[registration_id.unique_id()] = {registration_id,
- background_fetch_state};
+ completed_fetches_[registration_id.unique_id()] = std::make_pair(
+ registration_id,
+ controllers_iter->second->NewRegistration(background_fetch_state));
}
job_controllers_.erase(registration_id.unique_id());
@@ -453,7 +550,7 @@ void BackgroundFetchContext::DispatchClickEvent(const std::string& unique_id) {
// The fetch has succeeded or failed. (not aborted/cancelled).
event_dispatcher_.DispatchBackgroundFetchClickEvent(
iter->second.first /* registration_id */,
- iter->second.second /* background_fetch_state */, base::DoNothing());
+ std::move(iter->second.second) /* registration */, base::DoNothing());
completed_fetches_.erase(iter);
return;
}
@@ -462,9 +559,41 @@ void BackgroundFetchContext::DispatchClickEvent(const std::string& unique_id) {
auto controllers_iter = job_controllers_.find(unique_id);
if (controllers_iter == job_controllers_.end())
return;
+ // TODO(crbug.com/873630): Implement a background fetch state manager to
+ // keep track of states, and stop hard-coding it here.
+ auto registration = controllers_iter->second->NewRegistration(
+ blink::mojom::BackgroundFetchState::PENDING);
event_dispatcher_.DispatchBackgroundFetchClickEvent(
- controllers_iter->second->registration_id(),
- mojom::BackgroundFetchState::PENDING, base::DoNothing());
+ controllers_iter->second->registration_id(), std::move(registration),
+ base::DoNothing());
+}
+
+void BackgroundFetchContext::MatchRequests(
+ const BackgroundFetchRegistrationId& registration_id,
+ std::unique_ptr<BackgroundFetchRequestMatchParams> match_params,
+ blink::mojom::BackgroundFetchService::MatchRequestsCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ data_manager_->GetSettledFetchesForRegistration(
+ registration_id, std::move(match_params),
+ base::BindOnce(&BackgroundFetchContext::DidGetMatchingRequests,
+ weak_factory_.GetWeakPtr(), std::move(callback)));
+}
+
+void BackgroundFetchContext::DidGetMatchingRequests(
+ blink::mojom::BackgroundFetchService::MatchRequestsCallback callback,
+ blink::mojom::BackgroundFetchError error,
+ bool background_fetch_succeeded,
+ std::vector<BackgroundFetchSettledFetch> settled_fetches,
+ std::vector<std::unique_ptr<storage::BlobDataHandle>> blob_data_handles) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ // TODO(crbug.com/863016): Update to 0u once we've stopped sending an
+ // uncached response.
+ if (error != blink::mojom::BackgroundFetchError::NONE)
+ DCHECK_EQ(settled_fetches.size(), 1u);
+
+ std::move(callback).Run(std::move(settled_fetches));
}
void BackgroundFetchContext::LastObserverGarbageCollected(
diff --git a/chromium/content/browser/background_fetch/background_fetch_context.h b/chromium/content/browser/background_fetch/background_fetch_context.h
index a6b05e1267a..e25b9151c53 100644
--- a/chromium/content/browser/background_fetch/background_fetch_context.h
+++ b/chromium/content/browser/background_fetch/background_fetch_context.h
@@ -13,6 +13,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
+#include "base/optional.h"
#include "content/browser/background_fetch/background_fetch_data_manager_observer.h"
#include "content/browser/background_fetch/background_fetch_delegate_proxy.h"
#include "content/browser/background_fetch/background_fetch_event_dispatcher.h"
@@ -24,6 +25,7 @@
namespace storage {
class BlobDataHandle;
+class QuotaManagerProxy;
}
namespace content {
@@ -33,9 +35,12 @@ class BackgroundFetchDataManager;
struct BackgroundFetchOptions;
class BackgroundFetchRegistrationId;
class BackgroundFetchRegistrationNotifier;
+class BackgroundFetchRequestMatchParams;
+class BackgroundFetchRequestInfo;
class BackgroundFetchScheduler;
class BrowserContext;
class CacheStorageContextImpl;
+class RenderFrameHost;
class ServiceWorkerContextWrapper;
struct ServiceWorkerFetchRequest;
@@ -55,7 +60,8 @@ class CONTENT_EXPORT BackgroundFetchContext
BrowserContext* browser_context,
const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context,
const scoped_refptr<content::CacheStorageContextImpl>&
- cache_storage_context);
+ cache_storage_context,
+ scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy);
void InitializeOnIOThread();
@@ -85,6 +91,7 @@ class CONTENT_EXPORT BackgroundFetchContext
const std::vector<ServiceWorkerFetchRequest>& requests,
const BackgroundFetchOptions& options,
const SkBitmap& icon,
+ RenderFrameHost* render_frame_host,
blink::mojom::BackgroundFetchService::FetchCallback callback);
// Gets display size for the icon for Background Fetch UI.
@@ -92,6 +99,12 @@ class CONTENT_EXPORT BackgroundFetchContext
blink::mojom::BackgroundFetchService::GetIconDisplaySizeCallback
callback);
+ // Matches Background Fetch requests from the cache and returns responses.
+ void MatchRequests(
+ const BackgroundFetchRegistrationId& registration_id,
+ std::unique_ptr<BackgroundFetchRequestMatchParams> match_params,
+ blink::mojom::BackgroundFetchService::MatchRequestsCallback callback);
+
// Aborts the Background Fetch for the |registration_id|. The callback will be
// invoked with INVALID_ID if the registration has already completed or
// aborted, STORAGE_ERROR if an I/O error occurs, or NONE for success.
@@ -105,19 +118,31 @@ class CONTENT_EXPORT BackgroundFetchContext
const std::string& unique_id,
blink::mojom::BackgroundFetchRegistrationObserverPtr observer);
- // Updates the title of the Background Fetch identified by |registration_id|.
- // The |callback| will be invoked when the title has been updated, or an error
- // occurred that prevents it from doing so.
+ // Updates the title or icon of the Background Fetch identified by
+ // |registration_id|. The |callback| will be invoked when the title has been
+ // updated, or an error occurred that prevents it from doing so.
+ // The icon is wrapped in an optional. If the optional has a value then the
+ // internal |icon| is guarnteed to be not null.
void UpdateUI(
const BackgroundFetchRegistrationId& registration_id,
- const std::string& title,
+ const base::Optional<std::string>& title,
+ const base::Optional<SkBitmap>& icon,
blink::mojom::BackgroundFetchService::UpdateUICallback callback);
// BackgroundFetchDataManagerObserver implementation.
+ void OnRegistrationCreated(
+ const BackgroundFetchRegistrationId& registration_id,
+ const BackgroundFetchRegistration& registration,
+ const BackgroundFetchOptions& options,
+ const SkBitmap& icon,
+ int num_requests) override;
void OnUpdatedUI(const BackgroundFetchRegistrationId& registration_id,
- const std::string& title) override;
+ const base::Optional<std::string>& title,
+ const base::Optional<SkBitmap>& icon) override;
void OnServiceWorkerDatabaseCorrupted(
int64_t service_worker_registration_id) override;
+ void OnQuotaExceeded(
+ const BackgroundFetchRegistrationId& registration_id) override;
// ServiceWorkerContextCoreObserver implementation.
void OnRegistrationDeleted(int64_t registration_id,
@@ -125,6 +150,10 @@ class CONTENT_EXPORT BackgroundFetchContext
void OnStorageWiped() override;
private:
+ using GetPermissionCallback = base::OnceCallback<void(bool)>;
+
+ FRIEND_TEST_ALL_PREFIXES(BackgroundFetchServiceTest,
+ JobsInitializedOnBrowserRestart);
friend class BackgroundFetchServiceTest;
friend class BackgroundFetchJobControllerTest;
friend class base::DeleteHelper<BackgroundFetchContext>;
@@ -138,31 +167,28 @@ class CONTENT_EXPORT BackgroundFetchContext
// Creates a new Job Controller for the given |registration_id| and |options|,
// which will start fetching the files that are part of the registration.
- void CreateController(
- const BackgroundFetchRegistrationId& registration_id,
- const BackgroundFetchOptions& options,
- const SkBitmap& icon,
- const std::string& ui_title,
- size_t num_completed_requests,
- size_t num_requests,
- const std::vector<std::string>& outstanding_guids,
- std::unique_ptr<BackgroundFetchRegistration> registration);
+ void CreateController(const BackgroundFetchRegistrationId& registration_id,
+ const BackgroundFetchRegistration& registration,
+ const BackgroundFetchOptions& options,
+ const SkBitmap& icon,
+ const std::string& ui_title,
+ size_t num_completed_requests,
+ size_t num_requests,
+ std::vector<scoped_refptr<BackgroundFetchRequestInfo>>
+ active_fetch_requests);
// Called when an existing registration has been retrieved from the data
// manager. If the registration does not exist then |registration| is nullptr.
void DidGetRegistration(
blink::mojom::BackgroundFetchService::GetRegistrationCallback callback,
blink::mojom::BackgroundFetchError error,
- std::unique_ptr<BackgroundFetchRegistration> registration);
+ const BackgroundFetchRegistration& registration);
// Called when a new registration has been created by the data manager.
void DidCreateRegistration(
const BackgroundFetchRegistrationId& registration_id,
- const BackgroundFetchOptions& options,
- const SkBitmap& icon,
- size_t num_requests,
blink::mojom::BackgroundFetchError error,
- std::unique_ptr<BackgroundFetchRegistration> registration);
+ const BackgroundFetchRegistration& registration);
// Called by a JobController when it finishes processing. Also used to
// implement |Abort|.
@@ -182,6 +208,17 @@ class CONTENT_EXPORT BackgroundFetchContext
// retrieved from storage, and the Service Worker event can be invoked.
void DidGetSettledFetches(
const BackgroundFetchRegistrationId& registration_id,
+ std::unique_ptr<BackgroundFetchRegistration> registration,
+ blink::mojom::BackgroundFetchError error,
+ bool background_fetch_succeeded,
+ std::vector<BackgroundFetchSettledFetch> settled_fetches,
+ std::vector<std::unique_ptr<storage::BlobDataHandle>> blob_data_handles);
+
+ // Called when the sequence of matching settled fetches have been received
+ // from storage, and |callback| can be invoked to pass these on to the
+ // renderer.
+ void DidGetMatchingRequests(
+ blink::mojom::BackgroundFetchService::MatchRequestsCallback callback,
blink::mojom::BackgroundFetchError error,
bool background_fetch_succeeded,
std::vector<BackgroundFetchSettledFetch> settled_fetches,
@@ -208,7 +245,7 @@ class CONTENT_EXPORT BackgroundFetchContext
const BackgroundFetchRegistrationId& registration_id,
const std::vector<std::unique_ptr<storage::BlobDataHandle>>&
blob_data_handles,
- mojom::BackgroundFetchState background_fetch_state,
+ blink::mojom::BackgroundFetchState background_fetch_state,
bool preserve_info_to_dispatch_click_event = false);
// Called when the last JavaScript BackgroundFetchRegistration object has been
@@ -227,6 +264,17 @@ class CONTENT_EXPORT BackgroundFetchContext
// blink::mojom::kInvalidServiceWorkerRegistrationId.
void AbandonFetches(int64_t service_worker_registration_id);
+ // Check if |origin| has permission to start a fetch.
+ // virtual for testing.
+ void GetPermissionForOrigin(const url::Origin& origin,
+ RenderFrameHost* render_frame_host,
+ GetPermissionCallback callback);
+
+ // Callback for GetPermissionForOrigin.
+ void DidGetPermission(base::OnceClosure permission_closure,
+ const BackgroundFetchRegistrationId& registration_id,
+ bool has_permission);
+
// |this| is owned, indirectly, by the BrowserContext.
BrowserContext* browser_context_;
@@ -238,20 +286,19 @@ class CONTENT_EXPORT BackgroundFetchContext
std::unique_ptr<BackgroundFetchScheduler> scheduler_;
// Map from background fetch registration |unique_id|s to active job
- // controllers. Must be destroyed before |data_manager_| and
+ // controllers. Must be destroyed before |data_manager_|, |scheduler_| and
// |registration_notifier_|.
std::map<std::string, std::unique_ptr<BackgroundFetchJobController>>
job_controllers_;
- // Map from background fetch registration |unique_ids|s to {background fetch
- // registration id, fetch state}. An entry in here means the fetch has
- // completed. This information is needed after the fetch has completed.
+ // Map from |unique_id|s to {|registration_id|, |registration|}.
+ // An entry in here means the fetch has completed. This information is needed
+ // after the fetch has completed to dispatch the backgroundfetchclick event.
// TODO(crbug.com/857122): Clean this up when the UI is no longer showing.
- std::map<
- std::string,
- std::pair<BackgroundFetchRegistrationId, mojom::BackgroundFetchState>>
+ std::map<std::string,
+ std::pair<BackgroundFetchRegistrationId,
+ std::unique_ptr<BackgroundFetchRegistration>>>
completed_fetches_;
-
// Map from BackgroundFetchRegistrationIds to FetchCallbacks for active
// fetches. Must be destroyed before |data_manager_| and
// |registration_notifier_|. Since FetchCallback is a OnceCallback, please
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 c326cdc1da3..1fac2a819f9 100644
--- a/chromium/content/browser/background_fetch/background_fetch_data_manager.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_data_manager.cc
@@ -18,6 +18,7 @@
#include "content/browser/background_fetch/storage/delete_registration_task.h"
#include "content/browser/background_fetch/storage/get_developer_ids_task.h"
#include "content/browser/background_fetch/storage/get_metadata_task.h"
+#include "content/browser/background_fetch/storage/get_registration_task.h"
#include "content/browser/background_fetch/storage/get_settled_fetches_task.h"
#include "content/browser/background_fetch/storage/mark_registration_for_deletion_task.h"
#include "content/browser/background_fetch/storage/mark_request_complete_task.h"
@@ -28,44 +29,19 @@
#include "content/browser/storage_partition_impl.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
+#include "storage/browser/quota/quota_manager_proxy.h"
#include "third_party/blink/public/mojom/blob/blob.mojom.h"
namespace content {
-namespace {
-
-// Helper function to convert a BackgroundFetchRegistration proto into a
-// BackgroundFetchRegistration struct, and call the appropriate callback.
-void GetRegistrationFromMetadata(
- BackgroundFetchDataManager::GetRegistrationCallback callback,
- blink::mojom::BackgroundFetchError error,
- std::unique_ptr<proto::BackgroundFetchMetadata> metadata_proto) {
- if (!metadata_proto) {
- std::move(callback).Run(error, nullptr);
- return;
- }
-
- const auto& registration_proto = metadata_proto->registration();
- auto registration = std::make_unique<BackgroundFetchRegistration>();
- registration->developer_id = registration_proto.developer_id();
- registration->unique_id = registration_proto.unique_id();
- // TODO(crbug.com/774054): Uploads are not yet supported.
- registration->upload_total = registration_proto.upload_total();
- registration->uploaded = registration_proto.uploaded();
- registration->download_total = registration_proto.download_total();
- registration->downloaded = registration_proto.downloaded();
-
- std::move(callback).Run(error, std::move(registration));
-}
-
-} // namespace
-
BackgroundFetchDataManager::BackgroundFetchDataManager(
BrowserContext* browser_context,
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
- scoped_refptr<CacheStorageContextImpl> cache_storage_context)
+ scoped_refptr<CacheStorageContextImpl> cache_storage_context,
+ scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy)
: service_worker_context_(std::move(service_worker_context)),
cache_storage_context_(std::move(cache_storage_context)),
+ quota_manager_proxy_(std::move(quota_manager_proxy)),
weak_ptr_factory_(this) {
// Constructed on the UI thread, then used on the IO thread.
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -125,23 +101,8 @@ void BackgroundFetchDataManager::CreateRegistration(
GetRegistrationCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- auto registration_callback =
- base::BindOnce(&GetRegistrationFromMetadata, std::move(callback));
AddDatabaseTask(std::make_unique<background_fetch::CreateMetadataTask>(
- this, registration_id, requests, options, icon,
- std::move(registration_callback)));
-}
-
-void BackgroundFetchDataManager::GetMetadata(
- int64_t service_worker_registration_id,
- const url::Origin& origin,
- const std::string& developer_id,
- GetMetadataCallback callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- AddDatabaseTask(std::make_unique<background_fetch::GetMetadataTask>(
- this, service_worker_registration_id, origin, developer_id,
- std::move(callback)));
+ this, registration_id, requests, options, icon, std::move(callback)));
}
void BackgroundFetchDataManager::GetRegistration(
@@ -151,20 +112,20 @@ void BackgroundFetchDataManager::GetRegistration(
GetRegistrationCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- auto registration_callback =
- base::BindOnce(&GetRegistrationFromMetadata, std::move(callback));
- GetMetadata(service_worker_registration_id, origin, developer_id,
- std::move(registration_callback));
+ AddDatabaseTask(std::make_unique<background_fetch::GetRegistrationTask>(
+ this, service_worker_registration_id, origin, developer_id,
+ std::move(callback)));
}
void BackgroundFetchDataManager::UpdateRegistrationUI(
const BackgroundFetchRegistrationId& registration_id,
- const std::string& title,
+ const base::Optional<std::string>& title,
+ const base::Optional<SkBitmap>& icon,
blink::mojom::BackgroundFetchService::UpdateUICallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
AddDatabaseTask(std::make_unique<background_fetch::UpdateRegistrationUITask>(
- this, registration_id, title, std::move(callback)));
+ this, registration_id, title, icon, std::move(callback)));
}
void BackgroundFetchDataManager::PopNextRequest(
@@ -174,50 +135,49 @@ void BackgroundFetchDataManager::PopNextRequest(
auto start_next_request = base::BindOnce(
&BackgroundFetchDataManager::AddStartNextPendingRequestTask,
- weak_ptr_factory_.GetWeakPtr(),
- registration_id.service_worker_registration_id(), std::move(callback));
+ weak_ptr_factory_.GetWeakPtr(), registration_id, std::move(callback));
// Get the associated metadata, and add a StartNextPendingRequestTask.
- GetMetadata(registration_id.service_worker_registration_id(),
- registration_id.origin(), registration_id.developer_id(),
- std::move(start_next_request));
+ AddDatabaseTask(std::make_unique<background_fetch::GetRegistrationTask>(
+ this, registration_id.service_worker_registration_id(),
+ registration_id.origin(), registration_id.developer_id(),
+ std::move(start_next_request)));
}
void BackgroundFetchDataManager::AddStartNextPendingRequestTask(
- int64_t service_worker_registration_id,
+ const BackgroundFetchRegistrationId& registration_id,
NextRequestCallback callback,
blink::mojom::BackgroundFetchError error,
- std::unique_ptr<proto::BackgroundFetchMetadata> metadata) {
- if (!metadata) {
+ const BackgroundFetchRegistration& registration) {
+ if (error != blink::mojom::BackgroundFetchError::NONE) {
// Stop giving out requests as registration aborted (or otherwise finished).
std::move(callback).Run(nullptr /* request */);
return;
}
- DCHECK_EQ(error, blink::mojom::BackgroundFetchError::NONE);
AddDatabaseTask(
std::make_unique<background_fetch::StartNextPendingRequestTask>(
- this, service_worker_registration_id, std::move(metadata),
- std::move(callback)));
+ this, registration_id, registration, std::move(callback)));
}
void BackgroundFetchDataManager::MarkRequestAsComplete(
const BackgroundFetchRegistrationId& registration_id,
- BackgroundFetchRequestInfo* request,
- BackgroundFetchScheduler::MarkedCompleteCallback callback) {
+ scoped_refptr<BackgroundFetchRequestInfo> request_info,
+ base::OnceClosure closure) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
AddDatabaseTask(std::make_unique<background_fetch::MarkRequestCompleteTask>(
- this, registration_id, request, std::move(callback)));
+ this, registration_id, std::move(request_info), std::move(closure)));
}
void BackgroundFetchDataManager::GetSettledFetchesForRegistration(
const BackgroundFetchRegistrationId& registration_id,
+ std::unique_ptr<BackgroundFetchRequestMatchParams> match_params,
SettledFetchesCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
AddDatabaseTask(std::make_unique<background_fetch::GetSettledFetchesTask>(
- this, registration_id, std::move(callback)));
+ this, registration_id, std::move(match_params), std::move(callback)));
}
void BackgroundFetchDataManager::MarkRegistrationForDeletion(
diff --git a/chromium/content/browser/background_fetch/background_fetch_data_manager.h b/chromium/content/browser/background_fetch/background_fetch_data_manager.h
index 56119296c98..253831a6deb 100644
--- a/chromium/content/browser/background_fetch/background_fetch_data_manager.h
+++ b/chromium/content/browser/background_fetch/background_fetch_data_manager.h
@@ -18,6 +18,7 @@
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/observer_list.h"
+#include "base/optional.h"
#include "content/browser/background_fetch/background_fetch.pb.h"
#include "content/browser/background_fetch/background_fetch_registration_id.h"
#include "content/browser/background_fetch/background_fetch_scheduler.h"
@@ -30,12 +31,14 @@
namespace storage {
class BlobDataHandle;
+class QuotaManagerProxy;
}
namespace content {
class BackgroundFetchDataManagerObserver;
class BackgroundFetchRequestInfo;
+class BackgroundFetchRequestMatchParams;
struct BackgroundFetchSettledFetch;
class BrowserContext;
class CacheStorageManager;
@@ -65,20 +68,17 @@ class CONTENT_EXPORT BackgroundFetchDataManager
bool /* background_fetch_succeeded */,
std::vector<BackgroundFetchSettledFetch>,
std::vector<std::unique_ptr<storage::BlobDataHandle>>)>;
- using GetMetadataCallback =
- base::OnceCallback<void(blink::mojom::BackgroundFetchError,
- std::unique_ptr<proto::BackgroundFetchMetadata>)>;
using GetRegistrationCallback =
base::OnceCallback<void(blink::mojom::BackgroundFetchError,
- std::unique_ptr<BackgroundFetchRegistration>)>;
+ const BackgroundFetchRegistration&)>;
using NextRequestCallback =
base::OnceCallback<void(scoped_refptr<BackgroundFetchRequestInfo>)>;
- using NumRequestsCallback = base::OnceCallback<void(size_t)>;
BackgroundFetchDataManager(
BrowserContext* browser_context,
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
- scoped_refptr<CacheStorageContextImpl> cache_storage_context);
+ scoped_refptr<CacheStorageContextImpl> cache_storage_context,
+ scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy);
~BackgroundFetchDataManager() override;
@@ -104,12 +104,6 @@ class CONTENT_EXPORT BackgroundFetchDataManager
const SkBitmap& icon,
GetRegistrationCallback callback);
- // Get the BackgroundFetchMetadata.
- void GetMetadata(int64_t service_worker_registration_id,
- const url::Origin& origin,
- const std::string& developer_id,
- GetMetadataCallback callback);
-
// Get the BackgroundFetchRegistration.
void GetRegistration(int64_t service_worker_registration_id,
const url::Origin& origin,
@@ -119,26 +113,30 @@ class CONTENT_EXPORT BackgroundFetchDataManager
// Updates the UI values for a Background Fetch registration.
void UpdateRegistrationUI(
const BackgroundFetchRegistrationId& registration_id,
- const std::string& title,
+ const base::Optional<std::string>& title,
+ const base::Optional<SkBitmap>& icon,
blink::mojom::BackgroundFetchService::UpdateUICallback callback);
- // Reads all settled fetches for the given |registration_id|. Both the Request
- // and Response objects will be initialised based on the stored data. Will
- // invoke the |callback| when the list of fetches has been compiled.
+ // Reads the settled fetches for the given |registration_id| based on
+ // |match_params|. Both the Request and Response objects will be initialised
+ // based on the stored data. Will invoke the |callback| when the list of
+ // fetches has been compiled.
void GetSettledFetchesForRegistration(
const BackgroundFetchRegistrationId& registration_id,
+ std::unique_ptr<BackgroundFetchRequestMatchParams> match_params,
SettledFetchesCallback callback);
- // Marks that the backgroundfetched/backgroundfetchfail/backgroundfetchabort
- // event is being dispatched. It's not possible to call DeleteRegistration at
- // this point as JavaScript may hold a reference to a
- // BackgroundFetchRegistration object and we need to keep the corresponding
- // data around until the last such reference is released (or until shutdown).
- // We can't just move the Background Fetch registration's data to RAM as it
- // might consume too much memory. So instead this step disassociates the
- // |developer_id| from the |unique_id|, so that existing JS objects with a
- // reference to |unique_id| can still access the data, but it can no longer be
- // reached using GetIds or GetRegistration.
+ // Marks that the
+ // backgroundfetchsuccess/backgroundfetchfail/backgroundfetchabort event is
+ // being dispatched. It's not possible to call DeleteRegistration at this
+ // point as JavaScript may hold a reference to a BackgroundFetchRegistration
+ // object and we need to keep the corresponding data around until the last
+ // such reference is released (or until shutdown). We can't just move the
+ // Background Fetch registration's data to RAM as it might consume too much
+ // memory. So instead this step disassociates the |developer_id| from the
+ // |unique_id|, so that existing JS objects with a reference to |unique_id|
+ // can still access the data, but it can no longer be reached using GetIds or
+ // GetRegistration.
void MarkRegistrationForDeletion(
const BackgroundFetchRegistrationId& registration_id,
HandleBackgroundFetchErrorCallback callback);
@@ -157,18 +155,18 @@ class CONTENT_EXPORT BackgroundFetchDataManager
const url::Origin& origin,
blink::mojom::BackgroundFetchService::GetDeveloperIdsCallback callback);
- const base::ObserverList<BackgroundFetchDataManagerObserver>& observers() {
+ const base::ObserverList<BackgroundFetchDataManagerObserver>::Unchecked&
+ observers() {
return observers_;
}
// BackgroundFetchScheduler::RequestProvider implementation:
void PopNextRequest(const BackgroundFetchRegistrationId& registration_id,
NextRequestCallback callback) override;
-
void MarkRequestAsComplete(
const BackgroundFetchRegistrationId& registration_id,
- BackgroundFetchRequestInfo* request,
- BackgroundFetchScheduler::MarkedCompleteCallback callback) override;
+ scoped_refptr<BackgroundFetchRequestInfo> request_info,
+ base::OnceClosure closure) override;
void ShutdownOnIO();
@@ -191,12 +189,15 @@ class CONTENT_EXPORT BackgroundFetchDataManager
ChromeBlobStorageContext* blob_storage_context() const {
return blob_storage_context_.get();
}
+ storage::QuotaManagerProxy* quota_manager_proxy() const {
+ return quota_manager_proxy_.get();
+ }
void AddStartNextPendingRequestTask(
- int64_t service_worker_registration_id,
+ const BackgroundFetchRegistrationId& registration_id,
NextRequestCallback callback,
blink::mojom::BackgroundFetchError error,
- std::unique_ptr<proto::BackgroundFetchMetadata> metadata);
+ const BackgroundFetchRegistration& registration);
void AddDatabaseTask(std::unique_ptr<background_fetch::DatabaseTask> task);
@@ -213,6 +214,8 @@ class CONTENT_EXPORT BackgroundFetchDataManager
scoped_refptr<CacheStorageContextImpl> cache_storage_context_;
+ scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy_;
+
// The BackgroundFetch stores its own reference to CacheStorageManager
// in case StoragePartitionImpl is destoyed, which releases the reference.
scoped_refptr<CacheStorageManager> cache_manager_;
@@ -224,7 +227,7 @@ class CONTENT_EXPORT BackgroundFetchDataManager
// Invariant: the frontmost task, if any, has already been started.
base::queue<std::unique_ptr<background_fetch::DatabaseTask>> database_tasks_;
- base::ObserverList<BackgroundFetchDataManagerObserver> observers_;
+ base::ObserverList<BackgroundFetchDataManagerObserver>::Unchecked observers_;
// The |unique_id|s of registrations that have been deactivated since the
// browser was last started. They will be automatically deleted when the
diff --git a/chromium/content/browser/background_fetch/background_fetch_data_manager_observer.h b/chromium/content/browser/background_fetch/background_fetch_data_manager_observer.h
index 12981a841ba..ab1a9f2aca0 100644
--- a/chromium/content/browser/background_fetch/background_fetch_data_manager_observer.h
+++ b/chromium/content/browser/background_fetch/background_fetch_data_manager_observer.h
@@ -5,8 +5,16 @@
#ifndef CONTENT_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_DATA_MANAGER_OBSERVER_H_
#define CONTENT_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_DATA_MANAGER_OBSERVER_H_
+#include <memory>
+
+#include "base/optional.h"
+
+class SkBitmap;
+
namespace content {
+struct BackgroundFetchOptions;
+struct BackgroundFetchRegistration;
class BackgroundFetchRegistrationId;
// Observer interface for objects that would like to be notified about changes
@@ -14,15 +22,28 @@ class BackgroundFetchRegistrationId;
// will be invoked on the IO thread.
class BackgroundFetchDataManagerObserver {
public:
- // Called when the |title| for the Background Fetch |registration_id| has been
- // updated in the data store.
+ // Called when the Background Fetch |registration| has been created.
+ virtual void OnRegistrationCreated(
+ const BackgroundFetchRegistrationId& registration_id,
+ const BackgroundFetchRegistration& registration,
+ const BackgroundFetchOptions& options,
+ const SkBitmap& icon,
+ int num_requests) = 0;
+
+ // Called when the UI options for the Background Fetch |registration_id| have
+ // been updated in the data store.
virtual void OnUpdatedUI(const BackgroundFetchRegistrationId& registration_id,
- const std::string& title) = 0;
+ const base::Optional<std::string>& title,
+ const base::Optional<SkBitmap>& icon) = 0;
// Called if corrupted data is found in the Service Worker database.
virtual void OnServiceWorkerDatabaseCorrupted(
int64_t service_worker_registration_id) = 0;
+ // Called if the origin is out of quota during the fetch.
+ virtual void OnQuotaExceeded(
+ const BackgroundFetchRegistrationId& registration_id) = 0;
+
virtual ~BackgroundFetchDataManagerObserver() {}
};
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 acd1d25f874..4b2a1074e78 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
@@ -16,18 +16,25 @@
#include "base/guid.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
+#include "base/test/metrics/histogram_tester.h"
+#include "content/browser/background_fetch/background_fetch.pb.h"
#include "content/browser/background_fetch/background_fetch_data_manager_observer.h"
#include "content/browser/background_fetch/background_fetch_request_info.h"
+#include "content/browser/background_fetch/background_fetch_request_match_params.h"
#include "content/browser/background_fetch/background_fetch_test_base.h"
#include "content/browser/background_fetch/background_fetch_test_data_manager.h"
#include "content/browser/background_fetch/storage/database_helpers.h"
+#include "content/browser/background_fetch/storage/image_helpers.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"
#include "content/public/browser/background_fetch_response.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/storage_partition.h"
+#include "services/network/public/mojom/fetch_api.mojom.h"
#include "storage/browser/blob/blob_data_handle.h"
#include "testing/gmock/include/gmock/gmock.h"
+#include "third_party/blink/public/platform/modules/cache_storage/cache_storage.mojom.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkColor.h"
@@ -35,6 +42,7 @@ namespace content {
namespace {
using background_fetch::BackgroundFetchInitializationData;
+using ::testing::_;
using ::testing::UnorderedElementsAre;
using ::testing::IsEmpty;
@@ -60,16 +68,15 @@ void DidGetInitializationData(
std::move(quit_closure).Run();
}
-void DidCreateRegistration(
- base::Closure quit_closure,
- blink::mojom::BackgroundFetchError* out_error,
- blink::mojom::BackgroundFetchError error,
- std::unique_ptr<BackgroundFetchRegistration> registration) {
+void DidCreateRegistration(base::OnceClosure quit_closure,
+ blink::mojom::BackgroundFetchError* out_error,
+ blink::mojom::BackgroundFetchError error,
+ const BackgroundFetchRegistration& registration) {
*out_error = error;
std::move(quit_closure).Run();
}
-void DidGetError(base::Closure quit_closure,
+void DidGetError(base::OnceClosure quit_closure,
blink::mojom::BackgroundFetchError* out_error,
blink::mojom::BackgroundFetchError error) {
*out_error = error;
@@ -89,7 +96,8 @@ void DidGetRegistrationUserDataByKeyPrefix(
void AnnotateRequestInfoWithFakeDownloadManagerData(
BackgroundFetchRequestInfo* request_info,
- bool success = false) {
+ bool success = false,
+ bool over_quota = false) {
DCHECK(request_info);
std::string headers =
@@ -109,7 +117,7 @@ void AnnotateRequestInfoWithFakeDownloadManagerData(
// |kResponseFileSize| for tests that use filesize.
request_info->SetResult(std::make_unique<BackgroundFetchResult>(
base::Time::Now(), base::FilePath(), base::nullopt /* blob_handle */,
- kResponseFileSize));
+ over_quota ? kBackgroundFetchMaxQuotaBytes + 1 : kResponseFileSize));
}
void GetNumUserData(base::Closure quit_closure,
@@ -145,6 +153,32 @@ std::vector<ServiceWorkerFetchRequest> CreateValidRequests(
return requests;
}
+ServiceWorkerFetchRequest CreateValidRequestWithMethod(
+ const url::Origin& origin,
+ const std::string& method) {
+ ServiceWorkerFetchRequest request;
+ request.url = origin.GetURL();
+ request.method = method;
+ return request;
+}
+
+SkBitmap CreateTestIcon(int size = 42, SkColor color = SK_ColorGREEN) {
+ SkBitmap icon;
+ icon.allocN32Pixels(size, size);
+ icon.eraseColor(SK_ColorGREEN);
+ return icon;
+}
+
+void ExpectIconProperties(const SkBitmap& icon, int size, SkColor color) {
+ EXPECT_FALSE(icon.isNull());
+ EXPECT_EQ(icon.width(), size);
+ EXPECT_EQ(icon.height(), size);
+ for (int i = 0; i < icon.width(); i++) {
+ for (int j = 0; j < icon.height(); j++)
+ EXPECT_EQ(icon.getColor(i, j), color);
+ }
+}
+
} // namespace
class BackgroundFetchDataManagerTest
@@ -204,14 +238,14 @@ class BackgroundFetchDataManagerTest
run_loop.Run();
}
- std::unique_ptr<BackgroundFetchRegistration> GetRegistration(
+ BackgroundFetchRegistration GetRegistration(
int64_t service_worker_registration_id,
const url::Origin& origin,
const std::string developer_id,
blink::mojom::BackgroundFetchError* out_error) {
DCHECK(out_error);
- std::unique_ptr<BackgroundFetchRegistration> registration;
+ BackgroundFetchRegistration registration;
base::RunLoop run_loop;
background_fetch_data_manager_->GetRegistration(
service_worker_registration_id, origin, developer_id,
@@ -225,18 +259,16 @@ class BackgroundFetchDataManagerTest
std::unique_ptr<proto::BackgroundFetchMetadata> GetMetadata(
int64_t service_worker_registration_id,
- const url::Origin& origin,
- const std::string developer_id,
- blink::mojom::BackgroundFetchError* out_error) {
- DCHECK(out_error);
-
+ const std::string& unique_id) {
std::unique_ptr<proto::BackgroundFetchMetadata> metadata;
+
base::RunLoop run_loop;
- background_fetch_data_manager_->GetMetadata(
- service_worker_registration_id, origin, developer_id,
+ embedded_worker_test_helper()->context_wrapper()->GetRegistrationUserData(
+ service_worker_registration_id,
+ {background_fetch::RegistrationKey(unique_id)},
base::BindOnce(&BackgroundFetchDataManagerTest::DidGetMetadata,
base::Unretained(this), run_loop.QuitClosure(),
- out_error, &metadata));
+ &metadata));
run_loop.Run();
return metadata;
@@ -244,13 +276,14 @@ class BackgroundFetchDataManagerTest
void UpdateRegistrationUI(
const BackgroundFetchRegistrationId& registration_id,
- const std::string& updated_title,
+ const base::Optional<std::string>& updated_title,
+ const base::Optional<SkBitmap>& updated_icon,
blink::mojom::BackgroundFetchError* out_error) {
DCHECK(out_error);
base::RunLoop run_loop;
background_fetch_data_manager_->UpdateRegistrationUI(
- registration_id, updated_title,
+ registration_id, updated_title, updated_icon,
base::BindOnce(&BackgroundFetchDataManagerTest::DidUpdateRegistrationUI,
base::Unretained(this), run_loop.QuitClosure(),
out_error));
@@ -334,6 +367,9 @@ class BackgroundFetchDataManagerTest
// BackgroundFetchDataManager::GetSettledFetchesForRegistration().
void GetSettledFetchesForRegistration(
const BackgroundFetchRegistrationId& registration_id,
+ base::Optional<ServiceWorkerFetchRequest> request_to_match,
+ blink::mojom::QueryParamsPtr cache_query_params,
+ bool match_all,
blink::mojom::BackgroundFetchError* out_error,
bool* out_succeeded,
std::vector<BackgroundFetchSettledFetch>* out_settled_fetches) {
@@ -342,8 +378,10 @@ class BackgroundFetchDataManagerTest
DCHECK(out_settled_fetches);
base::RunLoop run_loop;
+ auto match_params = std::make_unique<BackgroundFetchRequestMatchParams>(
+ request_to_match, std::move(cache_query_params), match_all);
background_fetch_data_manager_->GetSettledFetchesForRegistration(
- registration_id,
+ registration_id, std::move(match_params),
base::BindOnce(&BackgroundFetchDataManagerTest::
DidGetSettledFetchesForRegistration,
base::Unretained(this), run_loop.QuitClosure(),
@@ -402,6 +440,78 @@ class BackgroundFetchDataManagerTest
return result;
}
+ void DeleteFromCache(const ServiceWorkerFetchRequest& request) {
+ CacheStorageCacheHandle handle;
+ {
+ base::RunLoop run_loop;
+ background_fetch_data_manager_->cache_manager()->OpenCache(
+ origin(), CacheStorageOwner::kBackgroundFetch,
+ kExampleUniqueId /* cache_name */,
+ base::BindOnce(&BackgroundFetchDataManagerTest::DidOpenCache,
+ base::Unretained(this), run_loop.QuitClosure(),
+ &handle));
+ run_loop.Run();
+ }
+
+ DCHECK(handle.value());
+
+ {
+ base::RunLoop run_loop;
+ std::vector<blink::mojom::BatchOperationPtr> operation_ptr_vec;
+ operation_ptr_vec.push_back(blink::mojom::BatchOperation::New());
+ operation_ptr_vec[0]->operation_type =
+ blink::mojom::OperationType::kDelete;
+ operation_ptr_vec[0]->request = request;
+
+ handle.value()->BatchOperation(
+ std::move(operation_ptr_vec), true /* fail_on_duplicates */,
+ base::BindOnce(&BackgroundFetchDataManagerTest::DidDeleteFromCache,
+ base::Unretained(this), run_loop.QuitClosure()),
+ base::DoNothing());
+
+ run_loop.Run();
+ }
+ }
+
+ // Returns the title and the icon.
+ std::pair<std::string, SkBitmap> GetUIOptions(
+ int64_t service_worker_registration_id) {
+ auto results = GetRegistrationUserDataByKeyPrefix(
+ service_worker_registration_id, background_fetch::kUIOptionsKeyPrefix);
+ DCHECK_LT(results.size(), 2u)
+ << "Using GetUIOptions with multiple registrations is unimplemented";
+
+ proto::BackgroundFetchUIOptions ui_options;
+ if (results.empty())
+ return {"", SkBitmap()};
+
+ bool did_parse = ui_options.ParseFromString(results[0]);
+ DCHECK(did_parse);
+
+ std::pair<std::string, SkBitmap> result{ui_options.title(), SkBitmap()};
+
+ if (ui_options.icon().empty())
+ return result;
+
+ // Deserialize icon.
+ {
+ base::RunLoop run_loop;
+ background_fetch::DeserializeIcon(
+ std::unique_ptr<std::string>(ui_options.release_icon()),
+ base::BindOnce(
+ [](base::OnceClosure quit_closure, SkBitmap* out_icon,
+ SkBitmap icon) {
+ DCHECK(out_icon);
+ *out_icon = std::move(icon);
+ std::move(quit_closure).Run();
+ },
+ run_loop.QuitClosure(), &result.second));
+ run_loop.Run();
+ }
+
+ return result;
+ }
+
// Gets information about the number of background fetch requests by state.
ResponseStateStats GetRequestStats(int64_t service_worker_registration_id) {
ResponseStateStats stats;
@@ -442,39 +552,45 @@ class BackgroundFetchDataManagerTest
}
// BackgroundFetchDataManagerObserver mocks:
- MOCK_METHOD2(OnUpdatedUI,
+ MOCK_METHOD5(OnRegistrationCreated,
+ void(const BackgroundFetchRegistrationId& registration_id,
+ const BackgroundFetchRegistration& registration,
+ const BackgroundFetchOptions& options,
+ const SkBitmap& icon,
+ int num_requests));
+ MOCK_METHOD3(OnUpdatedUI,
void(const BackgroundFetchRegistrationId& registration,
- const std::string& title));
+ const base::Optional<std::string>& title,
+ const base::Optional<SkBitmap>& icon));
MOCK_METHOD1(OnServiceWorkerDatabaseCorrupted,
void(int64_t service_worker_registration_id));
+ MOCK_METHOD1(OnQuotaExceeded,
+ void(const BackgroundFetchRegistrationId& registration_id));
protected:
- void DidGetRegistration(
- base::Closure quit_closure,
- blink::mojom::BackgroundFetchError* out_error,
- std::unique_ptr<BackgroundFetchRegistration>* out_registration,
- blink::mojom::BackgroundFetchError error,
- std::unique_ptr<BackgroundFetchRegistration> registration) {
- if (error == blink::mojom::BackgroundFetchError::NONE) {
- DCHECK(registration);
- }
+ void DidGetRegistration(base::OnceClosure quit_closure,
+ blink::mojom::BackgroundFetchError* out_error,
+ BackgroundFetchRegistration* out_registration,
+ blink::mojom::BackgroundFetchError error,
+ const BackgroundFetchRegistration& registration) {
*out_error = error;
- *out_registration = std::move(registration);
+ *out_registration = registration;
std::move(quit_closure).Run();
}
void DidGetMetadata(
base::OnceClosure quit_closure,
- blink::mojom::BackgroundFetchError* out_error,
std::unique_ptr<proto::BackgroundFetchMetadata>* out_metadata,
- blink::mojom::BackgroundFetchError error,
- std::unique_ptr<proto::BackgroundFetchMetadata> metadata) {
- if (error == blink::mojom::BackgroundFetchError::NONE) {
- DCHECK(metadata);
+ const std::vector<std::string>& data,
+ blink::ServiceWorkerStatusCode status) {
+ if (status == blink::ServiceWorkerStatusCode::kOk) {
+ DCHECK_EQ(data.size(), 1u);
+
+ auto metadata = std::make_unique<proto::BackgroundFetchMetadata>();
+ if (metadata->ParseFromString(data[0]))
+ *out_metadata = std::move(metadata);
}
- *out_error = error;
- *out_metadata = std::move(metadata);
std::move(quit_closure).Run();
}
@@ -537,7 +653,7 @@ class BackgroundFetchDataManagerTest
void DidMatchCache(base::OnceClosure quit_closure,
bool* out_result,
blink::mojom::CacheStorageError error,
- std::unique_ptr<ServiceWorkerResponse> response) {
+ blink::mojom::FetchAPIResponsePtr response) {
if (error == blink::mojom::CacheStorageError::kSuccess) {
DCHECK(response);
*out_result = true;
@@ -547,6 +663,22 @@ class BackgroundFetchDataManagerTest
std::move(quit_closure).Run();
}
+ void DidOpenCache(base::OnceClosure quit_closure,
+ CacheStorageCacheHandle* out_handle,
+ CacheStorageCacheHandle handle,
+ blink::mojom::CacheStorageError error) {
+ DCHECK(out_handle);
+ DCHECK_EQ(error, blink::mojom::CacheStorageError::kSuccess);
+ *out_handle = std::move(handle);
+ std::move(quit_closure).Run();
+ }
+
+ void DidDeleteFromCache(base::OnceClosure quit_closure,
+ blink::mojom::CacheStorageVerboseErrorPtr error) {
+ DCHECK_EQ(error->value, blink::mojom::CacheStorageError::kSuccess);
+ std::move(quit_closure).Run();
+ }
+
std::unique_ptr<BackgroundFetchTestDataManager>
background_fetch_data_manager_;
};
@@ -574,8 +706,12 @@ TEST_F(BackgroundFetchDataManagerTest, NoDuplicateRegistrations) {
EXPECT_EQ(error, blink::mojom::BackgroundFetchError::INVALID_ID);
// Creating the initial registration should succeed.
- CreateRegistration(registration_id1, requests, options, SkBitmap(), &error);
- EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ {
+ EXPECT_CALL(*this, OnRegistrationCreated(registration_id1, _, _, _, _));
+
+ CreateRegistration(registration_id1, requests, options, SkBitmap(), &error);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ }
// Different |unique_id|, since this is a new Background Fetch registration,
// even though it shares the same |developer_id|.
@@ -599,8 +735,33 @@ TEST_F(BackgroundFetchDataManagerTest, NoDuplicateRegistrations) {
// And now registering the second registration should work fine, since there
// is no longer an *active* registration with the same |developer_id|, even
// though the initial registration has not yet been deleted.
- CreateRegistration(registration_id2, requests, options, SkBitmap(), &error);
- EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ {
+ EXPECT_CALL(*this, OnRegistrationCreated(registration_id2, _, _, _, _));
+
+ CreateRegistration(registration_id2, requests, options, SkBitmap(), &error);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ }
+}
+
+TEST_F(BackgroundFetchDataManagerTest, ExceedingQuotaFailsCreation) {
+ // Tests that the BackgroundFetchDataManager correctly rejects creating a
+ // registration where the provided download total exceeds the available quota.
+
+ int64_t service_worker_registration_id = RegisterServiceWorker();
+ ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId,
+ service_worker_registration_id);
+
+ BackgroundFetchRegistrationId registration_id(service_worker_registration_id,
+ origin(), kExampleDeveloperId,
+ kExampleUniqueId);
+ std::vector<ServiceWorkerFetchRequest> requests;
+ BackgroundFetchOptions options;
+ options.download_total = kBackgroundFetchMaxQuotaBytes + 1;
+
+ blink::mojom::BackgroundFetchError error;
+
+ CreateRegistration(registration_id, requests, options, SkBitmap(), &error);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::QUOTA_EXCEEDED);
}
TEST_F(BackgroundFetchDataManagerTest, GetDeveloperIds) {
@@ -619,8 +780,12 @@ TEST_F(BackgroundFetchDataManagerTest, GetDeveloperIds) {
// Create a single registration.
BackgroundFetchRegistrationId registration_id1(
sw_id, origin(), kExampleDeveloperId, kExampleUniqueId);
- CreateRegistration(registration_id1, requests, options, SkBitmap(), &error);
- EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ {
+ EXPECT_CALL(*this, OnRegistrationCreated(registration_id1, _, _, _, _));
+
+ CreateRegistration(registration_id1, requests, options, SkBitmap(), &error);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ }
// Verify that the developer ID can be found.
developer_ids = GetDeveloperIds(sw_id, origin(), &error);
@@ -637,9 +802,12 @@ TEST_F(BackgroundFetchDataManagerTest, GetDeveloperIds) {
// Create another registration.
BackgroundFetchRegistrationId registration_id2(
sw_id, origin(), kAlternativeDeveloperId, kAlternativeUniqueId);
- CreateRegistration(registration_id2, requests, options, SkBitmap(), &error);
- EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ {
+ EXPECT_CALL(*this, OnRegistrationCreated(registration_id2, _, _, _, _));
+ CreateRegistration(registration_id2, requests, options, SkBitmap(), &error);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ }
// Verify that both developer IDs can be found.
developer_ids = GetDeveloperIds(sw_id, origin(), &error);
EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
@@ -666,31 +834,34 @@ TEST_F(BackgroundFetchDataManagerTest, GetRegistration) {
blink::mojom::BackgroundFetchError error;
// Create a single registration.
- CreateRegistration(registration_id, requests, options, SkBitmap(), &error);
- EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ {
+ EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _));
+
+ CreateRegistration(registration_id, requests, options, SkBitmap(), &error);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ }
// Verify that the registration can be retrieved.
auto registration =
GetRegistration(sw_id, origin(), kExampleDeveloperId, &error);
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
- ASSERT_TRUE(registration);
- EXPECT_EQ(kExampleUniqueId, registration->unique_id);
- EXPECT_EQ(kExampleDeveloperId, registration->developer_id);
+
+ EXPECT_EQ(kExampleUniqueId, registration.unique_id);
+ EXPECT_EQ(kExampleDeveloperId, registration.developer_id);
// Verify that retrieving using the wrong developer id doesn't work.
registration =
GetRegistration(sw_id, origin(), kAlternativeDeveloperId, &error);
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::INVALID_ID);
- ASSERT_FALSE(registration);
RestartDataManagerFromPersistentStorage();
// After a restart, GetRegistration should still find the registration.
registration = GetRegistration(sw_id, origin(), kExampleDeveloperId, &error);
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
- ASSERT_TRUE(registration);
- EXPECT_EQ(kExampleUniqueId, registration->unique_id);
- EXPECT_EQ(kExampleDeveloperId, registration->developer_id);
+
+ EXPECT_EQ(kExampleUniqueId, registration.unique_id);
+ EXPECT_EQ(kExampleDeveloperId, registration.developer_id);
}
TEST_F(BackgroundFetchDataManagerTest, GetMetadata) {
@@ -705,27 +876,23 @@ TEST_F(BackgroundFetchDataManagerTest, GetMetadata) {
blink::mojom::BackgroundFetchError error;
// Create a single registration.
- CreateRegistration(registration_id, requests, options, SkBitmap(), &error);
- EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ {
+ EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _));
+ CreateRegistration(registration_id, requests, options, SkBitmap(), &error);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ }
// Verify that the metadata can be retrieved.
- auto metadata = GetMetadata(sw_id, origin(), kExampleDeveloperId, &error);
- ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ auto metadata = GetMetadata(sw_id, kExampleUniqueId);
ASSERT_TRUE(metadata);
EXPECT_EQ(metadata->origin(), origin().Serialize());
EXPECT_NE(metadata->creation_microseconds_since_unix_epoch(), 0);
EXPECT_EQ(metadata->num_fetches(), static_cast<int>(requests.size()));
- // Verify that retrieving using the wrong developer id doesn't work.
- metadata = GetMetadata(sw_id, origin(), kAlternativeDeveloperId, &error);
- ASSERT_EQ(error, blink::mojom::BackgroundFetchError::INVALID_ID);
- ASSERT_FALSE(metadata);
-
RestartDataManagerFromPersistentStorage();
// After a restart, GetMetadata should still find the registration.
- metadata = GetMetadata(sw_id, origin(), kExampleDeveloperId, &error);
- ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ metadata = GetMetadata(sw_id, kExampleUniqueId);
ASSERT_TRUE(metadata);
EXPECT_EQ(metadata->origin(), origin().Serialize());
EXPECT_NE(metadata->creation_microseconds_since_unix_epoch(), 0);
@@ -743,22 +910,24 @@ TEST_F(BackgroundFetchDataManagerTest, LargeIconNotPersisted) {
BackgroundFetchOptions options;
blink::mojom::BackgroundFetchError error;
- SkBitmap icon;
- icon.allocN32Pixels(512, 512);
- icon.eraseColor(SK_ColorGREEN);
+ SkBitmap icon = CreateTestIcon(512 /* size */);
+ ASSERT_FALSE(background_fetch::ShouldPersistIcon(icon));
// Create a single registration.
- CreateRegistration(registration_id, requests, options, icon, &error);
- EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ {
+ EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _));
+
+ CreateRegistration(registration_id, requests, options, icon, &error);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ }
// Verify that the metadata can be retrieved.
- auto metadata = GetMetadata(sw_id, origin(), kExampleDeveloperId, &error);
- ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ auto metadata = GetMetadata(sw_id, kExampleUniqueId);
ASSERT_TRUE(metadata);
EXPECT_EQ(metadata->origin(), origin().Serialize());
EXPECT_NE(metadata->creation_microseconds_since_unix_epoch(), 0);
EXPECT_EQ(metadata->num_fetches(), static_cast<int>(requests.size()));
- EXPECT_TRUE(metadata->icon().empty());
+ EXPECT_TRUE(GetUIOptions(sw_id).second.isNull());
}
TEST_F(BackgroundFetchDataManagerTest, UpdateRegistrationUI) {
@@ -774,35 +943,93 @@ TEST_F(BackgroundFetchDataManagerTest, UpdateRegistrationUI) {
blink::mojom::BackgroundFetchError error;
// There should be no title before the registration.
- std::vector<std::string> title = GetRegistrationUserDataByKeyPrefix(
- sw_id, background_fetch::kTitleKeyPrefix);
- EXPECT_TRUE(title.empty());
+ EXPECT_TRUE(GetUIOptions(sw_id).first.empty());
// Create a single registration.
- CreateRegistration(registration_id, requests, options, SkBitmap(), &error);
- EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ {
+ EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _));
+
+ CreateRegistration(registration_id, requests, options, CreateTestIcon(),
+ &error);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ }
- // Verify that the title can be retrieved.
- title = GetRegistrationUserDataByKeyPrefix(sw_id,
- background_fetch::kTitleKeyPrefix);
- EXPECT_EQ(title.size(), 1u);
- ASSERT_EQ(title.front(), kInitialTitle);
+ // Verify that the UI Options can be retrieved.
+ {
+ auto ui_options = GetUIOptions(sw_id);
+ EXPECT_EQ(ui_options.first, kInitialTitle);
+ EXPECT_NO_FATAL_FAILURE(
+ ExpectIconProperties(ui_options.second, 42, SK_ColorGREEN));
+ }
- // Update the title.
+ // Update only the title.
{
- EXPECT_CALL(*this, OnUpdatedUI(registration_id, kUpdatedTitle));
+ EXPECT_CALL(*this,
+ OnUpdatedUI(registration_id,
+ base::Optional<std::string>(kUpdatedTitle), _));
- UpdateRegistrationUI(registration_id, kUpdatedTitle, &error);
+ UpdateRegistrationUI(registration_id, kUpdatedTitle, base::nullopt, &error);
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+
+ auto ui_options = GetUIOptions(sw_id);
+ // Expect new title.
+ EXPECT_EQ(ui_options.first, kUpdatedTitle);
+ // Expect same icon as before.
+ EXPECT_NO_FATAL_FAILURE(
+ ExpectIconProperties(ui_options.second, 42, SK_ColorGREEN));
}
- RestartDataManagerFromPersistentStorage();
+ // Update only the icon.
+ {
+ EXPECT_CALL(*this, OnUpdatedUI(registration_id, _, _));
+
+ UpdateRegistrationUI(registration_id, base::nullopt,
+ CreateTestIcon(24 /* size */), &error);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+
+ auto ui_options = GetUIOptions(sw_id);
+ // Expect the same title as before.
+ EXPECT_EQ(ui_options.first, kUpdatedTitle);
+ // Expect the new icon with the different size.
+ EXPECT_NO_FATAL_FAILURE(
+ ExpectIconProperties(ui_options.second, 24, SK_ColorGREEN));
+ }
+
+ // Update both the title and icon.
+ {
+ EXPECT_CALL(*this,
+ OnUpdatedUI(registration_id,
+ base::Optional<std::string>(kInitialTitle), _));
+
+ UpdateRegistrationUI(registration_id, kInitialTitle,
+ CreateTestIcon(66 /* size */), &error);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
- // After a restart, GetMetadata should find the new title.
- title = GetRegistrationUserDataByKeyPrefix(sw_id,
- background_fetch::kTitleKeyPrefix);
- EXPECT_EQ(title.size(), 1u);
- ASSERT_EQ(title.front(), kUpdatedTitle);
+ auto ui_options = GetUIOptions(sw_id);
+ // Expect the initial title again.
+ EXPECT_EQ(ui_options.first, kInitialTitle);
+ // Expect the new icon with the different size.
+ EXPECT_NO_FATAL_FAILURE(
+ ExpectIconProperties(ui_options.second, 66, SK_ColorGREEN));
+ }
+
+ // New title and an icon that's too large.
+ {
+ EXPECT_CALL(*this,
+ OnUpdatedUI(registration_id,
+ base::Optional<std::string>(kUpdatedTitle), _));
+
+ UpdateRegistrationUI(registration_id, kUpdatedTitle,
+ CreateTestIcon(512 /* size */), &error);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+
+ auto ui_options = GetUIOptions(sw_id);
+ // Expect the new title.
+ EXPECT_EQ(ui_options.first, kUpdatedTitle);
+ // Expect same icon as before.
+ EXPECT_NO_FATAL_FAILURE(
+ ExpectIconProperties(ui_options.second, 66, SK_ColorGREEN));
+ }
}
TEST_F(BackgroundFetchDataManagerTest, CreateAndDeleteRegistration) {
@@ -816,8 +1043,12 @@ TEST_F(BackgroundFetchDataManagerTest, CreateAndDeleteRegistration) {
BackgroundFetchOptions options;
blink::mojom::BackgroundFetchError error;
- CreateRegistration(registration_id1, requests, options, SkBitmap(), &error);
- EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ {
+ EXPECT_CALL(*this, OnRegistrationCreated(registration_id1, _, _, _, _));
+
+ CreateRegistration(registration_id1, requests, options, SkBitmap(), &error);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ }
RestartDataManagerFromPersistentStorage();
@@ -830,15 +1061,15 @@ TEST_F(BackgroundFetchDataManagerTest, CreateAndDeleteRegistration) {
// |service_worker_registration_id| should yield an error, even after
// restarting.
CreateRegistration(registration_id2, requests, options, SkBitmap(), &error);
- EXPECT_EQ(error, blink::mojom::BackgroundFetchError::DUPLICATED_DEVELOPER_ID);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::DUPLICATED_DEVELOPER_ID);
// Verify that the registration can be retrieved before deletion.
auto registration =
GetRegistration(sw_id, origin(), kExampleDeveloperId, &error);
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
- ASSERT_TRUE(registration);
- EXPECT_EQ(kExampleUniqueId, registration->unique_id);
- EXPECT_EQ(kExampleDeveloperId, registration->developer_id);
+
+ EXPECT_EQ(kExampleUniqueId, registration.unique_id);
+ EXPECT_EQ(kExampleDeveloperId, registration.developer_id);
// Deactivating the registration should succeed.
MarkRegistrationForDeletion(registration_id1, &error);
@@ -847,7 +1078,6 @@ TEST_F(BackgroundFetchDataManagerTest, CreateAndDeleteRegistration) {
// Verify that the registration cannot be retrieved after deletion
registration = GetRegistration(sw_id, origin(), kExampleDeveloperId, &error);
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::INVALID_ID);
- ASSERT_FALSE(registration);
RestartDataManagerFromPersistentStorage();
@@ -855,14 +1085,17 @@ TEST_F(BackgroundFetchDataManagerTest, CreateAndDeleteRegistration) {
// a restart.
registration = GetRegistration(sw_id, origin(), kExampleDeveloperId, &error);
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::INVALID_ID);
- ASSERT_FALSE(registration);
// And now registering the second registration should work fine, even after
// restarting, since there is no longer an *active* registration with the same
// |developer_id|, even though the initial registration has not yet been
// deleted.
- CreateRegistration(registration_id2, requests, options, SkBitmap(), &error);
- EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ {
+ EXPECT_CALL(*this, OnRegistrationCreated(registration_id2, _, _, _, _));
+
+ CreateRegistration(registration_id2, requests, options, SkBitmap(), &error);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ }
RestartDataManagerFromPersistentStorage();
@@ -893,8 +1126,13 @@ TEST_F(BackgroundFetchDataManagerTest, PopNextRequestAndMarkAsComplete) {
BackgroundFetchOptions options;
blink::mojom::BackgroundFetchError error;
- CreateRegistration(registration_id, requests, options, SkBitmap(), &error);
- EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ {
+ EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _));
+
+ CreateRegistration(registration_id, requests, options, SkBitmap(), &error);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ }
+
EXPECT_EQ(
GetRequestStats(sw_id),
(ResponseStateStats{2 /* pending_requests */, 0 /* active_requests */,
@@ -956,13 +1194,17 @@ TEST_F(BackgroundFetchDataManagerTest, DownloadTotalUpdated) {
BackgroundFetchOptions options;
blink::mojom::BackgroundFetchError error;
- CreateRegistration(registration_id, requests, options, SkBitmap(), &error);
- EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ {
+ EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _));
+
+ CreateRegistration(registration_id, requests, options, SkBitmap(), &error);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ }
auto registration =
GetRegistration(sw_id, origin(), kExampleDeveloperId, &error);
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
- EXPECT_EQ(registration->download_total, 0u);
+ EXPECT_EQ(registration.download_total, 0u);
scoped_refptr<BackgroundFetchRequestInfo> request_info;
PopNextRequest(registration_id, &request_info);
@@ -972,7 +1214,7 @@ TEST_F(BackgroundFetchDataManagerTest, DownloadTotalUpdated) {
registration = GetRegistration(sw_id, origin(), kExampleDeveloperId, &error);
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
- EXPECT_EQ(registration->download_total, kResponseFileSize);
+ EXPECT_EQ(registration.download_total, kResponseFileSize);
PopNextRequest(registration_id, &request_info);
AnnotateRequestInfoWithFakeDownloadManagerData(request_info.get(),
@@ -981,7 +1223,7 @@ TEST_F(BackgroundFetchDataManagerTest, DownloadTotalUpdated) {
registration = GetRegistration(sw_id, origin(), kExampleDeveloperId, &error);
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
- EXPECT_EQ(registration->download_total, 2 * kResponseFileSize);
+ EXPECT_EQ(registration.download_total, 2 * kResponseFileSize);
PopNextRequest(registration_id, &request_info);
AnnotateRequestInfoWithFakeDownloadManagerData(request_info.get(),
@@ -991,7 +1233,34 @@ TEST_F(BackgroundFetchDataManagerTest, DownloadTotalUpdated) {
registration = GetRegistration(sw_id, origin(), kExampleDeveloperId, &error);
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
// |download_total| is unchanged.
- EXPECT_EQ(registration->download_total, 2 * kResponseFileSize);
+ EXPECT_EQ(registration.download_total, 2 * kResponseFileSize);
+}
+
+TEST_F(BackgroundFetchDataManagerTest, ExceedingQuotaAbandonsFetch) {
+ int64_t sw_id = RegisterServiceWorker();
+ ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, sw_id);
+
+ BackgroundFetchRegistrationId registration_id(
+ sw_id, origin(), kExampleDeveloperId, kExampleUniqueId);
+ auto requests = CreateValidRequests(origin(), 3u /* num_requests */);
+
+ BackgroundFetchOptions options;
+ blink::mojom::BackgroundFetchError error;
+ {
+ EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _));
+
+ CreateRegistration(registration_id, requests, options, SkBitmap(), &error);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ }
+
+ scoped_refptr<BackgroundFetchRequestInfo> request_info;
+ PopNextRequest(registration_id, &request_info);
+ AnnotateRequestInfoWithFakeDownloadManagerData(
+ request_info.get(), true /* succeeded */, true /* over_quota */);
+ {
+ EXPECT_CALL(*this, OnQuotaExceeded(registration_id));
+ MarkRequestAsComplete(registration_id, request_info.get());
+ }
}
TEST_F(BackgroundFetchDataManagerTest, WriteToCache) {
@@ -1004,9 +1273,12 @@ TEST_F(BackgroundFetchDataManagerTest, WriteToCache) {
BackgroundFetchOptions options;
blink::mojom::BackgroundFetchError error;
+ {
+ EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _));
- CreateRegistration(registration_id, requests, options, SkBitmap(), &error);
- EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ CreateRegistration(registration_id, requests, options, SkBitmap(), &error);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ }
scoped_refptr<BackgroundFetchRequestInfo> request_info;
PopNextRequest(registration_id, &request_info);
@@ -1048,9 +1320,12 @@ TEST_F(BackgroundFetchDataManagerTest, CacheDeleted) {
BackgroundFetchOptions options;
blink::mojom::BackgroundFetchError error;
+ {
+ EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _));
- CreateRegistration(registration_id, {request}, options, SkBitmap(), &error);
- EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ CreateRegistration(registration_id, {request}, options, SkBitmap(), &error);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ }
scoped_refptr<BackgroundFetchRequestInfo> request_info;
PopNextRequest(registration_id, &request_info);
@@ -1075,14 +1350,20 @@ TEST_F(BackgroundFetchDataManagerTest, GetSettledFetchesForRegistration) {
int64_t sw_id = RegisterServiceWorker();
ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, sw_id);
- std::vector<ServiceWorkerFetchRequest> requests(2u);
+ std::vector<ServiceWorkerFetchRequest> requests =
+ CreateValidRequests(origin(), 2u /* num_requests */);
BackgroundFetchOptions options;
blink::mojom::BackgroundFetchError error;
BackgroundFetchRegistrationId registration_id(
sw_id, origin(), kExampleDeveloperId, kExampleUniqueId);
- CreateRegistration(registration_id, requests, options, SkBitmap(), &error);
- ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ {
+ EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _));
+
+ CreateRegistration(registration_id, requests, options, SkBitmap(), &error);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ }
+
EXPECT_EQ(
GetRequestStats(sw_id),
(ResponseStateStats{2 /* pending_requests */, 0 /* active_requests */,
@@ -1091,8 +1372,10 @@ TEST_F(BackgroundFetchDataManagerTest, GetSettledFetchesForRegistration) {
// Nothing is downloaded yet.
bool succeeded = false;
std::vector<BackgroundFetchSettledFetch> settled_fetches;
- GetSettledFetchesForRegistration(registration_id, &error, &succeeded,
- &settled_fetches);
+ GetSettledFetchesForRegistration(
+ registration_id, base::nullopt /* request_to_match */,
+ nullptr /* cache_query_params */, false /* match_all */, &error,
+ &succeeded, &settled_fetches);
EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
EXPECT_TRUE(succeeded);
EXPECT_EQ(settled_fetches.size(), 0u);
@@ -1112,8 +1395,10 @@ TEST_F(BackgroundFetchDataManagerTest, GetSettledFetchesForRegistration) {
(ResponseStateStats{0 /* pending_requests */, 0 /* active_requests */,
requests.size() /* completed_requests */}));
- GetSettledFetchesForRegistration(registration_id, &error, &succeeded,
- &settled_fetches);
+ GetSettledFetchesForRegistration(
+ registration_id, base::nullopt /* request_to_match */,
+ nullptr /* cache_query_params */, false /* match_all */, &error,
+ &succeeded, &settled_fetches);
EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
// We are marking the responses as failed in Download Manager.
@@ -1131,14 +1416,20 @@ TEST_F(BackgroundFetchDataManagerTest, GetSettledFetchesFromCache) {
BackgroundFetchOptions options;
blink::mojom::BackgroundFetchError error;
- CreateRegistration(registration_id, requests, options, SkBitmap(), &error);
- EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ {
+ EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _));
+
+ CreateRegistration(registration_id, requests, options, SkBitmap(), &error);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ }
bool succeeded = false;
std::vector<BackgroundFetchSettledFetch> settled_fetches;
// Nothing is downloaded yet.
- GetSettledFetchesForRegistration(registration_id, &error, &succeeded,
- &settled_fetches);
+ GetSettledFetchesForRegistration(
+ registration_id, base::nullopt /* request_to_match */,
+ nullptr /* cache_query_params */, false /* match_all */, &error,
+ &succeeded, &settled_fetches);
EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
EXPECT_TRUE(succeeded);
EXPECT_EQ(settled_fetches.size(), 0u);
@@ -1150,8 +1441,10 @@ TEST_F(BackgroundFetchDataManagerTest, GetSettledFetchesFromCache) {
true /* success */);
MarkRequestAsComplete(registration_id, request_info.get());
- GetSettledFetchesForRegistration(registration_id, &error, &succeeded,
- &settled_fetches);
+ GetSettledFetchesForRegistration(
+ registration_id, base::nullopt /* request_to_match */,
+ nullptr /* cache_query_params */, false /* match_all */, &error,
+ &succeeded, &settled_fetches);
EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
EXPECT_TRUE(succeeded);
EXPECT_EQ(settled_fetches.size(), 1u);
@@ -1162,8 +1455,10 @@ TEST_F(BackgroundFetchDataManagerTest, GetSettledFetchesFromCache) {
true /* success */);
MarkRequestAsComplete(registration_id, request_info.get());
- GetSettledFetchesForRegistration(registration_id, &error, &succeeded,
- &settled_fetches);
+ GetSettledFetchesForRegistration(
+ registration_id, base::nullopt /* request_to_match */,
+ nullptr /* cache_query_params */, false /* match_all */, &error,
+ &succeeded, &settled_fetches);
EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
EXPECT_TRUE(succeeded);
ASSERT_EQ(settled_fetches.size(), 2u);
@@ -1171,20 +1466,164 @@ TEST_F(BackgroundFetchDataManagerTest, GetSettledFetchesFromCache) {
// Sanity check that the responses are written to / read from the cache.
EXPECT_TRUE(MatchCache(requests[0]));
EXPECT_TRUE(MatchCache(requests[1]));
- EXPECT_EQ(settled_fetches[0].response.cache_storage_cache_name,
+ EXPECT_EQ(settled_fetches[0].response->cache_storage_cache_name,
kExampleUniqueId);
- EXPECT_EQ(settled_fetches[1].response.cache_storage_cache_name,
+ EXPECT_EQ(settled_fetches[1].response->cache_storage_cache_name,
kExampleUniqueId);
RestartDataManagerFromPersistentStorage();
- GetSettledFetchesForRegistration(registration_id, &error, &succeeded,
- &settled_fetches);
+ GetSettledFetchesForRegistration(
+ registration_id, base::nullopt /* request_to_match */,
+ nullptr /* cache_query_params */, false /* match_all */, &error,
+ &succeeded, &settled_fetches);
EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
EXPECT_TRUE(succeeded);
EXPECT_EQ(settled_fetches.size(), 2u);
}
+TEST_F(BackgroundFetchDataManagerTest, GetSettledFetchesForASpecificRequest) {
+ int64_t sw_id = RegisterServiceWorker();
+ ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, sw_id);
+
+ auto requests = CreateValidRequests(origin(), 2u /* num_requests */);
+ BackgroundFetchOptions options;
+ blink::mojom::BackgroundFetchError error;
+ BackgroundFetchRegistrationId registration_id(
+ sw_id, origin(), kExampleDeveloperId, kExampleUniqueId);
+
+ {
+ EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _));
+
+ CreateRegistration(registration_id, requests, options, SkBitmap(), &error);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ }
+
+ for (size_t i = 0; i < requests.size(); i++) {
+ SCOPED_TRACE(i);
+ scoped_refptr<BackgroundFetchRequestInfo> request_info;
+ PopNextRequest(registration_id, &request_info);
+ ASSERT_TRUE(request_info);
+ AnnotateRequestInfoWithFakeDownloadManagerData(request_info.get());
+ MarkRequestAsComplete(registration_id, request_info.get());
+ }
+
+ EXPECT_EQ(
+ GetRequestStats(sw_id),
+ (ResponseStateStats{0 /* pending_requests */, 0 /* active_requests */,
+ requests.size() /* completed_requests */}));
+
+ bool succeeded = false;
+ std::vector<BackgroundFetchSettledFetch> settled_fetches;
+ GetSettledFetchesForRegistration(
+ registration_id, requests[0] /* request_to_match */,
+ nullptr /* cache_query_params */, false /* match_all */, &error,
+ &succeeded, &settled_fetches);
+
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ // We are marking the responses as failed in Download Manager.
+ EXPECT_FALSE(succeeded);
+ EXPECT_EQ(settled_fetches.size(), 1u);
+}
+
+TEST_F(BackgroundFetchDataManagerTest,
+ GetSettledFetchesForANonMatchingRequest) {
+ int64_t sw_id = RegisterServiceWorker();
+ ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, sw_id);
+
+ auto requests = CreateValidRequests(origin(), 3u /* num_requests */);
+ BackgroundFetchOptions options;
+ blink::mojom::BackgroundFetchError error;
+ BackgroundFetchRegistrationId registration_id(
+ sw_id, origin(), kExampleDeveloperId, kExampleUniqueId);
+
+ {
+ EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _));
+
+ CreateRegistration(registration_id, requests, options, SkBitmap(), &error);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ }
+
+ for (size_t i = 0; i < requests.size() - 1; i++) {
+ SCOPED_TRACE(i);
+ scoped_refptr<BackgroundFetchRequestInfo> request_info;
+ PopNextRequest(registration_id, &request_info);
+ ASSERT_TRUE(request_info);
+ AnnotateRequestInfoWithFakeDownloadManagerData(request_info.get());
+ MarkRequestAsComplete(registration_id, request_info.get());
+ }
+
+ EXPECT_EQ(
+ GetRequestStats(sw_id),
+ (ResponseStateStats{1 /* pending_requests */, 0 /* active_requests */,
+ requests.size() - 1 /* completed_requests */}));
+
+ bool succeeded = false;
+ std::vector<BackgroundFetchSettledFetch> settled_fetches;
+ GetSettledFetchesForRegistration(
+ registration_id, requests[2] /* request_to_match */,
+ nullptr /* cache_query_params */, false /* match_all */, &error,
+ &succeeded, &settled_fetches);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ EXPECT_EQ(settled_fetches.size(), 1u);
+ EXPECT_EQ(settled_fetches[0].response->response_type,
+ network::mojom::FetchResponseType::kError);
+}
+
+TEST_F(BackgroundFetchDataManagerTest, IgnoreMethodAndMatchAll) {
+ int64_t sw_id = RegisterServiceWorker();
+ ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, sw_id);
+
+ std::vector<ServiceWorkerFetchRequest> requests = {
+ CreateValidRequestWithMethod(origin(), "GET"),
+ CreateValidRequestWithMethod(origin(), "POST")};
+
+ BackgroundFetchOptions options;
+ blink::mojom::BackgroundFetchError error;
+ BackgroundFetchRegistrationId registration_id(
+ sw_id, origin(), kExampleDeveloperId, kExampleUniqueId);
+
+ {
+ EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _));
+
+ CreateRegistration(registration_id, requests, options, SkBitmap(), &error);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ }
+
+ for (size_t i = 0; i < requests.size(); i++) {
+ SCOPED_TRACE(i);
+ scoped_refptr<BackgroundFetchRequestInfo> request_info;
+ PopNextRequest(registration_id, &request_info);
+ ASSERT_TRUE(request_info);
+ AnnotateRequestInfoWithFakeDownloadManagerData(request_info.get());
+ MarkRequestAsComplete(registration_id, request_info.get());
+ }
+
+ EXPECT_EQ(
+ GetRequestStats(sw_id),
+ (ResponseStateStats{0 /* pending_requests */, 0 /* active_requests */,
+ requests.size() /* completed_requests */}));
+
+ bool succeeded = false;
+ std::vector<BackgroundFetchSettledFetch> settled_fetches;
+ blink::mojom::QueryParamsPtr cache_query_params =
+ blink::mojom::QueryParams::New();
+ cache_query_params->ignore_method = true;
+ GetSettledFetchesForRegistration(
+ registration_id, requests[0] /* request_to_match */,
+ std::move(cache_query_params), true /* match_all */, &error, &succeeded,
+ &settled_fetches);
+
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ // We are marking the responses as failed in Download Manager.
+ EXPECT_FALSE(succeeded);
+ // If the ASSERT below fails, the Cache Storage API implementation has likely
+ // changed to distinguish keys by request data other than just the URL.
+ // Thank you! Please can you update the 1u below to 2u, or file a bug against
+ // component Background Fetch to do so.
+ ASSERT_EQ(settled_fetches.size(), 1u);
+}
+
TEST_F(BackgroundFetchDataManagerTest, Cleanup) {
// Tests that the BackgroundFetchDataManager cleans up registrations
// marked for deletion.
@@ -1202,8 +1641,12 @@ TEST_F(BackgroundFetchDataManagerTest, Cleanup) {
EXPECT_EQ(0u,
GetRegistrationUserDataByKeyPrefix(sw_id, kUserDataPrefix).size());
// Create a registration.
- CreateRegistration(registration_id, requests, options, SkBitmap(), &error);
- ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ {
+ EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _));
+
+ CreateRegistration(registration_id, requests, options, SkBitmap(), &error);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ }
// We expect as many pending entries as there are requests.
EXPECT_EQ(requests.size(),
@@ -1263,13 +1706,15 @@ TEST_F(BackgroundFetchDataManagerTest, GetInitializationData) {
// Register a Background Fetch.
BackgroundFetchRegistrationId registration_id(
sw_id, origin(), kExampleDeveloperId, kExampleUniqueId);
- SkBitmap icon;
- icon.allocN32Pixels(42, 42);
- icon.eraseColor(SK_ColorGREEN);
- CreateRegistration(registration_id, requests, options, icon, &error);
- ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
- UpdateRegistrationUI(registration_id, kUpdatedTitle, &error);
- ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+
+ {
+ EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _));
+
+ CreateRegistration(registration_id, requests, options, CreateTestIcon(),
+ &error);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ }
+
{
std::vector<BackgroundFetchInitializationData> data =
GetInitializationData();
@@ -1281,19 +1726,14 @@ TEST_F(BackgroundFetchDataManagerTest, GetInitializationData) {
EXPECT_EQ(init.registration.developer_id, kExampleDeveloperId);
EXPECT_EQ(init.options.title, kInitialTitle);
EXPECT_EQ(init.options.download_total, 42u);
- EXPECT_EQ(init.ui_title, kUpdatedTitle);
+ EXPECT_EQ(init.ui_title, kInitialTitle);
EXPECT_EQ(init.num_requests, requests.size());
EXPECT_EQ(init.num_completed_requests, 0u);
- EXPECT_TRUE(init.active_fetch_guids.empty());
+ EXPECT_TRUE(init.active_fetch_requests.empty());
// Check icon.
ASSERT_FALSE(init.icon.drawsNothing());
- EXPECT_EQ(icon.width(), init.icon.width());
- EXPECT_EQ(icon.height(), init.icon.height());
- for (int i = 0; i < icon.width(); i++) {
- for (int j = 0; j < icon.height(); j++)
- EXPECT_EQ(init.icon.getColor(i, j), SK_ColorGREEN);
- }
+ EXPECT_NO_FATAL_FAILURE(ExpectIconProperties(init.icon, 42, SK_ColorGREEN));
}
// Mark one request as complete and start another.
@@ -1311,14 +1751,28 @@ TEST_F(BackgroundFetchDataManagerTest, GetInitializationData) {
EXPECT_EQ(data[0].num_requests, requests.size());
EXPECT_EQ(data[0].num_completed_requests, 1u);
- EXPECT_EQ(data[0].active_fetch_guids.size(), 1u);
+ ASSERT_EQ(data[0].active_fetch_requests.size(), 1u);
+
+ const auto& init_request_info = data[0].active_fetch_requests[0];
+ ASSERT_TRUE(init_request_info);
+ EXPECT_EQ(request_info->download_guid(),
+ init_request_info->download_guid());
+ EXPECT_EQ(request_info->request_index(),
+ init_request_info->request_index());
+ EXPECT_EQ(request_info->fetch_request().Serialize(),
+ init_request_info->fetch_request().Serialize());
}
// Create another registration.
BackgroundFetchRegistrationId registration_id2(
sw_id, origin(), kAlternativeDeveloperId, kAlternativeUniqueId);
- CreateRegistration(registration_id2, requests, options, SkBitmap(), &error);
- EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ {
+ EXPECT_CALL(*this, OnRegistrationCreated(registration_id2, _, _, _, _));
+
+ CreateRegistration(registration_id2, requests, options, SkBitmap(), &error);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ }
+
{
std::vector<BackgroundFetchInitializationData> data =
GetInitializationData();
@@ -1339,11 +1793,15 @@ TEST_F(BackgroundFetchDataManagerTest, CreateInParallel) {
std::vector<blink::mojom::BackgroundFetchError> errors(5);
+ // We expect a single successful registration to be created.
+ EXPECT_CALL(*this, OnRegistrationCreated(_, _, _, _, _));
+
const int num_parallel_creates = 5;
base::RunLoop run_loop;
base::RepeatingClosure quit_once_all_finished_closure =
base::BarrierClosure(num_parallel_creates, run_loop.QuitClosure());
+
for (int i = 0; i < num_parallel_creates; i++) {
// New |unique_id| per iteration, since each is a distinct registration.
BackgroundFetchRegistrationId registration_id(
@@ -1377,4 +1835,74 @@ TEST_F(BackgroundFetchDataManagerTest, CreateInParallel) {
EXPECT_EQ(num_parallel_creates - 1, duplicated_developer_id_count);
}
+TEST_F(BackgroundFetchDataManagerTest, StorageErrorsReported) {
+ int64_t sw_id = RegisterServiceWorker();
+ ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, sw_id);
+
+ auto requests = CreateValidRequests(origin(), 3u /* num_requests */);
+ BackgroundFetchOptions options;
+ blink::mojom::BackgroundFetchError error;
+ BackgroundFetchRegistrationId registration_id(
+ sw_id, origin(), kExampleDeveloperId, kExampleUniqueId);
+
+ {
+ base::HistogramTester histogram_tester;
+ CreateRegistration(registration_id, requests, options, SkBitmap(), &error);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ histogram_tester.ExpectBucketCount(
+ "BackgroundFetch.Storage.CreateMetadataTask", 0 /* kNone */, 1);
+ }
+
+ BackgroundFetchRegistrationId registration_id2(
+ sw_id, url::Origin::Create(GURL("https://examplebad.com")),
+ kAlternativeDeveloperId, kAlternativeUniqueId);
+
+ {
+ base::HistogramTester histogram_tester;
+ // This should fail because the Service Worker doesn't exist.
+ CreateRegistration(registration_id2, requests, options, SkBitmap(), &error);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::STORAGE_ERROR);
+ histogram_tester.ExpectBucketCount(
+ "BackgroundFetch.Storage.CreateMetadataTask",
+ 1 /* kServiceWorkerStorageError */, 1);
+ }
+
+ scoped_refptr<BackgroundFetchRequestInfo> request_info;
+ PopNextRequest(registration_id, &request_info);
+ ASSERT_TRUE(request_info);
+ AnnotateRequestInfoWithFakeDownloadManagerData(request_info.get(),
+ true /* success */);
+ MarkRequestAsComplete(registration_id, request_info.get());
+
+ bool succeeded = false;
+ std::vector<BackgroundFetchSettledFetch> settled_fetches;
+
+ {
+ GetSettledFetchesForRegistration(
+ registration_id, base::nullopt /* request_to_match */,
+ nullptr /* cache_query_params */, false /* match_all */, &error,
+ &succeeded, &settled_fetches);
+
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ }
+
+ // Delete an expected entry to get a CachStorageError.
+ EXPECT_TRUE(MatchCache(requests[0]));
+ DeleteFromCache(requests[0]);
+ ASSERT_FALSE(MatchCache(requests[0]));
+
+ {
+ base::HistogramTester histogram_tester;
+ GetSettledFetchesForRegistration(
+ registration_id, base::nullopt /* request_to_match */,
+ nullptr /* cache_query_params */, false /* match_all */, &error,
+ &succeeded, &settled_fetches);
+
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::STORAGE_ERROR);
+ histogram_tester.ExpectBucketCount(
+ "BackgroundFetch.Storage.GetSettledFetchesTask",
+ 2 /* kCacheStorageError */, 1);
+ }
+}
+
} // namespace content
diff --git a/chromium/content/browser/background_fetch/background_fetch_delegate_proxy.cc b/chromium/content/browser/background_fetch/background_fetch_delegate_proxy.cc
index 90f63f92b31..c8048feda17 100644
--- a/chromium/content/browser/background_fetch/background_fetch_delegate_proxy.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_delegate_proxy.cc
@@ -41,6 +41,29 @@ class BackgroundFetchDelegateProxy::Core
return weak_ptr_factory_.GetWeakPtr();
}
+ void ForwardGetPermissionForOriginCallbackToIO(
+ BackgroundFetchDelegate::GetPermissionForOriginCallback callback,
+ bool has_permission) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(std::move(callback), has_permission));
+ }
+
+ void GetPermissionForOrigin(
+ const url::Origin& origin,
+ const ResourceRequestInfo::WebContentsGetter& wc_getter,
+ BackgroundFetchDelegate::GetPermissionForOriginCallback callback) {
+ if (delegate_) {
+ delegate_->GetPermissionForOrigin(
+ origin, wc_getter,
+ base::BindOnce(&Core::ForwardGetPermissionForOriginCallbackToIO,
+ weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+ } else {
+ std::move(callback).Run(false /* has_permission */);
+ }
+ }
+
void ForwardGetIconDisplaySizeCallbackToIO(
BackgroundFetchDelegate::GetIconDisplaySizeCallback callback,
const gfx::Size& display_size) {
@@ -127,7 +150,7 @@ class BackgroundFetchDelegateProxy::Core
if (fetch_request.mode == network::mojom::FetchRequestMode::kCORS ||
fetch_request.mode ==
network::mojom::FetchRequestMode::kCORSWithForcedPreflight ||
- (fetch_request.method != "GET" && fetch_request.method != "POST")) {
+ (fetch_request.method != "GET" && fetch_request.method != "HEAD")) {
headers.SetHeader("Origin", origin.Serialize());
}
@@ -143,11 +166,13 @@ class BackgroundFetchDelegateProxy::Core
delegate_->Abort(job_unique_id);
}
- void UpdateUI(const std::string& job_unique_id, const std::string& title) {
+ void UpdateUI(const std::string& job_unique_id,
+ const base::Optional<std::string>& title,
+ const base::Optional<SkBitmap>& icon) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (delegate_)
- delegate_->UpdateUI(job_unique_id, title);
+ delegate_->UpdateUI(job_unique_id, title, icon);
}
// BackgroundFetchDelegate::Client implementation:
@@ -239,8 +264,16 @@ void BackgroundFetchDelegateProxy::Core::OnDelegateShutdown() {
}
BackgroundFetchDelegateProxy::JobDetails::JobDetails(
- base::WeakPtr<Controller> controller)
- : controller(controller) {}
+ base::WeakPtr<Controller> controller,
+ std::vector<scoped_refptr<BackgroundFetchRequestInfo>>
+ active_fetch_requests)
+ : controller(controller) {
+ for (auto& request_info : active_fetch_requests) {
+ DCHECK(request_info);
+ std::string download_guid = request_info->download_guid();
+ current_request_map[std::move(download_guid)] = std::move(request_info);
+ }
+}
BackgroundFetchDelegateProxy::JobDetails::JobDetails(JobDetails&& details) =
default;
@@ -279,14 +312,28 @@ void BackgroundFetchDelegateProxy::GetIconDisplaySize(
ui_core_ptr_, std::move(callback)));
}
+void BackgroundFetchDelegateProxy::GetPermissionForOrigin(
+ const url::Origin& origin,
+ const ResourceRequestInfo::WebContentsGetter& wc_getter,
+ BackgroundFetchDelegate::GetPermissionForOriginCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&Core::GetPermissionForOrigin, ui_core_ptr_, origin,
+ wc_getter, std::move(callback)));
+}
+
void BackgroundFetchDelegateProxy::CreateDownloadJob(
base::WeakPtr<Controller> controller,
- std::unique_ptr<BackgroundFetchDescription> fetch_description) {
+ std::unique_ptr<BackgroundFetchDescription> fetch_description,
+ std::vector<scoped_refptr<BackgroundFetchRequestInfo>>
+ active_fetch_requests) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(!job_details_map_.count(fetch_description->job_unique_id));
- job_details_map_.emplace(fetch_description->job_unique_id,
- JobDetails(controller));
+ job_details_map_.emplace(
+ fetch_description->job_unique_id,
+ JobDetails(controller, std::move(active_fetch_requests)));
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
base::BindOnce(&Core::CreateDownloadJob, ui_core_ptr_,
@@ -313,13 +360,15 @@ void BackgroundFetchDelegateProxy::StartRequest(
job_unique_id, origin, request));
}
-void BackgroundFetchDelegateProxy::UpdateUI(const std::string& job_unique_id,
- const std::string& title) {
+void BackgroundFetchDelegateProxy::UpdateUI(
+ const std::string& job_unique_id,
+ const base::Optional<std::string>& title,
+ const base::Optional<SkBitmap>& icon) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(&Core::UpdateUI, ui_core_ptr_, job_unique_id, title));
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&Core::UpdateUI, ui_core_ptr_,
+ job_unique_id, title, icon));
}
void BackgroundFetchDelegateProxy::Abort(const std::string& job_unique_id) {
@@ -329,7 +378,7 @@ void BackgroundFetchDelegateProxy::Abort(const std::string& job_unique_id) {
BrowserThread::UI, FROM_HERE,
base::BindOnce(&Core::Abort, ui_core_ptr_, job_unique_id));
- job_details_map_.erase(job_details_map_.find(job_unique_id));
+ job_details_map_.erase(job_unique_id);
}
void BackgroundFetchDelegateProxy::OnJobCancelled(
@@ -367,6 +416,7 @@ void BackgroundFetchDelegateProxy::DidStartRequest(
const scoped_refptr<BackgroundFetchRequestInfo>& request_info =
job_details.current_request_map[guid];
+ DCHECK(request_info);
DCHECK_EQ(guid, request_info->download_guid());
request_info->PopulateWithResponse(std::move(response));
@@ -399,6 +449,7 @@ void BackgroundFetchDelegateProxy::OnDownloadUpdated(
if (job_details.controller) {
const scoped_refptr<BackgroundFetchRequestInfo>& request_info =
job_details.current_request_map[guid];
+ DCHECK(request_info);
DCHECK_EQ(guid, request_info->download_guid());
job_details.controller->DidUpdateRequest(request_info, bytes_downloaded);
}
@@ -420,6 +471,7 @@ void BackgroundFetchDelegateProxy::OnDownloadComplete(
const scoped_refptr<BackgroundFetchRequestInfo>& request_info =
job_details.current_request_map[guid];
+ DCHECK(request_info);
DCHECK_EQ(guid, request_info->download_guid());
request_info->SetResult(std::move(result));
diff --git a/chromium/content/browser/background_fetch/background_fetch_delegate_proxy.h b/chromium/content/browser/background_fetch/background_fetch_delegate_proxy.h
index 1084985b3be..d393db41cfc 100644
--- a/chromium/content/browser/background_fetch/background_fetch_delegate_proxy.h
+++ b/chromium/content/browser/background_fetch/background_fetch_delegate_proxy.h
@@ -14,6 +14,7 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
+#include "base/optional.h"
#include "content/browser/background_fetch/background_fetch_request_info.h"
#include "content/public/browser/background_fetch_delegate.h"
#include "content/public/browser/background_fetch_description.h"
@@ -65,6 +66,12 @@ class CONTENT_EXPORT BackgroundFetchDelegateProxy {
void GetIconDisplaySize(
BackgroundFetchDelegate::GetIconDisplaySizeCallback callback);
+ // Checks if the provided origin has permission to start a Background Fetch.
+ void GetPermissionForOrigin(
+ const url::Origin& origin,
+ const ResourceRequestInfo::WebContentsGetter& wc_getter,
+ BackgroundFetchDelegate::GetPermissionForOriginCallback callback);
+
// Creates a new download grouping described by |fetch_description|. Further
// downloads started by StartRequest will also use
// |fetch_description.job_unique_id| so that a notification can be updated
@@ -73,11 +80,15 @@ class CONTENT_EXPORT BackgroundFetchDelegateProxy {
// GUIDs of in progress downloads, while completed downloads are recorded in
// |fetch_description.completed_parts|. The size of the completed parts is
// recorded in |fetch_description.completed_parts_size| and total download
- // size is stored in |fetch_description.total_parts_size|. Should only be
- // called from the Controller (on the IO thread).
+ // size is stored in |fetch_description.total_parts_size|.
+ // |active_fetch_requests| contains the BackgroundFetchRequestInfos
+ // needed to correctly resume an ongoing fetch.
+ // Should only be called from the Controller (on the IO thread).
void CreateDownloadJob(
base::WeakPtr<Controller> controller,
- std::unique_ptr<BackgroundFetchDescription> fetch_description);
+ std::unique_ptr<BackgroundFetchDescription> fetch_description,
+ std::vector<scoped_refptr<BackgroundFetchRequestInfo>>
+ active_fetch_requests);
// Requests that the download manager start fetching |request|.
// Should only be called from the Controller (on the IO
@@ -87,8 +98,11 @@ class CONTENT_EXPORT BackgroundFetchDelegateProxy {
scoped_refptr<BackgroundFetchRequestInfo> request);
// Updates the representation of this registration in the user interface to
- // match the given |title|. Called from the Controller (on the IO thread).
- void UpdateUI(const std::string& job_unique_id, const std::string& title);
+ // match the given |title| or |icon|.
+ // Called from the Controller (on the IO thread).
+ void UpdateUI(const std::string& job_unique_id,
+ const base::Optional<std::string>& title,
+ const base::Optional<SkBitmap>& icon);
// Aborts in progress downloads for the given registration. Called from the
// Controller (on the IO thread) after it is aborted. May occur even if all
@@ -127,7 +141,9 @@ class CONTENT_EXPORT BackgroundFetchDelegateProxy {
base::WeakPtr<Core> ui_core_ptr_;
struct JobDetails {
- explicit JobDetails(base::WeakPtr<Controller> controller);
+ JobDetails(base::WeakPtr<Controller> controller,
+ std::vector<scoped_refptr<BackgroundFetchRequestInfo>>
+ active_fetch_requests);
JobDetails(JobDetails&& details);
~JobDetails();
diff --git a/chromium/content/browser/background_fetch/background_fetch_delegate_proxy_unittest.cc b/chromium/content/browser/background_fetch/background_fetch_delegate_proxy_unittest.cc
index 3b3a88a0e2a..8d142789922 100644
--- a/chromium/content/browser/background_fetch/background_fetch_delegate_proxy_unittest.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_delegate_proxy_unittest.cc
@@ -33,6 +33,12 @@ class FakeBackgroundFetchDelegate : public BackgroundFetchDelegate {
BackgroundFetchDelegate::GetIconDisplaySizeCallback callback) override {
std::move(callback).Run(gfx::Size(kIconDisplaySize, kIconDisplaySize));
}
+ void GetPermissionForOrigin(
+ const url::Origin& origin,
+ const ResourceRequestInfo::WebContentsGetter& wc_getter,
+ GetPermissionForOriginCallback callback) override {
+ std::move(callback).Run(true /* has_permission */);
+ }
void CreateDownloadJob(
std::unique_ptr<BackgroundFetchDescription> fetch_description) override {}
void DownloadUrl(const std::string& job_unique_id,
@@ -63,15 +69,16 @@ class FakeBackgroundFetchDelegate : public BackgroundFetchDelegate {
}
void UpdateUI(const std::string& job_unique_id,
- const std::string& title) override {
- ++title_update_count_;
+ const base::Optional<std::string>& title,
+ const base::Optional<SkBitmap>& icon) override {
+ ++ui_update_count_;
}
void set_complete_downloads(bool complete_downloads) {
complete_downloads_ = complete_downloads;
}
- int title_update_count_ = 0;
+ int ui_update_count_ = 0;
private:
void CompleteDownload(const std::string& job_unique_id,
@@ -163,7 +170,8 @@ TEST_F(BackgroundFetchDelegateProxyTest, StartRequest) {
0 /* completed_parts_size */, 0 /* total_parts_size */,
std::vector<std::string>());
delegate_proxy_.CreateDownloadJob(controller.weak_ptr_factory_.GetWeakPtr(),
- std::move(fetch_description));
+ std::move(fetch_description),
+ {} /* active_fetch_requests */);
delegate_proxy_.StartRequest(kExampleUniqueId, url::Origin(), request);
base::RunLoop().RunUntilIdle();
@@ -187,7 +195,8 @@ TEST_F(BackgroundFetchDelegateProxyTest, StartRequest_NotCompleted) {
0 /* completed_parts_size */, 0 /* total_parts_size */,
std::vector<std::string>());
delegate_proxy_.CreateDownloadJob(controller.weak_ptr_factory_.GetWeakPtr(),
- std::move(fetch_description));
+ std::move(fetch_description),
+ {} /* active_fetch_requests */);
delegate_proxy_.StartRequest(kExampleUniqueId, url::Origin(), request);
base::RunLoop().RunUntilIdle();
@@ -215,7 +224,8 @@ TEST_F(BackgroundFetchDelegateProxyTest, Abort) {
0 /* completed_parts_size */, 0 /* total_parts_size */,
std::vector<std::string>());
delegate_proxy_.CreateDownloadJob(controller.weak_ptr_factory_.GetWeakPtr(),
- std::move(fetch_description1));
+ std::move(fetch_description1),
+ {} /* active_fetch_requests */);
auto fetch_description2 = std::make_unique<BackgroundFetchDescription>(
kExampleUniqueId2, "Job 2", url::Origin(), SkBitmap(),
@@ -223,7 +233,8 @@ TEST_F(BackgroundFetchDelegateProxyTest, Abort) {
0 /* completed_parts_size */, 0 /* total_parts_size */,
std::vector<std::string>());
delegate_proxy_.CreateDownloadJob(controller2.weak_ptr_factory_.GetWeakPtr(),
- std::move(fetch_description2));
+ std::move(fetch_description2),
+ {} /* active_fetch_requests */);
delegate_proxy_.StartRequest(kExampleUniqueId, url::Origin(), request);
delegate_proxy_.StartRequest(kExampleUniqueId2, url::Origin(), request2);
@@ -259,7 +270,8 @@ TEST_F(BackgroundFetchDelegateProxyTest, UpdateUI) {
std::vector<std::string>());
delegate_proxy_.CreateDownloadJob(controller.weak_ptr_factory_.GetWeakPtr(),
- std::move(fetch_description));
+ std::move(fetch_description),
+ {} /* active_fetch_requests */);
delegate_proxy_.StartRequest(kExampleUniqueId, url::Origin(), request);
base::RunLoop().RunUntilIdle();
@@ -267,9 +279,9 @@ TEST_F(BackgroundFetchDelegateProxyTest, UpdateUI) {
EXPECT_TRUE(controller.request_started_);
EXPECT_TRUE(controller.request_completed_);
- delegate_proxy_.UpdateUI(kExampleUniqueId, "Job 1 Complete!");
+ delegate_proxy_.UpdateUI(kExampleUniqueId, "Job 1 Complete!", base::nullopt);
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(delegate_.title_update_count_, 1);
+ EXPECT_EQ(delegate_.ui_update_count_, 1);
}
} // namespace content
diff --git a/chromium/content/browser/background_fetch/background_fetch_embedded_worker_test_helper.cc b/chromium/content/browser/background_fetch/background_fetch_embedded_worker_test_helper.cc
index 81b2e3ae092..b1ba4db1748 100644
--- a/chromium/content/browser/background_fetch/background_fetch_embedded_worker_test_helper.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_embedded_worker_test_helper.cc
@@ -7,7 +7,6 @@
#include "base/callback.h"
#include "base/time/time.h"
#include "content/common/background_fetch/background_fetch_types.h"
-#include "content/common/service_worker/service_worker.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom.h"
namespace content {
@@ -20,13 +19,9 @@ BackgroundFetchEmbeddedWorkerTestHelper::
~BackgroundFetchEmbeddedWorkerTestHelper() = default;
void BackgroundFetchEmbeddedWorkerTestHelper::OnBackgroundFetchAbortEvent(
- const std::string& developer_id,
- const std::string& unique_id,
- const std::vector<BackgroundFetchSettledFetch>& fetches,
+ const BackgroundFetchRegistration& registration,
mojom::ServiceWorker::DispatchBackgroundFetchAbortEventCallback callback) {
- last_developer_id_ = developer_id;
- last_unique_id_ = unique_id;
- last_fetches_ = fetches;
+ last_registration_ = registration;
if (fail_abort_event_) {
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::REJECTED,
@@ -41,11 +36,9 @@ void BackgroundFetchEmbeddedWorkerTestHelper::OnBackgroundFetchAbortEvent(
}
void BackgroundFetchEmbeddedWorkerTestHelper::OnBackgroundFetchClickEvent(
- const std::string& developer_id,
- mojom::BackgroundFetchState state,
+ const BackgroundFetchRegistration& registration,
mojom::ServiceWorker::DispatchBackgroundFetchClickEventCallback callback) {
- last_developer_id_ = developer_id;
- last_state_ = state;
+ last_registration_ = registration;
if (fail_click_event_) {
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::REJECTED,
@@ -60,13 +53,9 @@ void BackgroundFetchEmbeddedWorkerTestHelper::OnBackgroundFetchClickEvent(
}
void BackgroundFetchEmbeddedWorkerTestHelper::OnBackgroundFetchFailEvent(
- const std::string& developer_id,
- const std::string& unique_id,
- const std::vector<BackgroundFetchSettledFetch>& fetches,
+ const BackgroundFetchRegistration& registration,
mojom::ServiceWorker::DispatchBackgroundFetchFailEventCallback callback) {
- last_developer_id_ = developer_id;
- last_unique_id_ = unique_id;
- last_fetches_ = fetches;
+ last_registration_ = registration;
if (fail_fetch_fail_event_) {
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::REJECTED,
@@ -80,14 +69,11 @@ void BackgroundFetchEmbeddedWorkerTestHelper::OnBackgroundFetchFailEvent(
fetch_fail_event_closure_.Run();
}
-void BackgroundFetchEmbeddedWorkerTestHelper::OnBackgroundFetchedEvent(
- const std::string& developer_id,
- const std::string& unique_id,
- const std::vector<BackgroundFetchSettledFetch>& fetches,
- mojom::ServiceWorker::DispatchBackgroundFetchedEventCallback callback) {
- last_developer_id_ = developer_id;
- last_unique_id_ = unique_id;
- last_fetches_ = fetches;
+void BackgroundFetchEmbeddedWorkerTestHelper::OnBackgroundFetchSuccessEvent(
+ const BackgroundFetchRegistration& registration,
+ mojom::ServiceWorker::DispatchBackgroundFetchSuccessEventCallback
+ callback) {
+ last_registration_ = registration;
if (fail_fetched_event_) {
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::REJECTED,
diff --git a/chromium/content/browser/background_fetch/background_fetch_embedded_worker_test_helper.h b/chromium/content/browser/background_fetch/background_fetch_embedded_worker_test_helper.h
index 312debdfb4e..9836bd9a72a 100644
--- a/chromium/content/browser/background_fetch/background_fetch_embedded_worker_test_helper.h
+++ b/chromium/content/browser/background_fetch/background_fetch_embedded_worker_test_helper.h
@@ -15,12 +15,6 @@
namespace content {
-struct BackgroundFetchSettledFetch;
-
-namespace mojom {
-enum class BackgroundFetchState;
-}
-
// Extension of the EmbeddedWorkerTestHelper that enables instrumentation of the
// events related to the Background Fetch API. Storage for these tests will
// always be kept in memory, as data persistence is tested elsewhere.
@@ -50,45 +44,28 @@ class BackgroundFetchEmbeddedWorkerTestHelper
fetched_event_closure_ = closure;
}
- const base::Optional<std::string>& last_developer_id() const {
- return last_developer_id_;
- }
- const base::Optional<std::string>& last_unique_id() const {
- return last_unique_id_;
- }
- const base::Optional<mojom::BackgroundFetchState>& last_state() const {
- return last_state_;
- }
- const base::Optional<std::vector<BackgroundFetchSettledFetch>> last_fetches()
- const {
- return last_fetches_;
+ const base::Optional<BackgroundFetchRegistration>& last_registration() const {
+ return last_registration_;
}
protected:
// EmbeddedWorkerTestHelper overrides:
void OnBackgroundFetchAbortEvent(
- const std::string& developer_id,
- const std::string& unique_id,
- const std::vector<BackgroundFetchSettledFetch>& fetches,
+ const BackgroundFetchRegistration& registration,
mojom::ServiceWorker::DispatchBackgroundFetchAbortEventCallback callback)
override;
void OnBackgroundFetchClickEvent(
- const std::string& developer_id,
- mojom::BackgroundFetchState state,
+ const BackgroundFetchRegistration& registration,
mojom::ServiceWorker::DispatchBackgroundFetchClickEventCallback callback)
override;
void OnBackgroundFetchFailEvent(
- const std::string& developer_id,
- const std::string& unique_id,
- const std::vector<BackgroundFetchSettledFetch>& fetches,
+ const BackgroundFetchRegistration& registration,
mojom::ServiceWorker::DispatchBackgroundFetchFailEventCallback callback)
override;
- void OnBackgroundFetchedEvent(
- const std::string& developer_id,
- const std::string& unique_id,
- const std::vector<BackgroundFetchSettledFetch>& fetches,
- mojom::ServiceWorker::DispatchBackgroundFetchedEventCallback callback)
- override;
+ void OnBackgroundFetchSuccessEvent(
+ const BackgroundFetchRegistration& registration,
+ mojom::ServiceWorker::DispatchBackgroundFetchSuccessEventCallback
+ callback) override;
private:
bool fail_abort_event_ = false;
@@ -101,10 +78,7 @@ class BackgroundFetchEmbeddedWorkerTestHelper
base::Closure fetch_fail_event_closure_;
base::Closure fetched_event_closure_;
- base::Optional<std::string> last_developer_id_;
- base::Optional<std::string> last_unique_id_;
- base::Optional<mojom::BackgroundFetchState> last_state_;
- base::Optional<std::vector<BackgroundFetchSettledFetch>> last_fetches_;
+ base::Optional<BackgroundFetchRegistration> last_registration_;
DISALLOW_COPY_AND_ASSIGN(BackgroundFetchEmbeddedWorkerTestHelper);
};
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 e80dd43eb28..caa02e975b4 100644
--- a/chromium/content/browser/background_fetch/background_fetch_event_dispatcher.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_event_dispatcher.cc
@@ -6,12 +6,14 @@
#include "base/bind.h"
#include "base/callback.h"
+#include "base/callback_helpers.h"
#include "base/metrics/histogram_functions.h"
#include "base/strings/stringprintf.h"
#include "content/browser/background_fetch/background_fetch_registration_id.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"
+#include "content/common/background_fetch/background_fetch_types.h"
#include "content/public/browser/browser_thread.h"
namespace content {
@@ -27,8 +29,8 @@ std::string HistogramSuffixForEventType(ServiceWorkerMetrics::EventType event) {
return "ClickEvent";
case ServiceWorkerMetrics::EventType::BACKGROUND_FETCH_FAIL:
return "FailEvent";
- case ServiceWorkerMetrics::EventType::BACKGROUND_FETCHED:
- return "FetchedEvent";
+ case ServiceWorkerMetrics::EventType::BACKGROUND_FETCH_SUCCESS:
+ return "SuccessEvent";
default:
NOTREACHED();
return std::string();
@@ -75,103 +77,99 @@ BackgroundFetchEventDispatcher::~BackgroundFetchEventDispatcher() {
void BackgroundFetchEventDispatcher::DispatchBackgroundFetchAbortEvent(
const BackgroundFetchRegistrationId& registration_id,
- const std::vector<BackgroundFetchSettledFetch>& fetches,
+ std::unique_ptr<BackgroundFetchRegistration> registration,
base::OnceClosure finished_closure) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
LoadServiceWorkerRegistrationForDispatch(
registration_id, ServiceWorkerMetrics::EventType::BACKGROUND_FETCH_ABORT,
std::move(finished_closure),
- base::Bind(
+ base::AdaptCallbackForRepeating(base::BindOnce(
&BackgroundFetchEventDispatcher::DoDispatchBackgroundFetchAbortEvent,
- registration_id.developer_id(), registration_id.unique_id(),
- fetches));
+ std::move(registration))));
}
void BackgroundFetchEventDispatcher::DoDispatchBackgroundFetchAbortEvent(
- const std::string& developer_id,
- const std::string& unique_id,
- const std::vector<BackgroundFetchSettledFetch>& fetches,
+ std::unique_ptr<BackgroundFetchRegistration> registration,
scoped_refptr<ServiceWorkerVersion> service_worker_version,
int request_id) {
DCHECK(service_worker_version);
+ DCHECK(registration);
service_worker_version->endpoint()->DispatchBackgroundFetchAbortEvent(
- developer_id, unique_id, fetches,
+ *registration,
service_worker_version->CreateSimpleEventCallback(request_id));
}
void BackgroundFetchEventDispatcher::DispatchBackgroundFetchClickEvent(
const BackgroundFetchRegistrationId& registration_id,
- mojom::BackgroundFetchState state,
+ std::unique_ptr<BackgroundFetchRegistration> registration,
base::OnceClosure finished_closure) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
LoadServiceWorkerRegistrationForDispatch(
registration_id, ServiceWorkerMetrics::EventType::BACKGROUND_FETCH_CLICK,
std::move(finished_closure),
- base::Bind(
+ base::AdaptCallbackForRepeating(base::BindOnce(
&BackgroundFetchEventDispatcher::DoDispatchBackgroundFetchClickEvent,
- registration_id.developer_id(), state));
+ std::move(registration))));
}
void BackgroundFetchEventDispatcher::DoDispatchBackgroundFetchClickEvent(
- const std::string& developer_id,
- mojom::BackgroundFetchState state,
+ std::unique_ptr<BackgroundFetchRegistration> registration,
scoped_refptr<ServiceWorkerVersion> service_worker_version,
int request_id) {
DCHECK(service_worker_version);
+ DCHECK(registration);
service_worker_version->endpoint()->DispatchBackgroundFetchClickEvent(
- developer_id, state,
+ *registration,
service_worker_version->CreateSimpleEventCallback(request_id));
}
void BackgroundFetchEventDispatcher::DispatchBackgroundFetchFailEvent(
const BackgroundFetchRegistrationId& registration_id,
- const std::vector<BackgroundFetchSettledFetch>& fetches,
+ std::unique_ptr<BackgroundFetchRegistration> registration,
base::OnceClosure finished_closure) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
LoadServiceWorkerRegistrationForDispatch(
registration_id, ServiceWorkerMetrics::EventType::BACKGROUND_FETCH_FAIL,
std::move(finished_closure),
- base::Bind(
+ base::AdaptCallbackForRepeating(base::BindOnce(
&BackgroundFetchEventDispatcher::DoDispatchBackgroundFetchFailEvent,
- registration_id.developer_id(), registration_id.unique_id(),
- fetches));
+ std::move(registration))));
}
void BackgroundFetchEventDispatcher::DoDispatchBackgroundFetchFailEvent(
- const std::string& developer_id,
- const std::string& unique_id,
- const std::vector<BackgroundFetchSettledFetch>& fetches,
+ std::unique_ptr<BackgroundFetchRegistration> registration,
scoped_refptr<ServiceWorkerVersion> service_worker_version,
int request_id) {
DCHECK(service_worker_version);
+ DCHECK(registration);
service_worker_version->endpoint()->DispatchBackgroundFetchFailEvent(
- developer_id, unique_id, fetches,
+ *registration,
service_worker_version->CreateSimpleEventCallback(request_id));
}
-void BackgroundFetchEventDispatcher::DispatchBackgroundFetchedEvent(
+void BackgroundFetchEventDispatcher::DispatchBackgroundFetchSuccessEvent(
const BackgroundFetchRegistrationId& registration_id,
- const std::vector<BackgroundFetchSettledFetch>& fetches,
+ std::unique_ptr<BackgroundFetchRegistration> registration,
base::OnceClosure finished_closure) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
LoadServiceWorkerRegistrationForDispatch(
- registration_id, ServiceWorkerMetrics::EventType::BACKGROUND_FETCHED,
+ registration_id,
+ ServiceWorkerMetrics::EventType::BACKGROUND_FETCH_SUCCESS,
std::move(finished_closure),
- base::Bind(
- &BackgroundFetchEventDispatcher::DoDispatchBackgroundFetchedEvent,
- registration_id.developer_id(), registration_id.unique_id(),
- fetches));
+ base::AdaptCallbackForRepeating(
+ base::BindOnce(&BackgroundFetchEventDispatcher::
+ DoDispatchBackgroundFetchSuccessEvent,
+ std::move(registration))));
}
-void BackgroundFetchEventDispatcher::DoDispatchBackgroundFetchedEvent(
- const std::string& developer_id,
- const std::string& unique_id,
- const std::vector<BackgroundFetchSettledFetch>& fetches,
+void BackgroundFetchEventDispatcher::DoDispatchBackgroundFetchSuccessEvent(
+ std::unique_ptr<BackgroundFetchRegistration> registration,
scoped_refptr<ServiceWorkerVersion> service_worker_version,
int request_id) {
DCHECK(service_worker_version);
- service_worker_version->endpoint()->DispatchBackgroundFetchedEvent(
- developer_id, unique_id, fetches,
+ DCHECK(registration);
+ service_worker_version->endpoint()->DispatchBackgroundFetchSuccessEvent(
+ *registration,
service_worker_version->CreateSimpleEventCallback(request_id));
}
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 f5358207186..4ab631be9a7 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,6 @@
namespace content {
class BackgroundFetchRegistrationId;
-struct BackgroundFetchSettledFetch;
class ServiceWorkerContextWrapper;
class ServiceWorkerRegistration;
class ServiceWorkerVersion;
@@ -45,29 +44,28 @@ class CONTENT_EXPORT BackgroundFetchEventDispatcher {
// background fetch was aborted by the user or another external event.
void DispatchBackgroundFetchAbortEvent(
const BackgroundFetchRegistrationId& registration_id,
- const std::vector<BackgroundFetchSettledFetch>& fetches,
+ std::unique_ptr<BackgroundFetchRegistration> registration,
base::OnceClosure finished_closure);
// Dispatches the `backgroundfetchclick` event, which indicates that the user
// interface displayed for an active background fetch was activated.
void DispatchBackgroundFetchClickEvent(
const BackgroundFetchRegistrationId& registration_id,
- mojom::BackgroundFetchState state,
+ std::unique_ptr<BackgroundFetchRegistration> registration,
base::OnceClosure finished_closure);
// Dispatches the `backgroundfetchfail` event, which indicates that a
- // background fetch has finished with one or more failed fetches. The request-
- // response pairs are included.
+ // background fetch has finished with one or more failed fetches.
void DispatchBackgroundFetchFailEvent(
const BackgroundFetchRegistrationId& registration_id,
- const std::vector<BackgroundFetchSettledFetch>& fetches,
+ std::unique_ptr<BackgroundFetchRegistration> registration,
base::OnceClosure finished_closure);
- // Dispatches the `backgroundfetched` event, which indicates that a background
- // fetch has successfully completed. The request-response pairs are included.
- void DispatchBackgroundFetchedEvent(
+ // Dispatches the `backgroundfetchsuccess` event, which indicates that a
+ // background fetch has successfully completed.
+ void DispatchBackgroundFetchSuccessEvent(
const BackgroundFetchRegistrationId& registration_id,
- const std::vector<BackgroundFetchSettledFetch>& fetches,
+ std::unique_ptr<BackgroundFetchRegistration> registration,
base::OnceClosure finished_closure);
private:
@@ -114,26 +112,19 @@ class CONTENT_EXPORT BackgroundFetchEventDispatcher {
// Methods that actually invoke the event on an activated Service Worker.
static void DoDispatchBackgroundFetchAbortEvent(
- const std::string& developer_id,
- const std::string& unique_id,
- const std::vector<BackgroundFetchSettledFetch>& fetches,
+ std::unique_ptr<BackgroundFetchRegistration> registration,
scoped_refptr<ServiceWorkerVersion> service_worker_version,
int request_id);
static void DoDispatchBackgroundFetchClickEvent(
- const std::string& developer_id,
- mojom::BackgroundFetchState state,
+ std::unique_ptr<BackgroundFetchRegistration> registration,
scoped_refptr<ServiceWorkerVersion> service_worker_version,
int request_id);
static void DoDispatchBackgroundFetchFailEvent(
- const std::string& developer_id,
- const std::string& unique_id,
- const std::vector<BackgroundFetchSettledFetch>& fetches,
+ std::unique_ptr<BackgroundFetchRegistration> registration,
scoped_refptr<ServiceWorkerVersion> service_worker_version,
int request_id);
- static void DoDispatchBackgroundFetchedEvent(
- const std::string& developer_id,
- const std::string& unique_id,
- const std::vector<BackgroundFetchSettledFetch>& fetches,
+ static void DoDispatchBackgroundFetchSuccessEvent(
+ std::unique_ptr<BackgroundFetchRegistration> registration,
scoped_refptr<ServiceWorkerVersion> service_worker_version,
int request_id);
diff --git a/chromium/content/browser/background_fetch/background_fetch_event_dispatcher_unittest.cc b/chromium/content/browser/background_fetch/background_fetch_event_dispatcher_unittest.cc
index dd6655ef7b2..415e48ebf61 100644
--- a/chromium/content/browser/background_fetch/background_fetch_event_dispatcher_unittest.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_event_dispatcher_unittest.cc
@@ -16,6 +16,7 @@
#include "content/browser/background_fetch/background_fetch_test_base.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/platform/modules/background_fetch/background_fetch.mojom.h"
namespace content {
namespace {
@@ -44,8 +45,13 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchInvalidRegistration) {
kExampleUniqueId);
base::RunLoop run_loop;
+ auto registration = CreateBackgroundFetchRegistration(
+ invalid_registration_id.developer_id(),
+ invalid_registration_id.unique_id(),
+ blink::mojom::BackgroundFetchState::FAILURE,
+ blink::mojom::BackgroundFetchFailureReason::QUOTA_EXCEEDED);
event_dispatcher_.DispatchBackgroundFetchAbortEvent(
- invalid_registration_id, {}, run_loop.QuitClosure());
+ invalid_registration_id, std::move(registration), run_loop.QuitClosure());
run_loop.Run();
@@ -71,19 +77,23 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchAbortEvent) {
{
base::RunLoop run_loop;
+ auto registration = CreateBackgroundFetchRegistration(
+ kExampleDeveloperId, kExampleUniqueId,
+ blink::mojom::BackgroundFetchState::FAILURE,
+ blink::mojom::BackgroundFetchFailureReason::CANCELLED_FROM_UI);
event_dispatcher_.DispatchBackgroundFetchAbortEvent(
- registration_id, fetches, run_loop.QuitClosure());
+ registration_id, std::move(registration), run_loop.QuitClosure());
run_loop.Run();
}
- ASSERT_TRUE(embedded_worker_test_helper()->last_developer_id().has_value());
+ ASSERT_TRUE(embedded_worker_test_helper()->last_registration().has_value());
EXPECT_EQ(kExampleDeveloperId,
- embedded_worker_test_helper()->last_developer_id().value());
- ASSERT_TRUE(embedded_worker_test_helper()->last_unique_id().has_value());
+ embedded_worker_test_helper()->last_registration()->developer_id);
EXPECT_EQ(kExampleUniqueId,
- embedded_worker_test_helper()->last_unique_id().value());
- ASSERT_TRUE(embedded_worker_test_helper()->last_fetches().has_value());
+ embedded_worker_test_helper()->last_registration()->unique_id);
+ EXPECT_EQ(blink::mojom::BackgroundFetchFailureReason::CANCELLED_FROM_UI,
+ embedded_worker_test_helper()->last_registration()->failure_reason);
histogram_tester_.ExpectUniqueSample(
"BackgroundFetch.EventDispatchResult.AbortEvent",
@@ -97,19 +107,22 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchAbortEvent) {
{
base::RunLoop run_loop;
- event_dispatcher_.DispatchBackgroundFetchAbortEvent(
- second_registration_id, fetches, run_loop.QuitClosure());
+ auto registration = CreateBackgroundFetchRegistration(
+ kExampleDeveloperId2, kExampleUniqueId2,
+ blink::mojom::BackgroundFetchState::FAILURE,
+ blink::mojom::BackgroundFetchFailureReason::QUOTA_EXCEEDED);
+ event_dispatcher_.DispatchBackgroundFetchAbortEvent(second_registration_id,
+ std::move(registration),
+ run_loop.QuitClosure());
run_loop.Run();
}
- ASSERT_TRUE(embedded_worker_test_helper()->last_developer_id().has_value());
+ ASSERT_TRUE(embedded_worker_test_helper()->last_registration().has_value());
EXPECT_EQ(kExampleDeveloperId2,
- embedded_worker_test_helper()->last_developer_id().value());
- ASSERT_TRUE(embedded_worker_test_helper()->last_unique_id().has_value());
+ embedded_worker_test_helper()->last_registration()->developer_id);
EXPECT_EQ(kExampleUniqueId2,
- embedded_worker_test_helper()->last_unique_id().value());
- ASSERT_TRUE(embedded_worker_test_helper()->last_fetches().has_value());
+ embedded_worker_test_helper()->last_registration()->unique_id);
histogram_tester_.ExpectBucketCount(
"BackgroundFetch.EventDispatchResult.AbortEvent",
@@ -133,20 +146,21 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchClickEvent) {
{
base::RunLoop run_loop;
+ auto registration = CreateBackgroundFetchRegistration(
+ kExampleDeveloperId, kExampleUniqueId,
+ blink::mojom::BackgroundFetchState::PENDING,
+ blink::mojom::BackgroundFetchFailureReason::NONE);
event_dispatcher_.DispatchBackgroundFetchClickEvent(
- registration_id, mojom::BackgroundFetchState::PENDING,
- run_loop.QuitClosure());
+ registration_id, std::move(registration), run_loop.QuitClosure());
run_loop.Run();
}
- ASSERT_TRUE(embedded_worker_test_helper()->last_developer_id().has_value());
+ ASSERT_TRUE(embedded_worker_test_helper()->last_registration().has_value());
EXPECT_EQ(kExampleDeveloperId,
- embedded_worker_test_helper()->last_developer_id().value());
-
- ASSERT_TRUE(embedded_worker_test_helper()->last_state().has_value());
- EXPECT_EQ(mojom::BackgroundFetchState::PENDING,
- embedded_worker_test_helper()->last_state());
+ embedded_worker_test_helper()->last_registration()->developer_id);
+ EXPECT_EQ(blink::mojom::BackgroundFetchState::PENDING,
+ embedded_worker_test_helper()->last_registration()->state);
histogram_tester_.ExpectUniqueSample(
"BackgroundFetch.EventDispatchResult.ClickEvent",
@@ -160,20 +174,22 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchClickEvent) {
{
base::RunLoop run_loop;
- event_dispatcher_.DispatchBackgroundFetchClickEvent(
- second_registration_id, mojom::BackgroundFetchState::SUCCEEDED,
- run_loop.QuitClosure());
+ auto registration = CreateBackgroundFetchRegistration(
+ kExampleDeveloperId2, kExampleUniqueId2,
+ blink::mojom::BackgroundFetchState::FAILURE,
+ blink::mojom::BackgroundFetchFailureReason::QUOTA_EXCEEDED);
+ event_dispatcher_.DispatchBackgroundFetchClickEvent(second_registration_id,
+ std::move(registration),
+ run_loop.QuitClosure());
run_loop.Run();
}
- ASSERT_TRUE(embedded_worker_test_helper()->last_developer_id().has_value());
+ ASSERT_TRUE(embedded_worker_test_helper()->last_registration().has_value());
EXPECT_EQ(kExampleDeveloperId2,
- embedded_worker_test_helper()->last_developer_id().value());
-
- ASSERT_TRUE(embedded_worker_test_helper()->last_state().has_value());
- EXPECT_EQ(mojom::BackgroundFetchState::SUCCEEDED,
- embedded_worker_test_helper()->last_state());
+ embedded_worker_test_helper()->last_registration()->developer_id);
+ EXPECT_EQ(blink::mojom::BackgroundFetchState::FAILURE,
+ embedded_worker_test_helper()->last_registration()->state);
histogram_tester_.ExpectBucketCount(
"BackgroundFetch.EventDispatchResult.ClickEvent",
@@ -195,31 +211,26 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchFailEvent) {
origin(), kExampleDeveloperId,
kExampleUniqueId);
- std::vector<BackgroundFetchSettledFetch> fetches;
- fetches.push_back(BackgroundFetchSettledFetch());
-
{
base::RunLoop run_loop;
- event_dispatcher_.DispatchBackgroundFetchFailEvent(registration_id, fetches,
- run_loop.QuitClosure());
+ auto registration = CreateBackgroundFetchRegistration(
+ kExampleDeveloperId, kExampleUniqueId,
+ blink::mojom::BackgroundFetchState::FAILURE,
+ blink::mojom::BackgroundFetchFailureReason::QUOTA_EXCEEDED);
+ event_dispatcher_.DispatchBackgroundFetchFailEvent(
+ registration_id, std::move(registration), run_loop.QuitClosure());
run_loop.Run();
}
- ASSERT_TRUE(embedded_worker_test_helper()->last_developer_id().has_value());
+ ASSERT_TRUE(embedded_worker_test_helper()->last_registration().has_value());
EXPECT_EQ(kExampleDeveloperId,
- embedded_worker_test_helper()->last_developer_id().value());
-
- ASSERT_TRUE(embedded_worker_test_helper()->last_fetches().has_value());
- EXPECT_EQ(fetches.size(),
- embedded_worker_test_helper()->last_fetches()->size());
+ embedded_worker_test_helper()->last_registration()->developer_id);
histogram_tester_.ExpectUniqueSample(
"BackgroundFetch.EventDispatchResult.FailEvent",
BackgroundFetchEventDispatcher::DISPATCH_RESULT_SUCCESS, 1);
- fetches.push_back(BackgroundFetchSettledFetch());
-
embedded_worker_test_helper()->set_fail_fetch_fail_event(true);
BackgroundFetchRegistrationId second_registration_id(
@@ -228,19 +239,19 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchFailEvent) {
{
base::RunLoop run_loop;
- event_dispatcher_.DispatchBackgroundFetchFailEvent(
- second_registration_id, fetches, run_loop.QuitClosure());
-
+ auto registration = CreateBackgroundFetchRegistration(
+ kExampleDeveloperId2, kExampleUniqueId2,
+ blink::mojom::BackgroundFetchState::FAILURE,
+ blink::mojom::BackgroundFetchFailureReason::QUOTA_EXCEEDED);
+ event_dispatcher_.DispatchBackgroundFetchFailEvent(second_registration_id,
+ std::move(registration),
+ run_loop.QuitClosure());
run_loop.Run();
}
- ASSERT_TRUE(embedded_worker_test_helper()->last_developer_id().has_value());
+ ASSERT_TRUE(embedded_worker_test_helper()->last_registration().has_value());
EXPECT_EQ(kExampleDeveloperId2,
- embedded_worker_test_helper()->last_developer_id().value());
-
- ASSERT_TRUE(embedded_worker_test_helper()->last_fetches().has_value());
- EXPECT_EQ(fetches.size(),
- embedded_worker_test_helper()->last_fetches()->size());
+ embedded_worker_test_helper()->last_registration()->developer_id);
histogram_tester_.ExpectBucketCount(
"BackgroundFetch.EventDispatchResult.FailEvent",
@@ -253,7 +264,7 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchFailEvent) {
blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected, 1);
}
-TEST_F(BackgroundFetchEventDispatcherTest, DispatchFetchedEvent) {
+TEST_F(BackgroundFetchEventDispatcherTest, DispatchFetchSuccessEvent) {
int64_t service_worker_registration_id = RegisterServiceWorker();
ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId,
service_worker_registration_id);
@@ -262,35 +273,29 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchFetchedEvent) {
origin(), kExampleDeveloperId,
kExampleUniqueId);
- std::vector<BackgroundFetchSettledFetch> fetches;
- fetches.push_back(BackgroundFetchSettledFetch());
-
{
base::RunLoop run_loop;
- event_dispatcher_.DispatchBackgroundFetchedEvent(registration_id, fetches,
- run_loop.QuitClosure());
+ auto registration = CreateBackgroundFetchRegistration(
+ kExampleDeveloperId, kExampleUniqueId,
+ blink::mojom::BackgroundFetchState::SUCCESS,
+ blink::mojom::BackgroundFetchFailureReason::NONE);
+ event_dispatcher_.DispatchBackgroundFetchSuccessEvent(
+ registration_id, std::move(registration), run_loop.QuitClosure());
run_loop.Run();
}
- ASSERT_TRUE(embedded_worker_test_helper()->last_developer_id().has_value());
+ ASSERT_TRUE(embedded_worker_test_helper()->last_registration().has_value());
EXPECT_EQ(kExampleDeveloperId,
- embedded_worker_test_helper()->last_developer_id().value());
+ embedded_worker_test_helper()->last_registration()->developer_id);
- ASSERT_TRUE(embedded_worker_test_helper()->last_unique_id().has_value());
EXPECT_EQ(kExampleUniqueId,
- embedded_worker_test_helper()->last_unique_id().value());
-
- ASSERT_TRUE(embedded_worker_test_helper()->last_fetches().has_value());
- EXPECT_EQ(fetches.size(),
- embedded_worker_test_helper()->last_fetches()->size());
+ embedded_worker_test_helper()->last_registration()->unique_id);
histogram_tester_.ExpectUniqueSample(
- "BackgroundFetch.EventDispatchResult.FetchedEvent",
+ "BackgroundFetch.EventDispatchResult.SuccessEvent",
BackgroundFetchEventDispatcher::DISPATCH_RESULT_SUCCESS, 1);
- fetches.push_back(BackgroundFetchSettledFetch());
-
embedded_worker_test_helper()->set_fail_fetched_event(true);
BackgroundFetchRegistrationId second_registration_id(
@@ -299,32 +304,31 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchFetchedEvent) {
{
base::RunLoop run_loop;
- event_dispatcher_.DispatchBackgroundFetchedEvent(
- second_registration_id, fetches, run_loop.QuitClosure());
+ auto registration = CreateBackgroundFetchRegistration(
+ kExampleDeveloperId2, kExampleUniqueId2,
+ blink::mojom::BackgroundFetchState::SUCCESS,
+ blink::mojom::BackgroundFetchFailureReason::NONE);
+ event_dispatcher_.DispatchBackgroundFetchSuccessEvent(
+ second_registration_id, std::move(registration),
+ run_loop.QuitClosure());
run_loop.Run();
}
- ASSERT_TRUE(embedded_worker_test_helper()->last_developer_id().has_value());
+ ASSERT_TRUE(embedded_worker_test_helper()->last_registration().has_value());
EXPECT_EQ(kExampleDeveloperId2,
- embedded_worker_test_helper()->last_developer_id().value());
-
- ASSERT_TRUE(embedded_worker_test_helper()->last_unique_id().has_value());
+ embedded_worker_test_helper()->last_registration()->developer_id);
EXPECT_EQ(kExampleUniqueId2,
- embedded_worker_test_helper()->last_unique_id().value());
-
- ASSERT_TRUE(embedded_worker_test_helper()->last_fetches().has_value());
- EXPECT_EQ(fetches.size(),
- embedded_worker_test_helper()->last_fetches()->size());
+ embedded_worker_test_helper()->last_registration()->unique_id);
histogram_tester_.ExpectBucketCount(
- "BackgroundFetch.EventDispatchResult.FetchedEvent",
+ "BackgroundFetch.EventDispatchResult.SuccessEvent",
BackgroundFetchEventDispatcher::DISPATCH_RESULT_SUCCESS, 1);
histogram_tester_.ExpectBucketCount(
- "BackgroundFetch.EventDispatchResult.FetchedEvent",
+ "BackgroundFetch.EventDispatchResult.SuccessEvent",
BackgroundFetchEventDispatcher::DISPATCH_RESULT_CANNOT_DISPATCH_EVENT, 1);
histogram_tester_.ExpectUniqueSample(
- "BackgroundFetch.EventDispatchFailure.Dispatch.FetchedEvent",
+ "BackgroundFetch.EventDispatchFailure.Dispatch.SuccessEvent",
blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected, 1);
}
diff --git a/chromium/content/browser/background_fetch/background_fetch_job_controller.cc b/chromium/content/browser/background_fetch/background_fetch_job_controller.cc
index 2b9a7e6681a..a2e82ba7bdd 100644
--- a/chromium/content/browser/background_fetch/background_fetch_job_controller.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_job_controller.cc
@@ -3,29 +3,29 @@
// found in the LICENSE file.
#include "content/browser/background_fetch/background_fetch_job_controller.h"
+#include "third_party/blink/public/platform/modules/background_fetch/background_fetch.mojom.h"
#include <utility>
-#include "content/browser/background_fetch/background_fetch_request_manager.h"
#include "content/public/browser/browser_thread.h"
namespace content {
BackgroundFetchJobController::BackgroundFetchJobController(
BackgroundFetchDelegateProxy* delegate_proxy,
+ BackgroundFetchScheduler* scheduler,
const BackgroundFetchRegistrationId& registration_id,
const BackgroundFetchOptions& options,
const SkBitmap& icon,
uint64_t bytes_downloaded,
- BackgroundFetchRequestManager* request_manager,
ProgressCallback progress_callback,
BackgroundFetchScheduler::FinishedCallback finished_callback)
- : BackgroundFetchScheduler::Controller(registration_id,
+ : BackgroundFetchScheduler::Controller(scheduler,
+ registration_id,
std::move(finished_callback)),
options_(options),
icon_(icon),
complete_requests_downloaded_bytes_cache_(bytes_downloaded),
- request_manager_(request_manager),
delegate_proxy_(delegate_proxy),
progress_callback_(std::move(progress_callback)),
weak_ptr_factory_(this) {
@@ -35,7 +35,8 @@ BackgroundFetchJobController::BackgroundFetchJobController(
void BackgroundFetchJobController::InitializeRequestStatus(
int completed_downloads,
int total_downloads,
- const std::vector<std::string>& outstanding_guids,
+ std::vector<scoped_refptr<BackgroundFetchRequestInfo>>
+ active_fetch_requests,
const std::string& ui_title) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -47,16 +48,21 @@ void BackgroundFetchJobController::InitializeRequestStatus(
total_downloads_ = total_downloads;
// TODO(nator): Update this when we support uploads.
- int total_downloads_size = options_.download_total;
+ total_downloads_size_ = options_.download_total;
+
+ std::vector<std::string> active_guids;
+ active_guids.reserve(active_fetch_requests.size());
+ for (const auto& request_info : active_fetch_requests)
+ active_guids.push_back(request_info->download_guid());
auto fetch_description = std::make_unique<BackgroundFetchDescription>(
registration_id().unique_id(), ui_title, registration_id().origin(),
icon_, completed_downloads, total_downloads,
- complete_requests_downloaded_bytes_cache_, total_downloads_size,
- outstanding_guids);
+ complete_requests_downloaded_bytes_cache_, total_downloads_size_,
+ std::move(active_guids));
- delegate_proxy_->CreateDownloadJob(GetWeakPtr(),
- std::move(fetch_description));
+ delegate_proxy_->CreateDownloadJob(GetWeakPtr(), std::move(fetch_description),
+ std::move(active_fetch_requests));
}
BackgroundFetchJobController::~BackgroundFetchJobController() {
@@ -68,12 +74,15 @@ bool BackgroundFetchJobController::HasMoreRequests() {
}
void BackgroundFetchJobController::StartRequest(
- scoped_refptr<BackgroundFetchRequestInfo> request) {
+ scoped_refptr<BackgroundFetchRequestInfo> request,
+ RequestFinishedCallback request_finished_callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK_LT(completed_downloads_, total_downloads_);
+ DCHECK(request_finished_callback);
DCHECK(request);
- active_request_download_bytes_[request->download_guid()] = 0;
+ active_request_downloaded_bytes_ = 0;
+ active_request_finished_callback_ = std::move(request_finished_callback);
delegate_proxy_->StartRequest(registration_id().unique_id(),
registration_id().origin(), request);
@@ -93,11 +102,10 @@ void BackgroundFetchJobController::DidUpdateRequest(
uint64_t bytes_downloaded) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- const std::string& download_guid = request->download_guid();
- if (active_request_download_bytes_[download_guid] == bytes_downloaded)
+ if (active_request_downloaded_bytes_ == bytes_downloaded)
return;
- active_request_download_bytes_[download_guid] = bytes_downloaded;
+ active_request_downloaded_bytes_ = bytes_downloaded;
progress_callback_.Run(registration_id().unique_id(), options_.download_total,
complete_requests_downloaded_bytes_cache_ +
@@ -108,43 +116,75 @@ void BackgroundFetchJobController::DidCompleteRequest(
const scoped_refptr<BackgroundFetchRequestInfo>& request) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- active_request_download_bytes_.erase(request->download_guid());
+ // It's possible for the DidCompleteRequest() callback to have been in-flight
+ // while this Job Controller was being aborted, in which case the
+ // |active_request_finished_callback_| will have been reset.
+ if (!active_request_finished_callback_)
+ return;
+
+ active_request_downloaded_bytes_ = 0;
+
complete_requests_downloaded_bytes_cache_ += request->GetFileSize();
++completed_downloads_;
- request_manager_->MarkRequestAsComplete(registration_id(), request.get());
+ std::move(active_request_finished_callback_).Run(request);
}
-void BackgroundFetchJobController::UpdateUI(const std::string& title) {
+void BackgroundFetchJobController::UpdateUI(
+ const base::Optional<std::string>& title,
+ const base::Optional<SkBitmap>& icon) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- delegate_proxy_->UpdateUI(registration_id().unique_id(), title);
+ delegate_proxy_->UpdateUI(registration_id().unique_id(), title, icon);
+}
+
+std::unique_ptr<BackgroundFetchRegistration>
+BackgroundFetchJobController::NewRegistration(
+ blink::mojom::BackgroundFetchState state) const {
+ return std::make_unique<BackgroundFetchRegistration>(
+ registration_id().developer_id(), registration_id().unique_id(),
+ 0 /* upload_total */, 0 /* uploaded */, total_downloads_size_,
+ complete_requests_downloaded_bytes_cache_, state, MojoFailureReason());
}
uint64_t BackgroundFetchJobController::GetInProgressDownloadedBytes() {
- uint64_t sum = 0;
- for (const auto& entry : active_request_download_bytes_)
- sum += entry.second;
- return sum;
+ return active_request_downloaded_bytes_;
+}
+
+// TODO(crbug.com/876691): Get rid of BackgroundFetchReasonToAbort and remove
+// this method.
+blink::mojom::BackgroundFetchFailureReason
+BackgroundFetchJobController::MojoFailureReason() const {
+ switch (reason_to_abort_) {
+ case BackgroundFetchReasonToAbort::NONE:
+ return blink::mojom::BackgroundFetchFailureReason::NONE;
+ case BackgroundFetchReasonToAbort::CANCELLED_FROM_UI:
+ return blink::mojom::BackgroundFetchFailureReason::CANCELLED_FROM_UI;
+ case BackgroundFetchReasonToAbort::ABORTED_BY_DEVELOPER:
+ return blink::mojom::BackgroundFetchFailureReason::CANCELLED_BY_DEVELOPER;
+ case BackgroundFetchReasonToAbort::TOTAL_DOWNLOAD_SIZE_EXCEEDED:
+ return blink::mojom::BackgroundFetchFailureReason::
+ TOTAL_DOWNLOAD_SIZE_EXCEEDED;
+ case BackgroundFetchReasonToAbort::SERVICE_WORKER_UNAVAILABLE:
+ return blink::mojom::BackgroundFetchFailureReason::
+ SERVICE_WORKER_UNAVAILABLE;
+ case BackgroundFetchReasonToAbort::QUOTA_EXCEEDED:
+ return blink::mojom::BackgroundFetchFailureReason::QUOTA_EXCEEDED;
+ }
+ NOTREACHED();
}
void BackgroundFetchJobController::Abort(
BackgroundFetchReasonToAbort reason_to_abort) {
+ reason_to_abort_ = reason_to_abort;
+
+ // Stop propagating any in-flight events to the scheduler.
+ active_request_finished_callback_.Reset();
+
+ // Cancel any in-flight downloads and UI through the BGFetchDelegate.
delegate_proxy_->Abort(registration_id().unique_id());
- std::vector<std::string> aborted_guids;
- for (const auto& pair : active_request_download_bytes_)
- aborted_guids.push_back(pair.first);
- request_manager_->OnJobAborted(registration_id(), std::move(aborted_guids));
- if (reason_to_abort != BackgroundFetchReasonToAbort::ABORTED_BY_DEVELOPER) {
- // Don't call Finish() here, so that we don't mark data for deletion while
- // there are active fetches.
- // Once the controller finishes processing, this function will be called
- // again. (BackgroundFetchScheduler's finished_callback_ will call
- // BackgroundFetchJobController::Abort() with |cancel_download| set to
- // true.)
- Finish(reason_to_abort);
- }
+ Finish(reason_to_abort);
}
} // namespace content
diff --git a/chromium/content/browser/background_fetch/background_fetch_job_controller.h b/chromium/content/browser/background_fetch/background_fetch_job_controller.h
index 780791dda8b..7bc8b2fbf9e 100644
--- a/chromium/content/browser/background_fetch/background_fetch_job_controller.h
+++ b/chromium/content/browser/background_fetch/background_fetch_job_controller.h
@@ -12,7 +12,9 @@
#include "base/callback.h"
#include "base/macros.h"
+#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
+#include "base/optional.h"
#include "content/browser/background_fetch/background_fetch_delegate_proxy.h"
#include "content/browser/background_fetch/background_fetch_registration_id.h"
#include "content/browser/background_fetch/background_fetch_request_info.h"
@@ -24,8 +26,6 @@
namespace content {
-class BackgroundFetchRequestManager;
-
// The JobController will be responsible for coordinating communication with the
// DownloadManager. It will get requests from the RequestManager and dispatch
// them to the DownloadService. It lives entirely on the IO thread.
@@ -46,13 +46,14 @@ class CONTENT_EXPORT BackgroundFetchJobController final
base::RepeatingCallback<void(const std::string& /* unique_id */,
uint64_t /* download_total */,
uint64_t /* downloaded */)>;
+
BackgroundFetchJobController(
BackgroundFetchDelegateProxy* delegate_proxy,
+ BackgroundFetchScheduler* scheduler,
const BackgroundFetchRegistrationId& registration_id,
const BackgroundFetchOptions& options,
const SkBitmap& icon,
uint64_t bytes_downloaded,
- BackgroundFetchRequestManager* request_manager,
ProgressCallback progress_callback,
BackgroundFetchScheduler::FinishedCallback finished_callback);
~BackgroundFetchJobController() override;
@@ -63,19 +64,35 @@ class CONTENT_EXPORT BackgroundFetchJobController final
void InitializeRequestStatus(
int completed_downloads,
int total_downloads,
- const std::vector<std::string>& outstanding_guids,
+ std::vector<scoped_refptr<BackgroundFetchRequestInfo>>
+ active_fetch_requests,
const std::string& ui_title);
// Gets the number of bytes downloaded for jobs that are currently running.
uint64_t GetInProgressDownloadedBytes();
- // Updates the UI (currently only job title) that's shown to the user as part
- // of a notification for instance.
- void UpdateUI(const std::string& title);
+ // Updates the UI that's shown to the user as part of a notification for
+ // instance.
+ void UpdateUI(const base::Optional<std::string>& title,
+ const base::Optional<SkBitmap>& icon);
+
+ // Returns a unique_ptr to a BackgroundFetchRegistration object
+ // created with member fields.
+ std::unique_ptr<BackgroundFetchRegistration> NewRegistration(
+ blink::mojom::BackgroundFetchState state) const;
// Returns the options with which this job is fetching data.
const BackgroundFetchOptions& options() const { return options_; }
+ // Returns total downloaded bytes.
+ int downloaded() const { return complete_requests_downloaded_bytes_cache_; }
+
+ // Returns total size of downloads, as indicated by the developer.
+ int download_total() const { return total_downloads_size_; }
+
+ // Returns the number of requests that comprise the whole job.
+ int total_downloads() const { return total_downloads_; }
+
base::WeakPtr<BackgroundFetchJobController> GetWeakPtr() {
return weak_ptr_factory_.GetWeakPtr();
}
@@ -91,10 +108,15 @@ class CONTENT_EXPORT BackgroundFetchJobController final
// BackgroundFetchScheduler::Controller implementation:
bool HasMoreRequests() override;
- void StartRequest(scoped_refptr<BackgroundFetchRequestInfo> request) override;
+ void StartRequest(scoped_refptr<BackgroundFetchRequestInfo> request,
+ RequestFinishedCallback request_finished_callback) override;
void Abort(BackgroundFetchReasonToAbort reason_to_abort) override;
private:
+ // Returns reason_to_abort_ as blink::mojom::BackgroundFetchFailureReason.
+ // TODO(crbug.com/876691): Get rid of BackgroundFetchReasonToAbort and remove
+ // this converter.
+ blink::mojom::BackgroundFetchFailureReason MojoFailureReason() const;
// Options for the represented background fetch registration.
BackgroundFetchOptions options_;
@@ -102,16 +124,18 @@ class CONTENT_EXPORT BackgroundFetchJobController final
// Icon for the represented background fetch registration.
SkBitmap icon_;
- // Map from in-progress |download_guid|s to number of bytes downloaded.
- base::flat_map<std::string, uint64_t> active_request_download_bytes_;
+ // Number of bytes downloaded for the active request.
+ uint64_t active_request_downloaded_bytes_ = 0;
+
+ // Finished callback to invoke when the active request has finished.
+ RequestFinishedCallback active_request_finished_callback_;
// Cache of downloaded byte count stored by the DataManager, to enable
// delivering progress events without having to read from the database.
uint64_t complete_requests_downloaded_bytes_cache_;
- // The RequestManager's lifetime is controlled by the BackgroundFetchContext
- // and will be kept alive until after the JobController is destroyed.
- BackgroundFetchRequestManager* request_manager_;
+ // Total downloads size, as indicated by the developer.
+ int total_downloads_size_ = 0;
// Proxy for interacting with the BackgroundFetchDelegate across thread
// boundaries. It is owned by the BackgroundFetchContext.
@@ -126,6 +150,10 @@ class CONTENT_EXPORT BackgroundFetchJobController final
// Number of the requests that have been completed so far.
int completed_downloads_ = 0;
+ // The reason background fetch was aborted.
+ BackgroundFetchReasonToAbort reason_to_abort_ =
+ BackgroundFetchReasonToAbort::NONE;
+
base::WeakPtrFactory<BackgroundFetchJobController> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(BackgroundFetchJobController);
diff --git a/chromium/content/browser/background_fetch/background_fetch_job_controller_unittest.cc b/chromium/content/browser/background_fetch/background_fetch_job_controller_unittest.cc
index 423fc1eb36d..b231b85f93f 100644
--- a/chromium/content/browser/background_fetch/background_fetch_job_controller_unittest.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_job_controller_unittest.cc
@@ -20,6 +20,7 @@
#include "content/browser/background_fetch/background_fetch_context.h"
#include "content/browser/background_fetch/background_fetch_data_manager.h"
#include "content/browser/background_fetch/background_fetch_registration_id.h"
+#include "content/browser/background_fetch/background_fetch_scheduler.h"
#include "content/browser/background_fetch/background_fetch_test_base.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/storage_partition_impl.h"
@@ -40,63 +41,41 @@ const char kExampleResponseData[] = "My response data";
enum class JobCompletionStatus { kRunning, kCompleted, kAborted };
-class FakeBackgroundFetchRequestManager : public BackgroundFetchRequestManager {
- public:
- void AddDownloadJob(const BackgroundFetchRegistrationId& registration_id,
- const std::set<std::string>& download_guids) {
- DCHECK(!registration_status_map_.count(registration_id.unique_id()));
- registration_status_map_.emplace(registration_id.unique_id(),
- RegistrationState(download_guids));
- }
-
- // BackgroundFetchRequestManager implementation:
- void MarkRequestAsComplete(
- const BackgroundFetchRegistrationId& registration_id,
- scoped_refptr<BackgroundFetchRequestInfo> request) override {
- DCHECK(registration_status_map_.count(registration_id.unique_id()));
- auto& state = registration_status_map_[registration_id.unique_id()];
-
- DCHECK_EQ(state.status, JobCompletionStatus::kRunning);
- DCHECK(state.uncompleted_downloads.count(request->download_guid()));
- state.uncompleted_downloads.erase(request->download_guid());
-
- if (state.uncompleted_downloads.size() == 0) {
- state.status = JobCompletionStatus::kCompleted;
- }
- }
+} // namespace
- void OnJobAborted(const BackgroundFetchRegistrationId& registration_id,
- std::vector<std::string> aborted_guids) override {
- DCHECK(registration_status_map_.count(registration_id.unique_id()));
- auto& state = registration_status_map_[registration_id.unique_id()];
- DCHECK_EQ(state.status, JobCompletionStatus::kRunning);
- state.status = JobCompletionStatus::kAborted;
- }
+class BackgroundFetchJobControllerTest : public BackgroundFetchTestBase {
+ public:
+ BackgroundFetchJobControllerTest() = default;
+ ~BackgroundFetchJobControllerTest() override = default;
+ // Returns the status for the active job for |registration_id|. The
+ // registration should only ever exist in |finished_requests_| in case the
+ // request was aborted, given the absence of a scheduler.
JobCompletionStatus GetCompletionStatus(
const BackgroundFetchRegistrationId& registration_id) {
- DCHECK(registration_status_map_.count(registration_id.unique_id()));
- return registration_status_map_[registration_id.unique_id()].status;
- }
+ if (finished_requests_.count(registration_id)) {
+ DCHECK_NE(finished_requests_[registration_id],
+ BackgroundFetchReasonToAbort::NONE);
- struct RegistrationState {
- RegistrationState() = default;
- explicit RegistrationState(const std::set<std::string>& downloads)
- : uncompleted_downloads(downloads) {}
- JobCompletionStatus status = JobCompletionStatus::kRunning;
- std::set<std::string> uncompleted_downloads;
- };
+ return JobCompletionStatus::kAborted;
+ }
- std::map<std::string, RegistrationState> registration_status_map_;
-};
+ DCHECK(pending_requests_counts_.count(registration_id));
+ if (!pending_requests_counts_[registration_id])
+ return JobCompletionStatus::kCompleted;
-} // namespace
+ return JobCompletionStatus::kRunning;
+ }
-class BackgroundFetchJobControllerTest : public BackgroundFetchTestBase {
- public:
- BackgroundFetchJobControllerTest() = default;
+ // To be called when a request for |registration_id| has finished.
+ void OnRequestFinished(
+ const BackgroundFetchRegistrationId& registration_id,
+ scoped_refptr<content::BackgroundFetchRequestInfo> request_info) {
+ DCHECK(pending_requests_counts_.count(registration_id));
- ~BackgroundFetchJobControllerTest() override = default;
+ EXPECT_GE(pending_requests_counts_[registration_id], 1);
+ pending_requests_counts_[registration_id]--;
+ }
// Creates a new Background Fetch registration, whose id will be stored in the
// |*registration_id|, and registers it with the DataManager for the included
@@ -116,7 +95,6 @@ class BackgroundFetchJobControllerTest : public BackgroundFetchTestBase {
base::GenerateGUID());
std::vector<scoped_refptr<BackgroundFetchRequestInfo>> request_infos;
- std::set<std::string> uncompleted_downloads_guids;
int request_counter = 0;
for (const auto& pair : request_data) {
ServiceWorkerFetchRequest fetch_request(
@@ -126,11 +104,9 @@ class BackgroundFetchJobControllerTest : public BackgroundFetchTestBase {
request_counter++, fetch_request);
request->InitializeDownloadGuid();
request_infos.push_back(request);
- uncompleted_downloads_guids.insert(request->download_guid());
}
- request_manager_.AddDownloadJob(*registration_id,
- uncompleted_downloads_guids);
+ pending_requests_counts_[*registration_id] = request_data.size();
if (auto_complete_requests) {
// Provide fake responses for the given |request_data| pairs.
@@ -155,15 +131,17 @@ class BackgroundFetchJobControllerTest : public BackgroundFetchTestBase {
delegate_proxy_ = std::make_unique<BackgroundFetchDelegateProxy>(delegate_);
auto controller = std::make_unique<BackgroundFetchJobController>(
- delegate_proxy_.get(), registration_id, BackgroundFetchOptions(),
- SkBitmap(), 0 /* bytes_downloaded */, &request_manager_,
+ delegate_proxy_.get(), context_->scheduler_.get(), registration_id,
+ BackgroundFetchOptions(), SkBitmap(), 0 /* bytes_downloaded */,
base::BindRepeating(
&BackgroundFetchJobControllerTest::DidUpdateProgress,
base::Unretained(this)),
- base::BindOnce(&BackgroundFetchJobControllerTest::OnJobFinished));
+ base::BindOnce(&BackgroundFetchJobControllerTest::DidFinishJob,
+ base::Unretained(this)));
controller->InitializeRequestStatus(
0, total_downloads, {} /* outstanding_guids */, "" /* ui_title */);
+
return controller;
}
@@ -180,10 +158,11 @@ class BackgroundFetchJobControllerTest : public BackgroundFetchTestBase {
StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
BrowserContext::GetDefaultStoragePartition(browser_context()));
- context_ = new BackgroundFetchContext(
+ context_ = base::MakeRefCounted<BackgroundFetchContext>(
browser_context(),
base::WrapRefCounted(embedded_worker_test_helper()->context_wrapper()),
- base::WrapRefCounted(partition->GetCacheStorageContext()));
+ base::WrapRefCounted(partition->GetCacheStorageContext()),
+ nullptr /* quota_manager_proxy */);
}
void TearDown() override {
@@ -195,11 +174,14 @@ class BackgroundFetchJobControllerTest : public BackgroundFetchTestBase {
}
protected:
- FakeBackgroundFetchRequestManager request_manager_;
scoped_refptr<BackgroundFetchContext> context_;
uint64_t last_downloaded_ = 0;
+ std::map<BackgroundFetchRegistrationId, int> pending_requests_counts_;
+ std::map<BackgroundFetchRegistrationId, BackgroundFetchReasonToAbort>
+ finished_requests_;
+
// Closure that will be invoked every time the JobController receives a
// progress update from a download.
base::RepeatingClosure job_progress_closure_;
@@ -217,8 +199,14 @@ class BackgroundFetchJobControllerTest : public BackgroundFetchTestBase {
job_progress_closure_.Run();
}
- static void OnJobFinished(const BackgroundFetchRegistrationId&,
- BackgroundFetchReasonToAbort reason_to_abort) {}
+ void DidFinishJob(const BackgroundFetchRegistrationId& registration_id,
+ BackgroundFetchReasonToAbort reason_to_abort) {
+ auto iter = pending_requests_counts_.find(registration_id);
+ DCHECK(iter != pending_requests_counts_.end());
+
+ finished_requests_[registration_id] = reason_to_abort;
+ pending_requests_counts_.erase(iter);
+ }
DISALLOW_COPY_AND_ASSIGN(BackgroundFetchJobControllerTest);
};
@@ -231,17 +219,20 @@ TEST_F(BackgroundFetchJobControllerTest, SingleRequestJob) {
true /* auto_complete_requests */);
EXPECT_EQ(JobCompletionStatus::kRunning,
- request_manager_.GetCompletionStatus(registration_id));
+ GetCompletionStatus(registration_id));
std::unique_ptr<BackgroundFetchJobController> controller =
CreateJobController(registration_id, requests.size());
- controller->StartRequest(requests[0]);
+ controller->StartRequest(
+ requests[0],
+ base::BindOnce(&BackgroundFetchJobControllerTest::OnRequestFinished,
+ base::Unretained(this), registration_id));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(JobCompletionStatus::kCompleted,
- request_manager_.GetCompletionStatus(registration_id));
+ GetCompletionStatus(registration_id));
}
TEST_F(BackgroundFetchJobControllerTest, MultipleRequestJob) {
@@ -255,31 +246,40 @@ TEST_F(BackgroundFetchJobControllerTest, MultipleRequestJob) {
true /* auto_complete_requests */);
EXPECT_EQ(JobCompletionStatus::kRunning,
- request_manager_.GetCompletionStatus(registration_id));
+ GetCompletionStatus(registration_id));
std::unique_ptr<BackgroundFetchJobController> controller =
CreateJobController(registration_id, requests.size());
- controller->StartRequest(requests[0]);
+ controller->StartRequest(
+ requests[0],
+ base::BindOnce(&BackgroundFetchJobControllerTest::OnRequestFinished,
+ base::Unretained(this), registration_id));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(JobCompletionStatus::kRunning,
- request_manager_.GetCompletionStatus(registration_id));
+ GetCompletionStatus(registration_id));
- controller->StartRequest(requests[1]);
+ controller->StartRequest(
+ requests[1],
+ base::BindOnce(&BackgroundFetchJobControllerTest::OnRequestFinished,
+ base::Unretained(this), registration_id));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(JobCompletionStatus::kRunning,
- request_manager_.GetCompletionStatus(registration_id));
+ GetCompletionStatus(registration_id));
- controller->StartRequest(requests[2]);
+ controller->StartRequest(
+ requests[2],
+ base::BindOnce(&BackgroundFetchJobControllerTest::OnRequestFinished,
+ base::Unretained(this), registration_id));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(JobCompletionStatus::kCompleted,
- request_manager_.GetCompletionStatus(registration_id));
+ GetCompletionStatus(registration_id));
}
TEST_F(BackgroundFetchJobControllerTest, Abort) {
@@ -290,18 +290,22 @@ TEST_F(BackgroundFetchJobControllerTest, Abort) {
true /* auto_complete_requests */);
EXPECT_EQ(JobCompletionStatus::kRunning,
- request_manager_.GetCompletionStatus(registration_id));
+ GetCompletionStatus(registration_id));
std::unique_ptr<BackgroundFetchJobController> controller =
CreateJobController(registration_id, requests.size());
- controller->StartRequest(requests[0]);
+ controller->StartRequest(
+ requests[0],
+ base::BindOnce(&BackgroundFetchJobControllerTest::OnRequestFinished,
+ base::Unretained(this), registration_id));
+
controller->Abort(BackgroundFetchReasonToAbort::CANCELLED_FROM_UI);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(JobCompletionStatus::kAborted,
- request_manager_.GetCompletionStatus(registration_id));
+ GetCompletionStatus(registration_id));
}
TEST_F(BackgroundFetchJobControllerTest, Progress) {
@@ -312,12 +316,15 @@ TEST_F(BackgroundFetchJobControllerTest, Progress) {
true /* auto_complete_requests */);
EXPECT_EQ(JobCompletionStatus::kRunning,
- request_manager_.GetCompletionStatus(registration_id));
+ GetCompletionStatus(registration_id));
std::unique_ptr<BackgroundFetchJobController> controller =
CreateJobController(registration_id, requests.size());
- controller->StartRequest(requests[0]);
+ controller->StartRequest(
+ requests[0],
+ base::BindOnce(&BackgroundFetchJobControllerTest::OnRequestFinished,
+ base::Unretained(this), registration_id));
{
base::RunLoop run_loop;
@@ -328,12 +335,12 @@ TEST_F(BackgroundFetchJobControllerTest, Progress) {
EXPECT_GT(last_downloaded_, 0u);
EXPECT_LT(last_downloaded_, strlen(kExampleResponseData));
EXPECT_EQ(JobCompletionStatus::kRunning,
- request_manager_.GetCompletionStatus(registration_id));
+ GetCompletionStatus(registration_id));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(JobCompletionStatus::kCompleted,
- request_manager_.GetCompletionStatus(registration_id));
+ GetCompletionStatus(registration_id));
EXPECT_EQ(last_downloaded_, strlen(kExampleResponseData));
}
@@ -345,7 +352,7 @@ TEST_F(BackgroundFetchJobControllerTest, ServiceWorkerRegistrationDeleted) {
true /* auto_complete_requests */);
EXPECT_EQ(JobCompletionStatus::kRunning,
- request_manager_.GetCompletionStatus(registration_id));
+ GetCompletionStatus(registration_id));
std::unique_ptr<BackgroundFetchJobController> controller =
CreateJobController(registration_id, requests.size());
@@ -357,7 +364,7 @@ TEST_F(BackgroundFetchJobControllerTest, ServiceWorkerRegistrationDeleted) {
base::RunLoop().RunUntilIdle();
EXPECT_EQ(JobCompletionStatus::kAborted,
- request_manager_.GetCompletionStatus(registration_id));
+ GetCompletionStatus(registration_id));
}
TEST_F(BackgroundFetchJobControllerTest, ServiceWorkerDatabaseDeleted) {
@@ -368,7 +375,7 @@ TEST_F(BackgroundFetchJobControllerTest, ServiceWorkerDatabaseDeleted) {
true /* auto_complete_requests */);
EXPECT_EQ(JobCompletionStatus::kRunning,
- request_manager_.GetCompletionStatus(registration_id));
+ GetCompletionStatus(registration_id));
std::unique_ptr<BackgroundFetchJobController> controller =
CreateJobController(registration_id, requests.size());
@@ -380,7 +387,7 @@ TEST_F(BackgroundFetchJobControllerTest, ServiceWorkerDatabaseDeleted) {
base::RunLoop().RunUntilIdle();
EXPECT_EQ(JobCompletionStatus::kAborted,
- request_manager_.GetCompletionStatus(registration_id));
+ GetCompletionStatus(registration_id));
}
} // namespace content
diff --git a/chromium/content/browser/background_fetch/background_fetch_request_manager.h b/chromium/content/browser/background_fetch/background_fetch_request_manager.h
deleted file mode 100644
index 6a264c80ea1..00000000000
--- a/chromium/content/browser/background_fetch/background_fetch_request_manager.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_REQUEST_MANAGER_H_
-#define CONTENT_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_REQUEST_MANAGER_H_
-
-#include <string>
-#include <vector>
-
-#include "base/callback_forward.h"
-#include "base/memory/scoped_refptr.h"
-
-namespace content {
-
-class BackgroundFetchRegistrationId;
-class BackgroundFetchRequestInfo;
-
-// Interface for manager requests that are part of a Background Fetch.
-// Implementations maintain a queue of requests for each given
-// |BackgroundFetchRegistrationId| that may be backed by a database.
-class BackgroundFetchRequestManager {
- public:
- virtual ~BackgroundFetchRequestManager() {}
-
- // Marks that the |request|, part of the Background Fetch identified by
- // |registration_id|, has completed.
- virtual void MarkRequestAsComplete(
- const BackgroundFetchRegistrationId& registration_id,
- scoped_refptr<BackgroundFetchRequestInfo> request) = 0;
-
- // Called when the job identified by |registration_id| has been aborted along
- // with the GUIDs of any associated downloads that were still active.
- virtual void OnJobAborted(
- const BackgroundFetchRegistrationId& registration_id,
- std::vector<std::string> aborted_guids) = 0;
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_REQUEST_MANAGER_H_
diff --git a/chromium/content/browser/background_fetch/background_fetch_request_match_params.cc b/chromium/content/browser/background_fetch/background_fetch_request_match_params.cc
new file mode 100644
index 00000000000..ddea56601a1
--- /dev/null
+++ b/chromium/content/browser/background_fetch/background_fetch_request_match_params.cc
@@ -0,0 +1,22 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/background_fetch/background_fetch_request_match_params.h"
+
+namespace content {
+
+BackgroundFetchRequestMatchParams::BackgroundFetchRequestMatchParams(
+ base::Optional<ServiceWorkerFetchRequest> request_to_match,
+ blink::mojom::QueryParamsPtr cache_query_params,
+ bool match_all)
+ : request_to_match_(std::move(request_to_match)),
+ cache_query_params_(std::move(cache_query_params)),
+ match_all_(match_all) {}
+
+BackgroundFetchRequestMatchParams::BackgroundFetchRequestMatchParams() =
+ default;
+BackgroundFetchRequestMatchParams::~BackgroundFetchRequestMatchParams() =
+ default;
+
+} // namespace content \ No newline at end of file
diff --git a/chromium/content/browser/background_fetch/background_fetch_request_match_params.h b/chromium/content/browser/background_fetch/background_fetch_request_match_params.h
new file mode 100644
index 00000000000..e43148b2a2e
--- /dev/null
+++ b/chromium/content/browser/background_fetch/background_fetch_request_match_params.h
@@ -0,0 +1,58 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_REQUEST_MATCH_PARAMS_H_
+#define CONTENT_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_REQUEST_MATCH_PARAMS_H_
+
+#include "base/optional.h"
+#include "content/common/service_worker/service_worker_types.h"
+#include "third_party/blink/public/platform/modules/cache_storage/cache_storage.mojom.h"
+
+namespace content {
+
+class CONTENT_EXPORT BackgroundFetchRequestMatchParams {
+ public:
+ BackgroundFetchRequestMatchParams();
+ BackgroundFetchRequestMatchParams(
+ base::Optional<ServiceWorkerFetchRequest> request_to_match,
+ blink::mojom::QueryParamsPtr cache_query_params,
+ bool match_all);
+ ~BackgroundFetchRequestMatchParams();
+
+ bool FilterByRequest() const {
+ return request_to_match_.has_value();
+ }
+
+ // Only call this method if a valid request_to_match was previously provided.
+ const ServiceWorkerFetchRequest& request_to_match() const {
+ DCHECK(request_to_match_.has_value());
+ return request_to_match_.value();
+ }
+
+ blink::mojom::QueryParamsPtr cloned_cache_query_params() const {
+ if (!cache_query_params_)
+ return nullptr;
+ return cache_query_params_->Clone();
+ }
+
+ bool match_all() const { return match_all_; }
+
+ private:
+ // If |request_to_match| is present, we get response(s) only for this request.
+ // If not present, response(s) for all requests (contained in the fetch) will
+ // be returned.
+ base::Optional<ServiceWorkerFetchRequest> request_to_match_;
+
+ // When nullptr, this has no effect on the response(s) returned.
+ blink::mojom::QueryParamsPtr cache_query_params_;
+
+ // Whether to return all matching responses from the cache storage.
+ bool match_all_ = false;
+
+ DISALLOW_COPY_AND_ASSIGN(BackgroundFetchRequestMatchParams);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_REQUEST_MATCH_PARAMS_H_
diff --git a/chromium/content/browser/background_fetch/background_fetch_scheduler.cc b/chromium/content/browser/background_fetch/background_fetch_scheduler.cc
index ba39a99d590..4fe7cf3fbaf 100644
--- a/chromium/content/browser/background_fetch/background_fetch_scheduler.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_scheduler.cc
@@ -10,10 +10,13 @@
namespace content {
BackgroundFetchScheduler::Controller::Controller(
+ BackgroundFetchScheduler* scheduler,
const BackgroundFetchRegistrationId& registration_id,
FinishedCallback finished_callback)
- : registration_id_(registration_id),
+ : scheduler_(scheduler),
+ registration_id_(registration_id),
finished_callback_(std::move(finished_callback)) {
+ DCHECK(scheduler_);
DCHECK(finished_callback_);
}
@@ -24,104 +27,121 @@ void BackgroundFetchScheduler::Controller::Finish(
DCHECK(reason_to_abort != BackgroundFetchReasonToAbort::NONE ||
!HasMoreRequests());
+ scheduler_->RemoveJobController(this);
+
+ // Developer-initiated abortions will have already marked the registration for
+ // deletion, so make sure that we don't execute the same code-path twice.
+ if (reason_to_abort == BackgroundFetchReasonToAbort::ABORTED_BY_DEVELOPER)
+ return;
+
+ // Race conditions make it possible for a controller to finish twice. This
+ // should be removed when the scheduler starts owning the controllers.
+ if (!finished_callback_)
+ return;
+
std::move(finished_callback_).Run(registration_id_, reason_to_abort);
}
BackgroundFetchScheduler::BackgroundFetchScheduler(
- BackgroundFetchScheduler::RequestProvider* request_provider)
+ RequestProvider* request_provider)
: request_provider_(request_provider) {}
BackgroundFetchScheduler::~BackgroundFetchScheduler() = default;
-void BackgroundFetchScheduler::RemoveJobController(
- const BackgroundFetchRegistrationId& registration_id) {
- for (auto iter = controller_queue_.begin(); iter != controller_queue_.end();
- /* no increment */) {
- if ((**iter).registration_id() == registration_id)
- iter = controller_queue_.erase(iter);
- else
- iter++;
- }
-}
+void BackgroundFetchScheduler::AddJobController(Controller* controller) {
+ DCHECK(controller);
-void BackgroundFetchScheduler::AddJobController(
- BackgroundFetchScheduler::Controller* controller) {
controller_queue_.push_back(controller);
- if (!controller_queue_.empty() &&
- download_controller_map_.size() < max_concurrent_downloads_) {
+ if (!active_controller_)
ScheduleDownload();
- }
}
-void BackgroundFetchScheduler::ScheduleDownload() {
- DCHECK(download_controller_map_.size() < max_concurrent_downloads_);
+void BackgroundFetchScheduler::RemoveJobController(Controller* controller) {
+ DCHECK(controller);
+
+ base::EraseIf(controller_queue_, [controller](Controller* queued_controller) {
+ return controller == queued_controller;
+ });
+
+ if (active_controller_ != controller)
+ return;
+
+ // TODO(peter): Move cancellation of requests to the scheduler.
+ active_controller_ = nullptr;
- if (lock_scheduler_ || controller_queue_.empty())
+ ScheduleDownload();
+}
+
+void BackgroundFetchScheduler::ScheduleDownload() {
+ DCHECK(!active_controller_);
+ if (controller_queue_.empty())
return;
- auto* controller = controller_queue_.front();
+ active_controller_ = controller_queue_.front();
controller_queue_.pop_front();
- // Making an async call, `ScheduleDownload` shouldn't be called anymore.
- lock_scheduler_ = true;
request_provider_->PopNextRequest(
- controller->registration_id(),
+ active_controller_->registration_id(),
base::BindOnce(&BackgroundFetchScheduler::DidPopNextRequest,
- base::Unretained(this), controller));
+ weak_ptr_factory_.GetWeakPtr()));
}
void BackgroundFetchScheduler::DidPopNextRequest(
- BackgroundFetchScheduler::Controller* controller,
scoped_refptr<BackgroundFetchRequestInfo> request_info) {
- DCHECK(controller);
- lock_scheduler_ = false; // Can schedule downloads again.
-
- // Storage error, fetch might have been aborted.
- if (!request_info) {
+ // It's possible for the |active_controller_| to have been aborted while the
+ // next request was being retrieved. Bail out when that happens.
+ if (!active_controller_) {
ScheduleDownload();
return;
}
- download_controller_map_[request_info->download_guid()] = controller;
- controller->StartRequest(request_info);
+ // There might've been a storage error when |request_info| could not be loaded
+ // from the database. Bail out in this case as well.
+ if (!request_info) {
+ // TODO(peter): Should we abort the |active_controller_| in this case?
+ active_controller_ = nullptr;
- if (download_controller_map_.size() < max_concurrent_downloads_)
ScheduleDownload();
+ return;
+ }
+
+ // Otherwise start the |request_info| through the live Job Controller.
+ active_controller_->StartRequest(
+ std::move(request_info),
+ base::BindOnce(&BackgroundFetchScheduler::MarkRequestAsComplete,
+ weak_ptr_factory_.GetWeakPtr()));
}
void BackgroundFetchScheduler::MarkRequestAsComplete(
- const BackgroundFetchRegistrationId& registration_id,
- scoped_refptr<BackgroundFetchRequestInfo> request) {
- DCHECK(download_controller_map_.count(request->download_guid()));
- auto* controller = download_controller_map_[request->download_guid()];
- download_controller_map_.erase(request->download_guid());
+ scoped_refptr<BackgroundFetchRequestInfo> request_info) {
+ // It's possible for the |active_controller_| to have been aborted while the
+ // request was being started. Bail out in that case.
+ if (!active_controller_)
+ return;
request_provider_->MarkRequestAsComplete(
- controller->registration_id(), request.get(),
+ active_controller_->registration_id(), std::move(request_info),
base::BindOnce(&BackgroundFetchScheduler::DidMarkRequestAsComplete,
- base::Unretained(this), controller));
+ weak_ptr_factory_.GetWeakPtr()));
}
-void BackgroundFetchScheduler::DidMarkRequestAsComplete(
- BackgroundFetchScheduler::Controller* controller) {
- if (controller->HasMoreRequests())
- controller_queue_.push_back(controller);
- else
- controller->Finish(BackgroundFetchReasonToAbort::NONE);
-
- ScheduleDownload();
-}
+void BackgroundFetchScheduler::DidMarkRequestAsComplete() {
+ // It's possible for the |active_controller_| to have been aborted while the
+ // request was being marked as completed. Bail out in that case.
+ if (!active_controller_)
+ return;
-void BackgroundFetchScheduler::OnJobAborted(
- const BackgroundFetchRegistrationId& registration_id,
- std::vector<std::string> aborted_guids) {
- // For every active download that was aborted, remove it and schedule a new
- // download.
- for (const auto& guid : aborted_guids) {
- download_controller_map_.erase(guid);
- ScheduleDownload();
+ // Continue with the |active_controller_| while there are files pending.
+ if (active_controller_->HasMoreRequests()) {
+ request_provider_->PopNextRequest(
+ active_controller_->registration_id(),
+ base::BindOnce(&BackgroundFetchScheduler::DidPopNextRequest,
+ weak_ptr_factory_.GetWeakPtr()));
+ return;
}
+
+ active_controller_->Finish(BackgroundFetchReasonToAbort::NONE);
}
} // namespace content
diff --git a/chromium/content/browser/background_fetch/background_fetch_scheduler.h b/chromium/content/browser/background_fetch/background_fetch_scheduler.h
index 243bb95e705..449ea6699f8 100644
--- a/chromium/content/browser/background_fetch/background_fetch_scheduler.h
+++ b/chromium/content/browser/background_fetch/background_fetch_scheduler.h
@@ -13,8 +13,8 @@
#include "base/callback.h"
#include "base/containers/circular_deque.h"
#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
#include "content/browser/background_fetch/background_fetch_registration_id.h"
-#include "content/browser/background_fetch/background_fetch_request_manager.h"
#include "content/common/content_export.h"
namespace content {
@@ -25,25 +25,26 @@ enum class BackgroundFetchReasonToAbort;
// Maintains a list of Controllers and chooses which ones should launch new
// downloads.
-class CONTENT_EXPORT BackgroundFetchScheduler
- : public BackgroundFetchRequestManager {
+class CONTENT_EXPORT BackgroundFetchScheduler {
public:
using FinishedCallback =
base::OnceCallback<void(const BackgroundFetchRegistrationId&,
BackgroundFetchReasonToAbort)>;
- using MarkedCompleteCallback = base::OnceCallback<void()>;
// Interface for download job controllers.
class CONTENT_EXPORT Controller {
public:
+ using RequestFinishedCallback =
+ base::OnceCallback<void(scoped_refptr<BackgroundFetchRequestInfo>)>;
+
virtual ~Controller();
// Returns whether the Controller has any pending download requests.
virtual bool HasMoreRequests() = 0;
// Requests the download manager to start fetching |request|.
- virtual void StartRequest(
- scoped_refptr<BackgroundFetchRequestInfo> request) = 0;
+ virtual void StartRequest(scoped_refptr<BackgroundFetchRequestInfo> request,
+ RequestFinishedCallback callback) = 0;
void Finish(BackgroundFetchReasonToAbort reason_to_abort);
@@ -52,10 +53,15 @@ class CONTENT_EXPORT BackgroundFetchScheduler
}
protected:
- Controller(const BackgroundFetchRegistrationId& registration_id,
+ Controller(BackgroundFetchScheduler* scheduler,
+ const BackgroundFetchRegistrationId& registration_id,
FinishedCallback finished_callback);
private:
+ // The |scheduler_| is guaranteed to outlive the controllers due to their
+ // declaration order in the BackgroundFetchContext.
+ BackgroundFetchScheduler* scheduler_;
+
BackgroundFetchRegistrationId registration_id_;
FinishedCallback finished_callback_;
};
@@ -73,57 +79,42 @@ class CONTENT_EXPORT BackgroundFetchScheduler
const BackgroundFetchRegistrationId& registration_id,
NextRequestCallback callback) = 0;
- // Marks |request| as complete and calls |callback| when done.
+ // Marks |request_info| as complete and calls |callback| when done.
virtual void MarkRequestAsComplete(
const BackgroundFetchRegistrationId& registration_id,
- BackgroundFetchRequestInfo* request,
- MarkedCompleteCallback callback) = 0;
+ scoped_refptr<BackgroundFetchRequestInfo> request_info,
+ base::OnceClosure closure) = 0;
};
explicit BackgroundFetchScheduler(RequestProvider* request_provider);
-
- ~BackgroundFetchScheduler() override;
+ ~BackgroundFetchScheduler();
// Adds a new job controller to the scheduler. May immediately start to
// schedule jobs for |controller|.
void AddJobController(Controller* controller);
- // Removes a job controller from the scheduler. Abort ongoing fetches on the
- // controller before calling this.
- // TODO(crbug.com/850075): Move management of active fetches to
- // BackgroundFetchScheduler.
- void RemoveJobController(
- const BackgroundFetchRegistrationId& registration_id);
-
- void set_max_concurrent_downloads(size_t new_max) {
- max_concurrent_downloads_ = new_max;
- }
-
- // BackgroundFetchRequestManager implementation:
- void MarkRequestAsComplete(
- const BackgroundFetchRegistrationId& registration_id,
- scoped_refptr<BackgroundFetchRequestInfo> request) override;
- void OnJobAborted(const BackgroundFetchRegistrationId& registration_id,
- std::vector<std::string> aborted_guids) override;
+ // Removes the |controller| from the scheduler. Pending updates will be
+ // ignored and it won't be considered for further requests.
+ void RemoveJobController(Controller* controller);
private:
void ScheduleDownload();
- void DidPopNextRequest(BackgroundFetchScheduler::Controller* controller,
- scoped_refptr<BackgroundFetchRequestInfo>);
+ void DidPopNextRequest(
+ scoped_refptr<BackgroundFetchRequestInfo> request_info);
- void DidMarkRequestAsComplete(
- BackgroundFetchScheduler::Controller* controller);
+ void MarkRequestAsComplete(
+ scoped_refptr<BackgroundFetchRequestInfo> request_info);
+ void DidMarkRequestAsComplete();
RequestProvider* request_provider_;
// The scheduler owns all the job controllers, holding them either in the
// controller queue or the guid to controller map.
base::circular_deque<Controller*> controller_queue_;
- std::map<std::string, Controller*> download_controller_map_;
+ Controller* active_controller_ = nullptr;
- bool lock_scheduler_ = false;
- size_t max_concurrent_downloads_ = 1;
+ base::WeakPtrFactory<BackgroundFetchScheduler> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(BackgroundFetchScheduler);
};
diff --git a/chromium/content/browser/background_fetch/background_fetch_scheduler_unittest.cc b/chromium/content/browser/background_fetch/background_fetch_scheduler_unittest.cc
index fdee316f59d..156d262cdaf 100644
--- a/chromium/content/browser/background_fetch/background_fetch_scheduler_unittest.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_scheduler_unittest.cc
@@ -31,10 +31,9 @@ class FakeController : public BackgroundFetchScheduler::Controller {
const std::string& name,
std::vector<std::string>* controller_sequence_list,
int total_jobs)
- : BackgroundFetchScheduler::Controller(
- registration_id,
- base::BindOnce(&FakeController::OnJobFinished)),
- scheduler_(scheduler),
+ : BackgroundFetchScheduler::Controller(scheduler,
+ registration_id,
+ base::DoNothing()),
controller_sequence_list_(controller_sequence_list),
name_(name),
total_jobs_(total_jobs) {}
@@ -43,28 +42,20 @@ class FakeController : public BackgroundFetchScheduler::Controller {
// BackgroundFetchScheduler::Controller implementation:
bool HasMoreRequests() override { return jobs_started_ < total_jobs_; }
- void StartRequest(
- scoped_refptr<BackgroundFetchRequestInfo> request) override {
+ void StartRequest(scoped_refptr<BackgroundFetchRequestInfo> request,
+ RequestFinishedCallback callback) override {
DCHECK_LT(jobs_started_, total_jobs_);
++jobs_started_;
controller_sequence_list_->push_back(name_ +
base::IntToString(jobs_started_));
+
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::BindOnce(&FakeController::OnDownloadCompleted,
- base::Unretained(this), std::move(request)));
+ base::BindOnce(std::move(callback), std::move(request)));
}
private:
- void OnDownloadCompleted(scoped_refptr<BackgroundFetchRequestInfo> request) {
- scheduler_->MarkRequestAsComplete(registration_id(), std::move(request));
- }
-
- static void OnJobFinished(const BackgroundFetchRegistrationId&,
- BackgroundFetchReasonToAbort reason_to_abort) {}
-
int jobs_started_ = 0;
- BackgroundFetchScheduler* scheduler_;
std::vector<std::string>* controller_sequence_list_;
std::string name_;
int total_jobs_;
@@ -108,9 +99,9 @@ class BackgroundFetchSchedulerTest
void MarkRequestAsComplete(
const BackgroundFetchRegistrationId& registration_id,
- BackgroundFetchRequestInfo* request,
- BackgroundFetchScheduler::MarkedCompleteCallback callback) override {
- std::move(callback).Run();
+ scoped_refptr<BackgroundFetchRequestInfo> request_info,
+ base::OnceClosure closure) override {
+ std::move(closure).Run();
}
protected:
@@ -156,46 +147,13 @@ TEST_F(BackgroundFetchSchedulerTest, TwoControllers) {
// Only one task is run at a time so after 3 barrier iterations, 3 tasks
// should have been have run.
- EXPECT_THAT(controller_sequence_list_, ElementsAre("A1", "B1", "A2"));
- }
-
- base::RunLoop().RunUntilIdle();
-
- EXPECT_THAT(controller_sequence_list_,
- ElementsAre("A1", "B1", "A2", "B2", "A3", "B3", "A4", "B4"));
-}
-
-TEST_F(BackgroundFetchSchedulerTest, TwoControllers_TwoConcurrent) {
- BackgroundFetchRegistrationId registration_id1(
- kExampleServiceWorkerRegistrationId, origin(), kExampleDeveloperId1,
- base::GenerateGUID());
- BackgroundFetchRegistrationId registration_id2(
- kExampleServiceWorkerRegistrationId, origin(), kExampleDeveloperId2,
- base::GenerateGUID());
- FakeController controller1(registration_id1, &scheduler_, "A",
- &controller_sequence_list_, 4);
- FakeController controller2(registration_id2, &scheduler_, "B",
- &controller_sequence_list_, 4);
-
- scheduler_.set_max_concurrent_downloads(2);
- scheduler_.AddJobController(&controller1);
- scheduler_.AddJobController(&controller2);
-
- {
- base::RunLoop run_loop;
- PostQuitAfterRepeatingBarriers(run_loop.QuitClosure(), 3);
- run_loop.Run();
-
- // Two tasks are run at a time so after 3 barrier iterations, 6 tasks should
- // have run.
- EXPECT_THAT(controller_sequence_list_,
- ElementsAre("A1", "B1", "A2", "B2", "A3", "B3"));
+ EXPECT_THAT(controller_sequence_list_, ElementsAre("A1", "A2", "A3"));
}
base::RunLoop().RunUntilIdle();
EXPECT_THAT(controller_sequence_list_,
- ElementsAre("A1", "B1", "A2", "B2", "A3", "B3", "A4", "B4"));
+ ElementsAre("A1", "A2", "A3", "A4", "B1", "B2", "B3", "B4"));
}
} // namespace content
diff --git a/chromium/content/browser/background_fetch/background_fetch_service_impl.cc b/chromium/content/browser/background_fetch/background_fetch_service_impl.cc
index 596cfaa0109..f116ff5aad3 100644
--- a/chromium/content/browser/background_fetch/background_fetch_service_impl.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_service_impl.cc
@@ -7,9 +7,11 @@
#include <memory>
#include "base/guid.h"
+#include "base/optional.h"
#include "content/browser/background_fetch/background_fetch_context.h"
#include "content/browser/background_fetch/background_fetch_metrics.h"
#include "content/browser/background_fetch/background_fetch_registration_id.h"
+#include "content/browser/background_fetch/background_fetch_request_match_params.h"
#include "content/browser/bad_message.h"
#include "content/browser/storage_partition_impl.h"
#include "content/common/service_worker/service_worker_types.h"
@@ -30,11 +32,12 @@ constexpr size_t kMaxTitleLength = 1024 * 1024;
} // namespace
// static
-void BackgroundFetchServiceImpl::Create(
+void BackgroundFetchServiceImpl::CreateForWorker(
blink::mojom::BackgroundFetchServiceRequest request,
RenderProcessHost* render_process_host,
const url::Origin& origin) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(
@@ -42,26 +45,53 @@ void BackgroundFetchServiceImpl::Create(
WrapRefCounted(static_cast<StoragePartitionImpl*>(
render_process_host->GetStoragePartition())
->GetBackgroundFetchContext()),
- origin, std::move(request)));
+ origin, nullptr /* render_frame_host */, std::move(request)));
+}
+
+// static
+void BackgroundFetchServiceImpl::CreateForFrame(
+ RenderProcessHost* render_process_host,
+ int render_frame_id,
+ blink::mojom::BackgroundFetchServiceRequest request) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ DCHECK(render_process_host);
+ auto* render_frame_host =
+ RenderFrameHost::FromID(render_process_host->GetID(), render_frame_id);
+ DCHECK(render_frame_host);
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(
+ BackgroundFetchServiceImpl::CreateOnIoThread,
+ WrapRefCounted(static_cast<StoragePartitionImpl*>(
+ render_process_host->GetStoragePartition())
+ ->GetBackgroundFetchContext()),
+ render_frame_host->GetLastCommittedOrigin(), render_frame_host,
+ std::move(request)));
}
// static
void BackgroundFetchServiceImpl::CreateOnIoThread(
scoped_refptr<BackgroundFetchContext> background_fetch_context,
url::Origin origin,
+ RenderFrameHost* render_frame_host,
blink::mojom::BackgroundFetchServiceRequest request) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- mojo::MakeStrongBinding(
- std::make_unique<BackgroundFetchServiceImpl>(
- std::move(background_fetch_context), std::move(origin)),
- std::move(request));
+
+ mojo::MakeStrongBinding(std::make_unique<BackgroundFetchServiceImpl>(
+ std::move(background_fetch_context),
+ std::move(origin), render_frame_host),
+ std::move(request));
}
BackgroundFetchServiceImpl::BackgroundFetchServiceImpl(
scoped_refptr<BackgroundFetchContext> background_fetch_context,
- url::Origin origin)
+ url::Origin origin,
+ RenderFrameHost* render_frame_host)
: background_fetch_context_(std::move(background_fetch_context)),
- origin_(std::move(origin)) {
+ origin_(std::move(origin)),
+ render_frame_host_(render_frame_host) {
DCHECK(background_fetch_context_);
}
@@ -93,7 +123,8 @@ void BackgroundFetchServiceImpl::Fetch(
base::GenerateGUID());
background_fetch_context_->StartFetch(registration_id, requests, options,
- icon, std::move(callback));
+ icon, render_frame_host_,
+ std::move(callback));
}
void BackgroundFetchServiceImpl::GetIconDisplaySize(
@@ -102,14 +133,37 @@ void BackgroundFetchServiceImpl::GetIconDisplaySize(
background_fetch_context_->GetIconDisplaySize(std::move(callback));
}
+void BackgroundFetchServiceImpl::MatchRequests(
+ int64_t service_worker_registration_id,
+ const std::string& developer_id,
+ const std::string& unique_id,
+ const base::Optional<ServiceWorkerFetchRequest>& request_to_match,
+ blink::mojom::QueryParamsPtr cache_query_params,
+ bool match_all,
+ MatchRequestsCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ BackgroundFetchRegistrationId registration_id(
+ service_worker_registration_id, origin_, developer_id, unique_id);
+
+ // Create BackgroundFetchMatchRequestParams.
+ auto match_params = std::make_unique<BackgroundFetchRequestMatchParams>(
+ request_to_match, std::move(cache_query_params), match_all);
+
+ background_fetch_context_->MatchRequests(
+ registration_id, std::move(match_params), std::move(callback));
+}
+
void BackgroundFetchServiceImpl::UpdateUI(
int64_t service_worker_registration_id,
const std::string& developer_id,
const std::string& unique_id,
- const std::string& title,
+ const base::Optional<std::string>& title,
+ const SkBitmap& icon,
UpdateUICallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (!ValidateUniqueId(unique_id) || !ValidateTitle(title)) {
+
+ if (!ValidateUniqueId(unique_id) || (title && !ValidateTitle(*title))) {
std::move(callback).Run(
blink::mojom::BackgroundFetchError::INVALID_ARGUMENT);
return;
@@ -117,7 +171,12 @@ void BackgroundFetchServiceImpl::UpdateUI(
BackgroundFetchRegistrationId registration_id(
service_worker_registration_id, origin_, developer_id, unique_id);
- background_fetch_context_->UpdateUI(registration_id, title,
+
+ // Wrap the icon in an optional for clarity.
+ auto optional_icon =
+ icon.isNull() ? base::nullopt : base::Optional<SkBitmap>(icon);
+
+ background_fetch_context_->UpdateUI(registration_id, title, optional_icon,
std::move(callback));
}
diff --git a/chromium/content/browser/background_fetch/background_fetch_service_impl.h b/chromium/content/browser/background_fetch/background_fetch_service_impl.h
index c61095e1a3c..5abcc9b3b18 100644
--- a/chromium/content/browser/background_fetch/background_fetch_service_impl.h
+++ b/chromium/content/browser/background_fetch/background_fetch_service_impl.h
@@ -20,6 +20,7 @@
namespace content {
class BackgroundFetchContext;
+class RenderFrameHost;
class RenderProcessHost;
struct BackgroundFetchOptions;
struct ServiceWorkerFetchRequest;
@@ -29,12 +30,19 @@ class CONTENT_EXPORT BackgroundFetchServiceImpl
public:
BackgroundFetchServiceImpl(
scoped_refptr<BackgroundFetchContext> background_fetch_context,
- url::Origin origin);
+ url::Origin origin,
+ RenderFrameHost* render_frame_host);
~BackgroundFetchServiceImpl() override;
- static void Create(blink::mojom::BackgroundFetchServiceRequest request,
- RenderProcessHost* render_process_host,
- const url::Origin& origin);
+ static void CreateForWorker(
+ blink::mojom::BackgroundFetchServiceRequest request,
+ RenderProcessHost* render_process_host,
+ const url::Origin& origin);
+
+ static void CreateForFrame(
+ RenderProcessHost* render_process_host,
+ int render_frame_id,
+ blink::mojom::BackgroundFetchServiceRequest request);
// blink::mojom::BackgroundFetchService implementation.
void Fetch(int64_t service_worker_registration_id,
@@ -44,10 +52,19 @@ class CONTENT_EXPORT BackgroundFetchServiceImpl
const SkBitmap& icon,
FetchCallback callback) override;
void GetIconDisplaySize(GetIconDisplaySizeCallback callback) override;
+ void MatchRequests(
+ int64_t service_worker_registration_id,
+ const std::string& developer_id,
+ const std::string& unique_id,
+ const base::Optional<ServiceWorkerFetchRequest>& request_to_match,
+ blink::mojom::QueryParamsPtr cache_query_params,
+ bool match_all,
+ MatchRequestsCallback callback) override;
void UpdateUI(int64_t service_worker_registration_id,
const std::string& developer_id,
const std::string& unique_id,
- const std::string& title,
+ const base::Optional<std::string>& title,
+ const SkBitmap& icon,
UpdateUICallback callback) override;
void Abort(int64_t service_worker_registration_id,
const std::string& developer_id,
@@ -66,6 +83,7 @@ class CONTENT_EXPORT BackgroundFetchServiceImpl
static void CreateOnIoThread(
scoped_refptr<BackgroundFetchContext> background_fetch_context,
url::Origin origin,
+ RenderFrameHost* render_frame_host,
blink::mojom::BackgroundFetchServiceRequest request);
// Validates and returns whether the |developer_id|, |unique_id|, |requests|
@@ -82,6 +100,8 @@ class CONTENT_EXPORT BackgroundFetchServiceImpl
const url::Origin origin_;
+ RenderFrameHost* render_frame_host_;
+
DISALLOW_COPY_AND_ASSIGN(BackgroundFetchServiceImpl);
};
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 6e2a9c67992..7ae027d417c 100644
--- a/chromium/content/browser/background_fetch/background_fetch_service_unittest.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_service_unittest.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <algorithm>
#include <map>
#include <memory>
#include <utility>
@@ -9,6 +10,7 @@
#include "base/auto_reset.h"
#include "base/macros.h"
#include "base/run_loop.h"
+#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/time/time.h"
@@ -47,6 +49,16 @@ blink::Manifest::ImageResource CreateIcon(const std::string& src,
return icon;
}
+bool ContainsHeader(const base::flat_map<std::string, std::string>& headers,
+ const std::string& target) {
+ return headers.cend() !=
+ std::find_if(headers.cbegin(), headers.cend(),
+ [target](const auto& pair) -> bool {
+ return base::EqualsCaseInsensitiveASCII(pair.first,
+ target);
+ });
+}
+
class BadMessageObserver {
public:
BadMessageObserver()
@@ -83,10 +95,11 @@ class BackgroundFetchServiceTest : public BackgroundFetchTestBase {
public:
ScopedCustomBackgroundFetchService(BackgroundFetchServiceTest* test,
const url::Origin& origin)
- : scoped_service_(
- &test->service_,
- std::make_unique<BackgroundFetchServiceImpl>(test->context_,
- origin)) {}
+ : scoped_service_(&test->service_,
+ std::make_unique<BackgroundFetchServiceImpl>(
+ test->context_,
+ origin,
+ nullptr /* render_frame_host */)) {}
private:
base::AutoReset<std::unique_ptr<BackgroundFetchServiceImpl>>
@@ -173,6 +186,24 @@ class BackgroundFetchServiceTest : public BackgroundFetchTestBase {
run_loop.Run();
}
+ // Calls BackgroundFetchServiceImpl::MatchRequests() to retrieve all settled
+ // fetches.
+ void MatchAllRequests(int64_t service_worker_registration_id,
+ const std::string& developer_id,
+ const std::string& unique_id,
+ std::vector<BackgroundFetchSettledFetch>* out_fetches) {
+ DCHECK(out_fetches);
+ base::RunLoop run_loop;
+ service_->MatchRequests(
+ service_worker_registration_id, developer_id, unique_id,
+ base::nullopt /* request_to_match*/, nullptr /* cache_query_params*/,
+ true /* match_all */,
+ base::BindOnce(&BackgroundFetchServiceTest::DidMatchAllRequests,
+ base::Unretained(this), run_loop.QuitClosure(),
+ out_fetches));
+ run_loop.Run();
+ }
+
// Synchronous wrapper for BackgroundFetchServiceImpl::UpdateUI().
void UpdateUI(int64_t service_worker_registration_id,
const std::string& developer_id,
@@ -183,7 +214,7 @@ class BackgroundFetchServiceTest : public BackgroundFetchTestBase {
base::RunLoop run_loop;
service_->UpdateUI(service_worker_registration_id, unique_id, developer_id,
- title,
+ title, SkBitmap(),
base::BindOnce(&BackgroundFetchServiceTest::DidGetError,
base::Unretained(this),
run_loop.QuitClosure(), out_error));
@@ -266,17 +297,18 @@ class BackgroundFetchServiceTest : public BackgroundFetchTestBase {
void SetUp() override {
BackgroundFetchTestBase::SetUp();
- context_ = new BackgroundFetchContext(
+ context_ = base::MakeRefCounted<BackgroundFetchContext>(
browser_context(),
base::WrapRefCounted(embedded_worker_test_helper()->context_wrapper()),
- nullptr /* cache_storage_context */);
+ nullptr /* cache_storage_context */, nullptr /* quota_manager_proxy */);
context_->SetDataManagerForTesting(
std::make_unique<BackgroundFetchTestDataManager>(
browser_context(), storage_partition(),
embedded_worker_test_helper()->context_wrapper()));
context_->InitializeOnIOThread();
- service_ = std::make_unique<BackgroundFetchServiceImpl>(context_, origin());
+ service_ = std::make_unique<BackgroundFetchServiceImpl>(
+ context_, origin(), nullptr /* render_frame_host */);
}
void TearDown() override {
@@ -290,9 +322,12 @@ class BackgroundFetchServiceTest : public BackgroundFetchTestBase {
base::RunLoop().RunUntilIdle();
}
+ protected:
+ scoped_refptr<BackgroundFetchContext> context_;
+
private:
void DidGetRegistration(
- base::Closure quit_closure,
+ base::OnceClosure quit_closure,
blink::mojom::BackgroundFetchError* out_error,
BackgroundFetchRegistration* out_registration,
blink::mojom::BackgroundFetchError error,
@@ -305,15 +340,14 @@ class BackgroundFetchServiceTest : public BackgroundFetchTestBase {
std::move(quit_closure).Run();
}
- void DidStartFetch(
- base::Closure quit_closure,
- blink::mojom::BackgroundFetchError error,
- std::unique_ptr<BackgroundFetchRegistration> registration) {
+ void DidStartFetch(base::OnceClosure quit_closure,
+ blink::mojom::BackgroundFetchError error,
+ const BackgroundFetchRegistration& registration) {
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
std::move(quit_closure).Run();
}
- void DidGetError(base::Closure quit_closure,
+ void DidGetError(base::OnceClosure quit_closure,
blink::mojom::BackgroundFetchError* out_error,
blink::mojom::BackgroundFetchError error) {
*out_error = error;
@@ -321,7 +355,7 @@ class BackgroundFetchServiceTest : public BackgroundFetchTestBase {
std::move(quit_closure).Run();
}
- void DidGetDeveloperIds(base::Closure quit_closure,
+ void DidGetDeveloperIds(base::OnceClosure quit_closure,
blink::mojom::BackgroundFetchError* out_error,
std::vector<std::string>* out_developer_ids,
blink::mojom::BackgroundFetchError error,
@@ -332,7 +366,14 @@ class BackgroundFetchServiceTest : public BackgroundFetchTestBase {
std::move(quit_closure).Run();
}
- scoped_refptr<BackgroundFetchContext> context_;
+ void DidMatchAllRequests(
+ base::OnceClosure quit_closure,
+ std::vector<BackgroundFetchSettledFetch>* out_fetches,
+ const std::vector<BackgroundFetchSettledFetch>& fetches) {
+ *out_fetches = fetches;
+ std::move(quit_closure).Run();
+ }
+
std::unique_ptr<BackgroundFetchServiceImpl> service_;
DISALLOW_COPY_AND_ASSIGN(BackgroundFetchServiceTest);
@@ -455,7 +496,8 @@ TEST_F(BackgroundFetchServiceTest, FetchDuplicatedRegistrationFailure) {
TEST_F(BackgroundFetchServiceTest, FetchSuccessEventDispatch) {
// This test starts a new Background Fetch, completes the registration, then
// fetches all files to complete the job, and then verifies that the
- // `backgroundfetched` event will be dispatched with the expected contents.
+ // `backgroundfetchsuccess` event will be dispatched with the expected
+ // contents.
int64_t service_worker_registration_id = RegisterServiceWorker();
ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId,
@@ -499,11 +541,10 @@ TEST_F(BackgroundFetchServiceTest, FetchSuccessEventDispatch) {
.Build()));
// Create the registration with the given |requests|.
+ BackgroundFetchRegistration registration;
{
BackgroundFetchOptions options;
-
blink::mojom::BackgroundFetchError error;
- BackgroundFetchRegistration registration;
// Create the first registration. This must succeed.
Fetch(service_worker_registration_id, kExampleDeveloperId, requests,
@@ -514,55 +555,58 @@ TEST_F(BackgroundFetchServiceTest, FetchSuccessEventDispatch) {
// Spin the |event_dispatched_loop| to wait for the dispatched event.
event_dispatched_loop.Run();
- ASSERT_TRUE(embedded_worker_test_helper()->last_developer_id().has_value());
- EXPECT_EQ(kExampleDeveloperId,
- embedded_worker_test_helper()->last_developer_id().value());
-
- ASSERT_TRUE(embedded_worker_test_helper()->last_fetches().has_value());
+ ASSERT_TRUE(embedded_worker_test_helper()->last_registration().has_value());
+ EXPECT_EQ(kExampleDeveloperId, registration.developer_id);
- std::vector<BackgroundFetchSettledFetch> fetches =
- embedded_worker_test_helper()->last_fetches().value();
+ // Get all the settled fetches and test properties.
+ std::vector<BackgroundFetchSettledFetch> fetches;
+ MatchAllRequests(service_worker_registration_id, registration.developer_id,
+ registration.unique_id, &fetches);
ASSERT_EQ(fetches.size(), requests.size());
for (size_t i = 0; i < fetches.size(); ++i) {
ASSERT_EQ(fetches[i].request.url, requests[i].url);
EXPECT_EQ(fetches[i].request.method, requests[i].method);
- EXPECT_EQ(fetches[i].response.url_list[0], fetches[i].request.url);
- EXPECT_EQ(fetches[i].response.response_type,
+ EXPECT_EQ(fetches[i].response->url_list[0], fetches[i].request.url);
+ EXPECT_EQ(fetches[i].response->response_type,
network::mojom::FetchResponseType::kDefault);
switch (i) {
case 0:
- EXPECT_EQ(fetches[i].response.status_code, kFirstResponseCode);
- EXPECT_EQ(fetches[i].response.headers.count("Content-Type"), 1u);
- EXPECT_EQ(fetches[i].response.headers.count("X-Cat"), 1u);
+ EXPECT_EQ(fetches[i].response->status_code, kFirstResponseCode);
+ EXPECT_TRUE(
+ ContainsHeader(fetches[i].response->headers, "Content-Type"));
+ EXPECT_TRUE(ContainsHeader(fetches[i].response->headers, "X-Cat"));
break;
case 1:
- EXPECT_EQ(fetches[i].response.status_code, kSecondResponseCode);
- EXPECT_EQ(fetches[i].response.headers.count("Content-Type"), 1u);
- EXPECT_EQ(fetches[i].response.headers.count("X-Cat"), 0u);
+ EXPECT_EQ(fetches[i].response->status_code, kSecondResponseCode);
+ EXPECT_TRUE(
+ ContainsHeader(fetches[i].response->headers, "Content-Type"));
+ EXPECT_FALSE(ContainsHeader(fetches[i].response->headers, "X-Cat"));
break;
case 2:
- EXPECT_EQ(fetches[i].response.status_code, kThirdResponseCode);
- EXPECT_EQ(fetches[i].response.headers.count("Content-Type"), 1u);
- EXPECT_EQ(fetches[i].response.headers.count("X-Cat"), 0u);
+ EXPECT_EQ(fetches[i].response->status_code, kThirdResponseCode);
+ EXPECT_TRUE(
+ ContainsHeader(fetches[i].response->headers, "Content-Type"));
+ EXPECT_FALSE(ContainsHeader(fetches[i].response->headers, "X-Cat"));
break;
default:
NOTREACHED();
}
// TODO(peter): change-detector tests for unsupported properties.
- EXPECT_EQ(fetches[i].response.error,
+ EXPECT_EQ(fetches[i].response->error,
blink::mojom::ServiceWorkerResponseError::kUnknown);
// Verify that all properties have a sensible value.
- EXPECT_FALSE(fetches[i].response.response_time.is_null());
+ EXPECT_FALSE(fetches[i].response->response_time.is_null());
// Verify that the response blobs have been populated. We cannot consume
// their data here since the handles have already been released.
- ASSERT_FALSE(fetches[i].response.blob_uuid.empty());
- ASSERT_GT(fetches[i].response.blob_size, 0u);
+ ASSERT_TRUE(fetches[i].response->blob);
+ ASSERT_FALSE(fetches[i].response->blob->uuid.empty());
+ ASSERT_GT(fetches[i].response->blob->size, 0u);
}
}
@@ -598,11 +642,12 @@ TEST_F(BackgroundFetchServiceTest, FetchFailEventDispatch) {
.Build()));
// Create the registration with the given |requests|.
+ BackgroundFetchRegistration registration;
+
{
BackgroundFetchOptions options;
blink::mojom::BackgroundFetchError error;
- BackgroundFetchRegistration registration;
// Create the first registration. This must succeed.
Fetch(service_worker_registration_id, kExampleDeveloperId, requests,
@@ -613,44 +658,42 @@ TEST_F(BackgroundFetchServiceTest, FetchFailEventDispatch) {
// Spin the |event_dispatched_loop| to wait for the dispatched event.
event_dispatched_loop.Run();
- ASSERT_TRUE(embedded_worker_test_helper()->last_developer_id().has_value());
- EXPECT_EQ(kExampleDeveloperId,
- embedded_worker_test_helper()->last_developer_id().value());
-
- ASSERT_TRUE(embedded_worker_test_helper()->last_fetches().has_value());
+ ASSERT_TRUE(embedded_worker_test_helper()->last_registration().has_value());
+ EXPECT_EQ(kExampleDeveloperId, registration.developer_id);
- std::vector<BackgroundFetchSettledFetch> fetches =
- embedded_worker_test_helper()->last_fetches().value();
+ // Get all the settled fetches and test properties.
+ std::vector<BackgroundFetchSettledFetch> fetches;
+ MatchAllRequests(service_worker_registration_id, registration.developer_id,
+ registration.unique_id, &fetches);
ASSERT_EQ(fetches.size(), requests.size());
for (size_t i = 0; i < fetches.size(); ++i) {
ASSERT_EQ(fetches[i].request.url, requests[i].url);
EXPECT_EQ(fetches[i].request.method, requests[i].method);
- EXPECT_EQ(fetches[i].response.url_list[0], fetches[i].request.url);
- EXPECT_EQ(fetches[i].response.response_type,
+ EXPECT_EQ(fetches[i].response->url_list[0], fetches[i].request.url);
+ EXPECT_EQ(fetches[i].response->response_type,
network::mojom::FetchResponseType::kDefault);
switch (i) {
case 0:
- EXPECT_EQ(fetches[i].response.status_code, 404);
+ EXPECT_EQ(fetches[i].response->status_code, 404);
break;
case 1:
- EXPECT_EQ(fetches[i].response.status_code, 0);
+ EXPECT_EQ(fetches[i].response->status_code, 0);
break;
default:
NOTREACHED();
}
- EXPECT_TRUE(fetches[i].response.headers.empty());
- EXPECT_TRUE(fetches[i].response.blob_uuid.empty());
- EXPECT_EQ(fetches[i].response.blob_size, 0u);
- EXPECT_FALSE(fetches[i].response.response_time.is_null());
+ EXPECT_TRUE(fetches[i].response->headers.empty());
+ EXPECT_FALSE(fetches[i].response->blob);
+ EXPECT_FALSE(fetches[i].response->response_time.is_null());
// TODO(peter): change-detector tests for unsupported properties.
- EXPECT_EQ(fetches[i].response.error,
+ EXPECT_EQ(fetches[i].response->error,
blink::mojom::ServiceWorkerResponseError::kUnknown);
- EXPECT_TRUE(fetches[i].response.cors_exposed_header_names.empty());
+ EXPECT_TRUE(fetches[i].response->cors_exposed_header_names.empty());
}
}
@@ -823,9 +866,9 @@ TEST_F(BackgroundFetchServiceTest, AbortEventDispatch) {
event_dispatched_loop.Run();
- ASSERT_TRUE(embedded_worker_test_helper()->last_developer_id().has_value());
+ ASSERT_TRUE(embedded_worker_test_helper()->last_registration().has_value());
EXPECT_EQ(kExampleDeveloperId,
- embedded_worker_test_helper()->last_developer_id().value());
+ embedded_worker_test_helper()->last_registration()->developer_id);
}
TEST_F(BackgroundFetchServiceTest, UniqueId) {
@@ -893,7 +936,7 @@ TEST_F(BackgroundFetchServiceTest, UniqueId) {
// Calling UpdateUI for the aborted registration should fail (unlike, say,
// calling UpdateUI before resolving the waitUntil promise of a
- // backgroundfetched or backgroundfetchfail event, both of which should
+ // backgroundfetchsuccess or backgroundfetchfail event, both of which should
// work even though that registration is no longer active).
UpdateUI(aborted_registration_id.service_worker_registration_id(),
aborted_registration_id.unique_id(),
@@ -1095,9 +1138,15 @@ TEST_F(BackgroundFetchServiceTest, JobsInitializedOnBrowserRestart) {
.Build()));
BackgroundFetchOptions options;
- // Only register the Fetch.
- StartFetch(service_worker_registration_id, kExampleDeveloperId, requests,
- options, SkBitmap());
+ // Only register the Fetch. In order to appropriately simulate a browser
+ // restart, we do not want the fetch to start yet.
+ {
+ base::AutoReset<bool> hang_registration_creation_for_testing(
+ &context_->hang_registration_creation_for_testing_, true);
+
+ StartFetch(service_worker_registration_id, kExampleDeveloperId, requests,
+ options, SkBitmap());
+ }
// Simulate browser restart by re-creating |context_| and |service_|.
SetUp();
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 fc5366e5abd..ef6f354e99c 100644
--- a/chromium/content/browser/background_fetch/background_fetch_test_base.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_test_base.cc
@@ -163,4 +163,16 @@ BackgroundFetchTestBase::CreateRequestWithProvidedResponse(
Referrer(), false /* is_reload */);
}
+std::unique_ptr<BackgroundFetchRegistration>
+BackgroundFetchTestBase::CreateBackgroundFetchRegistration(
+ const std::string& developer_id,
+ const std::string& unique_id,
+ blink::mojom::BackgroundFetchState state,
+ blink::mojom::BackgroundFetchFailureReason failure_reason) {
+ auto registration = std::make_unique<BackgroundFetchRegistration>(
+ developer_id, unique_id, 0 /* upload_total */, 0 /* uploaded */,
+ 0 /* download_total */, 0 /* downloaded */, state, failure_reason);
+ return registration;
+}
+
} // namespace content
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 a2bcc7365bd..9bb6f0b09c9 100644
--- a/chromium/content/browser/background_fetch/background_fetch_test_base.h
+++ b/chromium/content/browser/background_fetch/background_fetch_test_base.h
@@ -56,6 +56,14 @@ class BackgroundFetchTestBase : public ::testing::Test {
const GURL& url,
std::unique_ptr<TestResponse> response);
+ // Creates a BackgroundFetchRegistration object.
+ std::unique_ptr<BackgroundFetchRegistration>
+ CreateBackgroundFetchRegistration(
+ const std::string& developer_id,
+ const std::string& unique_id,
+ blink::mojom::BackgroundFetchState state,
+ blink::mojom::BackgroundFetchFailureReason failure_reason);
+
// Returns the embedded worker test helper instance, which can be used to
// influence the behavior of the Service Worker events.
BackgroundFetchEmbeddedWorkerTestHelper* embedded_worker_test_helper() {
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 b081be6b97c..2f4ebbb5bdf 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
@@ -29,6 +29,15 @@ class MockBGFQuotaManagerProxy : public MockQuotaManagerProxy {
delete client; // Directly delete, to avoid memory leak.
}
+ void GetUsageAndQuota(base::SequencedTaskRunner* original_task_runner,
+ const url::Origin& origin,
+ blink::mojom::StorageType type,
+ UsageAndQuotaCallback callback) override {
+ DCHECK(original_task_runner);
+ std::move(callback).Run(blink::mojom::QuotaStatusCode::kOk, 0 /* usage */,
+ kBackgroundFetchMaxQuotaBytes);
+ }
+
protected:
~MockBGFQuotaManagerProxy() override = default;
};
@@ -42,7 +51,8 @@ BackgroundFetchTestDataManager::BackgroundFetchTestDataManager(
bool mock_fill_response)
: BackgroundFetchDataManager(browser_context,
service_worker_context,
- nullptr /* cache_storage_context */),
+ nullptr /* cache_storage_context */,
+ nullptr /* quota_manager_proxy */),
browser_context_(browser_context),
storage_partition_(storage_partition),
mock_fill_response_(mock_fill_response) {}
@@ -57,13 +67,13 @@ void BackgroundFetchTestDataManager::InitializeOnIOThread() {
storage_partition_->GetPath().empty(), storage_partition_->GetPath(),
base::ThreadTaskRunnerHandle::Get().get(),
base::MakeRefCounted<MockSpecialStoragePolicy>());
- mock_quota_manager_->SetQuota(GURL("https://example.com/"),
- StorageType::kTemporary, 1024 * 1024 * 100);
+
+ quota_manager_proxy_ =
+ base::MakeRefCounted<MockBGFQuotaManagerProxy>(mock_quota_manager_.get());
cache_manager_ = CacheStorageManager::Create(
storage_partition_->GetPath(), base::ThreadTaskRunnerHandle::Get(),
- base::MakeRefCounted<MockBGFQuotaManagerProxy>(
- mock_quota_manager_.get()));
+ quota_manager_proxy_);
DCHECK(cache_manager_);
cache_manager_->SetBlobParametersForCache(
diff --git a/chromium/content/browser/background_fetch/background_fetch_test_data_manager.h b/chromium/content/browser/background_fetch/background_fetch_test_data_manager.h
index 9596d3f84d8..8cb5228b294 100644
--- a/chromium/content/browser/background_fetch/background_fetch_test_data_manager.h
+++ b/chromium/content/browser/background_fetch/background_fetch_test_data_manager.h
@@ -20,6 +20,9 @@ class MockQuotaManager;
class ServiceWorkerContextWrapper;
class StoragePartition;
+// Arbitrary quota that is large enough for test purposes.
+constexpr int64_t kBackgroundFetchMaxQuotaBytes = 42424242;
+
// Test DataManager that sets up a CacheStorageManager suited for test
// environments. Tests can also optionally override FillServiceWorkerResponse by
// setting |mock_fill_response| to true.
diff --git a/chromium/content/browser/background_fetch/mock_background_fetch_delegate.cc b/chromium/content/browser/background_fetch/mock_background_fetch_delegate.cc
index 72a098529cc..3655aae7eb8 100644
--- a/chromium/content/browser/background_fetch/mock_background_fetch_delegate.cc
+++ b/chromium/content/browser/background_fetch/mock_background_fetch_delegate.cc
@@ -6,6 +6,7 @@
#include <vector>
#include "base/files/file_util.h"
+#include "base/threading/sequenced_task_runner_handle.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/background_fetch/mock_background_fetch_delegate.h"
#include "content/public/browser/background_fetch_description.h"
@@ -56,6 +57,15 @@ MockBackgroundFetchDelegate::MockBackgroundFetchDelegate() {}
MockBackgroundFetchDelegate::~MockBackgroundFetchDelegate() {}
+void MockBackgroundFetchDelegate::GetPermissionForOrigin(
+ const url::Origin& origin,
+ const ResourceRequestInfo::WebContentsGetter& wc_getter,
+ GetPermissionForOriginCallback callback) {
+ base::SequencedTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(std::move(callback), true /* has_permission */));
+}
+
void MockBackgroundFetchDelegate::GetIconDisplaySize(
GetIconDisplaySizeCallback callback) {}
@@ -149,8 +159,10 @@ void MockBackgroundFetchDelegate::Abort(const std::string& job_unique_id) {
aborted_jobs_.insert(job_unique_id);
}
-void MockBackgroundFetchDelegate::UpdateUI(const std::string& job_unique_id,
- const std::string& title) {}
+void MockBackgroundFetchDelegate::UpdateUI(
+ const std::string& job_unique_id,
+ const base::Optional<std::string>& title,
+ const base::Optional<SkBitmap>& icon) {}
void MockBackgroundFetchDelegate::RegisterResponse(
const GURL& url,
diff --git a/chromium/content/browser/background_fetch/mock_background_fetch_delegate.h b/chromium/content/browser/background_fetch/mock_background_fetch_delegate.h
index 587f07116a5..fc64babe3cb 100644
--- a/chromium/content/browser/background_fetch/mock_background_fetch_delegate.h
+++ b/chromium/content/browser/background_fetch/mock_background_fetch_delegate.h
@@ -12,7 +12,9 @@
#include <vector>
#include "base/files/scoped_temp_dir.h"
+#include "base/optional.h"
#include "content/public/browser/background_fetch_delegate.h"
+#include "third_party/skia/include/core/SkBitmap.h"
#include "url/gurl.h"
namespace net {
@@ -63,6 +65,10 @@ class MockBackgroundFetchDelegate : public BackgroundFetchDelegate {
~MockBackgroundFetchDelegate() override;
// BackgroundFetchDelegate implementation:
+ void GetPermissionForOrigin(
+ const url::Origin& origin,
+ const ResourceRequestInfo::WebContentsGetter& wc_getter,
+ GetPermissionForOriginCallback callback) override;
void GetIconDisplaySize(
BackgroundFetchDelegate::GetIconDisplaySizeCallback callback) override;
void CreateDownloadJob(
@@ -75,7 +81,8 @@ class MockBackgroundFetchDelegate : public BackgroundFetchDelegate {
const net::HttpRequestHeaders& headers) override;
void Abort(const std::string& job_unique_id) override;
void UpdateUI(const std::string& job_unique_id,
- const std::string& title) override;
+ const base::Optional<std::string>& title,
+ const base::Optional<SkBitmap>& icon) override;
void RegisterResponse(const GURL& url,
std::unique_ptr<TestResponse> response);
diff --git a/chromium/content/browser/background_fetch/storage/README.md b/chromium/content/browser/background_fetch/storage/README.md
index a21b6bc1a03..ccaaa2e1a4e 100644
--- a/chromium/content/browser/background_fetch/storage/README.md
+++ b/chromium/content/browser/background_fetch/storage/README.md
@@ -26,8 +26,8 @@ value: "<serialized content::proto::BackgroundFetchMetadata>"
```
```
-key: "bgfetch_title_<unique_id>"
-value: "<ui_title>"
+key: "bgfetch_ui_options_<unique_id>"
+value: "<serialized content::proto::BackgroundFetchUIOptions>"
```
```
diff --git a/chromium/content/browser/background_fetch/storage/cleanup_task.cc b/chromium/content/browser/background_fetch/storage/cleanup_task.cc
index 8940c09d09d..96ac829f8ae 100644
--- a/chromium/content/browser/background_fetch/storage/cleanup_task.cc
+++ b/chromium/content/browser/background_fetch/storage/cleanup_task.cc
@@ -57,7 +57,8 @@ void CleanupTask::DidGetActiveUniqueIds(
case DatabaseStatus::kNotFound:
break;
case DatabaseStatus::kFailed:
- FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
+ SetStorageErrorAndFinish(
+ BackgroundFetchStorageError::kServiceWorkerStorageError);
return;
}
@@ -93,9 +94,14 @@ void CleanupTask::DidGetActiveUniqueIds(
}
void CleanupTask::FinishWithError(blink::mojom::BackgroundFetchError error) {
+ ReportStorageError();
Finished(); // Destroys |this|.
}
+std::string CleanupTask::HistogramName() const {
+ return "CleanupTask";
+}
+
} // namespace background_fetch
} // namespace content
diff --git a/chromium/content/browser/background_fetch/storage/cleanup_task.h b/chromium/content/browser/background_fetch/storage/cleanup_task.h
index e116f789a39..4bbfbe5ce35 100644
--- a/chromium/content/browser/background_fetch/storage/cleanup_task.h
+++ b/chromium/content/browser/background_fetch/storage/cleanup_task.h
@@ -38,6 +38,8 @@ class CleanupTask : public background_fetch::DatabaseTask {
void FinishWithError(blink::mojom::BackgroundFetchError error) override;
+ std::string HistogramName() const override;
+
base::WeakPtrFactory<CleanupTask> weak_factory_; // Keep as last.
DISALLOW_COPY_AND_ASSIGN(CleanupTask);
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 07fdeb13d8a..17665e2b145 100644
--- a/chromium/content/browser/background_fetch/storage/create_metadata_task.cc
+++ b/chromium/content/browser/background_fetch/storage/create_metadata_task.cc
@@ -6,37 +6,19 @@
#include <utility>
-#include "base/sequenced_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/task_scheduler/post_task.h"
-#include "base/task_scheduler/task_traits.h"
+#include "content/browser/background_fetch/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/background_fetch/storage/image_helpers.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
-#include "ui/gfx/image/image.h"
namespace content {
namespace background_fetch {
-namespace {
-
-std::string ConvertAndSerializeIcon(const SkBitmap& icon) {
- // Serialize the icon and copy the bytes over.
- std::string serialized_icon;
- auto icon_bytes = gfx::Image::CreateFrom1xBitmap(icon).As1xPNGBytes();
- serialized_icon.assign(icon_bytes->front_as<char>(),
- icon_bytes->front_as<char>() + icon_bytes->size());
- return serialized_icon;
-}
-
-} // namespace
-
-// The max icon resolution, this is used as a threshold to decide
-// whether the icon should be persisted.
-constexpr int kMaxIconResolution = 256 * 256;
-
CreateMetadataTask::CreateMetadataTask(
DatabaseTaskHost* host,
const BackgroundFetchRegistrationId& registration_id,
@@ -55,6 +37,25 @@ CreateMetadataTask::CreateMetadataTask(
CreateMetadataTask::~CreateMetadataTask() = default;
void CreateMetadataTask::Start() {
+ // Check if there is enough quota to download the data first.
+ if (options_.download_total > 0) {
+ IsQuotaAvailable(registration_id_.origin(), options_.download_total,
+ base::BindOnce(&CreateMetadataTask::DidGetIsQuotaAvailable,
+ weak_factory_.GetWeakPtr()));
+ } else {
+ // Proceed with the fetch.
+ GetRegistrationUniqueId();
+ }
+}
+
+void CreateMetadataTask::DidGetIsQuotaAvailable(bool is_available) {
+ if (!is_available)
+ FinishWithError(blink::mojom::BackgroundFetchError::QUOTA_EXCEEDED);
+ else
+ GetRegistrationUniqueId();
+}
+
+void CreateMetadataTask::GetRegistrationUniqueId() {
service_worker_context()->GetRegistrationUserData(
registration_id_.service_worker_registration_id(),
{ActiveRegistrationUniqueIdKey(registration_id_.developer_id())},
@@ -66,8 +67,7 @@ void CreateMetadataTask::DidGetUniqueId(const std::vector<std::string>& data,
blink::ServiceWorkerStatusCode status) {
switch (ToDatabaseStatus(status)) {
case DatabaseStatus::kNotFound:
- InitializeMetadataProto();
- return;
+ break;
case DatabaseStatus::kOk:
// Can't create a registration since there is already an active
// registration with the same |developer_id|. It must be deactivated
@@ -76,9 +76,21 @@ void CreateMetadataTask::DidGetUniqueId(const std::vector<std::string>& data,
blink::mojom::BackgroundFetchError::DUPLICATED_DEVELOPER_ID);
return;
case DatabaseStatus::kFailed:
- FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
+ SetStorageErrorAndFinish(
+ BackgroundFetchStorageError::kServiceWorkerStorageError);
return;
}
+
+ InitializeMetadataProto();
+
+ if (ShouldPersistIcon(icon_)) {
+ // Serialize the icon, then store all the metadata.
+ SerializeIcon(icon_, base::BindOnce(&CreateMetadataTask::DidSerializeIcon,
+ weak_factory_.GetWeakPtr()));
+ } else {
+ // Directly store the metadata.
+ StoreMetadata();
+ }
}
void CreateMetadataTask::InitializeMetadataProto() {
@@ -89,6 +101,10 @@ void CreateMetadataTask::InitializeMetadataProto() {
registration_proto->set_unique_id(registration_id_.unique_id());
registration_proto->set_developer_id(registration_id_.developer_id());
registration_proto->set_download_total(options_.download_total);
+ registration_proto->set_state(
+ proto::BackgroundFetchRegistration_BackgroundFetchState_PENDING);
+ registration_proto->set_failure_reason(
+ proto::BackgroundFetchRegistration_BackgroundFetchFailureReason_NONE);
// Set Options fields.
auto* options_proto = metadata_proto_->mutable_options();
@@ -126,40 +142,39 @@ void CreateMetadataTask::InitializeMetadataProto() {
metadata_proto_->set_creation_microseconds_since_unix_epoch(
(base::Time::Now() - base::Time::UnixEpoch()).InMicroseconds());
metadata_proto_->set_num_fetches(requests_.size());
-
- // Check if |icon_| should be persisted.
- if (icon_.height() * icon_.width() > kMaxIconResolution) {
- StoreMetadata();
- return;
- }
-
- // Do the initialization on a seperate thread to avoid blocking on
- // expensive operations (image conversions), then post back to IO thread
- // and continue normally.
- base::PostTaskWithTraitsAndReplyWithResult(
- FROM_HERE,
- {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN,
- base::TaskPriority::BACKGROUND},
- base::BindOnce(&ConvertAndSerializeIcon, icon_),
- base::BindOnce(&CreateMetadataTask::StoreIcon,
- weak_factory_.GetWeakPtr()));
}
-void CreateMetadataTask::StoreIcon(std::string serialized_icon) {
- DCHECK(metadata_proto_);
- metadata_proto_->set_icon(std::move(serialized_icon));
+void CreateMetadataTask::DidSerializeIcon(std::string serialized_icon) {
+ serialized_icon_ = std::move(serialized_icon);
StoreMetadata();
}
void CreateMetadataTask::StoreMetadata() {
DCHECK(metadata_proto_);
std::vector<std::pair<std::string, std::string>> entries;
- entries.reserve(requests_.size() * 2 + 1);
+ // - One BackgroundFetchPendingRequest per request
+ // - DeveloperId -> UniqueID
+ // - BackgroundFetchMetadata
+ // - BackgroundFetchUIOptions
+ entries.reserve(requests_.size() + 3);
std::string serialized_metadata_proto;
if (!metadata_proto_->SerializeToString(&serialized_metadata_proto)) {
- FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
+ SetStorageErrorAndFinish(
+ BackgroundFetchStorageError::kServiceWorkerStorageError);
+ return;
+ }
+
+ std::string serialized_ui_options_proto;
+ proto::BackgroundFetchUIOptions ui_options;
+ ui_options.set_title(options_.title);
+ if (!serialized_icon_.empty())
+ ui_options.set_icon(std::move(serialized_icon_));
+
+ if (!ui_options.SerializeToString(&serialized_ui_options_proto)) {
+ SetStorageErrorAndFinish(
+ BackgroundFetchStorageError::kServiceWorkerStorageError);
return;
}
@@ -168,7 +183,8 @@ void CreateMetadataTask::StoreMetadata() {
registration_id_.unique_id());
entries.emplace_back(RegistrationKey(registration_id_.unique_id()),
std::move(serialized_metadata_proto));
- entries.emplace_back(TitleKey(registration_id_.unique_id()), options_.title);
+ entries.emplace_back(UIOptionsKey(registration_id_.unique_id()),
+ serialized_ui_options_proto);
// Signed integers are used for request indexes to avoid unsigned gotchas.
for (int i = 0; i < base::checked_cast<int>(requests_.size()); i++) {
@@ -194,7 +210,8 @@ void CreateMetadataTask::DidStoreMetadata(
break;
case DatabaseStatus::kFailed:
case DatabaseStatus::kNotFound:
- FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
+ SetStorageErrorAndFinish(
+ BackgroundFetchStorageError::kServiceWorkerStorageError);
return;
}
@@ -203,12 +220,36 @@ void CreateMetadataTask::DidStoreMetadata(
void CreateMetadataTask::FinishWithError(
blink::mojom::BackgroundFetchError error) {
- if (error != blink::mojom::BackgroundFetchError::NONE)
- metadata_proto_.reset();
- std::move(callback_).Run(error, std::move(metadata_proto_));
+ BackgroundFetchRegistration registration;
+
+ if (error == blink::mojom::BackgroundFetchError::NONE) {
+ DCHECK(metadata_proto_);
+
+ bool converted =
+ ToBackgroundFetchRegistration(*metadata_proto_, &registration);
+ if (!converted) {
+ // Database corrupted.
+ SetStorageErrorAndFinish(
+ BackgroundFetchStorageError::kServiceWorkerStorageError);
+ return;
+ }
+
+ for (auto& observer : data_manager()->observers()) {
+ observer.OnRegistrationCreated(registration_id_, registration, options_,
+ icon_, requests_.size());
+ }
+ }
+
+ ReportStorageError();
+
+ std::move(callback_).Run(error, registration);
Finished(); // Destroys |this|.
}
+std::string CreateMetadataTask::HistogramName() const {
+ return "CreateMetadataTask";
+}
+
} // namespace background_fetch
} // namespace content
diff --git a/chromium/content/browser/background_fetch/storage/create_metadata_task.h b/chromium/content/browser/background_fetch/storage/create_metadata_task.h
index 48bc0d59541..33307624820 100644
--- a/chromium/content/browser/background_fetch/storage/create_metadata_task.h
+++ b/chromium/content/browser/background_fetch/storage/create_metadata_task.h
@@ -17,6 +17,8 @@
namespace content {
+struct BackgroundFetchRegistration;
+
namespace background_fetch {
// Creates Background Fetch metadata entries in the database.
@@ -24,7 +26,7 @@ class CreateMetadataTask : public DatabaseTask {
public:
using CreateMetadataCallback =
base::OnceCallback<void(blink::mojom::BackgroundFetchError,
- std::unique_ptr<proto::BackgroundFetchMetadata>)>;
+ const BackgroundFetchRegistration&)>;
CreateMetadataTask(DatabaseTaskHost* host,
const BackgroundFetchRegistrationId& registration_id,
@@ -38,10 +40,14 @@ class CreateMetadataTask : public DatabaseTask {
void Start() override;
private:
+ void DidGetIsQuotaAvailable(bool is_available);
+
+ void GetRegistrationUniqueId();
+
void DidGetUniqueId(const std::vector<std::string>& data,
blink::ServiceWorkerStatusCode status);
- void StoreIcon(std::string serialized_icon);
+ void DidSerializeIcon(std::string serialized_icon);
void StoreMetadata();
@@ -52,6 +58,8 @@ class CreateMetadataTask : public DatabaseTask {
void FinishWithError(blink::mojom::BackgroundFetchError error) override;
+ std::string HistogramName() const override;
+
BackgroundFetchRegistrationId registration_id_;
std::vector<ServiceWorkerFetchRequest> requests_;
BackgroundFetchOptions options_;
@@ -60,6 +68,8 @@ class CreateMetadataTask : public DatabaseTask {
std::unique_ptr<proto::BackgroundFetchMetadata> metadata_proto_;
+ std::string serialized_icon_;
+
base::WeakPtrFactory<CreateMetadataTask> weak_factory_; // Keep as last.
DISALLOW_COPY_AND_ASSIGN(CreateMetadataTask);
diff --git a/chromium/content/browser/background_fetch/storage/database_helpers.cc b/chromium/content/browser/background_fetch/storage/database_helpers.cc
index 4e4fadf265c..691e721e6ad 100644
--- a/chromium/content/browser/background_fetch/storage/database_helpers.cc
+++ b/chromium/content/browser/background_fetch/storage/database_helpers.cc
@@ -5,6 +5,7 @@
#include "content/browser/background_fetch/storage/database_helpers.h"
#include "base/strings/string_number_conversions.h"
+#include "third_party/blink/public/platform/modules/background_fetch/background_fetch.mojom.h"
namespace content {
@@ -23,8 +24,8 @@ std::string RegistrationKey(const std::string& unique_id) {
return kRegistrationKeyPrefix + unique_id;
}
-std::string TitleKey(const std::string& unique_id) {
- return kTitleKeyPrefix + unique_id;
+std::string UIOptionsKey(const std::string& unique_id) {
+ return kUIOptionsKeyPrefix + unique_id;
}
std::string PendingRequestKeyPrefix(const std::string& unique_id) {
@@ -81,12 +82,85 @@ DatabaseStatus ToDatabaseStatus(blink::ServiceWorkerStatusCode status) {
case blink::ServiceWorkerStatusCode::kErrorDiskCache:
case blink::ServiceWorkerStatusCode::kErrorRedundant:
case blink::ServiceWorkerStatusCode::kErrorDisallowed:
+ case blink::ServiceWorkerStatusCode::kErrorInvalidArguments:
break;
}
NOTREACHED();
return DatabaseStatus::kFailed;
}
+bool ToBackgroundFetchRegistration(
+ const proto::BackgroundFetchMetadata& metadata_proto,
+ BackgroundFetchRegistration* registration) {
+ DCHECK(registration);
+ const auto& registration_proto = metadata_proto.registration();
+
+ registration->developer_id = registration_proto.developer_id();
+ registration->unique_id = registration_proto.unique_id();
+ registration->upload_total = registration_proto.upload_total();
+ registration->uploaded = registration_proto.uploaded();
+ registration->download_total = registration_proto.download_total();
+ registration->downloaded = registration_proto.downloaded();
+ switch (registration_proto.state()) {
+ case proto::BackgroundFetchRegistration_BackgroundFetchState_PENDING:
+ registration->state = blink::mojom::BackgroundFetchState::PENDING;
+ break;
+ case proto::BackgroundFetchRegistration_BackgroundFetchState_FAILURE:
+ registration->state = blink::mojom::BackgroundFetchState::FAILURE;
+ break;
+ case proto::BackgroundFetchRegistration_BackgroundFetchState_SUCCESS:
+ registration->state = blink::mojom::BackgroundFetchState::SUCCESS;
+ break;
+ default:
+ NOTREACHED();
+ }
+
+ bool did_convert = MojoFailureReasonFromRegistrationProto(
+ registration_proto.failure_reason(), &registration->failure_reason);
+ return did_convert;
+}
+
+bool MojoFailureReasonFromRegistrationProto(
+ proto::BackgroundFetchRegistration::BackgroundFetchFailureReason
+ proto_failure_reason,
+ blink::mojom::BackgroundFetchFailureReason* failure_reason) {
+ DCHECK(failure_reason);
+ switch (proto_failure_reason) {
+ case proto::BackgroundFetchRegistration::NONE:
+ *failure_reason = blink::mojom::BackgroundFetchFailureReason::NONE;
+ return true;
+ case proto::BackgroundFetchRegistration::CANCELLED_FROM_UI:
+ *failure_reason =
+ blink::mojom::BackgroundFetchFailureReason::CANCELLED_FROM_UI;
+ return true;
+ case proto::BackgroundFetchRegistration::CANCELLED_BY_DEVELOPER:
+ *failure_reason =
+ blink::mojom::BackgroundFetchFailureReason::CANCELLED_BY_DEVELOPER;
+ return true;
+ case proto::BackgroundFetchRegistration::SERVICE_WORKER_UNAVAILABLE:
+ *failure_reason = blink::mojom::BackgroundFetchFailureReason::
+ SERVICE_WORKER_UNAVAILABLE;
+ return true;
+ case proto::BackgroundFetchRegistration::QUOTA_EXCEEDED:
+ *failure_reason =
+ blink::mojom::BackgroundFetchFailureReason::QUOTA_EXCEEDED;
+ return true;
+ case proto::BackgroundFetchRegistration::TOTAL_DOWNLOAD_SIZE_EXCEEDED:
+ *failure_reason = blink::mojom::BackgroundFetchFailureReason::
+ TOTAL_DOWNLOAD_SIZE_EXCEEDED;
+ return true;
+ case proto::BackgroundFetchRegistration::FETCH_ERROR:
+ *failure_reason = blink::mojom::BackgroundFetchFailureReason::FETCH_ERROR;
+ return true;
+ case proto::BackgroundFetchRegistration::BAD_STATUS:
+ *failure_reason = blink::mojom::BackgroundFetchFailureReason::BAD_STATUS;
+ return true;
+ }
+ LOG(ERROR) << "BackgroundFetchFailureReason from the metadata proto doesn't"
+ << " match any enum value. Possible database corruption.";
+ return false;
+}
+
} // namespace background_fetch
} // namespace content
diff --git a/chromium/content/browser/background_fetch/storage/database_helpers.h b/chromium/content/browser/background_fetch/storage/database_helpers.h
index a9741fe283c..bca77cdc83d 100644
--- a/chromium/content/browser/background_fetch/storage/database_helpers.h
+++ b/chromium/content/browser/background_fetch/storage/database_helpers.h
@@ -7,7 +7,11 @@
#include <string>
+#include "content/browser/background_fetch/background_fetch.pb.h"
+#include "content/common/background_fetch/background_fetch_types.h"
+#include "content/common/content_export.h"
#include "content/common/service_worker/service_worker_types.h"
+#include "content/public/browser/background_fetch_delegate.h"
#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
namespace content {
@@ -24,16 +28,17 @@ const char kSeparator[] = "_";
const char kActiveRegistrationUniqueIdKeyPrefix[] =
"bgfetch_active_registration_unique_id_";
const char kRegistrationKeyPrefix[] = "bgfetch_registration_";
-const char kTitleKeyPrefix[] = "bgfetch_title_";
+const char kUIOptionsKeyPrefix[] = "bgfetch_ui_options_";
const char kPendingRequestKeyPrefix[] = "bgfetch_pending_request_";
const char kActiveRequestKeyPrefix[] = "bgfetch_active_request_";
const char kCompletedRequestKeyPrefix[] = "bgfetch_completed_request_";
+// Database Keys.
std::string ActiveRegistrationUniqueIdKey(const std::string& developer_id);
-std::string RegistrationKey(const std::string& unique_id);
+CONTENT_EXPORT std::string RegistrationKey(const std::string& unique_id);
-std::string TitleKey(const std::string& unique_id);
+std::string UIOptionsKey(const std::string& unique_id);
std::string PendingRequestKeyPrefix(const std::string& unique_id);
@@ -48,10 +53,21 @@ std::string CompletedRequestKeyPrefix(const std::string& unique_id);
std::string CompletedRequestKey(const std::string& unique_id,
int request_index);
+// Database status.
enum class DatabaseStatus { kOk, kFailed, kNotFound };
DatabaseStatus ToDatabaseStatus(blink::ServiceWorkerStatusCode status);
+// Converts the |metadata_proto| to a BackgroundFetchRegistration object.
+bool ToBackgroundFetchRegistration(
+ const proto::BackgroundFetchMetadata& metadata_proto,
+ BackgroundFetchRegistration* registration);
+
+bool MojoFailureReasonFromRegistrationProto(
+ proto::BackgroundFetchRegistration_BackgroundFetchFailureReason
+ proto_failure_reason,
+ blink::mojom::BackgroundFetchFailureReason* failure_reason);
+
} // namespace background_fetch
} // namespace content
diff --git a/chromium/content/browser/background_fetch/storage/database_task.cc b/chromium/content/browser/background_fetch/storage/database_task.cc
index 62a5a758c1e..0029afb1318 100644
--- a/chromium/content/browser/background_fetch/storage/database_task.cc
+++ b/chromium/content/browser/background_fetch/storage/database_task.cc
@@ -6,15 +6,33 @@
#include <utility>
+#include "base/metrics/histogram_functions.h"
#include "content/browser/background_fetch/background_fetch_data_manager.h"
#include "content/browser/background_fetch/background_fetch_data_manager_observer.h"
#include "content/browser/background_fetch/storage/database_helpers.h"
+#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/public/browser/browser_thread.h"
+#include "storage/browser/quota/quota_manager_proxy.h"
namespace content {
namespace background_fetch {
+namespace {
+
+void DidGetUsageAndQuota(DatabaseTask::IsQuotaAvailableCallback callback,
+ int64_t size,
+ blink::mojom::QuotaStatusCode status,
+ int64_t usage,
+ int64_t quota) {
+ bool is_available =
+ status == blink::mojom::QuotaStatusCode::kOk && (usage + size) <= quota;
+
+ std::move(callback).Run(is_available);
+}
+
+} // namespace
+
DatabaseTaskHost::DatabaseTaskHost() : weak_factory_(this) {}
DatabaseTaskHost::~DatabaseTaskHost() = default;
@@ -61,6 +79,57 @@ void DatabaseTask::AbandonFetches(int64_t service_worker_registration_id) {
observer.OnServiceWorkerDatabaseCorrupted(service_worker_registration_id);
}
+void DatabaseTask::IsQuotaAvailable(const url::Origin& origin,
+ int64_t size,
+ IsQuotaAvailableCallback callback) {
+ DCHECK(quota_manager_proxy());
+ DCHECK_GT(size, 0);
+ quota_manager_proxy()->GetUsageAndQuota(
+ base::ThreadTaskRunnerHandle::Get().get(), origin,
+ blink::mojom::StorageType::kTemporary,
+ base::BindOnce(&DidGetUsageAndQuota, std::move(callback), size));
+}
+
+void DatabaseTask::SetStorageError(BackgroundFetchStorageError error) {
+ DCHECK_NE(BackgroundFetchStorageError::kNone, error);
+ switch (storage_error_) {
+ case BackgroundFetchStorageError::kNone:
+ storage_error_ = error;
+ break;
+ case BackgroundFetchStorageError::kServiceWorkerStorageError:
+ case BackgroundFetchStorageError::kCacheStorageError:
+ DCHECK(error == BackgroundFetchStorageError::kServiceWorkerStorageError ||
+ error == BackgroundFetchStorageError::kCacheStorageError);
+ if (storage_error_ != error)
+ storage_error_ = BackgroundFetchStorageError::kStorageError;
+ break;
+ case BackgroundFetchStorageError::kStorageError:
+ break;
+ }
+}
+
+void DatabaseTask::SetStorageErrorAndFinish(BackgroundFetchStorageError error) {
+ SetStorageError(error);
+ FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
+}
+
+void DatabaseTask::ReportStorageError() {
+ if (host_ != data_manager())
+ return; // This is a SubTask.
+
+ base::UmaHistogramEnumeration("BackgroundFetch.Storage." + HistogramName(),
+ storage_error_);
+}
+
+bool DatabaseTask::HasStorageError() {
+ return storage_error_ != BackgroundFetchStorageError::kNone;
+}
+
+std::string DatabaseTask::HistogramName() const {
+ NOTREACHED() << "HistogramName needs to be provided.";
+ return "GeneralDatabaseTask";
+}
+
ServiceWorkerContextWrapper* DatabaseTask::service_worker_context() {
DCHECK(data_manager()->service_worker_context());
return data_manager()->service_worker_context();
@@ -83,6 +152,10 @@ BackgroundFetchDataManager* DatabaseTask::data_manager() {
return host_->data_manager();
}
+storage::QuotaManagerProxy* DatabaseTask::quota_manager_proxy() {
+ return data_manager()->quota_manager_proxy();
+}
+
} // namespace background_fetch
} // namespace content
diff --git a/chromium/content/browser/background_fetch/storage/database_task.h b/chromium/content/browser/background_fetch/storage/database_task.h
index 3d5742cfa6e..471d9ca7656 100644
--- a/chromium/content/browser/background_fetch/storage/database_task.h
+++ b/chromium/content/browser/background_fetch/storage/database_task.h
@@ -16,6 +16,14 @@
#include "content/browser/cache_storage/cache_storage_manager.h"
#include "third_party/blink/public/platform/modules/background_fetch/background_fetch.mojom.h"
+namespace storage {
+class QuotaManagerProxy;
+} // namespace storage
+
+namespace url {
+class Origin;
+} // namespace url
+
namespace content {
class BackgroundFetchDataManager;
@@ -62,11 +70,23 @@ class DatabaseTaskHost {
// as they are added, and cannot outlive the parent DatabaseTask.
class DatabaseTask : public DatabaseTaskHost {
public:
+ using IsQuotaAvailableCallback =
+ base::OnceCallback<void(bool /* is_available */)>;
+
~DatabaseTask() override;
virtual void Start() = 0;
protected:
+ // This enum is append-only since it is used by UMA.
+ enum class BackgroundFetchStorageError {
+ kNone,
+ kServiceWorkerStorageError,
+ kCacheStorageError,
+ kStorageError,
+ kMaxValue = kStorageError
+ };
+
explicit DatabaseTask(DatabaseTaskHost* host);
// Each task MUST call this once finished, even if exceptions occur, to
@@ -80,25 +100,38 @@ class DatabaseTask : public DatabaseTaskHost {
// Abandon all fetches for a given service worker.
void AbandonFetches(int64_t service_worker_registration_id);
+ // Getters.
ServiceWorkerContextWrapper* service_worker_context();
-
CacheStorageManager* cache_manager();
-
std::set<std::string>& ref_counted_unique_ids();
-
ChromeBlobStorageContext* blob_storage_context();
+ storage::QuotaManagerProxy* quota_manager_proxy();
// DatabaseTaskHost implementation.
void OnTaskFinished(DatabaseTask* finished_subtask) override;
BackgroundFetchDataManager* data_manager() override;
+ // UMA reporting.
+ void SetStorageError(BackgroundFetchStorageError error);
+ void SetStorageErrorAndFinish(BackgroundFetchStorageError error);
+ void ReportStorageError();
+ bool HasStorageError();
+
+ // Quota.
+ void IsQuotaAvailable(const url::Origin& origin,
+ int64_t size,
+ IsQuotaAvailableCallback callback);
+
private:
// Each task must override this function and perform the following steps:
- // 1) Report error (UMA) if applicable.
+ // 1) Report storage error (UMA) if applicable.
// 2) Run the provided callback.
// 3) Call Finished().
virtual void FinishWithError(blink::mojom::BackgroundFetchError error) = 0;
+ // The Histogram name to report with the Error.
+ virtual std::string HistogramName() const;
+
DatabaseTaskHost* host_;
// Owns a reference to the CacheStorageManager in case Shutdown was
@@ -108,6 +141,10 @@ class DatabaseTask : public DatabaseTaskHost {
// Map the raw pointer to its unique_ptr, to make lookups easier.
std::map<DatabaseTask*, std::unique_ptr<DatabaseTask>> active_subtasks_;
+ // The storage error to report.
+ BackgroundFetchStorageError storage_error_ =
+ BackgroundFetchStorageError::kNone;
+
DISALLOW_COPY_AND_ASSIGN(DatabaseTask);
};
diff --git a/chromium/content/browser/background_fetch/storage/delete_registration_task.cc b/chromium/content/browser/background_fetch/storage/delete_registration_task.cc
index 5734680a96d..ade9a789b6f 100644
--- a/chromium/content/browser/background_fetch/storage/delete_registration_task.cc
+++ b/chromium/content/browser/background_fetch/storage/delete_registration_task.cc
@@ -57,12 +57,9 @@ DeleteRegistrationTask::~DeleteRegistrationTask() = default;
void DeleteRegistrationTask::Start() {
base::RepeatingClosure barrier_closure = base::BarrierClosure(
- 2u, base::BindOnce(
- [](base::WeakPtr<DeleteRegistrationTask> task) {
- if (task)
- task->FinishWithError(task->error_);
- },
- weak_factory_.GetWeakPtr()));
+ 2u, base::BindOnce(&DeleteRegistrationTask::FinishWithError,
+ weak_factory_.GetWeakPtr(),
+ blink::mojom::BackgroundFetchError::NONE));
#if DCHECK_IS_ON()
// Get the registration |developer_id| to check it was deactivated.
@@ -97,7 +94,7 @@ void DeleteRegistrationTask::DidGetRegistration(
base::BindOnce(&DCheckRegistrationNotActive, unique_id_));
} else {
// Service worker database has been corrupted. Abandon all fetches.
- error_ = blink::mojom::BackgroundFetchError::STORAGE_ERROR;
+ SetStorageError(BackgroundFetchStorageError::kServiceWorkerStorageError);
AbandonFetches(service_worker_registration_id_);
std::move(done_closure).Run();
}
@@ -107,7 +104,7 @@ void DeleteRegistrationTask::DidGetRegistration(
#endif // DCHECK_IS_ON()
std::vector<std::string> deletion_key_prefixes{
- RegistrationKey(unique_id_), TitleKey(unique_id_),
+ RegistrationKey(unique_id_), UIOptionsKey(unique_id_),
PendingRequestKeyPrefix(unique_id_), ActiveRequestKeyPrefix(unique_id_),
CompletedRequestKeyPrefix(unique_id_)};
@@ -125,7 +122,7 @@ void DeleteRegistrationTask::DidDeleteRegistration(
case DatabaseStatus::kNotFound:
break;
case DatabaseStatus::kFailed:
- error_ = blink::mojom::BackgroundFetchError::STORAGE_ERROR;
+ SetStorageError(BackgroundFetchStorageError::kServiceWorkerStorageError);
break;
}
std::move(done_closure).Run();
@@ -136,17 +133,24 @@ void DeleteRegistrationTask::DidDeleteCache(
blink::mojom::CacheStorageError error) {
if (error != blink::mojom::CacheStorageError::kSuccess &&
error != blink::mojom::CacheStorageError::kErrorNotFound) {
- error_ = blink::mojom::BackgroundFetchError::STORAGE_ERROR;
+ SetStorageError(BackgroundFetchStorageError::kCacheStorageError);
}
std::move(done_closure).Run();
}
void DeleteRegistrationTask::FinishWithError(
blink::mojom::BackgroundFetchError error) {
+ if (HasStorageError())
+ error = blink::mojom::BackgroundFetchError::STORAGE_ERROR;
+ ReportStorageError();
std::move(callback_).Run(error);
Finished(); // Destroys |this|.
}
+std::string DeleteRegistrationTask::HistogramName() const {
+ return "DeleteRegistrationTask";
+}
+
} // namespace background_fetch
} // namespace content
diff --git a/chromium/content/browser/background_fetch/storage/delete_registration_task.h b/chromium/content/browser/background_fetch/storage/delete_registration_task.h
index b25a7d19955..89195b80eff 100644
--- a/chromium/content/browser/background_fetch/storage/delete_registration_task.h
+++ b/chromium/content/browser/background_fetch/storage/delete_registration_task.h
@@ -43,15 +43,13 @@ class DeleteRegistrationTask : public background_fetch::DatabaseTask {
void FinishWithError(blink::mojom::BackgroundFetchError error) override;
+ std::string HistogramName() const override;
+
int64_t service_worker_registration_id_;
url::Origin origin_;
std::string unique_id_;
HandleBackgroundFetchErrorCallback callback_;
- // The error to report once all async work is completed.
- blink::mojom::BackgroundFetchError error_ =
- blink::mojom::BackgroundFetchError::NONE;
-
base::WeakPtrFactory<DeleteRegistrationTask> weak_factory_; // Keep as last.
DISALLOW_COPY_AND_ASSIGN(DeleteRegistrationTask);
diff --git a/chromium/content/browser/background_fetch/storage/get_developer_ids_task.cc b/chromium/content/browser/background_fetch/storage/get_developer_ids_task.cc
index 1f170218d83..78186816d01 100644
--- a/chromium/content/browser/background_fetch/storage/get_developer_ids_task.cc
+++ b/chromium/content/browser/background_fetch/storage/get_developer_ids_task.cc
@@ -48,17 +48,23 @@ void GetDeveloperIdsTask::DidGetUniqueIds(
break;
}
case DatabaseStatus::kFailed:
- FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
+ SetStorageErrorAndFinish(
+ BackgroundFetchStorageError::kServiceWorkerStorageError);
break;
}
}
void GetDeveloperIdsTask::FinishWithError(
blink::mojom::BackgroundFetchError error) {
+ ReportStorageError();
std::move(callback_).Run(error, std::move(developer_ids_));
Finished(); // Destroys |this|.
}
+std::string GetDeveloperIdsTask::HistogramName() const {
+ return "GetDeveloperIdsTask";
+}
+
} // namespace background_fetch
} // namespace content
diff --git a/chromium/content/browser/background_fetch/storage/get_developer_ids_task.h b/chromium/content/browser/background_fetch/storage/get_developer_ids_task.h
index e9db0880fcc..0d79dead061 100644
--- a/chromium/content/browser/background_fetch/storage/get_developer_ids_task.h
+++ b/chromium/content/browser/background_fetch/storage/get_developer_ids_task.h
@@ -40,6 +40,8 @@ class GetDeveloperIdsTask : public DatabaseTask {
void FinishWithError(blink::mojom::BackgroundFetchError error) override;
+ std::string HistogramName() const override;
+
int64_t service_worker_registration_id_;
url::Origin origin_;
diff --git a/chromium/content/browser/background_fetch/storage/get_initialization_data_task.cc b/chromium/content/browser/background_fetch/storage/get_initialization_data_task.cc
index 10db38fcd96..a5c1e3b5b5a 100644
--- a/chromium/content/browser/background_fetch/storage/get_initialization_data_task.cc
+++ b/chromium/content/browser/background_fetch/storage/get_initialization_data_task.cc
@@ -6,11 +6,13 @@
#include "base/barrier_closure.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/task_scheduler/post_task.h"
-#include "base/task_scheduler/task_traits.h"
+#include "base/task/post_task.h"
+#include "base/task/task_traits.h"
#include "content/browser/background_fetch/background_fetch.pb.h"
#include "content/browser/background_fetch/background_fetch_data_manager.h"
+#include "content/browser/background_fetch/background_fetch_request_info.h"
#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/service_worker/service_worker_context_wrapper.h"
#include "third_party/blink/public/common/manifest/manifest.h"
@@ -69,26 +71,27 @@ class InitializationSubTask : public DatabaseTask {
};
// Fills the BackgroundFetchInitializationData with the most recent UI title.
-class GetTitleTask : public InitializationSubTask {
+class GetUIOptionsTask : public InitializationSubTask {
public:
- GetTitleTask(DatabaseTaskHost* host,
- const SubTaskInit& sub_task_init,
- base::OnceClosure done_closure)
+ GetUIOptionsTask(DatabaseTaskHost* host,
+ const SubTaskInit& sub_task_init,
+ base::OnceClosure done_closure)
: InitializationSubTask(host, sub_task_init, std::move(done_closure)),
weak_factory_(this) {}
- ~GetTitleTask() override = default;
+ ~GetUIOptionsTask() override = default;
void Start() override {
service_worker_context()->GetRegistrationUserData(
sub_task_init().service_worker_registration_id,
- {TitleKey(sub_task_init().unique_id)},
- base::BindOnce(&GetTitleTask::DidGetTitle, weak_factory_.GetWeakPtr()));
+ {UIOptionsKey(sub_task_init().unique_id)},
+ base::BindOnce(&GetUIOptionsTask::DidGetUIOptions,
+ weak_factory_.GetWeakPtr()));
}
private:
- void DidGetTitle(const std::vector<std::string>& data,
- blink::ServiceWorkerStatusCode status) {
+ void DidGetUIOptions(const std::vector<std::string>& data,
+ blink::ServiceWorkerStatusCode status) {
switch (ToDatabaseStatus(status)) {
case DatabaseStatus::kFailed:
FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
@@ -98,12 +101,36 @@ class GetTitleTask : public InitializationSubTask {
break;
}
- if (!data.empty())
- sub_task_init().initialization_data->ui_title = data.front();
+ if (data.size() != 1u) {
+ FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
+ return;
+ }
+
+ proto::BackgroundFetchUIOptions ui_options;
+ if (!ui_options.ParseFromString(data[0])) {
+ FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
+ return;
+ }
+
+ if (!ui_options.title().empty())
+ sub_task_init().initialization_data->ui_title = ui_options.title();
+
+ if (!ui_options.icon().empty()) {
+ // Start an icon deserialization SubTask on another thread, then finish.
+ DeserializeIcon(std::unique_ptr<std::string>(ui_options.release_icon()),
+ base::BindOnce(&GetUIOptionsTask::DidDeserializeIcon,
+ weak_factory_.GetWeakPtr()));
+ } else {
+ FinishWithError(blink::mojom::BackgroundFetchError::NONE);
+ }
+ }
+
+ void DidDeserializeIcon(SkBitmap icon) {
+ sub_task_init().initialization_data->icon = std::move(icon);
FinishWithError(blink::mojom::BackgroundFetchError::NONE);
}
- base::WeakPtrFactory<GetTitleTask> weak_factory_; // Keep as last.
+ base::WeakPtrFactory<GetUIOptionsTask> weak_factory_; // Keep as last.
};
// Gets the number of completed fetches, the number of active fetches,
@@ -207,8 +234,16 @@ class GetRequestsTask : public InitializationSubTask {
return;
}
DCHECK_EQ(sub_task_init().unique_id, active_request.unique_id());
- sub_task_init().initialization_data->active_fetch_guids.push_back(
- active_request.download_guid());
+
+ auto request_info = base::MakeRefCounted<BackgroundFetchRequestInfo>(
+ active_request.request_index(),
+ ServiceWorkerFetchRequest::ParseFromString(
+ active_request.serialized_request()));
+ request_info->SetDownloadGuid(active_request.download_guid());
+
+ sub_task_init().initialization_data->active_fetch_requests.push_back(
+ std::move(request_info));
+
pending_requests_to_delete.push_back(PendingRequestKey(
active_request.unique_id(), active_request.request_index()));
}
@@ -243,48 +278,6 @@ class GetRequestsTask : public InitializationSubTask {
DISALLOW_COPY_AND_ASSIGN(GetRequestsTask);
};
-// Deserializes the icon and creates an SkBitmap from it.
-class DeserializeIconTask : public InitializationSubTask {
- public:
- DeserializeIconTask(DatabaseTaskHost* host,
- const SubTaskInit& sub_task_init,
- base::OnceClosure done_closure,
- std::string* serialized_icon)
- : InitializationSubTask(host, sub_task_init, std::move(done_closure)),
- serialized_icon_(serialized_icon),
- weak_factory_(this) {}
-
- ~DeserializeIconTask() override = default;
-
- void Start() override {
- base::PostTaskWithTraitsAndReplyWithResult(
- FROM_HERE,
- {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN,
- base::TaskPriority::BACKGROUND},
- base::BindOnce(&DeserializeIcon, std::move(serialized_icon_)),
- base::BindOnce(&DeserializeIconTask::StoreIcon,
- weak_factory_.GetWeakPtr()));
- }
-
- private:
- static SkBitmap DeserializeIcon(
- std::unique_ptr<std::string> serialized_icon) {
- return gfx::Image::CreateFrom1xPNGBytes(
- reinterpret_cast<const unsigned char*>(serialized_icon->c_str()),
- serialized_icon->size())
- .AsBitmap();
- }
-
- void StoreIcon(SkBitmap icon) {
- sub_task_init().initialization_data->icon = std::move(icon);
- FinishWithError(blink::mojom::BackgroundFetchError::NONE);
- }
-
- std::unique_ptr<std::string> serialized_icon_;
-
- base::WeakPtrFactory<DeserializeIconTask> weak_factory_; // Keep as last.
-};
-
// Fills the BackgroundFetchInitializationData with all the relevant information
// stored in the BackgroundFetchMetadata proto.
class FillFromMetadataTask : public InitializationSubTask {
@@ -382,18 +375,7 @@ class FillFromMetadataTask : public InitializationSubTask {
}
}
- if (!metadata.icon().empty()) {
- // Start an icon deserialization SubTask on another thread, then finish.
- AddSubTask(std::make_unique<DeserializeIconTask>(
- this, sub_task_init(),
- base::BindOnce(&FillFromMetadataTask::FinishWithError,
- weak_factory_.GetWeakPtr(),
- blink::mojom::BackgroundFetchError::NONE),
- metadata.release_icon()));
- } else {
- // Immediately finish.
- FinishWithError(blink::mojom::BackgroundFetchError::NONE);
- }
+ FinishWithError(blink::mojom::BackgroundFetchError::NONE);
}
base::WeakPtrFactory<FillFromMetadataTask> weak_factory_; // Keep as last.
@@ -416,9 +398,9 @@ class FillBackgroundFetchInitializationDataTask : public InitializationSubTask {
void Start() override {
// We need 3 queries to get the initialization data. These are wrapped
// in a BarrierClosure to avoid querying them serially.
- // 1. Metadata (+ icon deserialization)
+ // 1. Metadata
// 2. Request statuses and state sanitization
- // 3. UI Title
+ // 3. UI Options (+ icon deserialization)
base::RepeatingClosure barrier_closure = base::BarrierClosure(
3u,
base::BindOnce(
@@ -432,8 +414,8 @@ class FillBackgroundFetchInitializationDataTask : public InitializationSubTask {
barrier_closure));
AddSubTask(std::make_unique<GetRequestsTask>(this, sub_task_init(),
barrier_closure));
- AddSubTask(
- std::make_unique<GetTitleTask>(this, sub_task_init(), barrier_closure));
+ AddSubTask(std::make_unique<GetUIOptionsTask>(this, sub_task_init(),
+ barrier_closure));
}
private:
@@ -525,12 +507,25 @@ void GetInitializationDataTask::FinishWithError(
AddDatabaseTask(std::make_unique<MarkRegistrationForDeletionTask>(
data_manager(), data.second.registration_id, base::DoNothing()));
}
+
+ if (data.second.error ==
+ blink::mojom::BackgroundFetchError::STORAGE_ERROR) {
+ // The subtasks only access the Service Worker storage, so if there is
+ // a storage error, that would be the cause.
+ SetStorageError(BackgroundFetchStorageError::kServiceWorkerStorageError);
+ }
}
+ ReportStorageError();
+
std::move(callback_).Run(error, std::move(results));
Finished(); // Destroys |this|.
}
+std::string GetInitializationDataTask::HistogramName() const {
+ return "GetInitializationDataTask";
+}
+
} // namespace background_fetch
} // namespace content
diff --git a/chromium/content/browser/background_fetch/storage/get_initialization_data_task.h b/chromium/content/browser/background_fetch/storage/get_initialization_data_task.h
index 7946ba0a1f6..bae5662ccb6 100644
--- a/chromium/content/browser/background_fetch/storage/get_initialization_data_task.h
+++ b/chromium/content/browser/background_fetch/storage/get_initialization_data_task.h
@@ -10,6 +10,7 @@
#include <vector>
#include "base/callback.h"
+#include "base/memory/scoped_refptr.h"
#include "content/browser/background_fetch/background_fetch_registration_id.h"
#include "content/browser/background_fetch/storage/database_task.h"
#include "content/browser/service_worker/service_worker_info.h"
@@ -21,6 +22,8 @@
namespace content {
+class BackgroundFetchRequestInfo;
+
namespace background_fetch {
// All the information needed to create a JobController and resume the fetch
@@ -36,7 +39,7 @@ struct CONTENT_EXPORT BackgroundFetchInitializationData {
BackgroundFetchRegistration registration;
size_t num_requests;
size_t num_completed_requests;
- std::vector<std::string> active_fetch_guids;
+ std::vector<scoped_refptr<BackgroundFetchRequestInfo>> active_fetch_requests;
std::string ui_title;
// The error, if any, when getting the registration data.
@@ -82,6 +85,8 @@ class GetInitializationDataTask : public DatabaseTask {
void FinishWithError(blink::mojom::BackgroundFetchError error) override;
+ std::string HistogramName() const override;
+
GetInitializationDataCallback callback_;
// Map from the unique_id to the initialization data.
diff --git a/chromium/content/browser/background_fetch/storage/get_registration_task.cc b/chromium/content/browser/background_fetch/storage/get_registration_task.cc
new file mode 100644
index 00000000000..d5e9c45d2c3
--- /dev/null
+++ b/chromium/content/browser/background_fetch/storage/get_registration_task.cc
@@ -0,0 +1,74 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/background_fetch/storage/get_registration_task.h"
+
+#include "content/browser/background_fetch/background_fetch.pb.h"
+#include "content/browser/background_fetch/storage/database_helpers.h"
+#include "content/browser/background_fetch/storage/get_metadata_task.h"
+
+namespace content {
+
+namespace background_fetch {
+
+GetRegistrationTask::GetRegistrationTask(DatabaseTaskHost* host,
+ int64_t service_worker_registration_id,
+ const url::Origin& origin,
+ const std::string& developer_id,
+ GetRegistrationCallback callback)
+ : DatabaseTask(host),
+ service_worker_registration_id_(service_worker_registration_id),
+ origin_(origin),
+ developer_id_(developer_id),
+ callback_(std::move(callback)),
+ weak_factory_(this) {}
+
+GetRegistrationTask::~GetRegistrationTask() = default;
+
+void GetRegistrationTask::Start() {
+ AddSubTask(std::make_unique<GetMetadataTask>(
+ this, service_worker_registration_id_, origin_, developer_id_,
+ base::BindOnce(&GetRegistrationTask::DidGetMetadata,
+ weak_factory_.GetWeakPtr())));
+}
+
+void GetRegistrationTask::DidGetMetadata(
+ blink::mojom::BackgroundFetchError error,
+ std::unique_ptr<proto::BackgroundFetchMetadata> metadata_proto) {
+ metadata_proto_ = std::move(metadata_proto);
+ if (error == blink::mojom::BackgroundFetchError::STORAGE_ERROR)
+ SetStorageError(BackgroundFetchStorageError::kServiceWorkerStorageError);
+ FinishWithError(error);
+}
+
+void GetRegistrationTask::FinishWithError(
+ blink::mojom::BackgroundFetchError error) {
+ BackgroundFetchRegistration registration;
+
+ if (error == blink::mojom::BackgroundFetchError::NONE) {
+ DCHECK(metadata_proto_);
+
+ bool converted =
+ ToBackgroundFetchRegistration(*metadata_proto_, &registration);
+ if (!converted) {
+ // Database corrupted.
+ SetStorageErrorAndFinish(
+ BackgroundFetchStorageError::kServiceWorkerStorageError);
+ return;
+ }
+ }
+
+ ReportStorageError();
+
+ std::move(callback_).Run(error, registration);
+ Finished(); // Destroys |this|.
+}
+
+std::string GetRegistrationTask::HistogramName() const {
+ return "GetRegistrationTask";
+}
+
+} // namespace background_fetch
+
+} // namespace content
diff --git a/chromium/content/browser/background_fetch/storage/get_registration_task.h b/chromium/content/browser/background_fetch/storage/get_registration_task.h
new file mode 100644
index 00000000000..908b856807f
--- /dev/null
+++ b/chromium/content/browser/background_fetch/storage/get_registration_task.h
@@ -0,0 +1,68 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_BACKGROUND_FETCH_STORAGE_GET_REGISTRATION_TASK_H_
+#define CONTENT_BROWSER_BACKGROUND_FETCH_STORAGE_GET_REGISTRATION_TASK_H_
+
+#include <memory>
+#include <string>
+
+#include "base/callback_forward.h"
+#include "content/browser/background_fetch/storage/database_task.h"
+#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
+#include "url/origin.h"
+
+namespace content {
+
+namespace proto {
+class BackgroundFetchMetadata;
+}
+
+namespace background_fetch {
+
+// Gets an active Background Fetch metadata entry from the database.
+class GetRegistrationTask : public DatabaseTask {
+ public:
+ using GetRegistrationCallback =
+ base::OnceCallback<void(blink::mojom::BackgroundFetchError,
+ const BackgroundFetchRegistration&)>;
+
+ GetRegistrationTask(DatabaseTaskHost* host,
+ int64_t service_worker_registration_id,
+ const url::Origin& origin,
+ const std::string& developer_id,
+ GetRegistrationCallback callback);
+
+ ~GetRegistrationTask() override;
+
+ // DatabaseTask implementation:
+ void Start() override;
+
+ private:
+ void DidGetMetadata(
+ blink::mojom::BackgroundFetchError error,
+ std::unique_ptr<proto::BackgroundFetchMetadata> metadata_proto);
+
+ void FinishWithError(blink::mojom::BackgroundFetchError error) override;
+
+ std::string HistogramName() const override;
+
+ int64_t service_worker_registration_id_;
+ url::Origin origin_;
+ std::string developer_id_;
+
+ GetRegistrationCallback callback_;
+
+ std::unique_ptr<proto::BackgroundFetchMetadata> metadata_proto_;
+
+ base::WeakPtrFactory<GetRegistrationTask> weak_factory_; // Keep as last.
+
+ DISALLOW_COPY_AND_ASSIGN(GetRegistrationTask);
+};
+
+} // namespace background_fetch
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_BACKGROUND_FETCH_STORAGE_GET_REGISTRATION_TASK_H_
diff --git a/chromium/content/browser/background_fetch/storage/get_settled_fetches_task.cc b/chromium/content/browser/background_fetch/storage/get_settled_fetches_task.cc
index d74d797949a..1d9a170a594 100644
--- a/chromium/content/browser/background_fetch/storage/get_settled_fetches_task.cc
+++ b/chromium/content/browser/background_fetch/storage/get_settled_fetches_task.cc
@@ -17,9 +17,11 @@ namespace background_fetch {
GetSettledFetchesTask::GetSettledFetchesTask(
DatabaseTaskHost* host,
BackgroundFetchRegistrationId registration_id,
+ std::unique_ptr<BackgroundFetchRequestMatchParams> match_params,
SettledFetchesCallback callback)
: DatabaseTask(host),
registration_id_(registration_id),
+ match_params_(std::move(match_params)),
settled_fetches_callback_(std::move(callback)),
weak_factory_(this) {}
@@ -48,8 +50,7 @@ void GetSettledFetchesTask::DidOpenCache(
CacheStorageCacheHandle handle,
blink::mojom::CacheStorageError error) {
if (error != blink::mojom::CacheStorageError::kSuccess) {
- // TODO(crbug.com/780025): Log failures to UMA.
- error_ = blink::mojom::BackgroundFetchError::STORAGE_ERROR;
+ SetStorageError(BackgroundFetchStorageError::kCacheStorageError);
} else {
DCHECK(handle.value());
handle_ = std::move(handle);
@@ -64,9 +65,8 @@ void GetSettledFetchesTask::DidGetCompletedRequests(
switch (ToDatabaseStatus(status)) {
case DatabaseStatus::kOk:
break;
- // TODO(crbug.com/780025): Log failures to UMA.
case DatabaseStatus::kFailed:
- error_ = blink::mojom::BackgroundFetchError::STORAGE_ERROR;
+ SetStorageError(BackgroundFetchStorageError::kServiceWorkerStorageError);
break;
case DatabaseStatus::kNotFound:
background_fetch_succeeded_ = false;
@@ -80,7 +80,7 @@ void GetSettledFetchesTask::DidGetCompletedRequests(
if (!completed_requests_.back().ParseFromString(
serialized_completed_request)) {
// Service worker database has been corrupted. Abandon fetches.
- error_ = blink::mojom::BackgroundFetchError::STORAGE_ERROR;
+ SetStorageError(BackgroundFetchStorageError::kServiceWorkerStorageError);
background_fetch_succeeded_ = false;
AbandonFetches(registration_id_.service_worker_registration_id());
break;
@@ -92,6 +92,11 @@ void GetSettledFetchesTask::DidGetCompletedRequests(
}
void GetSettledFetchesTask::GetResponses() {
+ // Handle potential errors.
+ if (HasStorageError()) {
+ FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
+ return;
+ }
if (error_ != blink::mojom::BackgroundFetchError::NONE) {
FinishWithError(error_);
return;
@@ -101,19 +106,42 @@ void GetSettledFetchesTask::GetResponses() {
return;
}
- base::RepeatingClosure barrier_closure = base::BarrierClosure(
- completed_requests_.size(),
- base::BindOnce(&GetSettledFetchesTask::FinishWithError,
- weak_factory_.GetWeakPtr(),
- blink::mojom::BackgroundFetchError::NONE));
+ if (!match_params_->FilterByRequest()) {
+ // No request to match against has been specified. Process all completed
+ // requests.
+ // TODO(crbug.com/863016): Process all requests here, not just the
+ // completed ones.
+ base::RepeatingClosure barrier_closure = base::BarrierClosure(
+ completed_requests_.size(),
+ base::BindOnce(&GetSettledFetchesTask::FinishWithError,
+ weak_factory_.GetWeakPtr(),
+ blink::mojom::BackgroundFetchError::NONE));
+ settled_fetches_.reserve(completed_requests_.size());
+ for (const auto& completed_request : completed_requests_) {
+ settled_fetches_.emplace_back();
+ settled_fetches_.back().request =
+ std::move(ServiceWorkerFetchRequest::ParseFromString(
+ completed_request.serialized_request()));
+ FillResponse(&settled_fetches_.back(), barrier_closure);
+ }
+ return;
+ }
- settled_fetches_.reserve(completed_requests_.size());
- for (const auto& completed_request : completed_requests_) {
- settled_fetches_.emplace_back();
- settled_fetches_.back().request =
- std::move(ServiceWorkerFetchRequest::ParseFromString(
- completed_request.serialized_request()));
- FillResponse(&settled_fetches_.back(), barrier_closure);
+ // Get response(s) only for the relevant fetch.
+ settled_fetches_.emplace_back();
+ settled_fetches_.back().request = match_params_->request_to_match();
+
+ if (match_params_->match_all()) {
+ FillResponses(base::BindOnce(&GetSettledFetchesTask::FinishWithError,
+ weak_factory_.GetWeakPtr(),
+ blink::mojom::BackgroundFetchError::NONE));
+ return;
+ } else {
+ FillResponse(&settled_fetches_.back(),
+ base::BindOnce(&GetSettledFetchesTask::FinishWithError,
+ weak_factory_.GetWeakPtr(),
+ blink::mojom::BackgroundFetchError::NONE));
+ return;
}
}
@@ -125,48 +153,115 @@ void GetSettledFetchesTask::FillResponse(
auto request =
std::make_unique<ServiceWorkerFetchRequest>(settled_fetch->request);
-
- handle_.value()->Match(std::move(request), nullptr /* match_params */,
+ handle_.value()->Match(std::move(request),
+ match_params_->cloned_cache_query_params(),
base::BindOnce(&GetSettledFetchesTask::DidMatchRequest,
weak_factory_.GetWeakPtr(),
settled_fetch, std::move(callback)));
}
+void GetSettledFetchesTask::FillResponses(base::OnceClosure callback) {
+ DCHECK(match_params_->match_all());
+ DCHECK(match_params_->FilterByRequest());
+ DCHECK(!settled_fetches_.empty());
+ DCHECK(handle_.value());
+
+ // Make a copy.
+ auto request = std::make_unique<ServiceWorkerFetchRequest>(
+ match_params_->request_to_match());
+
+ handle_.value()->MatchAll(
+ std::move(request), match_params_->cloned_cache_query_params(),
+ base::BindOnce(&GetSettledFetchesTask::DidMatchAllResponsesForRequest,
+ weak_factory_.GetWeakPtr(), std::move(callback)));
+}
+
void GetSettledFetchesTask::DidMatchRequest(
BackgroundFetchSettledFetch* settled_fetch,
base::OnceClosure callback,
blink::mojom::CacheStorageError error,
- std::unique_ptr<ServiceWorkerResponse> cache_response) {
- if (error != blink::mojom::CacheStorageError::kSuccess) {
- DCHECK(settled_fetch);
+ blink::mojom::FetchAPIResponsePtr cache_response) {
+ DCHECK(settled_fetch);
+
+ // Handle error cases.
+ if (error == blink::mojom::CacheStorageError::kErrorNotFound) {
+ // This is currently being called once a fetch finishes, or when match() is
+ // called.
+ // In the first case, not finding a response is an error state. In the
+ // second case, it just means the developer passed a non-matching request.
+ // The if condition below picks the first one.
+ // TODO(crbug.com/863016): Once we stop sending settled_fetches with
+ // BackgroundFetch events, this won't be a storage error.
+ if (!match_params_->FilterByRequest())
+ SetStorageError(BackgroundFetchStorageError::kCacheStorageError);
+ } else if (error != blink::mojom::CacheStorageError::kSuccess) {
+ SetStorageError(BackgroundFetchStorageError::kCacheStorageError);
+ }
+
+ if (!cache_response) {
FillUncachedResponse(settled_fetch, std::move(callback));
return;
}
- settled_fetch->response = std::move(*cache_response);
+ settled_fetch->response = std::move(cache_response);
+ std::move(callback).Run();
+}
+
+void GetSettledFetchesTask::DidMatchAllResponsesForRequest(
+ base::OnceClosure callback,
+ blink::mojom::CacheStorageError error,
+ std::vector<blink::mojom::FetchAPIResponsePtr> cache_responses) {
+ if (error != blink::mojom::CacheStorageError::kSuccess &&
+ error != blink::mojom::CacheStorageError::kErrorNotFound) {
+ SetStorageError(BackgroundFetchStorageError::kCacheStorageError);
+ }
+
+ if (error != blink::mojom::CacheStorageError::kSuccess) {
+ DCHECK(!settled_fetches_.empty());
+ FillUncachedResponse(&settled_fetches_.back(), std::move(callback));
+ return;
+ }
+
+ settled_fetches_.clear();
+ settled_fetches_.reserve(cache_responses.size());
+ for (size_t i = 0; i < cache_responses.size(); ++i) {
+ settled_fetches_.emplace_back();
+ settled_fetches_.back().request = match_params_->request_to_match();
+ settled_fetches_.back().response = std::move(cache_responses[i]);
+ }
std::move(callback).Run();
}
+// TODO(crbug.com/863016): Get rid of this method.
void GetSettledFetchesTask::FillUncachedResponse(
BackgroundFetchSettledFetch* settled_fetch,
base::OnceClosure callback) {
background_fetch_succeeded_ = false;
// TODO(rayankans): Fill unmatched response with error reports.
- settled_fetch->response.response_type =
+ DCHECK(!settled_fetch->response);
+ settled_fetch->response = blink::mojom::FetchAPIResponse::New();
+ settled_fetch->response->response_type =
network::mojom::FetchResponseType::kError;
- settled_fetch->response.url_list.push_back(settled_fetch->request.url);
+ settled_fetch->response->url_list.push_back(settled_fetch->request.url);
std::move(callback).Run();
}
void GetSettledFetchesTask::FinishWithError(
blink::mojom::BackgroundFetchError error) {
+ if (HasStorageError())
+ error = blink::mojom::BackgroundFetchError::STORAGE_ERROR;
+ ReportStorageError();
std::move(settled_fetches_callback_)
.Run(error, background_fetch_succeeded_, std::move(settled_fetches_),
{} /* blob_data_handles */);
Finished(); // Destroys |this|.
}
+std::string GetSettledFetchesTask::HistogramName() const {
+ return "GetSettledFetchesTask";
+};
+
} // namespace background_fetch
} // namespace content
diff --git a/chromium/content/browser/background_fetch/storage/get_settled_fetches_task.h b/chromium/content/browser/background_fetch/storage/get_settled_fetches_task.h
index 6830c21d924..2b5183a09b5 100644
--- a/chromium/content/browser/background_fetch/storage/get_settled_fetches_task.h
+++ b/chromium/content/browser/background_fetch/storage/get_settled_fetches_task.h
@@ -8,6 +8,7 @@
#include "base/callback_forward.h"
#include "base/memory/scoped_refptr.h"
#include "content/browser/background_fetch/background_fetch.pb.h"
+#include "content/browser/background_fetch/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 "storage/browser/blob/blob_data_handle.h"
@@ -15,19 +16,26 @@
namespace content {
+class BackgroundFetchRequestMatchParams;
+
namespace background_fetch {
class GetSettledFetchesTask : public DatabaseTask {
public:
+ // TODO(nator): Remove BlobDataHandle since we're not using them.
using SettledFetchesCallback = base::OnceCallback<void(
blink::mojom::BackgroundFetchError,
bool,
std::vector<BackgroundFetchSettledFetch>,
std::vector<std::unique_ptr<storage::BlobDataHandle>>)>;
- GetSettledFetchesTask(DatabaseTaskHost* host,
- BackgroundFetchRegistrationId registration_id,
- SettledFetchesCallback callback);
+ // Gets settled fetches from cache storage, filtered according to
+ // |match_params|.
+ GetSettledFetchesTask(
+ DatabaseTaskHost* host,
+ BackgroundFetchRegistrationId registration_id,
+ std::unique_ptr<BackgroundFetchRequestMatchParams> match_params,
+ SettledFetchesCallback callback);
~GetSettledFetchesTask() override;
@@ -51,14 +59,24 @@ class GetSettledFetchesTask : public DatabaseTask {
void FillResponse(BackgroundFetchSettledFetch* settled_fetch,
base::OnceClosure callback);
+ void FillResponses(base::OnceClosure callback);
+
void DidMatchRequest(BackgroundFetchSettledFetch* settled_fetch,
base::OnceClosure callback,
blink::mojom::CacheStorageError error,
- std::unique_ptr<ServiceWorkerResponse> cache_response);
+ blink::mojom::FetchAPIResponsePtr cache_response);
+
+ void DidMatchAllResponsesForRequest(
+ base::OnceClosure callback,
+ blink::mojom::CacheStorageError error,
+ std::vector<blink::mojom::FetchAPIResponsePtr> cache_responses);
void FinishWithError(blink::mojom::BackgroundFetchError error) override;
+ std::string HistogramName() const override;
+
BackgroundFetchRegistrationId registration_id_;
+ std::unique_ptr<BackgroundFetchRequestMatchParams> match_params_;
SettledFetchesCallback settled_fetches_callback_;
// SettledFetchesCallback params.
diff --git a/chromium/content/browser/background_fetch/storage/image_helpers.cc b/chromium/content/browser/background_fetch/storage/image_helpers.cc
new file mode 100644
index 00000000000..8dc2076b199
--- /dev/null
+++ b/chromium/content/browser/background_fetch/storage/image_helpers.cc
@@ -0,0 +1,72 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/background_fetch/storage/image_helpers.h"
+
+#include "base/sequenced_task_runner.h"
+#include "base/task/post_task.h"
+#include "base/task/task_traits.h"
+#include "ui/gfx/image/image.h"
+
+namespace content {
+
+namespace background_fetch {
+
+namespace {
+
+// The max icon resolution, this is used as a threshold to decide
+// whether the icon should be persisted.
+constexpr int kMaxIconResolution = 256 * 256;
+
+std::string ConvertAndSerializeIcon(const SkBitmap& icon) {
+ std::string serialized_icon;
+ auto icon_bytes = gfx::Image::CreateFrom1xBitmap(icon).As1xPNGBytes();
+ serialized_icon.assign(icon_bytes->front_as<char>(),
+ icon_bytes->front_as<char>() + icon_bytes->size());
+ return serialized_icon;
+}
+
+SkBitmap DeserializeAndConvertIcon(
+ std::unique_ptr<std::string> serialized_icon) {
+ return gfx::Image::CreateFrom1xPNGBytes(
+ reinterpret_cast<const unsigned char*>(serialized_icon->c_str()),
+ serialized_icon->size())
+ .AsBitmap();
+}
+
+} // namespace
+
+bool ShouldPersistIcon(const SkBitmap& icon) {
+ return !icon.isNull() && (icon.height() * icon.width() <= kMaxIconResolution);
+}
+
+void SerializeIcon(const SkBitmap& icon, SerializeIconCallback callback) {
+ DCHECK(!icon.isNull());
+ // Do the serialization on a seperate thread to avoid blocking on
+ // expensive operations (image conversions), then post back to current
+ // thread and continue normally.
+ base::PostTaskWithTraitsAndReplyWithResult(
+ FROM_HERE,
+ {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN,
+ base::TaskPriority::BEST_EFFORT},
+ base::BindOnce(&ConvertAndSerializeIcon, icon), std::move(callback));
+}
+
+void DeserializeIcon(std::unique_ptr<std::string> serialized_icon,
+ DeserializeIconCallback callback) {
+ DCHECK(serialized_icon);
+ // Do the deserialization on a seperate thread to avoid blocking on
+ // expensive operations (image conversions), then post back to current
+ // thread and continue normally.
+ base::PostTaskWithTraitsAndReplyWithResult(
+ FROM_HERE,
+ {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN,
+ base::TaskPriority::BEST_EFFORT},
+ base::BindOnce(&DeserializeAndConvertIcon, std::move(serialized_icon)),
+ base::BindOnce(std::move(callback)));
+}
+
+} // namespace background_fetch
+
+} // namespace content
diff --git a/chromium/content/browser/background_fetch/storage/image_helpers.h b/chromium/content/browser/background_fetch/storage/image_helpers.h
new file mode 100644
index 00000000000..b42073d4bc6
--- /dev/null
+++ b/chromium/content/browser/background_fetch/storage/image_helpers.h
@@ -0,0 +1,41 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_BACKGROUND_FETCH_STORAGE_IMAGE_HELPERS_H_
+#define CONTENT_BROWSER_BACKGROUND_FETCH_STORAGE_IMAGE_HELPERS_H_
+
+#include <memory>
+#include <string>
+
+#include "base/callback_forward.h"
+#include "content/common/content_export.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+
+namespace content {
+
+namespace background_fetch {
+
+using SerializeIconCallback = base::OnceCallback<void(std::string)>;
+using DeserializeIconCallback = base::OnceCallback<void(SkBitmap)>;
+
+// Checks whether the icon should be stored on disk. This is only the case for
+// non-null |icon|s with a resolution of at most 256x256 pixels.
+CONTENT_EXPORT bool ShouldPersistIcon(const SkBitmap& icon);
+
+// Serializes the icon on a separate Task Runner. The |icon| will be serialized
+// as a 1x bitmap to raw PNG-encoded data
+CONTENT_EXPORT void SerializeIcon(const SkBitmap& icon,
+ SerializeIconCallback callback);
+
+// Deserializes the icon on a separate Task Runner. he |serialized_icon| must
+// contain raw PNG-encoded data, which will be decoded to a 1x bitmap.
+CONTENT_EXPORT void DeserializeIcon(
+ std::unique_ptr<std::string> serialized_icon,
+ DeserializeIconCallback callback);
+
+} // namespace background_fetch
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_BACKGROUND_FETCH_STORAGE_IMAGE_HELPERS_H_
diff --git a/chromium/content/browser/background_fetch/storage/image_helpers_unittest.cc b/chromium/content/browser/background_fetch/storage/image_helpers_unittest.cc
new file mode 100644
index 00000000000..b0ecce7941d
--- /dev/null
+++ b/chromium/content/browser/background_fetch/storage/image_helpers_unittest.cc
@@ -0,0 +1,92 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/background_fetch/storage/image_helpers.h"
+
+#include <memory>
+#include <string>
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/run_loop.h"
+#include "base/test/scoped_task_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+
+namespace content {
+
+namespace background_fetch {
+
+namespace {
+
+void DidSerializeIcon(base::OnceClosure quit_closure,
+ std::string* out_icon,
+ std::string icon) {
+ DCHECK(out_icon);
+ *out_icon = std::move(icon);
+ std::move(quit_closure).Run();
+}
+
+void DidDeserializeIcon(base::OnceClosure quit_closure,
+ SkBitmap* out_icon,
+ SkBitmap icon) {
+ DCHECK(out_icon);
+ *out_icon = std::move(icon);
+ std::move(quit_closure).Run();
+}
+
+TEST(BackgroundFetchImageHelpers, ShouldPersistIcon) {
+ SkBitmap null_icon;
+ EXPECT_FALSE(ShouldPersistIcon(null_icon));
+
+ SkBitmap large_icon;
+ large_icon.allocN32Pixels(512, 512);
+ EXPECT_FALSE(ShouldPersistIcon(large_icon));
+
+ SkBitmap valid_icon;
+ valid_icon.allocN32Pixels(42, 42);
+ EXPECT_TRUE(ShouldPersistIcon(valid_icon));
+}
+
+TEST(BackgroundFetchImageHelpers, SerializeRoundTrip) {
+ base::test::ScopedTaskEnvironment scoped_task_environment;
+
+ SkBitmap icon;
+ icon.allocN32Pixels(42, 42);
+ icon.eraseColor(SK_ColorGREEN);
+
+ // Serialize.
+ std::string serialized_icon;
+ {
+ base::RunLoop run_loop;
+ SerializeIcon(icon,
+ base::BindOnce(&DidSerializeIcon, run_loop.QuitClosure(),
+ &serialized_icon));
+ run_loop.Run();
+ }
+
+ // Deserialize.
+ SkBitmap result_icon;
+ {
+ base::RunLoop run_loop;
+ DeserializeIcon(std::make_unique<std::string>(serialized_icon),
+ base::BindOnce(&DidDeserializeIcon, run_loop.QuitClosure(),
+ &result_icon));
+ run_loop.Run();
+ }
+
+ ASSERT_FALSE(result_icon.isNull());
+ EXPECT_EQ(icon.height(), result_icon.height());
+ EXPECT_EQ(icon.width(), result_icon.width());
+ for (int i = 0; i < result_icon.width(); i++) {
+ for (int j = 0; j < result_icon.height(); j++)
+ EXPECT_EQ(result_icon.getColor(i, j), SK_ColorGREEN);
+ }
+}
+
+} // namespace
+
+} // namespace background_fetch
+
+} // namespace content
diff --git a/chromium/content/browser/background_fetch/storage/mark_registration_for_deletion_task.cc b/chromium/content/browser/background_fetch/storage/mark_registration_for_deletion_task.cc
index 1f12e1a190d..6007fb6b929 100644
--- a/chromium/content/browser/background_fetch/storage/mark_registration_for_deletion_task.cc
+++ b/chromium/content/browser/background_fetch/storage/mark_registration_for_deletion_task.cc
@@ -47,7 +47,8 @@ void MarkRegistrationForDeletionTask::DidGetActiveUniqueId(
FinishWithError(blink::mojom::BackgroundFetchError::INVALID_ID);
return;
case DatabaseStatus::kFailed:
- FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
+ SetStorageErrorAndFinish(
+ BackgroundFetchStorageError::kServiceWorkerStorageError);
return;
}
@@ -75,7 +76,8 @@ void MarkRegistrationForDeletionTask::DidGetActiveUniqueId(
} else {
// Service worker database has been corrupted. Abandon fetches.
AbandonFetches(registration_id_.service_worker_registration_id());
- FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
+ SetStorageErrorAndFinish(
+ BackgroundFetchStorageError::kServiceWorkerStorageError);
return;
}
}
@@ -87,7 +89,8 @@ void MarkRegistrationForDeletionTask::DidDeactivate(
case DatabaseStatus::kNotFound:
break;
case DatabaseStatus::kFailed:
- FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
+ SetStorageErrorAndFinish(
+ BackgroundFetchStorageError::kServiceWorkerStorageError);
return;
}
@@ -100,10 +103,15 @@ void MarkRegistrationForDeletionTask::DidDeactivate(
void MarkRegistrationForDeletionTask::FinishWithError(
blink::mojom::BackgroundFetchError error) {
+ ReportStorageError();
std::move(callback_).Run(error);
Finished(); // Destroys |this|.
}
+std::string MarkRegistrationForDeletionTask::HistogramName() const {
+ return "MarkRegistrationForDeletionTask";
+}
+
} // namespace background_fetch
} // namespace content
diff --git a/chromium/content/browser/background_fetch/storage/mark_registration_for_deletion_task.h b/chromium/content/browser/background_fetch/storage/mark_registration_for_deletion_task.h
index 0c78c17f2b2..a4119559daa 100644
--- a/chromium/content/browser/background_fetch/storage/mark_registration_for_deletion_task.h
+++ b/chromium/content/browser/background_fetch/storage/mark_registration_for_deletion_task.h
@@ -37,6 +37,8 @@ class MarkRegistrationForDeletionTask : public background_fetch::DatabaseTask {
void FinishWithError(blink::mojom::BackgroundFetchError error) override;
+ std::string HistogramName() const override;
+
BackgroundFetchRegistrationId registration_id_;
HandleBackgroundFetchErrorCallback callback_;
diff --git a/chromium/content/browser/background_fetch/storage/mark_request_complete_task.cc b/chromium/content/browser/background_fetch/storage/mark_request_complete_task.cc
index f416b06e4a6..a6c9de6c61a 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
@@ -8,6 +8,7 @@
#include "base/guid.h"
#include "content/browser/background_fetch/background_fetch_cross_origin_filter.h"
#include "content/browser/background_fetch/background_fetch_data_manager.h"
+#include "content/browser/background_fetch/background_fetch_data_manager_observer.h"
#include "content/browser/background_fetch/storage/database_helpers.h"
#include "content/browser/background_fetch/storage/get_metadata_task.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
@@ -39,11 +40,11 @@ MarkRequestCompleteTask::MarkRequestCompleteTask(
DatabaseTaskHost* host,
BackgroundFetchRegistrationId registration_id,
scoped_refptr<BackgroundFetchRequestInfo> request_info,
- MarkedCompleteCallback callback)
+ base::OnceClosure closure)
: DatabaseTask(host),
registration_id_(registration_id),
request_info_(std::move(request_info)),
- callback_(std::move(callback)),
+ closure_(std::move(closure)),
weak_factory_(this) {}
MarkRequestCompleteTask::~MarkRequestCompleteTask() = default;
@@ -59,7 +60,7 @@ void MarkRequestCompleteTask::Start() {
}
void MarkRequestCompleteTask::StoreResponse(base::OnceClosure done_closure) {
- auto response = std::make_unique<ServiceWorkerResponse>();
+ auto response = blink::mojom::FetchAPIResponse::New();
response->url_list = request_info_->GetURLChain();
// TODO(crbug.com/838837): fill error and cors_exposed_header_names in
// response.
@@ -82,6 +83,42 @@ void MarkRequestCompleteTask::StoreResponse(base::OnceClosure done_closure) {
return;
}
+ int64_t response_size = 0;
+ if (service_worker_context()->is_incognito()) {
+ // The blob contains the size.
+ if (request_info_->GetBlobDataHandle())
+ response_size = request_info_->GetBlobDataHandle()->size();
+ } else {
+ // The file contains the size.
+ response_size = request_info_->GetFileSize();
+ }
+
+ // We need to check if there is enough quota before writing the response to
+ // the cache.
+ if (response_size > 0) {
+ IsQuotaAvailable(
+ registration_id_.origin(), response_size,
+ base::BindOnce(&MarkRequestCompleteTask::DidGetIsQuotaAvailable,
+ weak_factory_.GetWeakPtr(), std::move(response),
+ std::move(done_closure)));
+ } else {
+ // Assume there is enough quota.
+ DidGetIsQuotaAvailable(std::move(response), std::move(done_closure),
+ true /* is_available */);
+ }
+}
+
+void MarkRequestCompleteTask::DidGetIsQuotaAvailable(
+ blink::mojom::FetchAPIResponsePtr response,
+ base::OnceClosure done_closure,
+ bool is_available) {
+ if (!is_available) {
+ for (auto& observer : data_manager()->observers())
+ observer.OnQuotaExceeded(registration_id_);
+ FinishWithError(blink::mojom::BackgroundFetchError::QUOTA_EXCEEDED);
+ return;
+ }
+
cache_manager()->OpenCache(
registration_id_.origin(), CacheStorageOwner::kBackgroundFetch,
registration_id_.unique_id() /* cache_name */,
@@ -91,7 +128,7 @@ void MarkRequestCompleteTask::StoreResponse(base::OnceClosure done_closure) {
}
void MarkRequestCompleteTask::PopulateResponseBody(
- ServiceWorkerResponse* response) {
+ blink::mojom::FetchAPIResponse* response) {
// Include the status code, status text and the response's body as a blob
// when this is allowed by the CORS protocol.
response->status_code = request_info_->GetResponseCode();
@@ -126,27 +163,25 @@ void MarkRequestCompleteTask::PopulateResponseBody(
if (!blob_data_handle)
return;
- response->blob_uuid = blob_data_handle->uuid();
- response->blob_size = blob_data_handle->size();
- blink::mojom::BlobPtr blob_ptr;
+ response->blob = blink::mojom::SerializedBlob::New();
+ response->blob->uuid = blob_data_handle->uuid();
+ response->blob->size = blob_data_handle->size();
storage::BlobImpl::Create(
std::make_unique<storage::BlobDataHandle>(*blob_data_handle),
- MakeRequest(&blob_ptr));
-
- response->blob =
- base::MakeRefCounted<storage::BlobHandle>(std::move(blob_ptr));
+ MakeRequest(&response->blob->blob));
}
void MarkRequestCompleteTask::DidOpenCache(
- std::unique_ptr<ServiceWorkerResponse> response,
+ blink::mojom::FetchAPIResponsePtr response,
base::OnceClosure done_closure,
CacheStorageCacheHandle handle,
blink::mojom::CacheStorageError error) {
if (error != blink::mojom::CacheStorageError::kSuccess) {
- // TODO(crbug.com/780025): Log failures to UMA.
+ SetStorageError(BackgroundFetchStorageError::kCacheStorageError);
CreateAndStoreCompletedRequest(std::move(done_closure));
return;
}
+
DCHECK(handle.value());
auto request = std::make_unique<ServiceWorkerFetchRequest>(
@@ -165,7 +200,8 @@ void MarkRequestCompleteTask::DidWriteToCache(
CacheStorageCacheHandle handle,
base::OnceClosure done_closure,
blink::mojom::CacheStorageError error) {
- // TODO(crbug.com/780025): Log failures to UMA.
+ if (error != blink::mojom::CacheStorageError::kSuccess)
+ SetStorageError(BackgroundFetchStorageError::kCacheStorageError);
CreateAndStoreCompletedRequest(std::move(done_closure));
}
@@ -196,7 +232,7 @@ void MarkRequestCompleteTask::DidStoreCompletedRequest(
break;
case DatabaseStatus::kFailed:
case DatabaseStatus::kNotFound:
- // TODO(crbug.com/780025): Log failures to UMA.
+ SetStorageError(BackgroundFetchStorageError::kServiceWorkerStorageError);
std::move(done_closure).Run();
return;
}
@@ -213,7 +249,8 @@ void MarkRequestCompleteTask::DidStoreCompletedRequest(
void MarkRequestCompleteTask::DidDeleteActiveRequest(
base::OnceClosure done_closure,
blink::ServiceWorkerStatusCode status) {
- // TODO(crbug.com/780025): Log failures to UMA.
+ if (ToDatabaseStatus(status) != DatabaseStatus::kOk)
+ SetStorageError(BackgroundFetchStorageError::kServiceWorkerStorageError);
std::move(done_closure).Run();
}
@@ -235,7 +272,7 @@ void MarkRequestCompleteTask::DidGetMetadata(
blink::mojom::BackgroundFetchError error,
std::unique_ptr<proto::BackgroundFetchMetadata> metadata) {
if (!metadata || error != blink::mojom::BackgroundFetchError::NONE) {
- // TODO(crbug.com/780025): Log failures to UMA.
+ SetStorageError(BackgroundFetchStorageError::kServiceWorkerStorageError);
std::move(done_closure).Run();
return;
}
@@ -255,16 +292,22 @@ void MarkRequestCompleteTask::DidGetMetadata(
void MarkRequestCompleteTask::DidStoreMetadata(
base::OnceClosure done_closure,
blink::ServiceWorkerStatusCode status) {
- // TODO(crbug.com/780025): Log failures to UMA.
+ SetStorageError(BackgroundFetchStorageError::kServiceWorkerStorageError);
std::move(done_closure).Run();
}
void MarkRequestCompleteTask::FinishWithError(
blink::mojom::BackgroundFetchError error) {
- std::move(callback_).Run();
+ ReportStorageError();
+
+ std::move(closure_).Run();
Finished();
}
+std::string MarkRequestCompleteTask::HistogramName() const {
+ return "MarkRequestCompleteTask";
+}
+
} // namespace background_fetch
} // namespace content
diff --git a/chromium/content/browser/background_fetch/storage/mark_request_complete_task.h b/chromium/content/browser/background_fetch/storage/mark_request_complete_task.h
index 9e96d1db298..09e11561eb4 100644
--- a/chromium/content/browser/background_fetch/storage/mark_request_complete_task.h
+++ b/chromium/content/browser/background_fetch/storage/mark_request_complete_task.h
@@ -21,13 +21,11 @@ namespace background_fetch {
// download response in cache storage.
class MarkRequestCompleteTask : public DatabaseTask {
public:
- using MarkedCompleteCallback = base::OnceCallback<void()>;
-
MarkRequestCompleteTask(
DatabaseTaskHost* host,
BackgroundFetchRegistrationId registration_id,
scoped_refptr<BackgroundFetchRequestInfo> request_info,
- MarkedCompleteCallback callback);
+ base::OnceClosure closure);
~MarkRequestCompleteTask() override;
@@ -37,9 +35,13 @@ class MarkRequestCompleteTask : public DatabaseTask {
private:
void StoreResponse(base::OnceClosure done_closure);
- void PopulateResponseBody(ServiceWorkerResponse* response);
+ void PopulateResponseBody(blink::mojom::FetchAPIResponse* response);
+
+ void DidGetIsQuotaAvailable(blink::mojom::FetchAPIResponsePtr response,
+ base::OnceClosure done_closure,
+ bool is_available);
- void DidOpenCache(std::unique_ptr<ServiceWorkerResponse> response,
+ void DidOpenCache(blink::mojom::FetchAPIResponsePtr response,
base::OnceClosure done_closure,
CacheStorageCacheHandle handle,
blink::mojom::CacheStorageError error);
@@ -67,9 +69,11 @@ class MarkRequestCompleteTask : public DatabaseTask {
void FinishWithError(blink::mojom::BackgroundFetchError error) override;
+ std::string HistogramName() const override;
+
BackgroundFetchRegistrationId registration_id_;
scoped_refptr<BackgroundFetchRequestInfo> request_info_;
- MarkedCompleteCallback callback_;
+ base::OnceClosure closure_;
proto::BackgroundFetchCompletedRequest completed_request_;
bool is_response_successful_ = true;
@@ -83,4 +87,4 @@ class MarkRequestCompleteTask : public DatabaseTask {
} // namespace content
-#endif // CONTENT_BROWSER_BACKGROUND_FETCH_STORAGE_MARK_REQUEST_COMPLETE_TASK_H_ \ No newline at end of file
+#endif // CONTENT_BROWSER_BACKGROUND_FETCH_STORAGE_MARK_REQUEST_COMPLETE_TASK_H_
diff --git a/chromium/content/browser/background_fetch/storage/start_next_pending_request_task.cc b/chromium/content/browser/background_fetch/storage/start_next_pending_request_task.cc
index 1cc5c796f32..acccbe39878 100644
--- a/chromium/content/browser/background_fetch/storage/start_next_pending_request_task.cc
+++ b/chromium/content/browser/background_fetch/storage/start_next_pending_request_task.cc
@@ -15,15 +15,15 @@ namespace background_fetch {
StartNextPendingRequestTask::StartNextPendingRequestTask(
DatabaseTaskHost* host,
- int64_t service_worker_registration_id,
- std::unique_ptr<proto::BackgroundFetchMetadata> metadata,
+ const BackgroundFetchRegistrationId& registration_id,
+ const BackgroundFetchRegistration& registration,
NextRequestCallback callback)
: DatabaseTask(host),
- service_worker_registration_id_(service_worker_registration_id),
- metadata_(std::move(metadata)),
+ registration_id_(registration_id),
+ registration_(registration),
callback_(std::move(callback)),
weak_factory_(this) {
- DCHECK(metadata_);
+ DCHECK(!registration_id_.is_null());
}
StartNextPendingRequestTask::~StartNextPendingRequestTask() = default;
@@ -34,8 +34,8 @@ void StartNextPendingRequestTask::Start() {
void StartNextPendingRequestTask::GetPendingRequests() {
service_worker_context()->GetRegistrationUserDataByKeyPrefix(
- service_worker_registration_id_,
- PendingRequestKeyPrefix(metadata_->registration().unique_id()),
+ registration_id_.service_worker_registration_id(),
+ PendingRequestKeyPrefix(registration_.unique_id),
base::BindOnce(&StartNextPendingRequestTask::DidGetPendingRequests,
weak_factory_.GetWeakPtr()));
}
@@ -46,8 +46,8 @@ void StartNextPendingRequestTask::DidGetPendingRequests(
switch (ToDatabaseStatus(status)) {
case DatabaseStatus::kNotFound:
case DatabaseStatus::kFailed:
- // TODO(crbug.com/780025): Log failures to UMA.
- FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
+ SetStorageErrorAndFinish(
+ BackgroundFetchStorageError::kServiceWorkerStorageError);
return;
case DatabaseStatus::kOk:
if (data.empty()) {
@@ -59,15 +59,16 @@ void StartNextPendingRequestTask::DidGetPendingRequests(
if (!pending_request_.ParseFromString(data.front())) {
// Service Worker database has been corrupted. Abandon fetches.
- AbandonFetches(service_worker_registration_id_);
- FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
+ AbandonFetches(registration_id_.service_worker_registration_id());
+ SetStorageErrorAndFinish(
+ BackgroundFetchStorageError::kServiceWorkerStorageError);
return;
}
// Make sure there isn't already an Active Request.
// This might happen if the browser is killed in-between writes.
service_worker_context()->GetRegistrationUserData(
- service_worker_registration_id_,
+ registration_id_.service_worker_registration_id(),
{ActiveRequestKey(pending_request_.unique_id(),
pending_request_.request_index())},
base::BindOnce(&StartNextPendingRequestTask::DidFindActiveRequest,
@@ -79,7 +80,8 @@ void StartNextPendingRequestTask::DidFindActiveRequest(
blink::ServiceWorkerStatusCode status) {
switch (ToDatabaseStatus(status)) {
case DatabaseStatus::kFailed:
- FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
+ SetStorageErrorAndFinish(
+ BackgroundFetchStorageError::kServiceWorkerStorageError);
return;
case DatabaseStatus::kNotFound:
CreateAndStoreActiveRequest();
@@ -88,8 +90,9 @@ void StartNextPendingRequestTask::DidFindActiveRequest(
// We already stored the active request.
if (!active_request_.ParseFromString(data.front())) {
// Service worker database has been corrupted. Abandon fetches.
- AbandonFetches(service_worker_registration_id_);
- FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
+ AbandonFetches(registration_id_.service_worker_registration_id());
+ SetStorageErrorAndFinish(
+ BackgroundFetchStorageError::kServiceWorkerStorageError);
return;
}
StartDownload();
@@ -109,7 +112,8 @@ void StartNextPendingRequestTask::CreateAndStoreActiveRequest() {
pending_request_.release_serialized_request());
service_worker_context()->StoreRegistrationUserData(
- service_worker_registration_id_, GURL(metadata_->origin()),
+ registration_id_.service_worker_registration_id(),
+ registration_id_.origin().GetURL(),
{{ActiveRequestKey(active_request_.unique_id(),
active_request_.request_index()),
active_request_.SerializeAsString()}},
@@ -124,7 +128,8 @@ void StartNextPendingRequestTask::DidStoreActiveRequest(
break;
case DatabaseStatus::kFailed:
case DatabaseStatus::kNotFound:
- FinishWithError(blink::mojom::BackgroundFetchError::NONE);
+ SetStorageErrorAndFinish(
+ BackgroundFetchStorageError::kServiceWorkerStorageError);
return;
}
StartDownload();
@@ -143,7 +148,7 @@ void StartNextPendingRequestTask::StartDownload() {
// Delete the pending request.
service_worker_context()->ClearRegistrationUserData(
- service_worker_registration_id_,
+ registration_id_.service_worker_registration_id(),
{PendingRequestKey(pending_request_.unique_id(),
pending_request_.request_index())},
base::BindOnce(&StartNextPendingRequestTask::DidDeletePendingRequest,
@@ -152,17 +157,28 @@ void StartNextPendingRequestTask::StartDownload() {
void StartNextPendingRequestTask::DidDeletePendingRequest(
blink::ServiceWorkerStatusCode status) {
- // TODO(crbug.com/780025): Log failures to UMA.
- FinishWithError(blink::mojom::BackgroundFetchError::NONE);
+ if (ToDatabaseStatus(status) != DatabaseStatus::kOk) {
+ SetStorageErrorAndFinish(
+ BackgroundFetchStorageError::kServiceWorkerStorageError);
+ } else {
+ FinishWithError(blink::mojom::BackgroundFetchError::NONE);
+ }
}
void StartNextPendingRequestTask::FinishWithError(
blink::mojom::BackgroundFetchError error) {
+ ReportStorageError();
+
if (callback_)
std::move(callback_).Run(nullptr /* request */);
+
Finished(); // Destroys |this|.
}
+std::string StartNextPendingRequestTask::HistogramName() const {
+ return "StartNextPendingRequestTask";
+}
+
} // namespace background_fetch
} // namespace content
diff --git a/chromium/content/browser/background_fetch/storage/start_next_pending_request_task.h b/chromium/content/browser/background_fetch/storage/start_next_pending_request_task.h
index 89ae0fb1bdf..5faaeb00e5f 100644
--- a/chromium/content/browser/background_fetch/storage/start_next_pending_request_task.h
+++ b/chromium/content/browser/background_fetch/storage/start_next_pending_request_task.h
@@ -9,6 +9,7 @@
#include "content/browser/background_fetch/background_fetch.pb.h"
#include "content/browser/background_fetch/background_fetch_request_info.h"
#include "content/browser/background_fetch/storage/database_task.h"
+#include "content/common/background_fetch/background_fetch_types.h"
#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
namespace content {
@@ -24,8 +25,8 @@ class StartNextPendingRequestTask : public DatabaseTask {
StartNextPendingRequestTask(
DatabaseTaskHost* host,
- int64_t service_worker_registration_id,
- std::unique_ptr<proto::BackgroundFetchMetadata> metadata,
+ const BackgroundFetchRegistrationId& registration_id,
+ const BackgroundFetchRegistration& registration,
NextRequestCallback callback);
~StartNextPendingRequestTask() override;
@@ -52,8 +53,10 @@ class StartNextPendingRequestTask : public DatabaseTask {
void FinishWithError(blink::mojom::BackgroundFetchError error) override;
- int64_t service_worker_registration_id_;
- std::unique_ptr<proto::BackgroundFetchMetadata> metadata_;
+ std::string HistogramName() const override;
+
+ BackgroundFetchRegistrationId registration_id_;
+ BackgroundFetchRegistration registration_;
NextRequestCallback callback_;
// protos don't support move semantics, so these class members will be used
diff --git a/chromium/content/browser/background_fetch/storage/update_registration_ui_task.cc b/chromium/content/browser/background_fetch/storage/update_registration_ui_task.cc
index 38ad299080f..e86b2d2e0f9 100644
--- a/chromium/content/browser/background_fetch/storage/update_registration_ui_task.cc
+++ b/chromium/content/browser/background_fetch/storage/update_registration_ui_task.cc
@@ -7,6 +7,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/background_fetch/storage/image_helpers.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "third_party/blink/public/platform/modules/background_fetch/background_fetch.mojom.h"
@@ -17,48 +18,113 @@ namespace background_fetch {
UpdateRegistrationUITask::UpdateRegistrationUITask(
DatabaseTaskHost* host,
const BackgroundFetchRegistrationId& registration_id,
- const std::string& updated_title,
+ const base::Optional<std::string>& title,
+ const base::Optional<SkBitmap>& icon,
UpdateRegistrationUICallback callback)
: DatabaseTask(host),
registration_id_(registration_id),
- updated_title_(updated_title),
+ title_(title),
+ icon_(icon),
callback_(std::move(callback)),
- weak_factory_(this) {}
+ weak_factory_(this) {
+ DCHECK(title_ || icon_);
+}
UpdateRegistrationUITask::~UpdateRegistrationUITask() = default;
void UpdateRegistrationUITask::Start() {
+ if (title_ && icon_ && ShouldPersistIcon(*icon_)) {
+ // Directly overwrite whatever's stored in the SWDB.
+ SerializeIcon(*icon_,
+ base::BindOnce(&UpdateRegistrationUITask::DidSerializeIcon,
+ weak_factory_.GetWeakPtr()));
+ return;
+ }
+
+ service_worker_context()->GetRegistrationUserData(
+ registration_id_.service_worker_registration_id(),
+ {UIOptionsKey(registration_id_.unique_id())},
+ base::BindOnce(&UpdateRegistrationUITask::DidGetUIOptions,
+ weak_factory_.GetWeakPtr()));
+}
+
+void UpdateRegistrationUITask::DidGetUIOptions(
+ const std::vector<std::string>& data,
+ blink::ServiceWorkerStatusCode status) {
+ switch (ToDatabaseStatus(status)) {
+ case DatabaseStatus::kFailed:
+ SetStorageErrorAndFinish(
+ BackgroundFetchStorageError::kServiceWorkerStorageError);
+ return;
+ case DatabaseStatus::kNotFound:
+ case DatabaseStatus::kOk:
+ break;
+ }
+
+ if (data.empty() || !ui_options_.ParseFromString(data[0])) {
+ SetStorageErrorAndFinish(
+ BackgroundFetchStorageError::kServiceWorkerStorageError);
+ return;
+ }
+
+ if (icon_ && ShouldPersistIcon(*icon_)) {
+ ui_options_.clear_icon();
+ SerializeIcon(*icon_,
+ base::BindOnce(&UpdateRegistrationUITask::DidSerializeIcon,
+ weak_factory_.GetWeakPtr()));
+ } else {
+ StoreUIOptions();
+ }
+}
+
+void UpdateRegistrationUITask::DidSerializeIcon(std::string serialized_icon) {
+ ui_options_.set_icon(std::move(serialized_icon));
+ StoreUIOptions();
+}
+
+void UpdateRegistrationUITask::StoreUIOptions() {
+ if (title_)
+ ui_options_.set_title(*title_);
+
service_worker_context()->StoreRegistrationUserData(
registration_id_.service_worker_registration_id(),
registration_id_.origin().GetURL(),
- {{TitleKey(registration_id_.unique_id()), updated_title_}},
- base::BindOnce(&UpdateRegistrationUITask::DidUpdateTitle,
+ {{UIOptionsKey(registration_id_.unique_id()),
+ ui_options_.SerializeAsString()}},
+ base::BindOnce(&UpdateRegistrationUITask::DidUpdateUIOptions,
weak_factory_.GetWeakPtr()));
}
-void UpdateRegistrationUITask::DidUpdateTitle(
+void UpdateRegistrationUITask::DidUpdateUIOptions(
blink::ServiceWorkerStatusCode status) {
switch (ToDatabaseStatus(status)) {
case DatabaseStatus::kOk:
break;
case DatabaseStatus::kFailed:
case DatabaseStatus::kNotFound:
- FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
+ SetStorageErrorAndFinish(
+ BackgroundFetchStorageError::kServiceWorkerStorageError);
return;
}
- for (auto& observer : data_manager()->observers())
- observer.OnUpdatedUI(registration_id_, updated_title_);
-
FinishWithError(blink::mojom::BackgroundFetchError::NONE);
}
void UpdateRegistrationUITask::FinishWithError(
blink::mojom::BackgroundFetchError error) {
+ for (auto& observer : data_manager()->observers())
+ observer.OnUpdatedUI(registration_id_, title_, icon_);
+
+ ReportStorageError();
+
std::move(callback_).Run(error);
Finished(); // Destroys |this|.
}
+std::string UpdateRegistrationUITask::HistogramName() const {
+ return "UpdateRegistrationUITask";
+}
+
} // namespace background_fetch
} // namespace content
diff --git a/chromium/content/browser/background_fetch/storage/update_registration_ui_task.h b/chromium/content/browser/background_fetch/storage/update_registration_ui_task.h
index 45a0a0fe8c5..1958f7ce24a 100644
--- a/chromium/content/browser/background_fetch/storage/update_registration_ui_task.h
+++ b/chromium/content/browser/background_fetch/storage/update_registration_ui_task.h
@@ -9,6 +9,7 @@
#include <string>
#include <vector>
+#include "base/optional.h"
#include "content/browser/background_fetch/background_fetch.pb.h"
#include "content/browser/background_fetch/storage/database_task.h"
#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
@@ -25,7 +26,8 @@ class UpdateRegistrationUITask : public DatabaseTask {
UpdateRegistrationUITask(DatabaseTaskHost* host,
const BackgroundFetchRegistrationId& registration_id,
- const std::string& updated_title,
+ const base::Optional<std::string>& title,
+ const base::Optional<SkBitmap>& icon,
UpdateRegistrationUICallback callback);
~UpdateRegistrationUITask() override;
@@ -33,12 +35,24 @@ class UpdateRegistrationUITask : public DatabaseTask {
void Start() override;
private:
- void DidUpdateTitle(blink::ServiceWorkerStatusCode status);
+ void DidGetUIOptions(const std::vector<std::string>& data,
+ blink::ServiceWorkerStatusCode status);
+
+ void DidSerializeIcon(std::string serialized_icon);
+
+ void StoreUIOptions();
+
+ void DidUpdateUIOptions(blink::ServiceWorkerStatusCode status);
void FinishWithError(blink::mojom::BackgroundFetchError error) override;
+ std::string HistogramName() const override;
+
BackgroundFetchRegistrationId registration_id_;
- std::string updated_title_;
+ base::Optional<std::string> title_;
+ base::Optional<SkBitmap> icon_;
+
+ proto::BackgroundFetchUIOptions ui_options_;
UpdateRegistrationUICallback callback_;
diff --git a/chromium/content/browser/bad_message.h b/chromium/content/browser/bad_message.h
index f5e39320ca6..aff08e3c28b 100644
--- a/chromium/content/browser/bad_message.h
+++ b/chromium/content/browser/bad_message.h
@@ -230,6 +230,8 @@ enum BadMessageReason {
PERMISSION_SERVICE_BAD_PERMISSION_DESCRIPTOR = 202,
RFH_BLOB_URL_TOKEN_FOR_NON_BLOB_URL = 203,
RFPH_BLOB_URL_TOKEN_FOR_NON_BLOB_URL = 204,
+ RFH_ERROR_PROCESS_NON_ERROR_COMMIT = 205,
+ RFH_ERROR_PROCESS_NON_UNIQUE_ORIGIN_COMMIT = 206,
// 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/OWNERS b/chromium/content/browser/blob_storage/OWNERS
index 49592325cf3..6869c793a27 100644
--- a/chromium/content/browser/blob_storage/OWNERS
+++ b/chromium/content/browser/blob_storage/OWNERS
@@ -1,5 +1,9 @@
+# Primary
dmurph@chromium.org
mek@chromium.org
+# Secondary
+pwnall@chromium.org
+
# TEAM: storage-dev@chromium.org
# COMPONENT: Blink>Storage>FileAPI
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 0900dbb6898..203e9c7e94a 100644
--- a/chromium/content/browser/blob_storage/chrome_blob_storage_context.cc
+++ b/chromium/content/browser/blob_storage/chrome_blob_storage_context.cc
@@ -16,8 +16,8 @@
#include "base/metrics/histogram_macros.h"
#include "base/single_thread_task_runner.h"
#include "base/supports_user_data.h"
+#include "base/task/post_task.h"
#include "base/task_runner.h"
-#include "base/task_scheduler/post_task.h"
#include "content/browser/resource_context_impl.h"
#include "content/public/browser/blob_handle.h"
#include "content/public/browser/browser_context.h"
@@ -117,7 +117,7 @@ ChromeBlobStorageContext* ChromeBlobStorageContext::GetFor(
// disk on the storage context.
if (!context->IsOffTheRecord() && io_thread_valid) {
file_task_runner = base::CreateTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BACKGROUND,
+ {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
// Removes our old blob directories if they exist.
BrowserThread::PostAfterStartupTask(
diff --git a/chromium/content/browser/bluetooth/bluetooth_metrics.cc b/chromium/content/browser/bluetooth/bluetooth_metrics.cc
index d6368e6548d..8b68152053c 100644
--- a/chromium/content/browser/bluetooth/bluetooth_metrics.cc
+++ b/chromium/content/browser/bluetooth/bluetooth_metrics.cc
@@ -33,8 +33,7 @@ int HashUUID(const std::string& canonical_uuid) {
// should be migrated to a dedicated histogram macro for hashed strings.
uint32_t data = base::PersistentHash(canonical_uuid);
- // Strip off the sign bit because UMA doesn't support negative values,
- // but takes a signed int as input.
+ // Strip off the sign bit to make the hash look nicer.
return static_cast<int>(data & 0x7fffffff);
}
diff --git a/chromium/content/browser/browser_child_process_host_impl.cc b/chromium/content/browser/browser_child_process_host_impl.cc
index 3fc3aa2f44c..993ba401697 100644
--- a/chromium/content/browser/browser_child_process_host_impl.cc
+++ b/chromium/content/browser/browser_child_process_host_impl.cc
@@ -61,7 +61,7 @@ static base::LazyInstance<
BrowserChildProcessHostImpl::BrowserChildProcessList>::DestructorAtExit
g_child_process_list = LAZY_INSTANCE_INITIALIZER;
-base::LazyInstance<base::ObserverList<BrowserChildProcessObserver>>::
+base::LazyInstance<base::ObserverList<BrowserChildProcessObserver>::Unchecked>::
DestructorAtExit g_browser_child_process_observers =
LAZY_INSTANCE_INITIALIZER;
@@ -186,7 +186,7 @@ BrowserChildProcessHostImpl::~BrowserChildProcessHostImpl() {
if (notify_child_disconnected_) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::BindOnce(&NotifyProcessHostDisconnected, data_));
+ base::BindOnce(&NotifyProcessHostDisconnected, data_.Duplicate()));
}
}
@@ -277,6 +277,7 @@ void BrowserChildProcessHostImpl::Launch(
weak_factory_.GetWeakPtr(),
base::ThreadTaskRunnerHandle::Get()),
terminate_on_shutdown));
+ ShareMetricsAllocatorToProcess();
}
const ChildProcessData& BrowserChildProcessHostImpl::GetData() const {
@@ -316,7 +317,7 @@ void BrowserChildProcessHostImpl::SetMetricsName(
void BrowserChildProcessHostImpl::SetHandle(base::ProcessHandle handle) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- data_.handle = handle;
+ data_.SetHandle(handle);
}
service_manager::mojom::ServiceRequest
@@ -358,7 +359,8 @@ ChildProcessTerminationInfo BrowserChildProcessHostImpl::GetTerminationInfo(
if (!child_process_) {
// If the delegate doesn't use Launch() helper.
ChildProcessTerminationInfo info;
- info.status = base::GetTerminationStatus(data_.handle, &info.exit_code);
+ info.status =
+ base::GetTerminationStatus(data_.GetHandle(), &info.exit_code);
return info;
}
return child_process_->GetChildTerminationInfo(known_dead);
@@ -381,16 +383,16 @@ void BrowserChildProcessHostImpl::OnChannelConnected(int32_t peer_pid) {
early_exit_watcher_.StopWatching();
#endif
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(&NotifyProcessHostConnected, data_));
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&NotifyProcessHostConnected, data_.Duplicate()));
delegate_->OnChannelConnected(peer_pid);
if (IsProcessLaunched()) {
- ShareMetricsAllocatorToProcess();
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::BindOnce(&NotifyProcessLaunchedAndConnected, data_));
+ base::BindOnce(&NotifyProcessLaunchedAndConnected, data_.Duplicate()));
}
}
@@ -435,13 +437,14 @@ void BrowserChildProcessHostImpl::OnChildDisconnected() {
// early exit watcher so GetTerminationStatus can close the process handle.
early_exit_watcher_.StopWatching();
#endif
- if (child_process_.get() || data_.handle) {
+ if (child_process_.get() || data_.GetHandle()) {
ChildProcessTerminationInfo info =
GetTerminationInfo(true /* known_dead */);
#if defined(OS_ANDROID)
delegate_->OnProcessCrashed(info.exit_code);
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(&NotifyProcessKilled, data_, info));
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&NotifyProcessKilled, data_.Duplicate(), info));
#else // OS_ANDROID
switch (info.status) {
case base::TERMINATION_STATUS_PROCESS_CRASHED:
@@ -449,7 +452,7 @@ void BrowserChildProcessHostImpl::OnChildDisconnected() {
delegate_->OnProcessCrashed(info.exit_code);
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::BindOnce(&NotifyProcessCrashed, data_, info));
+ base::BindOnce(&NotifyProcessCrashed, data_.Duplicate(), info));
UMA_HISTOGRAM_ENUMERATION("ChildProcess.Crashed2",
static_cast<ProcessType>(data_.process_type),
PROCESS_TYPE_MAX);
@@ -462,7 +465,7 @@ void BrowserChildProcessHostImpl::OnChildDisconnected() {
delegate_->OnProcessCrashed(info.exit_code);
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::BindOnce(&NotifyProcessKilled, data_, info));
+ base::BindOnce(&NotifyProcessKilled, data_.Duplicate(), info));
// Report that this child process was killed.
UMA_HISTOGRAM_ENUMERATION("ChildProcess.Killed2",
static_cast<ProcessType>(data_.process_type),
@@ -526,7 +529,8 @@ void BrowserChildProcessHostImpl::CreateMetricsAllocator() {
break;
case PROCESS_TYPE_GPU:
- memory_size = 64 << 10; // 64 KiB
+ // This needs to be larger for the display-compositor in the gpu process.
+ memory_size = 256 << 10; // 256 KiB
metrics_name = "GpuMetrics";
break;
@@ -600,15 +604,13 @@ void BrowserChildProcessHostImpl::OnProcessLaunched() {
early_exit_watcher_.StartWatchingOnce(process.Handle(), this);
#endif
- // TODO(rvargas) crbug.com/417532: Don't store a handle.
- data_.handle = process.Handle();
+ data_.SetHandle(process.Handle());
delegate_->OnProcessLaunched();
if (is_channel_connected_) {
- ShareMetricsAllocatorToProcess();
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::BindOnce(&NotifyProcessLaunchedAndConnected, data_));
+ base::BindOnce(&NotifyProcessLaunchedAndConnected, data_.Duplicate()));
}
}
diff --git a/chromium/content/browser/browser_context.cc b/chromium/content/browser/browser_context.cc
index 199a676de55..840cafc185f 100644
--- a/chromium/content/browser/browser_context.cc
+++ b/chromium/content/browser/browser_context.cc
@@ -22,7 +22,7 @@
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/rand_util.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/unguessable_token.h"
@@ -43,7 +43,6 @@
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/site_instance.h"
-#include "content/public/browser/webrtc_event_logger.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/service_manager_connection.h"
#include "content/public/common/service_names.mojom.h"
@@ -396,12 +395,12 @@ void BrowserContext::DeliverPushMessage(
BrowserContext* browser_context,
const GURL& origin,
int64_t service_worker_registration_id,
- const PushEventPayload& payload,
+ base::Optional<std::string> payload,
const base::Callback<void(mojom::PushDeliveryStatus)>& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
PushMessagingRouter::DeliverMessage(browser_context, origin,
- service_worker_registration_id, payload,
- callback);
+ service_worker_registration_id,
+ std::move(payload), callback);
}
// static
@@ -588,13 +587,6 @@ void BrowserContext::Initialize(
RegisterCommonBrowserInterfaces(connection);
connection->Start();
}
-
- if (!browser_context->IsOffTheRecord()) {
- WebRtcEventLogger* const logger = WebRtcEventLogger::Get();
- if (logger) {
- logger->EnableForBrowserContext(browser_context, base::OnceClosure());
- }
- }
}
// static
@@ -647,11 +639,6 @@ BrowserContext::~BrowserContext() {
DCHECK(was_notify_will_be_destroyed_called_);
- WebRtcEventLogger* const logger = WebRtcEventLogger::Get();
- if (logger) {
- logger->DisableForBrowserContext(this, base::OnceClosure());
- }
-
RemoveBrowserContextFromUserIdMap(this);
if (GetUserData(kDownloadManagerKeyName))
@@ -694,4 +681,9 @@ media::VideoDecodePerfHistory* BrowserContext::GetVideoDecodePerfHistory() {
return decode_history;
}
+download::InProgressDownloadManager*
+BrowserContext::RetriveInProgressDownloadManager() {
+ return nullptr;
+}
+
} // namespace content
diff --git a/chromium/content/browser/browser_main_loop.cc b/chromium/content/browser/browser_main_loop.cc
index eb942391306..5cea69cfba0 100644
--- a/chromium/content/browser/browser_main_loop.cc
+++ b/chromium/content/browser/browser_main_loop.cc
@@ -38,7 +38,7 @@
#include "base/strings/string_split.h"
#include "base/synchronization/waitable_event.h"
#include "base/system_monitor/system_monitor.h"
-#include "base/task_scheduler/initialization_util.h"
+#include "base/task/task_scheduler/initialization_util.h"
#include "base/threading/thread.h"
#include "base/threading/thread_restrictions.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -54,6 +54,7 @@
#include "components/tracing/common/tracing_switches.h"
#include "components/viz/common/features.h"
#include "components/viz/common/switches.h"
+#include "components/viz/host/gpu_host_impl.h"
#include "components/viz/host/host_frame_sink_manager.h"
#include "components/viz/service/display_embedder/compositing_mode_reporter_impl.h"
#include "components/viz/service/display_embedder/server_shared_bitmap_manager.h"
@@ -68,7 +69,7 @@
#include "content/browser/download/download_resource_handler.h"
#include "content/browser/download/save_file_manager.h"
#include "content/browser/gpu/browser_gpu_channel_host_factory.h"
-#include "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
+#include "content/browser/gpu/browser_gpu_client_delegate.h"
#include "content/browser/gpu/compositor_util.h"
#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "content/browser/gpu/gpu_process_host.h"
@@ -83,6 +84,7 @@
#include "content/browser/net/browser_online_state_observer.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
+#include "content/browser/scheduler/responsiveness/watcher.h"
#include "content/browser/service_manager/service_manager_context.h"
#include "content/browser/speech/speech_recognition_manager_impl.h"
#include "content/browser/startup_data_impl.h"
@@ -128,6 +130,8 @@
#include "ppapi/buildflags/buildflags.h"
#include "services/audio/public/cpp/audio_system_factory.h"
#include "services/audio/public/mojom/constants.mojom.h"
+#include "services/content/public/cpp/navigable_contents_view.h"
+#include "services/network/transitional_url_loader_factory_owner.h"
#include "services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.h"
#include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
#include "services/resource_coordinator/public/mojom/service_constants.mojom.h"
@@ -153,6 +157,7 @@
#if defined(OS_ANDROID)
#include "base/android/jni_android.h"
+#include "base/trace_event/cpufreq_monitor_android.h"
#include "components/tracing/common/graphics_memory_dump_provider_android.h"
#include "content/browser/android/browser_startup_controller.h"
#include "content/browser/android/launcher_thread.h"
@@ -295,12 +300,8 @@ void OnStoppedStartupTracing(const base::FilePath& trace_file) {
VLOG(0) << "Completed startup tracing to " << trace_file.value();
}
-// Disable optimizations for this block of functions so the compiler doesn't
-// merge them all together. This makes it possible to tell what thread was
-// unresponsive by inspecting the callstack.
-MSVC_DISABLE_OPTIMIZE()
-MSVC_PUSH_DISABLE_WARNING(4748)
-
+// Tell compiler not to inline this function so it's possible to tell what
+// thread was unresponsive by inspecting the callstack.
NOINLINE void ResetThread_IO(
std::unique_ptr<BrowserProcessSubThread> io_thread) {
const int line_number = __LINE__;
@@ -308,9 +309,6 @@ NOINLINE void ResetThread_IO(
base::debug::Alias(&line_number);
}
-MSVC_POP_WARNING()
-MSVC_ENABLE_OPTIMIZE();
-
#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.
@@ -436,6 +434,9 @@ void SetFileUrlPathAliasForIpcFuzzer() {
}
#endif
+const base::Feature kBrowserResponsivenessCalculator{
+ "BrowserResponsivenessCalculator", base::FEATURE_DISABLED_BY_DEFAULT};
+
} // namespace
#if defined(USE_X11)
@@ -501,8 +502,9 @@ class HDRProxy {
auto* gpu_process_host =
GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, false);
if (gpu_process_host) {
- gpu_process_host->RequestHDRStatus(
- base::BindRepeating(&HDRProxy::GotResultOnIOThread));
+ auto* gpu_service = gpu_process_host->gpu_host()->gpu_service();
+ gpu_service->RequestHDRStatus(
+ base::BindOnce(&HDRProxy::GotResultOnIOThread));
} else {
bool hdr_enabled = false;
GotResultOnIOThread(hdr_enabled);
@@ -642,8 +644,7 @@ int BrowserMainLoop::EarlyInitialization() {
// Up the priority of the UI thread unless it was already high (since recent
// versions of Android (O+) do this automatically).
if (base::PlatformThread::GetCurrentThreadPriority() <
- base::ThreadPriority::DISPLAY ||
- base::FeatureList::IsEnabled(features::kOverrideUIThreadPriority)) {
+ base::ThreadPriority::DISPLAY) {
base::PlatformThread::SetCurrentThreadPriority(
base::ThreadPriority::DISPLAY);
}
@@ -757,7 +758,7 @@ void BrowserMainLoop::PostMainMessageLoopStart() {
BrowserThread::GetTaskRunnerForThread(BrowserThread::UI));
}
- if (features::IsAshInBrowserProcess()) {
+ if (!features::IsMultiProcessMash()) {
discardable_shared_memory_manager_ =
std::make_unique<discardable_memory::DiscardableSharedMemoryManager>();
// TODO(boliu): kSingleProcess check is a temporary workaround for
@@ -788,6 +789,9 @@ void BrowserMainLoop::PostMainMessageLoopStart() {
screen_orientation_delegate_.reset(
new ScreenOrientationDelegateAndroid());
}
+
+ base::trace_event::TraceLog::GetInstance()->AddEnabledStateObserver(
+ base::trace_event::CPUFreqMonitor::GetInstance());
#endif
if (parsed_command_line_.HasSwitch(
@@ -811,6 +815,7 @@ void BrowserMainLoop::PostMainMessageLoopStart() {
skia::SkiaMemoryDumpProvider::GetInstance(), "Skia", nullptr);
base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
sql::SqlMemoryDumpProvider::GetInstance(), "Sql", nullptr);
+ network::TransitionalURLLoaderFactoryOwner::DisallowUsageInProcess();
}
int BrowserMainLoop::PreCreateThreads() {
@@ -1118,9 +1123,8 @@ void BrowserMainLoop::ShutdownThreadsAndCleanUp() {
device_monitor_mac_.reset();
#endif
- if (BrowserGpuChannelHostFactory::instance()) {
+ if (BrowserGpuChannelHostFactory::instance())
BrowserGpuChannelHostFactory::instance()->CloseChannel();
- }
// Shutdown the Service Manager and IPC.
service_manager_context_.reset();
@@ -1207,7 +1211,7 @@ void BrowserMainLoop::GetCompositingModeReporter(
// CompositingModeReporter.
return;
#else
- if (!features::IsAshInBrowserProcess()) {
+ if (features::IsUsingWindowService()) {
// Mash == ChromeOS, which doesn't support software compositing, so no need
// to report compositing mode.
return;
@@ -1242,7 +1246,7 @@ int BrowserMainLoop::BrowserThreadsStarted() {
InitializeMojo();
#if BUILDFLAG(ENABLE_MUS)
- if (!features::IsAshInBrowserProcess()) {
+ if (features::IsUsingWindowService()) {
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableSurfaceSynchronization);
}
@@ -1273,11 +1277,11 @@ int BrowserMainLoop::BrowserThreadsStarted() {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(
- &GpuProcessHost::InitFontRenderParamsOnIO,
+ &viz::GpuHostImpl::InitFontRenderParams,
gfx::GetFontRenderParams(gfx::FontRenderParamsQuery(), nullptr)));
- // If mus is not hosting viz, then the browser must.
- bool browser_is_viz_host = features::IsAshInBrowserProcess();
+ // 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;
@@ -1326,7 +1330,9 @@ int BrowserMainLoop::BrowserThreadsStarted() {
}
#if defined(USE_AURA)
- if (browser_is_viz_host) {
+ // 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());
}
@@ -1471,6 +1477,11 @@ int BrowserMainLoop::BrowserThreadsStarted() {
SystemHotkeyHelperMac::GetInstance()->DeferredLoadSystemHotkeys();
#endif // defined(OS_MACOSX)
+ if (base::FeatureList::IsEnabled(kBrowserResponsivenessCalculator)) {
+ responsiveness_watcher_ = new responsiveness::Watcher;
+ responsiveness_watcher_->SetUp();
+ }
+
#if defined(OS_ANDROID)
media::SetMediaDrmBridgeClient(GetContentClient()->GetMediaDrmBridgeClient());
#endif
@@ -1548,9 +1559,9 @@ 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::IsAshInBrowserProcess()
- ? aura::Env::Mode::LOCAL
- : aura::Env::Mode::MUS);
+ env_ = aura::Env::CreateInstance(features::IsUsingWindowService()
+ ? aura::Env::Mode::MUS
+ : aura::Env::Mode::LOCAL);
#endif // defined(USE_AURA)
if (parts_)
@@ -1597,6 +1608,10 @@ void BrowserMainLoop::InitializeMojo() {
GetContentClient()->OnServiceManagerConnected(
ServiceManagerConnection::GetForProcess());
+ // Ensure that any NavigableContentsViews constructed in the browser process
+ // know they're running in the same process as the service.
+ content::NavigableContentsView::SetClientRunningInServiceProcess();
+
tracing_controller_ = std::make_unique<content::TracingControllerImpl>();
content::BackgroundTracingManagerImpl::GetInstance()
->AddMetadataGeneratorFunction();
diff --git a/chromium/content/browser/browser_main_loop.h b/chromium/content/browser/browser_main_loop.h
index 040f1b63136..feebf19dc5f 100644
--- a/chromium/content/browser/browser_main_loop.h
+++ b/chromium/content/browser/browser_main_loop.h
@@ -102,6 +102,10 @@ class SwapMetricsDriver;
class TracingControllerImpl;
struct MainFunctionParams;
+namespace responsiveness {
+class Watcher;
+} // namespace responsiveness
+
#if defined(OS_ANDROID)
class ScreenOrientationDelegate;
#endif
@@ -370,6 +374,7 @@ class CONTENT_EXPORT BrowserMainLoop {
discardable_shared_memory_manager_;
scoped_refptr<SaveFileManager> save_file_manager_;
std::unique_ptr<content::TracingControllerImpl> tracing_controller_;
+ scoped_refptr<responsiveness::Watcher> responsiveness_watcher_;
#if !defined(OS_ANDROID)
// A SharedBitmapManager used to sharing and mapping IDs to shared memory
// between processes for software compositing. When the display compositor is
diff --git a/chromium/content/browser/browser_main_loop_unittest.cc b/chromium/content/browser/browser_main_loop_unittest.cc
index 46955a01c56..a4bebc6547d 100644
--- a/chromium/content/browser/browser_main_loop_unittest.cc
+++ b/chromium/content/browser/browser_main_loop_unittest.cc
@@ -7,7 +7,7 @@
#include "base/command_line.h"
#include "base/message_loop/message_loop.h"
#include "base/sys_info.h"
-#include "base/task_scheduler/task_scheduler.h"
+#include "base/task/task_scheduler/task_scheduler.h"
#include "base/test/scoped_command_line.h"
#include "content/browser/browser_thread_impl.h"
#include "content/public/browser/browser_thread.h"
diff --git a/chromium/content/browser/browser_main_runner_impl.cc b/chromium/content/browser/browser_main_runner_impl.cc
index e0c7136869b..94dc07ff40b 100644
--- a/chromium/content/browser/browser_main_runner_impl.cc
+++ b/chromium/content/browser/browser_main_runner_impl.cc
@@ -75,10 +75,9 @@ int BrowserMainRunnerImpl::Initialize(const MainFunctionParams& parameters) {
const base::TimeTicks start_time_step1 = base::TimeTicks::Now();
- base::SamplingHeapProfiler::InitTLSSlot();
+ base::SamplingHeapProfiler::Init();
if (parameters.command_line.HasSwitch(switches::kSamplingHeapProfiler)) {
- base::SamplingHeapProfiler* profiler =
- base::SamplingHeapProfiler::GetInstance();
+ base::SamplingHeapProfiler* profiler = base::SamplingHeapProfiler::Get();
unsigned sampling_interval = 0;
bool parsed =
base::StringToUint(parameters.command_line.GetSwitchValueASCII(
@@ -183,7 +182,7 @@ void BrowserMainRunnerImpl::Shutdown() {
// startup tracing becomes a version of shutdown tracing).
// There are two cases:
// 1. Startup duration is not reached.
- // 2. Or startup duration is not specified for --trace-config-file flag.
+ // 2. Or if the trace should be saved to file for --trace-config-file flag.
std::unique_ptr<BrowserShutdownProfileDumper> startup_profiler;
if (tracing::TraceStartupConfig::GetInstance()
->IsTracingStartupForDuration()) {
@@ -193,7 +192,8 @@ void BrowserMainRunnerImpl::Shutdown() {
startup_profiler.reset(
new BrowserShutdownProfileDumper(main_loop_->startup_trace_file()));
}
- } else if (tracing::TraceStartupConfig::GetInstance()->IsEnabled()) {
+ } else if (tracing::TraceStartupConfig::GetInstance()
+ ->ShouldTraceToResultFile()) {
base::FilePath result_file = main_loop_->GetStartupTraceFileName();
startup_profiler.reset(new BrowserShutdownProfileDumper(result_file));
}
diff --git a/chromium/content/browser/browser_plugin/browser_plugin_guest.cc b/chromium/content/browser/browser_plugin/browser_plugin_guest.cc
index f56ce93c3d5..e5f885ab4bc 100644
--- a/chromium/content/browser/browser_plugin/browser_plugin_guest.cc
+++ b/chromium/content/browser/browser_plugin/browser_plugin_guest.cc
@@ -16,6 +16,7 @@
#include "base/pickle.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
+#include "components/viz/common/features.h"
#include "components/viz/common/surfaces/surface_info.h"
#include "components/viz/service/surfaces/surface.h"
#include "content/browser/browser_plugin/browser_plugin_embedder.h"
@@ -408,7 +409,8 @@ void BrowserPluginGuest::PointerLockPermissionResponse(bool allow) {
void BrowserPluginGuest::FirstSurfaceActivation(
const viz::SurfaceInfo& surface_info) {
- if (features::IsAshInBrowserProcess()) {
+ if (!features::IsUsingWindowService() &&
+ !features::IsSurfaceSynchronizationEnabled()) {
SendMessageToEmbedder(
std::make_unique<BrowserPluginMsg_FirstSurfaceActivation>(
browser_plugin_instance_id(), surface_info));
@@ -436,6 +438,10 @@ void BrowserPluginGuest::ResendEventToEmbedder(
ui::LatencyInfo latency_info =
ui::WebInputEventTraits::CreateLatencyInfoForWebGestureEvent(
resent_gesture_event);
+ // The touch action may not be set for the embedder because the
+ // GestureScrollBegin is sent to the guest view. In this case, set the touch
+ // action of the embedder to Auto to prevent crash.
+ GetOwnerRenderWidgetHost()->input_router()->ForceSetTouchActionAuto();
view->ProcessGestureEvent(resent_gesture_event, latency_info);
} else if (event.GetType() == blink::WebInputEvent::kMouseWheel) {
blink::WebMouseWheelEvent resent_wheel_event;
@@ -661,7 +667,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::IsAshInBrowserProcess()) {
+ if (attached() && !features::IsUsingWindowService()) {
RenderWidgetHostViewGuest* rwhv = static_cast<RenderWidgetHostViewGuest*>(
web_contents()->GetRenderWidgetHostView());
if (rwhv) {
@@ -764,11 +770,12 @@ void BrowserPluginGuest::Attach(
// change embedders before attach completes. If the embedder goes away,
// so does the guest and so we will never call WillAttachComplete because
// we have a weak ptr.
- delegate_->WillAttach(embedder_web_contents, browser_plugin_instance_id,
- params.is_full_page_plugin,
- base::Bind(&BrowserPluginGuest::OnWillAttachComplete,
- weak_ptr_factory_.GetWeakPtr(),
- embedder_web_contents, params));
+ delegate_->WillAttach(
+ embedder_web_contents, browser_plugin_instance_id,
+ params.is_full_page_plugin,
+ base::BindOnce(&BrowserPluginGuest::OnWillAttachComplete,
+ weak_ptr_factory_.GetWeakPtr(), embedder_web_contents,
+ params));
}
void BrowserPluginGuest::OnWillAttachComplete(
@@ -916,7 +923,7 @@ void BrowserPluginGuest::OnImeCommitText(
->GetWidget()
->GetWidgetInputHandler()
->ImeCommitText(text, ui_ime_text_spans, replacement_range,
- relative_cursor_pos);
+ relative_cursor_pos, base::OnceClosure());
}
void BrowserPluginGuest::OnImeFinishComposingText(
diff --git a/chromium/content/browser/browser_process_sub_thread.cc b/chromium/content/browser/browser_process_sub_thread.cc
index 876318dc799..9172012c111 100644
--- a/chromium/content/browser/browser_process_sub_thread.cc
+++ b/chromium/content/browser/browser_process_sub_thread.cc
@@ -11,7 +11,6 @@
#include "base/trace_event/memory_dump_manager.h"
#include "content/browser/browser_child_process_host_impl.h"
#include "content/browser/browser_thread_impl.h"
-#include "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
#include "content/browser/notification_service_impl.h"
#include "content/browser/utility_process_host.h"
#include "content/common/child_process_host_impl.h"
@@ -162,10 +161,8 @@ void BrowserProcessSubThread::CompleteInitializationOnBrowserThread() {
}
}
-// We disable optimizations for Run specifications so the compiler doesn't merge
-// them all together.
-MSVC_DISABLE_OPTIMIZE()
-MSVC_PUSH_DISABLE_WARNING(4748)
+// Mark following two functions as NOINLINE so the compiler doesn't merge
+// them together.
NOINLINE void BrowserProcessSubThread::UIThreadRun(base::RunLoop* run_loop) {
const int line_number = __LINE__;
@@ -179,9 +176,6 @@ NOINLINE void BrowserProcessSubThread::IOThreadRun(base::RunLoop* run_loop) {
base::debug::Alias(&line_number);
}
-MSVC_POP_WARNING()
-MSVC_ENABLE_OPTIMIZE();
-
void BrowserProcessSubThread::IOThreadCleanUp() {
DCHECK_CALLED_ON_VALID_THREAD(browser_thread_checker_);
@@ -222,10 +216,6 @@ void BrowserProcessSubThread::IOThreadCleanUp() {
// and delete the BrowserChildProcessHost instances to release whatever
// IO thread only resources they are referencing.
BrowserChildProcessHostImpl::TerminateAll();
-
- // Unregister GpuMemoryBuffer dump provider before IO thread is shut down.
- base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
- BrowserGpuMemoryBufferManager::current());
}
} // namespace content
diff --git a/chromium/content/browser/browser_side_navigation_browsertest.cc b/chromium/content/browser/browser_side_navigation_browsertest.cc
index b4cf78fea84..852370df647 100644
--- a/chromium/content/browser/browser_side_navigation_browsertest.cc
+++ b/chromium/content/browser/browser_side_navigation_browsertest.cc
@@ -422,7 +422,7 @@ IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest,
shell()->web_contents()->GetMainFrame());
// Prepare a file for the upload form.
- base::ThreadRestrictions::ScopedAllowIO allow_io_for_temp_dir;
+ base::ScopedAllowBlockingForTesting allow_blocking;
base::ScopedTempDir temp_dir;
base::FilePath file_path;
std::string file_content("test-file-content");
diff --git a/chromium/content/browser/browser_thread_browsertest.cc b/chromium/content/browser/browser_thread_browsertest.cc
new file mode 100644
index 00000000000..25bf7fcd3a6
--- /dev/null
+++ b/chromium/content/browser/browser_thread_browsertest.cc
@@ -0,0 +1,51 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/bind_helpers.h"
+#include "base/task/post_task.h"
+#include "base/test/gtest_util.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/test/content_browser_test.h"
+
+namespace content {
+
+class BrowserThreadPostTaskBeforeInitBrowserTest : public ContentBrowserTest {
+ protected:
+ void SetUp() override {
+ // This should fail because the TaskScheduler + TaskExecutor weren't created
+ // yet.
+ EXPECT_DCHECK_DEATH(base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
+ base::DoNothing()));
+
+ // Obtaining a TaskRunner should also fail.
+ EXPECT_DCHECK_DEATH(base::CreateTaskRunnerWithTraits({BrowserThread::IO}));
+
+ ContentBrowserTest::SetUp();
+ }
+};
+
+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()));
+ }
+};
+
+IN_PROC_BROWSER_TEST_F(BrowserThreadPostTaskBeforeThreadCreationBrowserTest,
+ ExpectFailures) {}
+
+} // namespace content
diff --git a/chromium/content/browser/browser_thread_impl.cc b/chromium/content/browser/browser_thread_impl.cc
index 4443c7bbc4c..d90d84982a4 100644
--- a/chromium/content/browser/browser_thread_impl.cc
+++ b/chromium/content/browser/browser_thread_impl.cc
@@ -15,9 +15,11 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/sequence_checker.h"
+#include "base/task/task_executor.h"
#include "base/threading/platform_thread.h"
#include "base/time/time.h"
#include "build/build_config.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/content_browser_client.h"
namespace content {
@@ -161,6 +163,68 @@ bool PostTaskHelper(BrowserThread::ID identifier,
}
}
+class BrowserThreadTaskExecutor : public base::TaskExecutor {
+ public:
+ BrowserThreadTaskExecutor() {}
+ ~BrowserThreadTaskExecutor() override {}
+
+ // base::TaskExecutor implementation.
+ bool PostDelayedTaskWithTraits(const base::Location& from_here,
+ const base::TaskTraits& traits,
+ base::OnceClosure task,
+ base::TimeDelta delay) override {
+ return PostTaskHelper(
+ GetBrowserThreadIdentifier(traits), from_here, std::move(task), delay,
+ traits.GetExtension<BrowserTaskTraitsExtension>().nestable());
+ }
+
+ scoped_refptr<base::TaskRunner> CreateTaskRunnerWithTraits(
+ const base::TaskTraits& traits) override {
+ return GetTaskRunnerForThread(GetBrowserThreadIdentifier(traits));
+ }
+
+ scoped_refptr<base::SequencedTaskRunner> CreateSequencedTaskRunnerWithTraits(
+ const base::TaskTraits& traits) override {
+ return GetTaskRunnerForThread(GetBrowserThreadIdentifier(traits));
+ }
+
+ scoped_refptr<base::SingleThreadTaskRunner>
+ CreateSingleThreadTaskRunnerWithTraits(
+ const base::TaskTraits& traits,
+ base::SingleThreadTaskRunnerThreadMode thread_mode) override {
+ // It's not possible to request DEDICATED access to a BrowserThread.
+ DCHECK_EQ(thread_mode, base::SingleThreadTaskRunnerThreadMode::SHARED);
+ return GetTaskRunnerForThread(GetBrowserThreadIdentifier(traits));
+ }
+
+#if defined(OS_WIN)
+ scoped_refptr<base::SingleThreadTaskRunner> CreateCOMSTATaskRunnerWithTraits(
+ const base::TaskTraits& traits,
+ base::SingleThreadTaskRunnerThreadMode thread_mode) override {
+ // Only the UI thread supports COM.
+ DCHECK_EQ(GetBrowserThreadIdentifier(traits), BrowserThread::UI);
+ return CreateSingleThreadTaskRunnerWithTraits(traits, thread_mode);
+ }
+#endif // defined(OS_WIN)
+
+ private:
+ BrowserThread::ID GetBrowserThreadIdentifier(const base::TaskTraits& traits) {
+ DCHECK_EQ(traits.extension_id(), BrowserTaskTraitsExtension::kExtensionId);
+ BrowserThread::ID id =
+ traits.GetExtension<BrowserTaskTraitsExtension>().browser_thread();
+ DCHECK_LT(id, BrowserThread::ID_COUNT);
+ return id;
+ }
+
+ scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunnerForThread(
+ BrowserThread::ID identifier) {
+ return g_task_runners.Get().proxies[identifier];
+ }
+};
+
+// |g_browser_thread_task_executor| is intentionally leaked on shutdown.
+BrowserThreadTaskExecutor* g_browser_thread_task_executor = nullptr;
+
} // namespace
BrowserThreadImpl::BrowserThreadImpl(
@@ -339,4 +403,21 @@ BrowserThread::GetTaskRunnerForThread(ID identifier) {
return g_task_runners.Get().proxies[identifier];
}
+// static
+void BrowserThreadImpl::CreateTaskExecutor() {
+ DCHECK(!g_browser_thread_task_executor);
+ g_browser_thread_task_executor = new BrowserThreadTaskExecutor();
+ base::RegisterTaskExecutor(BrowserTaskTraitsExtension::kExtensionId,
+ g_browser_thread_task_executor);
+}
+
+// static
+void BrowserThreadImpl::ResetTaskExecutorForTesting() {
+ DCHECK(g_browser_thread_task_executor);
+ base::UnregisterTaskExecutorForTesting(
+ BrowserTaskTraitsExtension::kExtensionId);
+ delete g_browser_thread_task_executor;
+ g_browser_thread_task_executor = nullptr;
+}
+
} // namespace content
diff --git a/chromium/content/browser/browser_thread_impl.h b/chromium/content/browser/browser_thread_impl.h
index cd0759c3f58..5789a29e1c5 100644
--- a/chromium/content/browser/browser_thread_impl.h
+++ b/chromium/content/browser/browser_thread_impl.h
@@ -39,6 +39,13 @@ class CONTENT_EXPORT BrowserThreadImpl : public BrowserThread {
// |identifier|.
static void ResetGlobalsForTesting(BrowserThread::ID identifier);
+ // Creates and registers a TaskExecutor that facilitates posting tasks to a
+ // BrowserThread via //base/task/post_task.h.
+ static void CreateTaskExecutor();
+
+ // Unregister and delete the TaskExecutor after a test.
+ static void ResetTaskExecutorForTesting();
+
private:
// Restrict instantiation to BrowserProcessSubThread as it performs important
// initialization that shouldn't be bypassed (except by BrowserMainLoop for
diff --git a/chromium/content/browser/browser_thread_unittest.cc b/chromium/content/browser/browser_thread_unittest.cc
index cf5b1635992..f27b5b97f7f 100644
--- a/chromium/content/browser/browser_thread_unittest.cc
+++ b/chromium/content/browser/browser_thread_unittest.cc
@@ -12,9 +12,13 @@
#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/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/public/browser/browser_task_traits.h"
#include "content/public/test/test_browser_thread.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
@@ -33,6 +37,8 @@ class BrowserThreadTest : public testing::Test {
protected:
void SetUp() override {
+ BrowserThreadImpl::CreateTaskExecutor();
+
ui_thread_ = std::make_unique<BrowserProcessSubThread>(BrowserThread::UI);
ui_thread_->Start();
@@ -51,6 +57,7 @@ class BrowserThreadTest : public testing::Test {
BrowserThreadImpl::ResetGlobalsForTesting(BrowserThread::UI);
BrowserThreadImpl::ResetGlobalsForTesting(BrowserThread::IO);
+ BrowserThreadImpl::ResetTaskExecutorForTesting();
}
// Prepares this BrowserThreadTest for Release() to be invoked. |on_release|
@@ -59,8 +66,9 @@ class BrowserThreadTest : public testing::Test {
on_release_ = std::move(on_release);
}
- static void BasicFunction(base::OnceClosure continuation) {
- EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ static void BasicFunction(base::OnceClosure continuation,
+ BrowserThread::ID target) {
+ EXPECT_TRUE(BrowserThread::CurrentlyOn(target));
std::move(continuation).Run();
}
@@ -87,7 +95,7 @@ class BrowserThreadTest : public testing::Test {
std::unique_ptr<BrowserProcessSubThread> ui_thread_;
std::unique_ptr<BrowserProcessSubThread> io_thread_;
- base::MessageLoop loop_;
+ base::test::ScopedTaskEnvironment scoped_task_environment_;
// Must be set before Release() to verify the deletion is intentional. Will be
// run from the next call to Release(). mutable so it can be consumed from
// Release().
@@ -136,7 +144,17 @@ TEST_F(BrowserThreadTest, PostTask) {
base::RunLoop run_loop;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::BindOnce(&BasicFunction, run_loop.QuitWhenIdleClosure()));
+ base::BindOnce(&BasicFunction, run_loop.QuitWhenIdleClosure(),
+ BrowserThread::IO));
+ run_loop.Run();
+}
+
+TEST_F(BrowserThreadTest, PostTaskWithTraits) {
+ base::RunLoop run_loop;
+ EXPECT_TRUE(base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO, NonNestable()},
+ base::BindOnce(&BasicFunction, run_loop.QuitWhenIdleClosure(),
+ BrowserThread::IO)));
run_loop.Run();
}
@@ -161,11 +179,53 @@ TEST_F(BrowserThreadTest, PostTaskViaTaskRunner) {
BrowserThread::GetTaskRunnerForThread(BrowserThread::IO);
base::RunLoop run_loop;
task_runner->PostTask(
- FROM_HERE,
- base::BindOnce(&BasicFunction, run_loop.QuitWhenIdleClosure()));
+ FROM_HERE, base::BindOnce(&BasicFunction, run_loop.QuitWhenIdleClosure(),
+ BrowserThread::IO));
+ run_loop.Run();
+}
+
+TEST_F(BrowserThreadTest, PostTaskViaTaskRunnerWithTraits) {
+ scoped_refptr<base::TaskRunner> task_runner =
+ base::CreateTaskRunnerWithTraits({BrowserThread::IO});
+ base::RunLoop run_loop;
+ EXPECT_TRUE(task_runner->PostTask(
+ FROM_HERE, base::BindOnce(&BasicFunction, run_loop.QuitWhenIdleClosure(),
+ BrowserThread::IO)));
+ run_loop.Run();
+}
+
+TEST_F(BrowserThreadTest, PostTaskViaSequencedTaskRunnerWithTraits) {
+ scoped_refptr<base::SequencedTaskRunner> task_runner =
+ base::CreateSequencedTaskRunnerWithTraits({BrowserThread::IO});
+ base::RunLoop run_loop;
+ EXPECT_TRUE(task_runner->PostTask(
+ FROM_HERE, base::BindOnce(&BasicFunction, run_loop.QuitWhenIdleClosure(),
+ BrowserThread::IO)));
+ run_loop.Run();
+}
+
+TEST_F(BrowserThreadTest, PostTaskViaSingleThreadTaskRunnerWithTraits) {
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner =
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO});
+ base::RunLoop run_loop;
+ EXPECT_TRUE(task_runner->PostTask(
+ FROM_HERE, base::BindOnce(&BasicFunction, run_loop.QuitWhenIdleClosure(),
+ BrowserThread::IO)));
run_loop.Run();
}
+#if defined(OS_WIN)
+TEST_F(BrowserThreadTest, PostTaskViaCOMSTATaskRunnerWithTraits) {
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner =
+ base::CreateCOMSTATaskRunnerWithTraits({BrowserThread::UI});
+ base::RunLoop run_loop;
+ EXPECT_TRUE(task_runner->PostTask(
+ FROM_HERE, base::BindOnce(&BasicFunction, run_loop.QuitWhenIdleClosure(),
+ BrowserThread::UI)));
+ run_loop.Run();
+}
+#endif // defined(OS_WIN)
+
TEST_F(BrowserThreadTest, ReleaseViaTaskRunner) {
scoped_refptr<base::SingleThreadTaskRunner> task_runner =
BrowserThread::GetTaskRunnerForThread(BrowserThread::UI);
@@ -176,6 +236,15 @@ TEST_F(BrowserThreadTest, ReleaseViaTaskRunner) {
run_loop.Run();
}
+TEST_F(BrowserThreadTest, ReleaseViaTaskRunnerWithTraits) {
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner =
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI});
+ base::RunLoop run_loop;
+ ExpectRelease(run_loop.QuitWhenIdleClosure());
+ task_runner->ReleaseSoon(FROM_HERE, this);
+ run_loop.Run();
+}
+
TEST_F(BrowserThreadTest, PostTaskAndReply) {
// Most of the heavy testing for PostTaskAndReply() is done inside the
// task runner test. This just makes sure we get piped through at all.
@@ -186,6 +255,16 @@ TEST_F(BrowserThreadTest, PostTaskAndReply) {
run_loop.Run();
}
+TEST_F(BrowserThreadTest, PostTaskAndReplyWithTraits) {
+ // Most of the heavy testing for PostTaskAndReply() is done inside the
+ // task runner test. This just makes sure we get piped through at all.
+ base::RunLoop run_loop;
+ ASSERT_TRUE(base::PostTaskWithTraitsAndReply(FROM_HERE, {BrowserThread::IO},
+ base::DoNothing(),
+ run_loop.QuitWhenIdleClosure()));
+ run_loop.Run();
+}
+
TEST_F(BrowserThreadTest, RunsTasksInCurrentSequencedDuringShutdown) {
bool did_shutdown = false;
base::RunLoop loop;
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 cba9445e35b..e569410d369 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
@@ -128,6 +128,8 @@ BrowsingDataFilterBuilderImpl::BuildGeneralFilter() const {
network::mojom::ClearDataFilterPtr
BrowsingDataFilterBuilderImpl::BuildNetworkServiceFilter() const {
+ if (IsEmptyBlacklist())
+ return nullptr;
network::mojom::ClearDataFilterPtr filter =
network::mojom::ClearDataFilter::New();
filter->type = (mode_ == Mode::WHITELIST)
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 3226847af60..5d0afd56593 100644
--- a/chromium/content/browser/browsing_data/browsing_data_remover_impl.cc
+++ b/chromium/content/browser/browsing_data/browsing_data_remover_impl.cc
@@ -227,7 +227,8 @@ void BrowsingDataRemoverImpl::RemoveInternal(
void BrowsingDataRemoverImpl::RunNextTask() {
DCHECK(!task_queue_.empty());
- const RemovalTask& removal_task = task_queue_.front();
+ RemovalTask& removal_task = task_queue_.front();
+ removal_task.task_started = base::Time::Now();
RemoveImpl(removal_task.delete_begin, removal_task.delete_end,
removal_task.remove_mask, *removal_task.filter_builder,
@@ -278,7 +279,7 @@ void BrowsingDataRemoverImpl::RemoveImpl(
//////////////////////////////////////////////////////////////////////////////
// INITIALIZATION
- base::Callback<bool(const GURL& url)> filter =
+ base::RepeatingCallback<bool(const GURL& url)> filter =
filter_builder.BuildGeneralFilter();
//////////////////////////////////////////////////////////////////////////////
@@ -303,7 +304,7 @@ void BrowsingDataRemoverImpl::RemoveImpl(
network::mojom::ClearDataFilterPtr service_filter =
filter_builder.BuildNetworkServiceFilter();
- DCHECK(service_filter->origins.empty())
+ DCHECK(!service_filter || service_filter->origins.empty())
<< "Origin-based deletion is not suitable for channel IDs.";
BrowserContext::GetDefaultStoragePartition(browser_context_)
@@ -418,23 +419,23 @@ void BrowsingDataRemoverImpl::RemoveImpl(
// TODO(msramek): Clear the cache of all renderers.
+ // TODO(crbug.com/813882): implement retry on network service.
if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
// The clearing of the HTTP cache happens in the network service process
- // when enabled.
+ // 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(),
CreatePendingTaskCompletionClosureForMojo());
+ } else {
+ storage_partition->ClearHttpAndMediaCaches(
+ delete_begin, delete_end,
+ filter_builder.IsEmptyBlacklist()
+ ? base::Callback<bool(const GURL&)>()
+ : filter,
+ CreatePendingTaskCompletionClosureForMojo());
}
- // In the network service case, the call below will only clear the media
- // cache.
- // TODO(crbug.com/813882): implement retry on network service.
- storage_partition->ClearHttpAndMediaCaches(
- delete_begin, delete_end,
- filter_builder.IsEmptyBlacklist() ? base::Callback<bool(const GURL&)>()
- : std::move(filter),
- CreatePendingTaskCompletionClosureForMojo());
-
// When clearing cache, wipe accumulated network related data
// (TransportSecurityState and HttpServerPropertiesManager data).
network_context->ClearNetworkingHistorySince(
@@ -550,9 +551,22 @@ void BrowsingDataRemoverImpl::Notify() {
// itself in the meantime.
DCHECK(!task_queue_.empty());
- if (task_queue_.front().observer != nullptr &&
- observer_list_.HasObserver(task_queue_.front().observer)) {
- task_queue_.front().observer->OnBrowsingDataRemoverDone();
+ const RemovalTask& task = task_queue_.front();
+ if (task.observer != nullptr && observer_list_.HasObserver(task.observer)) {
+ task.observer->OnBrowsingDataRemoverDone();
+ }
+ if (task.filter_builder->GetMode() == BrowsingDataFilterBuilder::BLACKLIST) {
+ base::TimeDelta delta = base::Time::Now() - task.task_started;
+ // Full and partial deletions are often implemented differently, so
+ // we track them in seperate metrics.
+ if (task.delete_begin.is_null() && task.delete_end.is_max() &&
+ task.filter_builder->IsEmptyBlacklist()) {
+ UMA_HISTOGRAM_MEDIUM_TIMES(
+ "History.ClearBrowsingData.Duration.FullDeletion", delta);
+ } else {
+ UMA_HISTOGRAM_MEDIUM_TIMES(
+ "History.ClearBrowsingData.Duration.PartialDeletion", delta);
+ }
}
task_queue_.pop();
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 1b02d6fc28e..4d4f3c9d485 100644
--- a/chromium/content/browser/browsing_data/browsing_data_remover_impl.h
+++ b/chromium/content/browser/browsing_data/browsing_data_remover_impl.h
@@ -116,6 +116,7 @@ class CONTENT_EXPORT BrowsingDataRemoverImpl
int origin_type_mask;
std::unique_ptr<BrowsingDataFilterBuilder> filter_builder;
Observer* observer;
+ base::Time task_started;
};
// Setter for |is_removing_|; DCHECKs that we can only start removing if we're
@@ -194,7 +195,7 @@ class CONTENT_EXPORT BrowsingDataRemoverImpl
int num_pending_tasks_ = 0;
// Observers of the global state and individual tasks.
- base::ObserverList<Observer, true> observer_list_;
+ base::ObserverList<Observer, true>::Unchecked observer_list_;
// We do not own this.
StoragePartition* storage_partition_for_testing_;
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 2f95096b273..a82100fd443 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
@@ -321,7 +321,7 @@ class RemoveChannelIDTester : public net::SSLConfigService::Observer {
}
void GetChannelIDList(net::ChannelIDStore::ChannelIDList* channel_ids) {
- GetChannelIDStore()->GetAllChannelIDs(base::Bind(
+ GetChannelIDStore()->GetAllChannelIDs(base::BindOnce(
&RemoveChannelIDTester::GetAllChannelIDsCallback, channel_ids));
}
diff --git a/chromium/content/browser/browsing_data/clear_site_data_handler.cc b/chromium/content/browser/browsing_data/clear_site_data_handler.cc
new file mode 100644
index 00000000000..fc99ea9a22b
--- /dev/null
+++ b/chromium/content/browser/browsing_data/clear_site_data_handler.cc
@@ -0,0 +1,449 @@
+// 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/browsing_data/clear_site_data_handler.h"
+
+#include "base/command_line.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/scoped_observer.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browsing_data_filter_builder.h"
+#include "content/public/browser/browsing_data_remover.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/common/origin_util.h"
+#include "net/base/load_flags.h"
+#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
+#include "net/http/http_response_headers.h"
+
+namespace content {
+
+namespace {
+
+// Datatypes.
+const char kDatatypeWildcard[] = "\"*\"";
+const char kDatatypeCookies[] = "\"cookies\"";
+const char kDatatypeStorage[] = "\"storage\"";
+const char kDatatypeCache[] = "\"cache\"";
+
+// Pretty-printed log output.
+const char kConsoleMessageTemplate[] = "Clear-Site-Data header on '%s': %s";
+const char kConsoleMessageCleared[] = "Cleared data types: %s.";
+const char kConsoleMessageDatatypeSeparator[] = ", ";
+
+bool AreExperimentalFeaturesEnabled() {
+ return base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableExperimentalWebPlatformFeatures);
+}
+
+// Represents the parameters as a single number to be recorded in a histogram.
+int ParametersMask(bool clear_cookies, bool clear_storage, bool clear_cache) {
+ return static_cast<int>(clear_cookies) * (1 << 0) +
+ static_cast<int>(clear_storage) * (1 << 1) +
+ static_cast<int>(clear_cache) * (1 << 2);
+}
+
+// Helper class to find the BrowserContext associated with the request and
+// requests the actual clearing of data for |origin|. The data types to be
+// deleted are determined by |clear_cookies|, |clear_storage|, and
+// |clear_cache|. |web_contents_getter| identifies the WebContents from which
+// the request originated.
+// TODO(crbug.com/876931): |SiteDataClearer| could be merged into
+// |ClearSiteDataHandler| to make things cleaner.
+class SiteDataClearer : public BrowsingDataRemover::Observer {
+ public:
+ static void Run(
+ const base::RepeatingCallback<WebContents*()>& web_contents_getter,
+ const url::Origin& origin,
+ bool clear_cookies,
+ bool clear_storage,
+ bool clear_cache,
+ base::OnceClosure callback) {
+ WebContents* web_contents = web_contents_getter.Run();
+ if (!web_contents)
+ return;
+
+ (new SiteDataClearer(web_contents, origin, clear_cookies, clear_storage,
+ clear_cache, std::move(callback)))
+ ->RunAndDestroySelfWhenDone();
+ }
+
+ private:
+ SiteDataClearer(const WebContents* web_contents,
+ const url::Origin& origin,
+ bool clear_cookies,
+ bool clear_storage,
+ bool clear_cache,
+ base::OnceClosure callback)
+ : origin_(origin),
+ clear_cookies_(clear_cookies),
+ clear_storage_(clear_storage),
+ clear_cache_(clear_cache),
+ callback_(std::move(callback)),
+ pending_task_count_(0),
+ remover_(nullptr),
+ scoped_observer_(this) {
+ remover_ = BrowserContext::GetBrowsingDataRemover(
+ web_contents->GetBrowserContext());
+ DCHECK(remover_);
+ scoped_observer_.Add(remover_);
+ }
+
+ ~SiteDataClearer() override {}
+
+ void RunAndDestroySelfWhenDone() {
+ // Cookies and channel IDs are scoped to
+ // a) eTLD+1 of |origin|'s host if |origin|'s host is a registrable domain
+ // or a subdomain thereof
+ // b) |origin|'s host exactly if it is an IP address or an internal hostname
+ // (e.g. "localhost" or "fileserver").
+ // TODO(msramek): What about plugin data?
+ if (clear_cookies_) {
+ std::string domain = GetDomainAndRegistry(
+ origin_.host(),
+ net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
+
+ if (domain.empty())
+ domain = origin_.host(); // IP address or internal hostname.
+
+ std::unique_ptr<BrowsingDataFilterBuilder> domain_filter_builder(
+ BrowsingDataFilterBuilder::Create(
+ BrowsingDataFilterBuilder::WHITELIST));
+ domain_filter_builder->AddRegisterableDomain(domain);
+
+ pending_task_count_++;
+ remover_->RemoveWithFilterAndReply(
+ base::Time(), base::Time::Max(),
+ BrowsingDataRemover::DATA_TYPE_COOKIES |
+ BrowsingDataRemover::DATA_TYPE_CHANNEL_IDS |
+ BrowsingDataRemover::DATA_TYPE_AVOID_CLOSING_CONNECTIONS,
+ BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB |
+ BrowsingDataRemover::ORIGIN_TYPE_PROTECTED_WEB,
+ std::move(domain_filter_builder), this);
+ }
+
+ // Delete origin-scoped data.
+ int remove_mask = 0;
+ if (clear_storage_)
+ remove_mask |= BrowsingDataRemover::DATA_TYPE_DOM_STORAGE;
+ if (clear_cache_)
+ remove_mask |= BrowsingDataRemover::DATA_TYPE_CACHE;
+
+ if (remove_mask) {
+ std::unique_ptr<BrowsingDataFilterBuilder> origin_filter_builder(
+ BrowsingDataFilterBuilder::Create(
+ BrowsingDataFilterBuilder::WHITELIST));
+ origin_filter_builder->AddOrigin(origin_);
+
+ pending_task_count_++;
+ remover_->RemoveWithFilterAndReply(
+ base::Time(), base::Time::Max(), remove_mask,
+ BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB |
+ BrowsingDataRemover::ORIGIN_TYPE_PROTECTED_WEB,
+ std::move(origin_filter_builder), this);
+ }
+
+ DCHECK_GT(pending_task_count_, 0);
+ }
+
+ // BrowsingDataRemover::Observer:
+ void OnBrowsingDataRemoverDone() override {
+ DCHECK(pending_task_count_);
+ if (--pending_task_count_)
+ return;
+
+ std::move(callback_).Run();
+ delete this;
+ }
+
+ url::Origin origin_;
+ bool clear_cookies_;
+ bool clear_storage_;
+ bool clear_cache_;
+ base::OnceClosure callback_;
+ int pending_task_count_;
+ BrowsingDataRemover* remover_;
+ ScopedObserver<BrowsingDataRemover, BrowsingDataRemover::Observer>
+ scoped_observer_;
+};
+
+// Outputs a single |formatted_message| on the UI thread.
+void OutputFormattedMessage(WebContents* web_contents,
+ ConsoleMessageLevel level,
+ const std::string& formatted_text) {
+ if (web_contents)
+ web_contents->GetMainFrame()->AddMessageToConsole(level, formatted_text);
+}
+
+} // namespace
+
+////////////////////////////////////////////////////////////////////////////////
+// ConsoleMessagesDelegate
+
+ClearSiteDataHandler::ConsoleMessagesDelegate::ConsoleMessagesDelegate()
+ : output_formatted_message_function_(
+ base::BindRepeating(&OutputFormattedMessage)) {}
+
+ClearSiteDataHandler::ConsoleMessagesDelegate::~ConsoleMessagesDelegate() {}
+
+void ClearSiteDataHandler::ConsoleMessagesDelegate::AddMessage(
+ const GURL& url,
+ const std::string& text,
+ ConsoleMessageLevel level) {
+ messages_.push_back({url, text, level});
+}
+
+void ClearSiteDataHandler::ConsoleMessagesDelegate::OutputMessages(
+ const base::RepeatingCallback<WebContents*()>& web_contents_getter) {
+ if (messages_.empty())
+ return;
+
+ WebContents* web_contents = web_contents_getter.Run();
+
+ for (const auto& message : messages_) {
+ // Prefix each message with |kConsoleMessageTemplate|.
+ output_formatted_message_function_.Run(
+ web_contents, message.level,
+ base::StringPrintf(kConsoleMessageTemplate, message.url.spec().c_str(),
+ message.text.c_str()));
+ }
+
+ messages_.clear();
+}
+
+void ClearSiteDataHandler::ConsoleMessagesDelegate::
+ SetOutputFormattedMessageFunctionForTesting(
+ const OutputFormattedMessageFunction& function) {
+ output_formatted_message_function_ = function;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// ClearSiteDataHandler
+
+// static
+void ClearSiteDataHandler::HandleHeader(
+ base::RepeatingCallback<WebContents*()> web_contents_getter,
+ const GURL& url,
+ const std::string& header_value,
+ int load_flags,
+ base::OnceClosure callback) {
+ ClearSiteDataHandler handler(std::move(web_contents_getter), url,
+ header_value, load_flags, std::move(callback),
+ std::make_unique<ConsoleMessagesDelegate>());
+ handler.HandleHeaderAndOutputConsoleMessages();
+}
+
+// static
+bool ClearSiteDataHandler::ParseHeaderForTesting(
+ const std::string& header,
+ bool* clear_cookies,
+ bool* clear_storage,
+ bool* clear_cache,
+ ConsoleMessagesDelegate* delegate,
+ const GURL& current_url) {
+ return ClearSiteDataHandler::ParseHeader(header, clear_cookies, clear_storage,
+ clear_cache, delegate, current_url);
+}
+
+ClearSiteDataHandler::ClearSiteDataHandler(
+ base::RepeatingCallback<WebContents*()> web_contents_getter,
+ const GURL& url,
+ const std::string& header_value,
+ int load_flags,
+ base::OnceClosure callback,
+ std::unique_ptr<ConsoleMessagesDelegate> delegate)
+ : web_contents_getter_(std::move(web_contents_getter)),
+ url_(url),
+ header_value_(header_value),
+ load_flags_(load_flags),
+ callback_(std::move(callback)),
+ delegate_(std::move(delegate)) {
+ DCHECK(web_contents_getter_);
+ DCHECK(delegate_);
+}
+
+ClearSiteDataHandler::~ClearSiteDataHandler() = default;
+
+bool ClearSiteDataHandler::HandleHeaderAndOutputConsoleMessages() {
+ bool deferred = Run();
+
+ // If the redirect is deferred, wait until it is resumed.
+ // TODO(crbug.com/876931): Delay output until next frame for navigations.
+ if (!deferred) {
+ OutputConsoleMessages();
+ RunCallbackNotDeferred();
+ }
+
+ return deferred;
+}
+
+bool ClearSiteDataHandler::Run() {
+ // Only accept the header on secure non-unique origins.
+ if (!IsOriginSecure(url_)) {
+ delegate_->AddMessage(url_, "Not supported for insecure origins.",
+ CONSOLE_MESSAGE_LEVEL_ERROR);
+ return false;
+ }
+
+ url::Origin origin = url::Origin::Create(url_);
+ if (origin.unique()) {
+ delegate_->AddMessage(url_, "Not supported for unique origins.",
+ CONSOLE_MESSAGE_LEVEL_ERROR);
+ return false;
+ }
+
+ // The LOAD_DO_NOT_SAVE_COOKIES flag prohibits the request from doing any
+ // modification to cookies. Clear-Site-Data applies this restriction to other
+ // data types as well.
+ // TODO(msramek): Consider showing a blocked icon via
+ // TabSpecificContentSettings and reporting the action in the "Blocked"
+ // section of the cookies dialog in OIB.
+ if (load_flags_ & net::LOAD_DO_NOT_SAVE_COOKIES) {
+ delegate_->AddMessage(
+ url_,
+ "The request's credentials mode prohibits modifying cookies "
+ "and other local data.",
+ CONSOLE_MESSAGE_LEVEL_ERROR);
+ return false;
+ }
+
+ bool clear_cookies;
+ bool clear_storage;
+ bool clear_cache;
+
+ if (!ClearSiteDataHandler::ParseHeader(header_value_, &clear_cookies,
+ &clear_storage, &clear_cache,
+ delegate_.get(), url_)) {
+ return false;
+ }
+
+ // Record the call parameters.
+ UMA_HISTOGRAM_ENUMERATION(
+ "Navigation.ClearSiteData.Parameters",
+ ParametersMask(clear_cookies, clear_storage, clear_cache), (1 << 3));
+
+ ExecuteClearingTask(
+ origin, clear_cookies, clear_storage, clear_cache,
+ base::BindOnce(&ClearSiteDataHandler::TaskFinished,
+ base::TimeTicks::Now(), std::move(delegate_),
+ web_contents_getter_, std::move(callback_)));
+
+ return true;
+}
+
+// static
+bool ClearSiteDataHandler::ParseHeader(const std::string& header,
+ bool* clear_cookies,
+ bool* clear_storage,
+ bool* clear_cache,
+ ConsoleMessagesDelegate* delegate,
+ const GURL& current_url) {
+ if (!base::IsStringASCII(header)) {
+ delegate->AddMessage(current_url, "Must only contain ASCII characters.",
+ CONSOLE_MESSAGE_LEVEL_ERROR);
+ return false;
+ }
+
+ *clear_cookies = false;
+ *clear_storage = false;
+ *clear_cache = false;
+
+ std::vector<std::string> input_types = base::SplitString(
+ header, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+ std::string output_types;
+
+ for (unsigned i = 0; i < input_types.size(); i++) {
+ bool* data_type = nullptr;
+
+ if (AreExperimentalFeaturesEnabled() &&
+ input_types[i] == kDatatypeWildcard) {
+ input_types.push_back(kDatatypeCookies);
+ input_types.push_back(kDatatypeStorage);
+ input_types.push_back(kDatatypeCache);
+ continue;
+ } else if (input_types[i] == kDatatypeCookies) {
+ data_type = clear_cookies;
+ } else if (input_types[i] == kDatatypeStorage) {
+ data_type = clear_storage;
+ } else if (input_types[i] == kDatatypeCache) {
+ data_type = clear_cache;
+ } else {
+ delegate->AddMessage(
+ current_url,
+ base::StringPrintf("Unrecognized type: %s.", input_types[i].c_str()),
+ CONSOLE_MESSAGE_LEVEL_ERROR);
+ continue;
+ }
+
+ DCHECK(data_type);
+
+ if (*data_type)
+ continue;
+
+ *data_type = true;
+ if (!output_types.empty())
+ output_types += kConsoleMessageDatatypeSeparator;
+ output_types += input_types[i];
+ }
+
+ if (!*clear_cookies && !*clear_storage && !*clear_cache) {
+ delegate->AddMessage(current_url, "No recognized types specified.",
+ CONSOLE_MESSAGE_LEVEL_ERROR);
+ return false;
+ }
+
+ // Pretty-print which types are to be cleared.
+ // TODO(crbug.com/798760): Remove the disclaimer about cookies.
+ std::string console_output =
+ base::StringPrintf(kConsoleMessageCleared, output_types.c_str());
+ if (*clear_cookies) {
+ console_output +=
+ " Clearing channel IDs and HTTP authentication cache is currently not"
+ " supported, as it breaks active network connections.";
+ }
+ delegate->AddMessage(current_url, console_output, CONSOLE_MESSAGE_LEVEL_INFO);
+
+ return true;
+}
+
+void ClearSiteDataHandler::ExecuteClearingTask(const url::Origin& origin,
+ bool clear_cookies,
+ bool clear_storage,
+ bool clear_cache,
+ base::OnceClosure callback) {
+ SiteDataClearer::Run(web_contents_getter_, origin, clear_cookies,
+ clear_storage, clear_cache, std::move(callback));
+}
+
+// static
+void ClearSiteDataHandler::TaskFinished(
+ base::TimeTicks clearing_started,
+ std::unique_ptr<ConsoleMessagesDelegate> delegate,
+ base::RepeatingCallback<WebContents*()> web_contents_getter,
+ base::OnceClosure callback) {
+ DCHECK(!clearing_started.is_null());
+
+ UMA_HISTOGRAM_CUSTOM_TIMES("Navigation.ClearSiteData.Duration",
+ base::TimeTicks::Now() - clearing_started,
+ base::TimeDelta::FromMilliseconds(1),
+ base::TimeDelta::FromSeconds(1), 50);
+
+ // TODO(crbug.com/876931): Delay output until next frame for navigations.
+ delegate->OutputMessages(web_contents_getter);
+
+ std::move(callback).Run();
+}
+
+void ClearSiteDataHandler::OutputConsoleMessages() {
+ delegate_->OutputMessages(web_contents_getter_);
+}
+
+void ClearSiteDataHandler::RunCallbackNotDeferred() {
+ std::move(callback_).Run();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/browsing_data/clear_site_data_handler.h b/chromium/content/browser/browsing_data/clear_site_data_handler.h
new file mode 100644
index 00000000000..2a509de4d4c
--- /dev/null
+++ b/chromium/content/browser/browsing_data/clear_site_data_handler.h
@@ -0,0 +1,162 @@
+// 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_BROWSING_DATA_CLEAR_SITE_DATA_HANDLER_H_
+#define CONTENT_BROWSER_BROWSING_DATA_CLEAR_SITE_DATA_HANDLER_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/time/time.h"
+#include "content/common/content_export.h"
+#include "content/public/common/console_message_level.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+namespace content {
+
+class WebContents;
+
+// This handler parses the Clear-Site-Data header and executes the clearing
+// of browsing data. The resource load is delayed until the header is parsed
+// and, if valid, until the browsing data are deleted. See the W3C working draft
+// at https://w3c.github.io/webappsec-clear-site-data/.
+class CONTENT_EXPORT ClearSiteDataHandler {
+ public:
+ // Stores and outputs console messages.
+ class CONTENT_EXPORT ConsoleMessagesDelegate {
+ public:
+ struct Message {
+ GURL url;
+ std::string text;
+ ConsoleMessageLevel level;
+ };
+
+ using OutputFormattedMessageFunction = base::RepeatingCallback<
+ void(WebContents*, ConsoleMessageLevel, const std::string&)>;
+
+ ConsoleMessagesDelegate();
+ virtual ~ConsoleMessagesDelegate();
+
+ // Logs a |text| message from |url| with |level|.
+ virtual void AddMessage(const GURL& url,
+ const std::string& text,
+ ConsoleMessageLevel level);
+
+ // Outputs stored messages to the console of WebContents identified by
+ // |web_contents_getter|.
+ virtual void OutputMessages(
+ const base::RepeatingCallback<WebContents*()>& web_contents_getter);
+
+ const std::vector<Message>& messages() const { return messages_; }
+
+ protected:
+ void SetOutputFormattedMessageFunctionForTesting(
+ const OutputFormattedMessageFunction& function);
+
+ private:
+ std::vector<Message> messages_;
+ OutputFormattedMessageFunction output_formatted_message_function_;
+ };
+
+ // |header_value| is the string value of the 'Clear-Site-Data' header. This
+ // method calls ParseHeader() to parse it, and then ExecuteClearingTask() if
+ // applicable.
+ static void HandleHeader(
+ base::RepeatingCallback<WebContents*()> web_contents_getter,
+ const GURL& url,
+ const std::string& header_value,
+ int load_flags,
+ base::OnceClosure callback);
+
+ // Exposes ParseHeader() publicly for testing.
+ static bool ParseHeaderForTesting(const std::string& header,
+ bool* clear_cookies,
+ bool* clear_storage,
+ bool* clear_cache,
+ ConsoleMessagesDelegate* delegate,
+ const GURL& current_url);
+
+ protected:
+ ClearSiteDataHandler(
+ base::RepeatingCallback<WebContents*()> web_contents_getter,
+ const GURL& url,
+ const std::string& header_value,
+ int load_flags,
+ base::OnceClosure callback,
+ std::unique_ptr<ConsoleMessagesDelegate> delegate);
+ virtual ~ClearSiteDataHandler();
+
+ // Calls |HandleHeaderImpl| to handle headers, and output console message if
+ // not deferred. Returns |true| if the request was deferred.
+ bool HandleHeaderAndOutputConsoleMessages();
+
+ // Handles headers and maybe execute clearing task. Returns |true| if the
+ // request was deferred.
+ bool Run();
+
+ // Parses the value of the 'Clear-Site-Data' header and outputs whether
+ // the header requests to |clear_cookies|, |clear_storage|, and |clear_cache|.
+ // The |delegate| will be filled with messages to be output in the console,
+ // prepended by the |current_url|. Returns true if parsing was successful.
+ static bool ParseHeader(const std::string& header,
+ bool* clear_cookies,
+ bool* clear_storage,
+ bool* clear_cache,
+ ConsoleMessagesDelegate* delegate,
+ const GURL& current_url);
+
+ // Executes the clearing task. Can be overridden for testing.
+ virtual void ExecuteClearingTask(const url::Origin& origin,
+ bool clear_cookies,
+ bool clear_storage,
+ bool clear_cache,
+ base::OnceClosure callback);
+
+ // Signals that a parsing and deletion task was finished.
+ // |clearing_started| is the time when the last clearing operation started.
+ // Used when clearing finishes to compute the duration.
+ static void TaskFinished(
+ base::TimeTicks clearing_started,
+ std::unique_ptr<ConsoleMessagesDelegate> delegate,
+ base::RepeatingCallback<WebContents*()> web_contents_getter,
+ base::OnceClosure callback);
+
+ // Outputs the console messages in the |delegate_|.
+ void OutputConsoleMessages();
+
+ // Run the callback to resume loading. No clearing actions were conducted.
+ void RunCallbackNotDeferred();
+
+ const GURL& GetURLForTesting();
+
+ private:
+ // Required to clear the data.
+ base::RepeatingCallback<WebContents*()> web_contents_getter_;
+
+ // Target URL whose data will be cleared.
+ GURL url_;
+
+ // Raw string value of the 'Clear-Site-Data' header.
+ std::string header_value_;
+
+ // Load flags of the current request, used to check cookie policies.
+ int load_flags_;
+
+ // Used to notify that the clearing has completed. Callers could resuming
+ // loading after this point.
+ base::OnceClosure callback_;
+
+ // The delegate that stores and outputs console messages.
+ std::unique_ptr<ConsoleMessagesDelegate> delegate_;
+
+ DISALLOW_COPY_AND_ASSIGN(ClearSiteDataHandler);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_BROWSING_DATA_CLEAR_SITE_DATA_HANDLER_H_
diff --git a/chromium/content/browser/browsing_data/clear_site_data_throttle_browsertest.cc b/chromium/content/browser/browsing_data/clear_site_data_handler_browsertest.cc
index 8fba2e45093..0bf7f3c6adc 100644
--- a/chromium/content/browser/browsing_data/clear_site_data_throttle_browsertest.cc
+++ b/chromium/content/browser/browsing_data/clear_site_data_handler_browsertest.cc
@@ -2,8 +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/browsing_data/clear_site_data_throttle.h"
-
+#include <algorithm>
#include <memory>
#include "base/bind.h"
@@ -24,6 +23,9 @@
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/common/service_manager_connection.h"
+#include "content/public/common/service_names.mojom.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/cache_test_util.h"
#include "content/public/test/content_browser_test.h"
@@ -32,6 +34,7 @@
#include "content/public/test/test_navigation_observer.h"
#include "content/shell/browser/shell.h"
#include "net/base/escape.h"
+#include "net/base/net_errors.h"
#include "net/base/url_util.h"
#include "net/cookies/cookie_store.h"
#include "net/dns/mock_host_resolver.h"
@@ -39,6 +42,9 @@
#include "net/test/embedded_test_server/http_response.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
+#include "services/network/public/cpp/features.h"
+#include "services/network/public/mojom/network_service_test.mojom.h"
+#include "services/service_manager/public/cpp/connector.h"
#include "storage/browser/quota/quota_settings.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "url/origin.h"
@@ -137,6 +143,7 @@ class ServiceWorkerActivationObserver
// ServiceWorkerContextCoreObserver overrides.
void OnVersionStateChanged(int64_t version_id,
+ const GURL& scope,
ServiceWorkerVersion::Status) override {
if (context_->GetLiveVersion(version_id)->status() ==
ServiceWorkerVersion::ACTIVATED) {
@@ -153,14 +160,22 @@ class ServiceWorkerActivationObserver
} // namespace
-class ClearSiteDataThrottleBrowserTest : public ContentBrowserTest {
+class ClearSiteDataHandlerBrowserTest : public ContentBrowserTest {
public:
void SetUpCommandLine(base::CommandLine* command_line) override {
ContentBrowserTest::SetUpCommandLine(command_line);
- // We're redirecting all hosts to localhost even on HTTPS, so we'll get
- // certificate errors.
- command_line->AppendSwitch(switches::kIgnoreCertificateErrors);
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService))
+ is_network_service_enabled_ = true;
+
+ if (is_network_service_enabled_) {
+ // |MockCertVerifier| only seems to work when Network Service was enabled.
+ command_line->AppendSwitch(switches::kUseMockCertVerifierForTesting);
+ } else {
+ // We're redirecting all hosts to localhost even on HTTPS, so we'll get
+ // certificate errors.
+ command_line->AppendSwitch(switches::kIgnoreCertificateErrors);
+ }
}
void SetUpOnMainThread() override {
@@ -172,17 +187,21 @@ class ClearSiteDataThrottleBrowserTest : public ContentBrowserTest {
// Set up HTTP and HTTPS test servers that handle all hosts.
host_resolver()->AddRule("*", "127.0.0.1");
+ if (is_network_service_enabled_)
+ SetUpMockCertVerifier(net::OK);
+
embedded_test_server()->RegisterRequestHandler(
- base::Bind(&ClearSiteDataThrottleBrowserTest::HandleRequest,
- base::Unretained(this)));
+ base::BindRepeating(&ClearSiteDataHandlerBrowserTest::HandleRequest,
+ base::Unretained(this)));
ASSERT_TRUE(embedded_test_server()->Start());
+ // Set up HTTPS server.
https_server_.reset(new net::EmbeddedTestServer(
net::test_server::EmbeddedTestServer::TYPE_HTTPS));
https_server_->SetSSLConfig(net::EmbeddedTestServer::CERT_OK);
https_server_->RegisterRequestHandler(
- base::Bind(&ClearSiteDataThrottleBrowserTest::HandleRequest,
- base::Unretained(this)));
+ base::BindRepeating(&ClearSiteDataHandlerBrowserTest::HandleRequest,
+ base::Unretained(this)));
ASSERT_TRUE(https_server_->Start());
// Initialize the cookie store pointer on the IO thread.
@@ -190,11 +209,9 @@ class ClearSiteDataThrottleBrowserTest : public ContentBrowserTest {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(
- &ClearSiteDataThrottleBrowserTest::InitializeCookieStore,
+ &ClearSiteDataHandlerBrowserTest::InitializeCookieStore,
base::Unretained(this),
- base::Unretained(
- BrowserContext::GetDefaultStoragePartition(browser_context())
- ->GetURLRequestContext()),
+ base::Unretained(storage_partition()->GetURLRequestContext()),
run_loop.QuitClosure()));
run_loop.Run();
}
@@ -203,6 +220,10 @@ class ClearSiteDataThrottleBrowserTest : public ContentBrowserTest {
return shell()->web_contents()->GetBrowserContext();
}
+ StoragePartition* storage_partition() {
+ return BrowserContext::GetDefaultStoragePartition(browser_context());
+ }
+
void InitializeCookieStore(
net::URLRequestContextGetter* request_context_getter,
base::Closure callback) {
@@ -214,30 +235,30 @@ class ClearSiteDataThrottleBrowserTest : public ContentBrowserTest {
// Adds a cookie for the |url|. Used in the cookie integration tests.
void AddCookie(const GURL& url) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ network::mojom::CookieManager* cookie_manager =
+ storage_partition()->GetCookieManagerForBrowserProcess();
+
+ std::unique_ptr<net::CanonicalCookie> cookie(net::CanonicalCookie::Create(
+ url, "A=1", base::Time::Now(), net::CookieOptions()));
+
base::RunLoop run_loop;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(
- &net::CookieStore::SetCookieWithOptionsAsync,
- base::Unretained(cookie_store_), url, "A=1", net::CookieOptions(),
- base::Bind(&ClearSiteDataThrottleBrowserTest::AddCookieCallback,
- run_loop.QuitClosure())));
+ cookie_manager->SetCanonicalCookie(
+ *cookie, true /* secure_source */, false /* modify_http_only */,
+ base::BindOnce(&ClearSiteDataHandlerBrowserTest::AddCookieCallback,
+ run_loop.QuitClosure()));
run_loop.Run();
}
// Retrieves the list of all cookies. Used in the cookie integration tests.
net::CookieList GetCookies() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ network::mojom::CookieManager* cookie_manager =
+ storage_partition()->GetCookieManagerForBrowserProcess();
base::RunLoop run_loop;
net::CookieList cookie_list;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(
- &net::CookieStore::GetAllCookiesAsync,
- base::Unretained(cookie_store_),
- base::Bind(&ClearSiteDataThrottleBrowserTest::GetCookiesCallback,
- run_loop.QuitClosure(),
- base::Unretained(&cookie_list))));
+ cookie_manager->GetAllCookies(base::BindRepeating(
+ &ClearSiteDataHandlerBrowserTest::GetCookiesCallback,
+ run_loop.QuitClosure(), base::Unretained(&cookie_list)));
run_loop.Run();
return cookie_list;
}
@@ -247,8 +268,7 @@ class ClearSiteDataThrottleBrowserTest : public ContentBrowserTest {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
ServiceWorkerContextWrapper* service_worker_context =
static_cast<ServiceWorkerContextWrapper*>(
- BrowserContext::GetDefaultStoragePartition(browser_context())
- ->GetServiceWorkerContext());
+ storage_partition()->GetServiceWorkerContext());
GURL scope_url = https_server()->GetURL(origin, "/");
GURL js_url = https_server()->GetURL(origin, "/?file=worker.js");
@@ -262,7 +282,7 @@ class ClearSiteDataThrottleBrowserTest : public ContentBrowserTest {
&ServiceWorkerContextWrapper::RegisterServiceWorker,
base::Unretained(service_worker_context), js_url, options,
base::Bind(
- &ClearSiteDataThrottleBrowserTest::AddServiceWorkerCallback,
+ &ClearSiteDataHandlerBrowserTest::AddServiceWorkerCallback,
base::Unretained(this))));
// Wait for its activation.
@@ -281,8 +301,7 @@ class ClearSiteDataThrottleBrowserTest : public ContentBrowserTest {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
ServiceWorkerContextWrapper* service_worker_context =
static_cast<ServiceWorkerContextWrapper*>(
- BrowserContext::GetDefaultStoragePartition(browser_context())
- ->GetServiceWorkerContext());
+ storage_partition()->GetServiceWorkerContext());
std::vector<ServiceWorkerUsageInfo> service_workers;
base::RunLoop run_loop;
@@ -293,7 +312,7 @@ class ClearSiteDataThrottleBrowserTest : public ContentBrowserTest {
&ServiceWorkerContextWrapper::GetAllOriginsInfo,
base::Unretained(service_worker_context),
base::Bind(
- &ClearSiteDataThrottleBrowserTest::GetServiceWorkersCallback,
+ &ClearSiteDataHandlerBrowserTest::GetServiceWorkersCallback,
base::Unretained(this), run_loop.QuitClosure(),
base::Unretained(&service_workers))));
run_loop.Run();
@@ -301,6 +320,44 @@ class ClearSiteDataThrottleBrowserTest : public ContentBrowserTest {
return service_workers;
}
+ void CreateCacheEntry(const GURL& url) {
+ if (is_network_service_enabled_) {
+ ASSERT_EQ(net::OK, LoadBasicRequest(
+ storage_partition()->GetNetworkContext(), url));
+ } else {
+ if (!cache_test_util_)
+ cache_test_util_ = std::make_unique<CacheTestUtil>(storage_partition());
+ cache_test_util_->CreateCacheEntries({url.spec()});
+ }
+ }
+
+ bool TestCacheEntry(const GURL& url) {
+ if (is_network_service_enabled_) {
+ return LoadBasicRequest(storage_partition()->GetNetworkContext(), url,
+ 0 /* process_id */, 0 /* render_frame_id */,
+ net::LOAD_ONLY_FROM_CACHE) == net::OK;
+ } else {
+ std::vector<std::string> cache_keys = cache_test_util_->GetEntryKeys();
+ return std::find(cache_keys.begin(), cache_keys.end(), url.spec()) !=
+ cache_keys.end();
+ }
+ }
+
+ // Causes |!g_base_sync_primitives_disallowed.Get().Get()| issue if we don't
+ // destroy it before test ends.
+ void DestroyCacheTestUtilIfNecessary() {
+ if (cache_test_util_)
+ cache_test_util_ = nullptr;
+ }
+
+ GURL GetURLForHTTPSHost1(const std::string& relative_url) {
+ return https_server_->GetURL("origin1.com", relative_url);
+ }
+
+ GURL GetURLForHTTPSHost2(const std::string& relative_url) {
+ return https_server_->GetURL("origin2.com", relative_url);
+ }
+
TestBrowsingDataRemoverDelegate* delegate() { return &embedder_delegate_; }
net::EmbeddedTestServer* https_server() { return https_server_.get(); }
@@ -375,12 +432,32 @@ class ClearSiteDataThrottleBrowserTest : public ContentBrowserTest {
response->set_content(buffer.get());
}
+ if (base::StartsWith(request.relative_url, "/cachetime",
+ base::CompareCase::SENSITIVE)) {
+ response->set_content(
+ "<html><head><title>Cache: max-age=60</title></head></html>");
+ response->set_content_type("text/html");
+ response->AddCustomHeader("Cache-Control", "max-age=60");
+ }
+
return std::move(response);
}
+ void SetUpMockCertVerifier(int32_t default_result) {
+ DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService));
+ network::mojom::NetworkServiceTestPtr network_service_test;
+ ServiceManagerConnection::GetForProcess()->GetConnector()->BindInterface(
+ mojom::kNetworkServiceName, &network_service_test);
+
+ base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed);
+ network_service_test->MockCertVerifierSetDefaultResult(
+ default_result, run_loop.QuitClosure());
+ run_loop.Run();
+ }
+
// Callback handler for AddCookie().
static void AddCookieCallback(const base::Closure& callback, bool success) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
ASSERT_TRUE(success);
callback.Run();
}
@@ -389,7 +466,7 @@ class ClearSiteDataThrottleBrowserTest : public ContentBrowserTest {
static void GetCookiesCallback(const base::Closure& callback,
net::CookieList* out_cookie_list,
const net::CookieList& cookie_list) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
*out_cookie_list = cookie_list;
callback.Run();
}
@@ -406,6 +483,12 @@ class ClearSiteDataThrottleBrowserTest : public ContentBrowserTest {
callback.Run();
}
+ // We can only use |MockCertVerifier| when Network Service was enabled.
+ bool is_network_service_enabled_ = false;
+
+ // Only used when |is_network_service_enabled_| is false.
+ std::unique_ptr<CacheTestUtil> cache_test_util_ = nullptr;
+
std::unique_ptr<net::EmbeddedTestServer> https_server_;
TestBrowsingDataRemoverDelegate embedder_delegate_;
@@ -422,7 +505,7 @@ class ClearSiteDataThrottleBrowserTest : public ContentBrowserTest {
#else
#define MAYBE_RedirectNavigation RedirectNavigation
#endif
-IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowserTest,
+IN_PROC_BROWSER_TEST_F(ClearSiteDataHandlerBrowserTest,
MAYBE_RedirectNavigation) {
GURL page_urls[3] = {
https_server()->GetURL("origin1.com", "/"),
@@ -470,7 +553,7 @@ IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowserTest,
#else
#define MAYBE_RedirectResourceLoad RedirectResourceLoad
#endif
-IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowserTest,
+IN_PROC_BROWSER_TEST_F(ClearSiteDataHandlerBrowserTest,
MAYBE_RedirectResourceLoad) {
GURL resource_urls[3] = {
https_server()->GetURL("origin1.com", "/redirect-start"),
@@ -515,7 +598,7 @@ IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowserTest,
}
// Tests that the Clear-Site-Data header is ignored for insecure origins.
-IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowserTest, InsecureNavigation) {
+IN_PROC_BROWSER_TEST_F(ClearSiteDataHandlerBrowserTest, InsecureNavigation) {
// ClearSiteData() should not be called on HTTP.
GURL url = embedded_test_server()->GetURL("example.com", "/");
AddQuery(&url, "header", kClearCookiesHeader);
@@ -529,7 +612,7 @@ IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowserTest, InsecureNavigation) {
// Tests that the Clear-Site-Data header is honored for secure resource loads
// and ignored for insecure ones.
-IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowserTest,
+IN_PROC_BROWSER_TEST_F(ClearSiteDataHandlerBrowserTest,
SecureAndInsecureResourceLoad) {
GURL insecure_image =
embedded_test_server()->GetURL("example.com", "/image.png");
@@ -593,7 +676,7 @@ IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowserTest,
// Tests that the Clear-Site-Data header is ignored for service worker resource
// loads.
-IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowserTest, ServiceWorker) {
+IN_PROC_BROWSER_TEST_F(ClearSiteDataHandlerBrowserTest, ServiceWorker) {
GURL origin1 = https_server()->GetURL("origin1.com", "/");
GURL origin2 = https_server()->GetURL("origin2.com", "/");
GURL origin3 = https_server()->GetURL("origin3.com", "/");
@@ -651,7 +734,7 @@ IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowserTest, ServiceWorker) {
#else
#define MAYBE_Credentials Credentials
#endif
-IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowserTest, MAYBE_Credentials) {
+IN_PROC_BROWSER_TEST_F(ClearSiteDataHandlerBrowserTest, MAYBE_Credentials) {
GURL page_template = https_server()->GetURL("origin1.com", "/");
GURL same_origin_resource =
https_server()->GetURL("origin1.com", "/resource");
@@ -710,8 +793,7 @@ IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowserTest, MAYBE_Credentials) {
// Tests that the credentials flag is correctly taken into account when it
// interpretation changes after redirect.
-IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowserTest,
- CredentialsOnRedirect) {
+IN_PROC_BROWSER_TEST_F(ClearSiteDataHandlerBrowserTest, CredentialsOnRedirect) {
GURL urls[2] = {
https_server()->GetURL("origin1.com", "/image.png"),
https_server()->GetURL("origin2.com", "/image.png"),
@@ -752,15 +834,15 @@ IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowserTest,
}
// Tests that ClearSiteData() is called for the correct data types.
-IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowserTest, Types) {
+IN_PROC_BROWSER_TEST_F(ClearSiteDataHandlerBrowserTest, Types) {
GURL base_url = https_server()->GetURL("example.com", "/");
- struct TestCase {
+ const struct TestCase {
const char* value;
bool remove_cookies;
bool remove_storage;
bool remove_cache;
- } test_cases[] = {
+ } kTestCases[] = {
{"\"cookies\"", true, false, false},
{"\"storage\"", false, true, false},
{"\"cache\"", false, false, true},
@@ -770,7 +852,7 @@ IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowserTest, Types) {
{"\"cookies\", \"storage\", \"cache\"", true, true, true},
};
- for (const TestCase& test_case : test_cases) {
+ for (const TestCase& test_case : kTestCases) {
GURL url = base_url;
AddQuery(&url, "header", test_case.value);
@@ -785,7 +867,7 @@ IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowserTest, Types) {
}
// Integration test for the deletion of cookies.
-IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowserTest,
+IN_PROC_BROWSER_TEST_F(ClearSiteDataHandlerBrowserTest,
CookiesIntegrationTest) {
AddCookie(https_server()->GetURL("origin1.com", "/abc"));
AddCookie(https_server()->GetURL("subdomain.origin1.com", "/"));
@@ -809,7 +891,7 @@ IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowserTest,
}
// Integration test for the unregistering of service workers.
-IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowserTest,
+IN_PROC_BROWSER_TEST_F(ClearSiteDataHandlerBrowserTest,
StorageServiceWorkersIntegrationTest) {
AddServiceWorker("origin1.com");
AddServiceWorker("origin2.com");
@@ -850,45 +932,41 @@ IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowserTest,
// local storage, indexed DB, etc.
// Integration test for the deletion of cache entries.
-// NOTE: This test might be flaky. disk_cache::Backend calls back before cache
-// entries are actually written to the disk. Other tests using CacheTestUtil
-// show that a timeout of around 1s between cache operations is necessary to
-// avoid flakiness.
-IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowserTest, CacheIntegrationTest) {
- const int kTimeoutMs = 1000;
-
- CacheTestUtil util(
- BrowserContext::GetDefaultStoragePartition(browser_context()));
- std::string url1 = https_server()->GetURL("origin1.com", "/foo").spec();
- std::string url2 = https_server()->GetURL("origin1.com", "/bar").spec();
- std::string url3 = https_server()->GetURL("origin2.com", "/foo").spec();
- std::string url4 = https_server()->GetURL("origin2.com", "/bar").spec();
-
- std::set<std::string> entries_to_create = {url1, url2, url3, url4};
- util.CreateCacheEntries(entries_to_create);
- base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(kTimeoutMs));
+IN_PROC_BROWSER_TEST_F(ClearSiteDataHandlerBrowserTest, CacheIntegrationTest) {
+ GURL url1 = GetURLForHTTPSHost1("/cachetime/foo");
+ GURL url2 = GetURLForHTTPSHost1("/cachetime/bar");
+ GURL url3 = GetURLForHTTPSHost2("/cachetime/foo");
+ GURL url4 = GetURLForHTTPSHost2("/cachetime/bar");
+
+ // Load the url to create cache entries.
+ CreateCacheEntry(url1);
+ CreateCacheEntry(url2);
+ CreateCacheEntry(url3);
+ CreateCacheEntry(url4);
// There are four cache entries on two origins.
- std::vector<std::string> cache_keys = util.GetEntryKeys();
- EXPECT_EQ(4u, cache_keys.size());
+ EXPECT_TRUE(TestCacheEntry(url1));
+ EXPECT_TRUE(TestCacheEntry(url2));
+ EXPECT_TRUE(TestCacheEntry(url3));
+ EXPECT_TRUE(TestCacheEntry(url4));
- // Let Clear-Site-Data delete the "cache" of "origin1.com".
- GURL url = https_server()->GetURL("origin1.com", "/clear-site-data");
+ // Let Clear-Site-Data delete the "cache" of HTTPS host 2.
+ GURL url = GetURLForHTTPSHost2("/clear-site-data");
AddQuery(&url, "header", "\"cache\"");
NavigateToURL(shell(), url);
- base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(kTimeoutMs));
-
- // Only "origin2.com" now has cache entries.
- cache_keys = util.GetEntryKeys();
- ASSERT_EQ(2u, cache_keys.size());
- std::sort(cache_keys.begin(), cache_keys.end());
- EXPECT_EQ(url4, cache_keys[0]);
- EXPECT_EQ(url3, cache_keys[1]);
+
+ // Only HTTPS host 1 now has cache entries.
+ EXPECT_TRUE(TestCacheEntry(url1));
+ EXPECT_TRUE(TestCacheEntry(url2));
+ EXPECT_FALSE(TestCacheEntry(url3));
+ EXPECT_FALSE(TestCacheEntry(url4));
+
+ DestroyCacheTestUtilIfNecessary();
}
// Tests that closing the tab right after executing Clear-Site-Data does
// not crash.
-IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowserTest, ClosedTab) {
+IN_PROC_BROWSER_TEST_F(ClearSiteDataHandlerBrowserTest, ClosedTab) {
GURL url = https_server()->GetURL("example.com", "/");
AddQuery(&url, "header", kClearCookiesHeader);
shell()->LoadURL(url);
diff --git a/chromium/content/browser/browsing_data/clear_site_data_handler_unittest.cc b/chromium/content/browser/browsing_data/clear_site_data_handler_unittest.cc
new file mode 100644
index 00000000000..c49509edccf
--- /dev/null
+++ b/chromium/content/browser/browsing_data/clear_site_data_handler_unittest.cc
@@ -0,0 +1,485 @@
+// 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/browsing_data/clear_site_data_handler.h"
+
+#include <memory>
+
+#include "base/bind_helpers.h"
+#include "base/memory/ref_counted.h"
+#include "base/run_loop.h"
+#include "base/strings/stringprintf.h"
+#include "base/test/scoped_command_line.h"
+#include "base/test/scoped_task_environment.h"
+#include "content/public/browser/resource_request_info.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "net/base/load_flags.h"
+#include "net/http/http_util.h"
+#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
+#include "net/url_request/redirect_info.h"
+#include "net/url_request/url_request_job.h"
+#include "net/url_request/url_request_test_util.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::_;
+
+namespace content {
+
+using ConsoleMessagesDelegate = ClearSiteDataHandler::ConsoleMessagesDelegate;
+using Message = ClearSiteDataHandler::ConsoleMessagesDelegate::Message;
+
+namespace {
+
+const char kClearCookiesHeader[] = "\"cookies\"";
+
+WebContents* FakeWebContentsGetter() {
+ return nullptr;
+}
+
+// A slightly modified ClearSiteDataHandler for testing with dummy clearing
+// functionality.
+class TestHandler : public ClearSiteDataHandler {
+ public:
+ TestHandler(base::RepeatingCallback<WebContents*()> web_contents_getter,
+ const GURL& url,
+ const std::string& header_value,
+ int load_flags,
+ base::OnceClosure callback,
+ std::unique_ptr<ConsoleMessagesDelegate> delegate)
+ : ClearSiteDataHandler(std::move(web_contents_getter),
+ url,
+ header_value,
+ load_flags,
+ std::move(callback),
+ std::move(delegate)) {}
+ ~TestHandler() override = default;
+
+ // |HandleHeaderAndOutputConsoleMessages()| is protected and not visible in
+ // test cases.
+ bool DoHandleHeader() { return HandleHeaderAndOutputConsoleMessages(); }
+
+ MOCK_METHOD4(ClearSiteData,
+ void(const url::Origin& origin,
+ bool clear_cookies,
+ bool clear_storage,
+ bool clear_cache));
+
+ protected:
+ void ExecuteClearingTask(const url::Origin& origin,
+ bool clear_cookies,
+ bool clear_storage,
+ bool clear_cache,
+ base::OnceClosure callback) override {
+ ClearSiteData(origin, clear_cookies, clear_storage, clear_cache);
+
+ // NOTE: ResourceThrottle expects Resume() to be called asynchronously.
+ // For the purposes of this test, synchronous call works correctly, and
+ // is preferable for simplicity, so that we don't have to synchronize
+ // between triggering Clear-Site-Data and verifying test expectations.
+ std::move(callback).Run();
+ }
+};
+
+// A ConsoleDelegate that copies message to a vector |message_buffer| owned by
+// the caller instead of outputs to the console.
+// We need this override because otherwise messages are outputted as soon as
+// request finished, and we don't have a chance to check them.
+class VectorConsoleMessagesDelegate : public ConsoleMessagesDelegate {
+ public:
+ VectorConsoleMessagesDelegate(std::vector<Message>* message_buffer)
+ : message_buffer_(message_buffer) {}
+ ~VectorConsoleMessagesDelegate() override = default;
+
+ void OutputMessages(const base::RepeatingCallback<WebContents*()>&
+ web_contents_getter) override {
+ *message_buffer_ = messages();
+ }
+
+ private:
+ std::vector<Message>* message_buffer_;
+};
+
+// A ConsoleDelegate that outputs messages to a string |output_buffer| owned
+// by the caller instead of to the console (losing the level information).
+class StringConsoleMessagesDelegate : public ConsoleMessagesDelegate {
+ public:
+ StringConsoleMessagesDelegate(std::string* output_buffer) {
+ SetOutputFormattedMessageFunctionForTesting(base::BindRepeating(
+ &StringConsoleMessagesDelegate::OutputFormattedMessage,
+ base::Unretained(output_buffer)));
+ }
+
+ ~StringConsoleMessagesDelegate() override {}
+
+ private:
+ static void OutputFormattedMessage(std::string* output_buffer,
+ WebContents* web_contents,
+ ConsoleMessageLevel level,
+ const std::string& formatted_text) {
+ *output_buffer += formatted_text + "\n";
+ }
+};
+
+} // namespace
+
+class ClearSiteDataHandlerTest : public testing::Test {
+ public:
+ ClearSiteDataHandlerTest()
+ : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}
+
+ private:
+ TestBrowserThreadBundle thread_bundle_;
+
+ DISALLOW_COPY_AND_ASSIGN(ClearSiteDataHandlerTest);
+};
+
+TEST_F(ClearSiteDataHandlerTest, ParseHeaderAndExecuteClearingTask) {
+ struct TestCase {
+ const char* header;
+ bool cookies;
+ bool storage;
+ bool cache;
+ };
+
+ std::vector<TestCase> standard_test_cases = {
+ // One data type.
+ {"\"cookies\"", true, false, false},
+ {"\"storage\"", false, true, false},
+ {"\"cache\"", false, false, true},
+
+ // Two data types.
+ {"\"cookies\", \"storage\"", true, true, false},
+ {"\"cookies\", \"cache\"", true, false, true},
+ {"\"storage\", \"cache\"", false, true, true},
+
+ // Three data types.
+ {"\"storage\", \"cache\", \"cookies\"", true, true, true},
+ {"\"cache\", \"cookies\", \"storage\"", true, true, true},
+ {"\"cookies\", \"storage\", \"cache\"", true, true, true},
+
+ // The wildcard datatype is not yet shipped.
+ {"\"*\", \"storage\"", false, true, false},
+ {"\"cookies\", \"*\", \"storage\"", true, true, false},
+ {"\"*\", \"cookies\", \"*\"", true, false, false},
+
+ // Different formatting.
+ {"\"cookies\"", true, false, false},
+
+ // Duplicates.
+ {"\"cookies\", \"cookies\"", true, false, false},
+
+ // Other JSON-formatted items in the list.
+ {"\"storage\", { \"other_params\": {} }", false, true, false},
+
+ // Unknown types are ignored, but we still proceed with the deletion for
+ // those that we recognize.
+ {"\"cache\", \"foo\"", false, false, true},
+ };
+
+ std::vector<TestCase> experimental_test_cases = {
+ // Wildcard.
+ {"\"*\"", true, true, true},
+ {"\"*\", \"storage\"", true, true, true},
+ {"\"cache\", \"*\", \"storage\"", true, true, true},
+ {"\"*\", \"cookies\", \"*\"", true, true, true},
+ };
+
+ const std::vector<TestCase>* test_case_sets[] = {&standard_test_cases,
+ &experimental_test_cases};
+
+ for (const std::vector<TestCase>* test_cases : test_case_sets) {
+ base::test::ScopedCommandLine scoped_command_line;
+ if (test_cases == &experimental_test_cases) {
+ scoped_command_line.GetProcessCommandLine()->AppendSwitch(
+ switches::kEnableExperimentalWebPlatformFeatures);
+ }
+
+ for (const TestCase& test_case : *test_cases) {
+ SCOPED_TRACE(test_case.header);
+
+ // Test that ParseHeader works correctly.
+ bool actual_cookies;
+ bool actual_storage;
+ bool actual_cache;
+
+ GURL url("https://example.com");
+ ConsoleMessagesDelegate console_delegate;
+
+ EXPECT_TRUE(ClearSiteDataHandler::ParseHeaderForTesting(
+ test_case.header, &actual_cookies, &actual_storage, &actual_cache,
+ &console_delegate, url));
+
+ EXPECT_EQ(test_case.cookies, actual_cookies);
+ EXPECT_EQ(test_case.storage, actual_storage);
+ EXPECT_EQ(test_case.cache, actual_cache);
+
+ // Test that a call with the above parameters actually reaches
+ // ExecuteClearingTask().
+ net::TestURLRequestContext context;
+ std::unique_ptr<net::URLRequest> request(context.CreateRequest(
+ url, net::DEFAULT_PRIORITY, nullptr, TRAFFIC_ANNOTATION_FOR_TESTS));
+ TestHandler handler(base::BindRepeating(&FakeWebContentsGetter),
+ request->url(), test_case.header,
+ request->load_flags(), base::DoNothing(),
+ std::make_unique<ConsoleMessagesDelegate>());
+
+ EXPECT_CALL(handler,
+ ClearSiteData(url::Origin::Create(url), test_case.cookies,
+ test_case.storage, test_case.cache));
+ bool defer = handler.DoHandleHeader();
+ EXPECT_TRUE(defer);
+
+ testing::Mock::VerifyAndClearExpectations(&handler);
+ }
+ }
+}
+
+TEST_F(ClearSiteDataHandlerTest, InvalidHeader) {
+ struct TestCase {
+ const char* header;
+ const char* console_message;
+ } test_cases[] = {{"", "No recognized types specified.\n"},
+ {"\"unclosed",
+ "Unrecognized type: \"unclosed.\n"
+ "No recognized types specified.\n"},
+ {"\"passwords\"",
+ "Unrecognized type: \"passwords\".\n"
+ "No recognized types specified.\n"},
+ // The wildcard datatype is not yet shipped.
+ {"[ \"*\" ]",
+ "Unrecognized type: [ \"*\" ].\n"
+ "No recognized types specified.\n"},
+ {"[ \"list\" ]",
+ "Unrecognized type: [ \"list\" ].\n"
+ "No recognized types specified.\n"},
+ {"{ \"cookies\": [ \"a\" ] }",
+ "Unrecognized type: { \"cookies\": [ \"a\" ] }.\n"
+ "No recognized types specified.\n"},
+ {"\"кукис\", \"сторидж\", \"кэш\"",
+ "Must only contain ASCII characters.\n"}};
+
+ for (const TestCase& test_case : test_cases) {
+ SCOPED_TRACE(test_case.header);
+
+ bool actual_cookies;
+ bool actual_storage;
+ bool actual_cache;
+
+ ConsoleMessagesDelegate console_delegate;
+
+ EXPECT_FALSE(ClearSiteDataHandler::ParseHeaderForTesting(
+ test_case.header, &actual_cookies, &actual_storage, &actual_cache,
+ &console_delegate, GURL()));
+
+ std::string multiline_message;
+ for (const auto& message : console_delegate.messages()) {
+ EXPECT_EQ(CONSOLE_MESSAGE_LEVEL_ERROR, message.level);
+ multiline_message += message.text + "\n";
+ }
+
+ EXPECT_EQ(test_case.console_message, multiline_message);
+ }
+}
+
+TEST_F(ClearSiteDataHandlerTest, ClearCookieSuccess) {
+ net::TestURLRequestContext context;
+ std::unique_ptr<net::URLRequest> request(
+ context.CreateRequest(GURL("https://example.com"), net::DEFAULT_PRIORITY,
+ nullptr, TRAFFIC_ANNOTATION_FOR_TESTS));
+ std::vector<Message> message_buffer;
+ TestHandler handler(
+ base::BindRepeating(&FakeWebContentsGetter), request->url(),
+ kClearCookiesHeader, request->load_flags(), base::DoNothing(),
+ std::make_unique<VectorConsoleMessagesDelegate>(&message_buffer));
+
+ EXPECT_CALL(handler, ClearSiteData(_, _, _, _));
+ bool defer = handler.DoHandleHeader();
+ EXPECT_TRUE(defer);
+ EXPECT_EQ(1u, message_buffer.size());
+ EXPECT_EQ(
+ "Cleared data types: \"cookies\". "
+ "Clearing channel IDs and HTTP authentication cache is currently "
+ "not supported, as it breaks active network connections.",
+ message_buffer.front().text);
+ EXPECT_EQ(message_buffer.front().level, CONSOLE_MESSAGE_LEVEL_INFO);
+ testing::Mock::VerifyAndClearExpectations(&handler);
+}
+
+TEST_F(ClearSiteDataHandlerTest, LoadDoNotSaveCookies) {
+ net::TestURLRequestContext context;
+ std::unique_ptr<net::URLRequest> request(
+ context.CreateRequest(GURL("https://example.com"), net::DEFAULT_PRIORITY,
+ nullptr, TRAFFIC_ANNOTATION_FOR_TESTS));
+ request->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES);
+ std::vector<Message> message_buffer;
+ TestHandler handler(
+ base::BindRepeating(&FakeWebContentsGetter), request->url(),
+ kClearCookiesHeader, request->load_flags(), base::DoNothing(),
+ std::make_unique<VectorConsoleMessagesDelegate>(&message_buffer));
+
+ EXPECT_CALL(handler, ClearSiteData(_, _, _, _)).Times(0);
+ bool defer = handler.DoHandleHeader();
+ EXPECT_FALSE(defer);
+ EXPECT_EQ(1u, message_buffer.size());
+ EXPECT_EQ(
+ "The request's credentials mode prohibits modifying cookies "
+ "and other local data.",
+ message_buffer.front().text);
+ EXPECT_EQ(CONSOLE_MESSAGE_LEVEL_ERROR, message_buffer.front().level);
+ testing::Mock::VerifyAndClearExpectations(&handler);
+}
+
+TEST_F(ClearSiteDataHandlerTest, InvalidOrigin) {
+ struct TestCase {
+ const char* origin;
+ bool expect_success;
+ std::string error_message; // Tested only if |expect_success| = false.
+ } kTestCases[] = {
+ // The handler only works on secure origins.
+ {"https://secure-origin.com", true, ""},
+ {"filesystem:https://secure-origin.com/temporary/", true, ""},
+
+ // That includes localhost.
+ {"http://localhost", true, ""},
+
+ // Not on insecure origins.
+ {"http://insecure-origin.com", false,
+ "Not supported for insecure origins."},
+ {"filesystem:http://insecure-origin.com/temporary/", false,
+ "Not supported for insecure origins."},
+
+ // Not on unique origins.
+ {"data:unique-origin;", false, "Not supported for unique origins."},
+ };
+
+ net::TestURLRequestContext context;
+
+ for (const TestCase& test_case : kTestCases) {
+ std::unique_ptr<net::URLRequest> request(
+ context.CreateRequest(GURL(test_case.origin), net::DEFAULT_PRIORITY,
+ nullptr, TRAFFIC_ANNOTATION_FOR_TESTS));
+ std::vector<Message> message_buffer;
+ TestHandler handler(
+ base::BindRepeating(&FakeWebContentsGetter), request->url(),
+ kClearCookiesHeader, request->load_flags(), base::DoNothing(),
+ std::make_unique<VectorConsoleMessagesDelegate>(&message_buffer));
+
+ EXPECT_CALL(handler, ClearSiteData(_, _, _, _))
+ .Times(test_case.expect_success ? 1 : 0);
+
+ bool defer = handler.DoHandleHeader();
+
+ EXPECT_EQ(defer, test_case.expect_success);
+ EXPECT_EQ(message_buffer.size(), 1u);
+ EXPECT_EQ(test_case.expect_success ? CONSOLE_MESSAGE_LEVEL_INFO
+ : CONSOLE_MESSAGE_LEVEL_ERROR,
+ message_buffer.front().level);
+ if (!test_case.expect_success) {
+ EXPECT_EQ(test_case.error_message, message_buffer.front().text);
+ }
+ testing::Mock::VerifyAndClearExpectations(&handler);
+ }
+}
+
+// Verifies that console outputs from various actions on different URLs
+// are correctly pretty-printed to the console.
+TEST_F(ClearSiteDataHandlerTest, FormattedConsoleOutput) {
+ struct TestCase {
+ const char* header;
+ const char* url;
+ const char* output;
+ } kTestCases[] = {
+ // Successful deletion outputs one line, and in case of cookies, also
+ // a disclaimer about omitted data (https://crbug.com/798760).
+ {"\"cookies\"", "https://origin1.com/foo",
+ "Clear-Site-Data header on 'https://origin1.com/foo': "
+ "Cleared data types: \"cookies\". "
+ "Clearing channel IDs and HTTP authentication cache is currently "
+ "not supported, as it breaks active network connections.\n"},
+
+ // Another successful deletion.
+ {"\"storage\"", "https://origin2.com/foo",
+ "Clear-Site-Data header on 'https://origin2.com/foo': "
+ "Cleared data types: \"storage\".\n"},
+
+ // Redirect to the same URL. Unsuccessful deletion outputs two lines.
+ {"\"foo\"", "https://origin2.com/foo",
+ "Clear-Site-Data header on 'https://origin2.com/foo': "
+ "Unrecognized type: \"foo\".\n"
+ "Clear-Site-Data header on 'https://origin2.com/foo': "
+ "No recognized types specified.\n"},
+
+ // Redirect to another URL. Another unsuccessful deletion.
+ {"\"some text\"", "https://origin3.com/bar",
+ "Clear-Site-Data header on 'https://origin3.com/bar': "
+ "Unrecognized type: \"some text\".\n"
+ "Clear-Site-Data header on 'https://origin3.com/bar': "
+ "No recognized types specified.\n"},
+
+ // Yet another on the same URL.
+ {"\"passwords\"", "https://origin3.com/bar",
+ "Clear-Site-Data header on 'https://origin3.com/bar': "
+ "Unrecognized type: \"passwords\".\n"
+ "Clear-Site-Data header on 'https://origin3.com/bar': "
+ "No recognized types specified.\n"},
+
+ // Successful deletion on the same URL.
+ {"\"cache\"", "https://origin3.com/bar",
+ "Clear-Site-Data header on 'https://origin3.com/bar': "
+ "Cleared data types: \"cache\".\n"},
+
+ // Redirect to the original URL.
+ // Successful deletion outputs one line.
+ {"", "https://origin1.com/foo",
+ "Clear-Site-Data header on 'https://origin1.com/foo': "
+ "No recognized types specified.\n"}};
+
+ // TODO(crbug.com/876931): Delay output until next frame for navigations.
+ bool kHandlerTypeIsNavigation[] = {false};
+
+ for (bool navigation : kHandlerTypeIsNavigation) {
+ SCOPED_TRACE(navigation ? "Navigation test." : "Subresource test.");
+
+ net::TestURLRequestContext context;
+ std::unique_ptr<net::URLRequest> request(
+ context.CreateRequest(GURL(kTestCases[0].url), net::DEFAULT_PRIORITY,
+ nullptr, TRAFFIC_ANNOTATION_FOR_TESTS));
+
+ std::string output_buffer;
+ std::string last_seen_console_output;
+
+ // |NetworkServiceClient| creates a new |ClearSiteDataHandler| for each
+ // navigation, redirect, or subresource header responses.
+ for (size_t i = 0; i < base::size(kTestCases); i++) {
+ TestHandler handler(
+ base::BindRepeating(&FakeWebContentsGetter), GURL(kTestCases[i].url),
+ kTestCases[i].header, request->load_flags(), base::DoNothing(),
+ std::make_unique<StringConsoleMessagesDelegate>(&output_buffer));
+ handler.DoHandleHeader();
+
+ // For navigations, the console should be still empty. For subresource
+ // requests, messages should be added progressively.
+ if (navigation) {
+ EXPECT_TRUE(output_buffer.empty());
+ } else {
+ EXPECT_EQ(last_seen_console_output + kTestCases[i].output,
+ output_buffer);
+ }
+
+ last_seen_console_output = output_buffer;
+ }
+
+ // At the end, the console must contain all messages regardless of whether
+ // it was a navigation or a subresource request.
+ std::string expected_output;
+ for (struct TestCase& test_case : kTestCases)
+ expected_output += test_case.output;
+ EXPECT_EQ(expected_output, output_buffer);
+ }
+}
+
+} // 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 2f644a6dd4d..ba0a6e39c53 100644
--- a/chromium/content/browser/browsing_data/clear_site_data_throttle.cc
+++ b/chromium/content/browser/browsing_data/clear_site_data_throttle.cc
@@ -34,22 +34,24 @@ namespace content {
namespace {
-const char kNameForLogging[] = "ClearSiteDataThrottle";
+// Appending '2' to avoid naming conflicts with 'clear_site_data_handler.h' in
+// jumbo builds. This file will be removed later as mentioned in the header.
+const char kNameForLogging2[] = "ClearSiteDataThrottle";
-const char kClearSiteDataHeader[] = "Clear-Site-Data";
+const char kClearSiteDataHeader2[] = "Clear-Site-Data";
// Datatypes.
-const char kDatatypeWildcard[] = "\"*\"";
-const char kDatatypeCookies[] = "\"cookies\"";
-const char kDatatypeStorage[] = "\"storage\"";
-const char kDatatypeCache[] = "\"cache\"";
+const char kDatatypeWildcard2[] = "\"*\"";
+const char kDatatypeCookies2[] = "\"cookies\"";
+const char kDatatypeStorage2[] = "\"storage\"";
+const char kDatatypeCache2[] = "\"cache\"";
// Pretty-printed log output.
-const char kConsoleMessageTemplate[] = "Clear-Site-Data header on '%s': %s";
-const char kConsoleMessageCleared[] = "Cleared data types: %s.";
-const char kConsoleMessageDatatypeSeparator[] = ", ";
+const char kConsoleMessageTemplate2[] = "Clear-Site-Data header on '%s': %s";
+const char kConsoleMessageCleared2[] = "Cleared data types: %s.";
+const char kConsoleMessageDatatypeSeparator2[] = ", ";
-bool AreExperimentalFeaturesEnabled() {
+bool AreExperimentalFeaturesEnabled2() {
return base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableExperimentalWebPlatformFeatures);
}
@@ -60,7 +62,7 @@ bool IsNavigationRequest(net::URLRequest* request) {
}
// Represents the parameters as a single number to be recorded in a histogram.
-int ParametersMask(bool clear_cookies, bool clear_storage, bool clear_cache) {
+int ParametersMask2(bool clear_cookies, bool clear_storage, bool clear_cache) {
return static_cast<int>(clear_cookies) * (1 << 0) +
static_cast<int>(clear_storage) * (1 << 1) +
static_cast<int>(clear_cache) * (1 << 2);
@@ -202,9 +204,9 @@ class UIThreadSiteDataClearer : public BrowsingDataRemover::Observer {
};
// Outputs a single |formatted_message| on the UI thread.
-void OutputFormattedMessage(WebContents* web_contents,
- ConsoleMessageLevel level,
- const std::string& formatted_text) {
+void OutputFormattedMessage2(WebContents* web_contents,
+ ConsoleMessageLevel level,
+ const std::string& formatted_text) {
if (web_contents)
web_contents->GetMainFrame()->AddMessageToConsole(level, formatted_text);
}
@@ -222,10 +224,10 @@ void OutputMessagesOnUIThread(
WebContents* web_contents = web_contents_getter.Run();
for (const auto& message : messages) {
- // Prefix each message with |kConsoleMessageTemplate|.
+ // Prefix each message with |kConsoleMessageTemplate2|.
output_formatted_message_function.Run(
web_contents, message.level,
- base::StringPrintf(kConsoleMessageTemplate, message.url.spec().c_str(),
+ base::StringPrintf(kConsoleMessageTemplate2, message.url.spec().c_str(),
message.text.c_str()));
}
}
@@ -236,7 +238,8 @@ void OutputMessagesOnUIThread(
// ConsoleMessagesDelegate
ClearSiteDataThrottle::ConsoleMessagesDelegate::ConsoleMessagesDelegate()
- : output_formatted_message_function_(base::Bind(&OutputFormattedMessage)) {}
+ : output_formatted_message_function_(
+ base::BindRepeating(&OutputFormattedMessage2)) {}
ClearSiteDataThrottle::ConsoleMessagesDelegate::~ConsoleMessagesDelegate() {}
@@ -292,7 +295,7 @@ ClearSiteDataThrottle::~ClearSiteDataThrottle() {
}
const char* ClearSiteDataThrottle::GetNameForLogging() const {
- return kNameForLogging;
+ return kNameForLogging2;
}
void ClearSiteDataThrottle::WillRedirectRequest(
@@ -351,7 +354,7 @@ bool ClearSiteDataThrottle::HandleHeader() {
std::string header_value;
if (!headers ||
- !headers->GetNormalizedHeader(kClearSiteDataHeader, &header_value)) {
+ !headers->GetNormalizedHeader(kClearSiteDataHeader2, &header_value)) {
return false;
}
@@ -422,7 +425,7 @@ bool ClearSiteDataThrottle::HandleHeader() {
// Record the call parameters.
UMA_HISTOGRAM_ENUMERATION(
"Navigation.ClearSiteData.Parameters",
- ParametersMask(clear_cookies, clear_storage, clear_cache), (1 << 3));
+ ParametersMask2(clear_cookies, clear_storage, clear_cache), (1 << 3));
base::WeakPtr<ClearSiteDataThrottle> weak_ptr =
weak_ptr_factory_.GetWeakPtr();
@@ -463,17 +466,17 @@ bool ClearSiteDataThrottle::ParseHeader(const std::string& header,
for (unsigned i = 0; i < input_types.size(); i++) {
bool* data_type = nullptr;
- if (AreExperimentalFeaturesEnabled() &&
- input_types[i] == kDatatypeWildcard) {
- input_types.push_back(kDatatypeCookies);
- input_types.push_back(kDatatypeStorage);
- input_types.push_back(kDatatypeCache);
+ if (AreExperimentalFeaturesEnabled2() &&
+ input_types[i] == kDatatypeWildcard2) {
+ input_types.push_back(kDatatypeCookies2);
+ input_types.push_back(kDatatypeStorage2);
+ input_types.push_back(kDatatypeCache2);
continue;
- } else if (input_types[i] == kDatatypeCookies) {
+ } else if (input_types[i] == kDatatypeCookies2) {
data_type = clear_cookies;
- } else if (input_types[i] == kDatatypeStorage) {
+ } else if (input_types[i] == kDatatypeStorage2) {
data_type = clear_storage;
- } else if (input_types[i] == kDatatypeCache) {
+ } else if (input_types[i] == kDatatypeCache2) {
data_type = clear_cache;
} else {
delegate->AddMessage(
@@ -490,7 +493,7 @@ bool ClearSiteDataThrottle::ParseHeader(const std::string& header,
*data_type = true;
if (!output_types.empty())
- output_types += kConsoleMessageDatatypeSeparator;
+ output_types += kConsoleMessageDatatypeSeparator2;
output_types += input_types[i];
}
@@ -503,7 +506,7 @@ bool ClearSiteDataThrottle::ParseHeader(const std::string& header,
// Pretty-print which types are to be cleared.
// TODO(crbug.com/798760): Remove the disclaimer about cookies.
std::string console_output =
- base::StringPrintf(kConsoleMessageCleared, output_types.c_str());
+ base::StringPrintf(kConsoleMessageCleared2, output_types.c_str());
if (*clear_cookies) {
console_output +=
" Clearing channel IDs and HTTP authentication cache is currently not"
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 31d26541c9f..053ce9fe6f2 100644
--- a/chromium/content/browser/browsing_data/clear_site_data_throttle.h
+++ b/chromium/content/browser/browsing_data/clear_site_data_throttle.h
@@ -34,6 +34,9 @@ namespace content {
class WebContents;
+// TODO(crbug.com/876931): To be removed after Network Service was enabled by
+// default. The header will be handled by |NetworkServiceNetworkDelegate| and
+// |ClearSiteDataHandler| instead.
// This throttle parses the Clear-Site-Data header and executes the clearing
// of browsing data. The resource load is delayed until the header is parsed
// and, if valid, until the browsing data are deleted. See the W3C working draft
diff --git a/chromium/content/browser/browsing_data/conditional_cache_deletion_helper.cc b/chromium/content/browser/browsing_data/conditional_cache_deletion_helper.cc
index fcaa95d6025..d0a5a8e4e67 100644
--- a/chromium/content/browser/browsing_data/conditional_cache_deletion_helper.cc
+++ b/chromium/content/browser/browsing_data/conditional_cache_deletion_helper.cc
@@ -85,8 +85,8 @@ void ConditionalCacheDeletionHelper::IterateOverEntries(int error) {
previous_entry_ = current_entry_;
error = iterator_->OpenNextEntry(
&current_entry_,
- base::Bind(&ConditionalCacheDeletionHelper::IterateOverEntries,
- base::Unretained(this)));
+ base::BindOnce(&ConditionalCacheDeletionHelper::IterateOverEntries,
+ base::Unretained(this)));
}
}
diff --git a/chromium/content/browser/browsing_data/storage_partition_http_cache_data_remover.cc b/chromium/content/browser/browsing_data/storage_partition_http_cache_data_remover.cc
index df1debded9d..a6551a0c099 100644
--- a/chromium/content/browser/browsing_data/storage_partition_http_cache_data_remover.cc
+++ b/chromium/content/browser/browsing_data/storage_partition_http_cache_data_remover.cc
@@ -9,8 +9,11 @@
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/browsing_data/conditional_cache_deletion_helper.h"
+#include "content/browser/code_cache/generated_code_cache.h"
+#include "content/browser/code_cache/generated_code_cache_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/storage_partition.h"
+#include "content/public/common/content_features.h"
#include "net/disk_cache/disk_cache.h"
#include "net/http/http_cache.h"
#include "net/url_request/url_request_context.h"
@@ -24,12 +27,14 @@ StoragePartitionHttpCacheDataRemover::StoragePartitionHttpCacheDataRemover(
base::Time delete_begin,
base::Time delete_end,
net::URLRequestContextGetter* main_context_getter,
- net::URLRequestContextGetter* media_context_getter)
+ net::URLRequestContextGetter* media_context_getter,
+ GeneratedCodeCacheContext* generated_code_cache_context)
: url_predicate_(url_predicate),
delete_begin_(delete_begin),
delete_end_(delete_end),
main_context_getter_(main_context_getter),
media_context_getter_(media_context_getter),
+ generated_code_cache_context_(generated_code_cache_context),
next_cache_state_(CacheState::NONE),
cache_(nullptr) {}
@@ -42,7 +47,8 @@ StoragePartitionHttpCacheDataRemover::CreateForRange(
return new StoragePartitionHttpCacheDataRemover(
base::Callback<bool(const GURL&)>(), // Null callback.
delete_begin, delete_end, storage_partition->GetURLRequestContext(),
- storage_partition->GetMediaURLRequestContext());
+ storage_partition->GetMediaURLRequestContext(),
+ storage_partition->GetGeneratedCodeCacheContext());
}
// static.
@@ -55,7 +61,8 @@ StoragePartitionHttpCacheDataRemover::CreateForURLsAndRange(
return new StoragePartitionHttpCacheDataRemover(
url_predicate, delete_begin, delete_end,
storage_partition->GetURLRequestContext(),
- storage_partition->GetMediaURLRequestContext());
+ storage_partition->GetMediaURLRequestContext(),
+ storage_partition->GetGeneratedCodeCacheContext());
}
StoragePartitionHttpCacheDataRemover::~StoragePartitionHttpCacheDataRemover() {}
@@ -90,7 +97,8 @@ void StoragePartitionHttpCacheDataRemover::ClearedHttpCache() {
// The expected state sequence is CacheState::NONE --> CacheState::CREATE_MAIN
// --> CacheState::DELETE_MAIN --> CacheState::CREATE_MEDIA -->
-// CacheState::DELETE_MEDIA --> CacheState::DONE, and any errors are ignored.
+// CacheState::DELETE_MEDIA --> CacheState::DELETE_CODE --> CacheState::DONE,
+// and any errors are ignored.
void StoragePartitionHttpCacheDataRemover::DoClearCache(int rv) {
DCHECK_NE(CacheState::NONE, next_cache_state_);
@@ -108,7 +116,7 @@ void StoragePartitionHttpCacheDataRemover::DoClearCache(int rv) {
if (!getter) {
next_cache_state_ = (next_cache_state_ == CacheState::CREATE_MAIN)
? CacheState::CREATE_MEDIA
- : CacheState::DONE;
+ : CacheState::DELETE_CODE;
break;
}
@@ -127,15 +135,15 @@ void StoragePartitionHttpCacheDataRemover::DoClearCache(int rv) {
rv = http_cache->GetBackend(
&cache_,
- base::Bind(&StoragePartitionHttpCacheDataRemover::DoClearCache,
- base::Unretained(this)));
+ base::BindOnce(&StoragePartitionHttpCacheDataRemover::DoClearCache,
+ base::Unretained(this)));
break;
}
case CacheState::DELETE_MAIN:
case CacheState::DELETE_MEDIA: {
next_cache_state_ = (next_cache_state_ == CacheState::DELETE_MAIN)
? CacheState::CREATE_MEDIA
- : CacheState::DONE;
+ : CacheState::DELETE_CODE;
// |cache_| can be null if it cannot be initialized.
if (cache_) {
@@ -148,19 +156,38 @@ void StoragePartitionHttpCacheDataRemover::DoClearCache(int rv) {
&StoragePartitionHttpCacheDataRemover::DoClearCache,
base::Unretained(this)));
} else if (delete_begin_.is_null() && delete_end_.is_max()) {
- rv = cache_->DoomAllEntries(
- base::Bind(&StoragePartitionHttpCacheDataRemover::DoClearCache,
- base::Unretained(this)));
+ rv = cache_->DoomAllEntries(base::BindOnce(
+ &StoragePartitionHttpCacheDataRemover::DoClearCache,
+ base::Unretained(this)));
} else {
rv = cache_->DoomEntriesBetween(
delete_begin_, delete_end_,
- base::Bind(&StoragePartitionHttpCacheDataRemover::DoClearCache,
- base::Unretained(this)));
+ base::BindOnce(
+ &StoragePartitionHttpCacheDataRemover::DoClearCache,
+ base::Unretained(this)));
}
cache_ = nullptr;
}
break;
}
+ case CacheState::DELETE_CODE: {
+ next_cache_state_ = CacheState::DONE;
+ if (base::FeatureList::IsEnabled(features::kIsolatedCodeCache)) {
+ DCHECK(generated_code_cache_context_);
+ GeneratedCodeCache* code_cache =
+ generated_code_cache_context_->generated_code_cache();
+ if (code_cache) {
+ auto callback = base::BindRepeating(
+ &StoragePartitionHttpCacheDataRemover::DoClearCache,
+ base::Unretained(this));
+ // TODO(crbug.com/866419): Currently we just clear the entire cache.
+ // Change it to conditionally clear the entries based on the
+ // filters.
+ rv = code_cache->ClearCache(callback);
+ }
+ }
+ break;
+ }
case CacheState::DONE: {
cache_ = nullptr;
next_cache_state_ = CacheState::NONE;
diff --git a/chromium/content/browser/browsing_data/storage_partition_http_cache_data_remover.h b/chromium/content/browser/browsing_data/storage_partition_http_cache_data_remover.h
index 6d644173b52..665a8f4e6b8 100644
--- a/chromium/content/browser/browsing_data/storage_partition_http_cache_data_remover.h
+++ b/chromium/content/browser/browsing_data/storage_partition_http_cache_data_remover.h
@@ -25,6 +25,7 @@ class URLRequestContextGetter;
namespace content {
class StoragePartition;
+class GeneratedCodeCacheContext;
// Helper to remove http cache data from a StoragePartition.
class StoragePartitionHttpCacheDataRemover {
@@ -56,6 +57,7 @@ class StoragePartitionHttpCacheDataRemover {
CREATE_MEDIA,
DELETE_MAIN,
DELETE_MEDIA,
+ DELETE_CODE,
DONE
};
@@ -64,7 +66,8 @@ class StoragePartitionHttpCacheDataRemover {
base::Time delete_begin,
base::Time delete_end,
net::URLRequestContextGetter* main_context_getter,
- net::URLRequestContextGetter* media_context_getter);
+ net::URLRequestContextGetter* media_context_getter,
+ GeneratedCodeCacheContext* generated_code_cache_context);
// StoragePartitionHttpCacheDataRemover deletes itself (using DeleteHelper)
// and is not supposed to be deleted by other objects so make destructor
@@ -84,6 +87,7 @@ class StoragePartitionHttpCacheDataRemover {
const scoped_refptr<net::URLRequestContextGetter> main_context_getter_;
const scoped_refptr<net::URLRequestContextGetter> media_context_getter_;
+ const scoped_refptr<GeneratedCodeCacheContext> generated_code_cache_context_;
base::OnceClosure done_callback_;
diff --git a/chromium/content/browser/browsing_instance.cc b/chromium/content/browser/browsing_instance.cc
index 3758184e743..9b24ae580a6 100644
--- a/chromium/content/browser/browsing_instance.cc
+++ b/chromium/content/browser/browsing_instance.cc
@@ -21,16 +21,15 @@ BrowsingInstance::BrowsingInstance(BrowserContext* browser_context)
}
bool BrowsingInstance::HasSiteInstance(const GURL& url) {
- std::string site =
- SiteInstanceImpl::GetSiteForURL(browser_context_, url)
- .possibly_invalid_spec();
+ std::string site = SiteInstance::GetSiteForURL(browser_context_, url)
+ .possibly_invalid_spec();
return site_instance_map_.find(site) != site_instance_map_.end();
}
scoped_refptr<SiteInstanceImpl> BrowsingInstance::GetSiteInstanceForURL(
const GURL& url) {
- std::string site = SiteInstanceImpl::GetSiteForURL(browser_context_, url)
+ std::string site = SiteInstance::GetSiteForURL(browser_context_, url)
.possibly_invalid_spec();
SiteInstanceMap::iterator i = site_instance_map_.find(site);
diff --git a/chromium/content/browser/cache_storage/OWNERS b/chromium/content/browser/cache_storage/OWNERS
index f802dd14208..fd09fa5dd2c 100644
--- a/chromium/content/browser/cache_storage/OWNERS
+++ b/chromium/content/browser/cache_storage/OWNERS
@@ -1,6 +1,7 @@
nhiroki@chromium.org
jkarlin@chromium.org
jsbell@chromium.org
+pwnall@chromium.org
# TEAM: storage-dev@chromium.org
# COMPONENT: Blink>Storage>CacheStorage
diff --git a/chromium/content/browser/cache_storage/cache_storage.cc b/chromium/content/browser/cache_storage/cache_storage.cc
index d91b54a4d2a..78508c8b6f1 100644
--- a/chromium/content/browser/cache_storage/cache_storage.cc
+++ b/chromium/content/browser/cache_storage/cache_storage.cc
@@ -104,7 +104,7 @@ struct CacheStorage::CacheMatchResponse {
~CacheMatchResponse() = default;
CacheStorageError error;
- std::unique_ptr<ServiceWorkerResponse> service_worker_response;
+ blink::mojom::FetchAPIResponsePtr response;
std::unique_ptr<storage::BlobDataHandle> blob_data_handle;
};
@@ -717,7 +717,7 @@ void CacheStorage::MatchAllCaches(
void CacheStorage::WriteToCache(
const std::string& cache_name,
std::unique_ptr<ServiceWorkerFetchRequest> request,
- std::unique_ptr<ServiceWorkerResponse> response,
+ blink::mojom::FetchAPIResponsePtr response,
CacheStorage::ErrorCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -1038,7 +1038,7 @@ void CacheStorage::MatchCacheDidMatch(
CacheStorageCacheHandle cache_handle,
CacheStorageCache::ResponseCallback callback,
CacheStorageError error,
- std::unique_ptr<ServiceWorkerResponse> response) {
+ blink::mojom::FetchAPIResponsePtr response) {
std::move(callback).Run(error, std::move(response));
}
@@ -1076,10 +1076,9 @@ void CacheStorage::MatchAllCachesDidMatch(
CacheMatchResponse* out_match_response,
const base::RepeatingClosure& barrier_closure,
CacheStorageError error,
- std::unique_ptr<ServiceWorkerResponse> service_worker_response) {
+ blink::mojom::FetchAPIResponsePtr response) {
out_match_response->error = error;
- out_match_response->service_worker_response =
- std::move(service_worker_response);
+ out_match_response->response = std::move(response);
barrier_closure.Run();
}
@@ -1090,7 +1089,7 @@ void CacheStorage::MatchAllCachesDidMatchAll(
if (match_response.error == CacheStorageError::kErrorNotFound)
continue;
std::move(callback).Run(match_response.error,
- std::move(match_response.service_worker_response));
+ std::move(match_response.response));
return;
}
std::move(callback).Run(CacheStorageError::kErrorNotFound, nullptr);
@@ -1099,7 +1098,7 @@ void CacheStorage::MatchAllCachesDidMatchAll(
void CacheStorage::WriteToCacheImpl(
const std::string& cache_name,
std::unique_ptr<ServiceWorkerFetchRequest> request,
- std::unique_ptr<ServiceWorkerResponse> response,
+ blink::mojom::FetchAPIResponsePtr response,
CacheStorage::ErrorCallback callback) {
CacheStorageCacheHandle cache_handle = GetLoadedCache(cache_name);
diff --git a/chromium/content/browser/cache_storage/cache_storage.h b/chromium/content/browser/cache_storage/cache_storage.h
index af34ef18253..a594d0923ea 100644
--- a/chromium/content/browser/cache_storage/cache_storage.h
+++ b/chromium/content/browser/cache_storage/cache_storage.h
@@ -121,7 +121,7 @@ class CONTENT_EXPORT CacheStorage : public CacheStorageCacheObserver {
// Puts the request/response pair in the cache.
void WriteToCache(const std::string& cache_name,
std::unique_ptr<ServiceWorkerFetchRequest> request,
- std::unique_ptr<ServiceWorkerResponse> response,
+ blink::mojom::FetchAPIResponsePtr response,
CacheStorage::ErrorCallback callback);
// Sums the sizes of each cache and closes them. Runs |callback| with the
@@ -214,18 +214,17 @@ class CONTENT_EXPORT CacheStorage : public CacheStorageCacheObserver {
void MatchCacheDidMatch(CacheStorageCacheHandle cache_handle,
CacheStorageCache::ResponseCallback callback,
blink::mojom::CacheStorageError error,
- std::unique_ptr<ServiceWorkerResponse> response);
+ blink::mojom::FetchAPIResponsePtr response);
// The MatchAllCaches callbacks are below.
void MatchAllCachesImpl(std::unique_ptr<ServiceWorkerFetchRequest> request,
blink::mojom::QueryParamsPtr match_params,
CacheStorageCache::ResponseCallback callback);
- void MatchAllCachesDidMatch(
- CacheStorageCacheHandle cache_handle,
- CacheMatchResponse* out_match_response,
- const base::RepeatingClosure& barrier_closure,
- blink::mojom::CacheStorageError error,
- std::unique_ptr<ServiceWorkerResponse> service_worker_response);
+ void MatchAllCachesDidMatch(CacheStorageCacheHandle cache_handle,
+ CacheMatchResponse* out_match_response,
+ const base::RepeatingClosure& barrier_closure,
+ blink::mojom::CacheStorageError error,
+ blink::mojom::FetchAPIResponsePtr response);
void MatchAllCachesDidMatchAll(
std::unique_ptr<std::vector<CacheMatchResponse>> match_responses,
CacheStorageCache::ResponseCallback callback);
@@ -233,7 +232,7 @@ class CONTENT_EXPORT CacheStorage : public CacheStorageCacheObserver {
// WriteToCache callbacks.
void WriteToCacheImpl(const std::string& cache_name,
std::unique_ptr<ServiceWorkerFetchRequest> request,
- std::unique_ptr<ServiceWorkerResponse> response,
+ blink::mojom::FetchAPIResponsePtr response,
CacheStorage::ErrorCallback callback);
void GetSizeThenCloseAllCachesImpl(SizeCallback callback);
diff --git a/chromium/content/browser/cache_storage/cache_storage_cache.cc b/chromium/content/browser/cache_storage/cache_storage_cache.cc
index f853ed819ad..a4e3aa14d58 100644
--- a/chromium/content/browser/cache_storage/cache_storage_cache.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_cache.cc
@@ -14,6 +14,7 @@
#include "base/barrier_closure.h"
#include "base/bind_helpers.h"
+#include "base/containers/flat_map.h"
#include "base/files/file_path.h"
#include "base/guid.h"
#include "base/macros.h"
@@ -22,6 +23,7 @@
#include "base/numerics/checked_math.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/cache_storage/cache_storage.pb.h"
#include "content/browser/cache_storage/cache_storage_blob_to_disk_cache.h"
@@ -48,14 +50,18 @@
#include "storage/browser/quota/quota_manager_proxy.h"
#include "storage/common/blob_storage/blob_handle.h"
#include "storage/common/storage_histograms.h"
+#include "third_party/blink/public/common/cache_storage/cache_storage_utils.h"
#include "third_party/blink/public/mojom/quota/quota_types.mojom.h"
using blink::mojom::CacheStorageError;
+using blink::mojom::CacheStorageVerboseError;
namespace content {
namespace {
+using ResponseHeaderMap = base::flat_map<std::string, std::string>;
+
const size_t kMaxQueryCacheResultBytes =
1024 * 1024 * 10; // 10MB query cache limit
@@ -131,8 +137,12 @@ void ReadMetadataDidReadMetadata(disk_cache::Entry* entry,
bool VaryMatches(const ServiceWorkerHeaderMap& request,
const ServiceWorkerHeaderMap& cached_request,
- const ServiceWorkerHeaderMap& response) {
- ServiceWorkerHeaderMap::const_iterator vary_iter = response.find("vary");
+ const ResponseHeaderMap& response) {
+ auto vary_iter = std::find_if(
+ response.begin(), response.end(),
+ [](const ResponseHeaderMap::value_type& pair) -> bool {
+ return base::CompareCaseInsensitiveASCII(pair.first, "vary") == 0;
+ });
if (vary_iter == response.end())
return true;
@@ -161,6 +171,84 @@ bool VaryMatches(const ServiceWorkerHeaderMap& request,
return true;
}
+// Check a batch operation list for duplicate entries. A StackVector
+// must be passed to store any resulting duplicate URL strings. Returns
+// true if any duplicates were found.
+bool FindDuplicateOperations(
+ const std::vector<blink::mojom::BatchOperationPtr>& operations,
+ std::vector<std::string>* duplicate_url_list_out) {
+ using blink::mojom::BatchOperation;
+ DCHECK(duplicate_url_list_out);
+
+ if (operations.size() < 2) {
+ return false;
+ }
+
+ // Create a temporary sorted vector of the operations to support quickly
+ // finding potentially duplicate entries. Multiple entries may have the
+ // same URL, but differ by VARY header, so a sorted list is easier to
+ // work with than a map.
+ //
+ // Note, this will use 512 bytes of stack space on 64-bit devices. The
+ // static size attempts to accommodate most typical Cache.addAll() uses in
+ // service worker install events while not blowing up the stack too much.
+ base::StackVector<BatchOperation*, 64> sorted;
+ sorted->reserve(operations.size());
+ for (const auto& op : operations) {
+ sorted->push_back(op.get());
+ }
+ std::sort(sorted->begin(), sorted->end(),
+ [](BatchOperation* left, BatchOperation* right) {
+ return left->request.url < right->request.url;
+ });
+
+ // Check each entry in the sorted vector for any duplicates. Since the
+ // list is sorted we only need to inspect the immediate neighbors that
+ // have the same URL. This results in an average complexity of O(n log n).
+ // If the entire list has entries with the same URL and different VARY
+ // headers then this devolves into O(n^2).
+ for (auto outer = sorted->cbegin(); outer != sorted->cend(); ++outer) {
+ const BatchOperation* outer_op = *outer;
+
+ // Note, the spec checks CacheQueryOptions like ignoreSearch, etc, but
+ // currently there is no way for script to trigger a batch operation with
+ // multiple entries and non-default options. The only exposed API that
+ // supports multiple operations is addAll() and it does not allow options
+ // to be passed. Therefore we assume we do not need to take any options
+ // into account here.
+ DCHECK(!outer_op->match_params);
+
+ // If this entry already matches a duplicate we found, then just skip
+ // ahead to find any remaining duplicates.
+ if (!duplicate_url_list_out->empty() &&
+ outer_op->request.url.spec() == duplicate_url_list_out->back()) {
+ continue;
+ }
+
+ for (auto inner = std::next(outer); inner != sorted->cend(); ++inner) {
+ const BatchOperation* inner_op = *inner;
+ // Since the list is sorted we can stop looking at neighbors after
+ // the first different URL.
+ if (outer_op->request.url != inner_op->request.url) {
+ break;
+ }
+ // VaryMatches() is asymmetric since the operation depends on the VARY
+ // header in the target response. Since we only visit each pair of
+ // entries once we need to perform the VaryMatches() call in both
+ // directions.
+ if (VaryMatches(outer_op->request.headers, inner_op->request.headers,
+ inner_op->response->headers) ||
+ VaryMatches(outer_op->request.headers, inner_op->request.headers,
+ outer_op->response->headers)) {
+ duplicate_url_list_out->push_back(inner_op->request.url.spec());
+ break;
+ }
+ }
+ }
+
+ return !duplicate_url_list_out->empty();
+}
+
GURL RemoveQueryParam(const GURL& url) {
url::Replacements<char> replacements;
replacements.ClearQuery();
@@ -223,42 +311,41 @@ std::unique_ptr<ServiceWorkerFetchRequest> CreateRequest(
return request;
}
-std::unique_ptr<ServiceWorkerResponse> CreateResponse(
+blink::mojom::FetchAPIResponsePtr CreateResponse(
const proto::CacheMetadata& metadata,
const std::string& cache_name) {
- std::unique_ptr<std::vector<GURL>> url_list =
- std::make_unique<std::vector<GURL>>();
+ std::vector<GURL> url_list;
// From Chrome 57, proto::CacheMetadata's url field was deprecated.
UMA_HISTOGRAM_BOOLEAN("ServiceWorkerCache.Response.HasDeprecatedURL",
metadata.response().has_url());
if (metadata.response().has_url()) {
- url_list->push_back(GURL(metadata.response().url()));
+ url_list.push_back(GURL(metadata.response().url()));
} else {
- url_list->reserve(metadata.response().url_list_size());
+ url_list.reserve(metadata.response().url_list_size());
for (int i = 0; i < metadata.response().url_list_size(); ++i)
- url_list->push_back(GURL(metadata.response().url_list(i)));
+ url_list.push_back(GURL(metadata.response().url_list(i)));
}
- std::unique_ptr<ServiceWorkerHeaderMap> headers =
- std::make_unique<ServiceWorkerHeaderMap>();
+ ResponseHeaderMap headers;
for (int i = 0; i < metadata.response().headers_size(); ++i) {
const proto::CacheHeaderMap header = metadata.response().headers(i);
DCHECK_EQ(std::string::npos, header.name().find('\0'));
DCHECK_EQ(std::string::npos, header.value().find('\0'));
- headers->insert(std::make_pair(header.name(), header.value()));
+ headers.insert(std::make_pair(header.name(), header.value()));
}
- return std::make_unique<ServiceWorkerResponse>(
- std::move(url_list), metadata.response().status_code(),
+ return blink::mojom::FetchAPIResponse::New(
+ url_list, metadata.response().status_code(),
metadata.response().status_text(),
ProtoResponseTypeToFetchResponseType(metadata.response().response_type()),
- std::move(headers), "", 0, nullptr /* blob */,
+ headers, nullptr /* blob */,
blink::mojom::ServiceWorkerResponseError::kUnknown,
base::Time::FromInternalValue(metadata.response().response_time()),
- true /* is_in_cache_storage */, cache_name,
- std::make_unique<ServiceWorkerHeaderList>(
+ cache_name,
+ std::vector<std::string>(
metadata.response().cors_exposed_header_names().begin(),
- metadata.response().cors_exposed_header_names().end()));
+ metadata.response().cors_exposed_header_names().end()),
+ true /* is_in_cache_storage */, nullptr /* side_data_blob */);
}
// The size of opaque (non-cors) resource responses are padded in order
@@ -285,9 +372,9 @@ bool ShouldPadResourceSize(const content::proto::CacheResponse* response) {
response->url_list_size());
}
-bool ShouldPadResourceSize(const ServiceWorkerResponse* response) {
- return ShouldPadResponseType(response->response_type,
- !response->url_list.empty());
+bool ShouldPadResourceSize(const blink::mojom::FetchAPIResponse& response) {
+ return ShouldPadResponseType(response.response_type,
+ !response.url_list.empty());
}
int64_t CalculateResponsePaddingInternal(
@@ -357,7 +444,7 @@ class CacheStorageCache::BlobDataHandle
// The state needed to pass between CacheStorageCache::Put callbacks.
struct CacheStorageCache::PutContext {
PutContext(std::unique_ptr<ServiceWorkerFetchRequest> request,
- std::unique_ptr<ServiceWorkerResponse> response,
+ blink::mojom::FetchAPIResponsePtr response,
blink::mojom::BlobPtr blob,
blink::mojom::BlobPtr side_data_blob,
CacheStorageCache::ErrorCallback callback)
@@ -369,7 +456,7 @@ struct CacheStorageCache::PutContext {
// Input parameters to the Put function.
std::unique_ptr<ServiceWorkerFetchRequest> request;
- std::unique_ptr<ServiceWorkerResponse> response;
+ blink::mojom::FetchAPIResponsePtr response;
blink::mojom::BlobPtr blob;
blink::mojom::BlobPtr side_data_blob;
@@ -384,7 +471,7 @@ struct CacheStorageCache::QueryCacheResult {
explicit QueryCacheResult(base::Time entry_time) : entry_time(entry_time) {}
std::unique_ptr<ServiceWorkerFetchRequest> request;
- std::unique_ptr<ServiceWorkerResponse> response;
+ blink::mojom::FetchAPIResponsePtr response;
disk_cache::ScopedEntryPtr entry;
base::Time entry_time;
};
@@ -495,7 +582,7 @@ void CacheStorageCache::MatchAll(
ResponsesCallback callback) {
if (backend_state_ == BACKEND_CLOSED) {
std::move(callback).Run(CacheStorageError::kErrorStorage,
- std::vector<ServiceWorkerResponse>());
+ std::vector<blink::mojom::FetchAPIResponsePtr>());
return;
}
@@ -529,31 +616,83 @@ void CacheStorageCache::WriteSideData(ErrorCallback callback,
void CacheStorageCache::BatchOperation(
std::vector<blink::mojom::BatchOperationPtr> operations,
- ErrorCallback callback,
+ bool fail_on_duplicates,
+ VerboseErrorCallback callback,
BadMessageCallback bad_message_callback) {
+ // This method may produce a warning message that should be returned in the
+ // final VerboseErrorCallback. A message may be present in both the failure
+ // and success paths.
+ base::Optional<std::string> message;
+
if (backend_state_ == BACKEND_CLOSED) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::BindOnce(std::move(callback), CacheStorageError::kErrorStorage));
+ FROM_HERE, base::BindOnce(std::move(callback),
+ CacheStorageVerboseError::New(
+ CacheStorageError::kErrorStorage,
+ std::move(message))));
return;
}
+ // From BatchCacheOperations:
+ //
+ // https://w3c.github.io/ServiceWorker/#batch-cache-operations-algorithm
+ //
+ // "If the result of running Query Cache with operation’s request,
+ // operation’s options, and addedItems is not empty, throw an
+ // InvalidStateError DOMException."
+ //
+ // Note, we are currently only rejecting on duplicates based on a feature
+ // flag while web compat is assessed. (https://crbug.com/720919)
+ std::vector<std::string> duplicate_url_list;
+ if (FindDuplicateOperations(operations, &duplicate_url_list)) {
+ // If we found any duplicates we need to at least warn the user. Format
+ // the URL list into a comma-separated list.
+ std::string url_list_string = base::JoinString(duplicate_url_list, ", ");
+
+ // Place the duplicate list into an error message.
+ // NOTE: This must use kDuplicateOperationsBaseMessage in the string so
+ // that the renderer can identify successes with duplicates and log the
+ // appropriate use counter.
+ // TODO(crbug.com/877737): Remove this note once the cache.addAll()
+ // duplicate rejection finally ships.
+ message.emplace(base::StringPrintf(
+ "%s (%s)", blink::cache_storage::kDuplicateOperationBaseMessage,
+ url_list_string.c_str()));
+
+ // Depending on the feature flag, we may treat this as an error or allow
+ // the batch operation to continue.
+ if (fail_on_duplicates) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(std::move(callback),
+ CacheStorageVerboseError::New(
+ CacheStorageError::kErrorDuplicateOperation,
+ std::move(message))));
+ return;
+ }
+ }
+
// Estimate the required size of the put operations. The size of the deletes
// is unknown and not considered.
base::CheckedNumeric<uint64_t> safe_space_required = 0;
base::CheckedNumeric<uint64_t> safe_side_data_size = 0;
for (const auto& operation : operations) {
if (operation->operation_type == blink::mojom::OperationType::kPut) {
- safe_space_required += operation->response->blob_size;
- safe_side_data_size += operation->response->side_data_blob_size;
+ safe_space_required +=
+ (operation->response->blob ? operation->response->blob->size : 0);
+ safe_side_data_size += (operation->response->side_data_blob
+ ? operation->response->side_data_blob->size
+ : 0);
}
}
if (!safe_space_required.IsValid() || !safe_side_data_size.IsValid()) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, std::move(bad_message_callback));
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::BindOnce(std::move(callback), CacheStorageError::kErrorStorage));
+ FROM_HERE, base::BindOnce(std::move(callback),
+ CacheStorageVerboseError::New(
+ CacheStorageError::kErrorStorage,
+ std::move(message))));
return;
}
uint64_t space_required = safe_space_required.ValueOrDie();
@@ -570,12 +709,12 @@ void CacheStorageCache::BatchOperation(
base::BindOnce(&CacheStorageCache::BatchDidGetUsageAndQuota,
weak_ptr_factory_.GetWeakPtr(), std::move(operations),
std::move(callback), std::move(bad_message_callback),
- space_required, side_data_size));
+ std::move(message), space_required, side_data_size));
return;
}
BatchDidGetUsageAndQuota(std::move(operations), std::move(callback),
- std::move(bad_message_callback),
+ std::move(bad_message_callback), std::move(message),
0 /* space_required */, 0 /* side_data_size */,
blink::mojom::QuotaStatusCode::kOk, 0 /* usage */,
0 /* quota */);
@@ -583,8 +722,9 @@ void CacheStorageCache::BatchOperation(
void CacheStorageCache::BatchDidGetUsageAndQuota(
std::vector<blink::mojom::BatchOperationPtr> operations,
- ErrorCallback callback,
+ VerboseErrorCallback callback,
BadMessageCallback bad_message_callback,
+ base::Optional<std::string> message,
uint64_t space_required,
uint64_t side_data_size,
blink::mojom::QuotaStatusCode status_code,
@@ -599,15 +739,19 @@ void CacheStorageCache::BatchDidGetUsageAndQuota(
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, std::move(bad_message_callback));
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::BindOnce(std::move(callback), CacheStorageError::kErrorStorage));
+ FROM_HERE, base::BindOnce(std::move(callback),
+ CacheStorageVerboseError::New(
+ CacheStorageError::kErrorStorage,
+ std::move(message))));
return;
}
if (status_code != blink::mojom::QuotaStatusCode::kOk ||
safe_space_required.ValueOrDie() > quota) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(std::move(callback),
- CacheStorageError::kErrorQuotaExceeded));
+ CacheStorageVerboseError::New(
+ CacheStorageError::kErrorQuotaExceeded,
+ std::move(message))));
return;
}
bool skip_side_data = safe_space_required_with_side_data.ValueOrDie() > quota;
@@ -620,10 +764,10 @@ void CacheStorageCache::BatchDidGetUsageAndQuota(
auto barrier_closure = base::BarrierClosure(
operations.size(),
base::BindOnce(&CacheStorageCache::BatchDidAllOperations,
- weak_ptr_factory_.GetWeakPtr(), callback_copy));
+ weak_ptr_factory_.GetWeakPtr(), callback_copy, message));
auto completion_callback = base::BindRepeating(
&CacheStorageCache::BatchDidOneOperation, weak_ptr_factory_.GetWeakPtr(),
- std::move(barrier_closure), std::move(callback_copy));
+ std::move(barrier_closure), std::move(callback_copy), std::move(message));
// Operations may synchronously invoke |callback| which could release the
// last reference to this instance. Hold a handle for the duration of this
@@ -635,8 +779,6 @@ void CacheStorageCache::BatchDidGetUsageAndQuota(
switch (operation->operation_type) {
case blink::mojom::OperationType::kPut:
if (skip_side_data) {
- operation->response->side_data_blob_uuid = std::string();
- operation->response->side_data_blob_size = 0;
operation->response->side_data_blob = nullptr;
Put(std::move(operation), completion_callback);
} else {
@@ -659,21 +801,26 @@ void CacheStorageCache::BatchDidGetUsageAndQuota(
void CacheStorageCache::BatchDidOneOperation(
base::OnceClosure completion_closure,
- ErrorCallback error_callback,
+ VerboseErrorCallback error_callback,
+ base::Optional<std::string> message,
CacheStorageError error) {
if (error != CacheStorageError::kSuccess) {
// This relies on |callback| being created by AdaptCallbackForRepeating
// and ignoring anything but the first invocation.
- std::move(error_callback).Run(error);
+ std::move(error_callback)
+ .Run(CacheStorageVerboseError::New(error, std::move(message)));
}
std::move(completion_closure).Run();
}
-void CacheStorageCache::BatchDidAllOperations(ErrorCallback callback) {
+void CacheStorageCache::BatchDidAllOperations(
+ VerboseErrorCallback callback,
+ base::Optional<std::string> message) {
// This relies on |callback| being created by AdaptCallbackForRepeating
// and ignoring anything but the first invocation.
- std::move(callback).Run(CacheStorageError::kSuccess);
+ std::move(callback).Run(CacheStorageVerboseError::New(
+ CacheStorageError::kSuccess, std::move(message)));
}
void CacheStorageCache::Keys(std::unique_ptr<ServiceWorkerFetchRequest> request,
@@ -967,7 +1114,7 @@ void CacheStorageCache::QueryCacheDidReadMetadata(
if (query_cache_context->query_types & QUERY_CACHE_RESPONSES_WITH_BODIES) {
query_cache_context->estimated_out_bytes +=
- match->response->EstimatedStructSize();
+ EstimatedResponseSizeWithoutBlob(*match->response);
if (query_cache_context->estimated_out_bytes > max_query_size_bytes_) {
std::move(query_cache_context->callback)
.Run(CacheStorageError::kErrorQueryTooLarge, nullptr);
@@ -1000,11 +1147,29 @@ bool CacheStorageCache::QueryCacheResultCompare(const QueryCacheResult& lhs,
}
// static
+size_t CacheStorageCache::EstimatedResponseSizeWithoutBlob(
+ const blink::mojom::FetchAPIResponse& response) {
+ size_t size = sizeof(blink::mojom::FetchAPIResponse);
+ for (const auto& url : response.url_list)
+ size += url.spec().size();
+ size += response.status_text.size();
+ if (response.cache_storage_cache_name)
+ size += response.cache_storage_cache_name->size();
+ for (const auto& key_and_value : response.headers) {
+ size += key_and_value.first.size();
+ size += key_and_value.second.size();
+ }
+ for (const auto& header : response.cors_exposed_header_names)
+ size += header.size();
+ return size;
+}
+
+// static
int64_t CacheStorageCache::CalculateResponsePadding(
- const ServiceWorkerResponse& response,
+ const blink::mojom::FetchAPIResponse& response,
const crypto::SymmetricKey* padding_key,
int side_data_size) {
- if (!ShouldPadResourceSize(&response))
+ if (!ShouldPadResourceSize(response))
return 0;
return CalculateResponsePaddingInternal(response.url_list.back().spec(),
padding_key, side_data_size);
@@ -1028,7 +1193,7 @@ void CacheStorageCache::MatchImpl(
void CacheStorageCache::MatchDidMatchAll(
ResponseCallback callback,
CacheStorageError match_all_error,
- std::vector<ServiceWorkerResponse> match_all_responses) {
+ std::vector<blink::mojom::FetchAPIResponsePtr> match_all_responses) {
if (match_all_error != CacheStorageError::kSuccess) {
std::move(callback).Run(match_all_error, nullptr);
return;
@@ -1039,10 +1204,8 @@ void CacheStorageCache::MatchDidMatchAll(
return;
}
- std::unique_ptr<ServiceWorkerResponse> response =
- std::make_unique<ServiceWorkerResponse>(match_all_responses[0]);
-
- std::move(callback).Run(CacheStorageError::kSuccess, std::move(response));
+ std::move(callback).Run(CacheStorageError::kSuccess,
+ std::move(match_all_responses[0]));
}
void CacheStorageCache::MatchAllImpl(
@@ -1052,7 +1215,7 @@ void CacheStorageCache::MatchAllImpl(
DCHECK_NE(BACKEND_UNINITIALIZED, backend_state_);
if (backend_state_ != BACKEND_OPEN) {
std::move(callback).Run(CacheStorageError::kErrorStorage,
- std::vector<ServiceWorkerResponse>());
+ std::vector<blink::mojom::FetchAPIResponsePtr>());
return;
}
@@ -1068,15 +1231,16 @@ void CacheStorageCache::MatchAllDidQueryCache(
CacheStorageError error,
std::unique_ptr<QueryCacheResults> query_cache_results) {
if (error != CacheStorageError::kSuccess) {
- std::move(callback).Run(error, std::vector<ServiceWorkerResponse>());
+ std::move(callback).Run(error,
+ std::vector<blink::mojom::FetchAPIResponsePtr>());
return;
}
- std::vector<ServiceWorkerResponse> out_responses;
+ std::vector<blink::mojom::FetchAPIResponsePtr> out_responses;
out_responses.reserve(query_cache_results->size());
for (auto& result : *query_cache_results) {
- out_responses.push_back(*result.response);
+ out_responses.push_back(std::move(result.response));
}
std::move(callback).Run(CacheStorageError::kSuccess,
@@ -1232,14 +1396,11 @@ void CacheStorageCache::Put(blink::mojom::BatchOperationPtr operation,
operation->request.headers, operation->request.referrer,
operation->request.is_reload));
- std::unique_ptr<ServiceWorkerResponse> response =
- std::make_unique<ServiceWorkerResponse>(*operation->response);
-
- Put(std::move(request), std::move(response), std::move(callback));
+ Put(std::move(request), std::move(operation->response), std::move(callback));
}
void CacheStorageCache::Put(std::unique_ptr<ServiceWorkerFetchRequest> request,
- std::unique_ptr<ServiceWorkerResponse> response,
+ blink::mojom::FetchAPIResponsePtr response,
ErrorCallback callback) {
DCHECK(BACKEND_OPEN == backend_state_ || initializing_);
@@ -1247,9 +1408,9 @@ void CacheStorageCache::Put(std::unique_ptr<ServiceWorkerFetchRequest> request,
blink::mojom::BlobPtr side_data_blob;
if (response->blob)
- blob = response->blob->Clone();
+ blob.Bind(std::move(response->blob->blob));
if (response->side_data_blob)
- side_data_blob = response->side_data_blob->Clone();
+ side_data_blob.Bind(std::move(response->side_data_blob->blob));
UMA_HISTOGRAM_ENUMERATION("ServiceWorkerCache.Cache.AllWritesResponseType",
response->response_type);
@@ -1355,7 +1516,7 @@ void CacheStorageCache::PutDidCreateEntry(
response_metadata->add_url_list(url.spec());
response_metadata->set_response_time(
put_context->response->response_time.ToInternalValue());
- for (ServiceWorkerHeaderMap::const_iterator it =
+ for (ResponseHeaderMap::const_iterator it =
put_context->response->headers.begin();
it != put_context->response->headers.end(); ++it) {
DCHECK_EQ(std::string::npos, it->first.find('\0'));
@@ -1405,7 +1566,7 @@ void CacheStorageCache::PutDidWriteHeaders(
if (rv > 0)
storage::RecordBytesWritten(kRecordBytesLabel, rv);
- if (ShouldPadResourceSize(put_context->response.get())) {
+ if (ShouldPadResourceSize(*put_context->response)) {
cache_padding_ += CalculateResponsePadding(*put_context->response,
cache_padding_key_.get(),
0 /* side_data_size */);
@@ -1413,7 +1574,8 @@ void CacheStorageCache::PutDidWriteHeaders(
// The metadata is written, now for the response content. The data is streamed
// from the blob into the cache entry.
- if (put_context->response->blob_uuid.empty()) {
+ if (!put_context->response->blob ||
+ put_context->response->blob->uuid.empty()) {
UpdateCacheSize(base::BindOnce(std::move(put_context->callback),
CacheStorageError::kSuccess));
return;
@@ -1508,7 +1670,7 @@ void CacheStorageCache::PaddingDidQueryCache(
int64_t cache_padding = 0;
if (error == CacheStorageError::kSuccess) {
for (const auto& result : *query_cache_results) {
- if (ShouldPadResourceSize(result.response.get())) {
+ if (ShouldPadResourceSize(*result.response)) {
int32_t side_data_size =
result.entry ? result.entry->GetDataSize(INDEX_SIDE_DATA) : 0;
cache_padding += CalculateResponsePadding(
@@ -1612,7 +1774,7 @@ void CacheStorageCache::DeleteDidQueryCache(
for (auto& result : *query_cache_results) {
disk_cache::ScopedEntryPtr entry = std::move(result.entry);
- if (ShouldPadResourceSize(result.response.get())) {
+ if (ShouldPadResourceSize(*result.response)) {
cache_padding_ -=
CalculateResponsePadding(*result.response, cache_padding_key_.get(),
entry->GetDataSize(INDEX_SIDE_DATA));
@@ -1759,7 +1921,7 @@ void CacheStorageCache::InitDidCreateBackend(
auto calculate_size_callback =
base::AdaptCallbackForRepeating(std::move(callback));
- int rv = backend_->CalculateSizeOfAllEntries(base::Bind(
+ int rv = backend_->CalculateSizeOfAllEntries(base::BindOnce(
&CacheStorageCache::InitGotCacheSize, weak_ptr_factory_.GetWeakPtr(),
calculate_size_callback, cache_create_error));
@@ -1836,15 +1998,17 @@ void CacheStorageCache::InitGotCacheSizeAndPadding(
std::move(callback).Run();
}
-void CacheStorageCache::PopulateResponseBody(disk_cache::ScopedEntryPtr entry,
- ServiceWorkerResponse* response) {
+void CacheStorageCache::PopulateResponseBody(
+ disk_cache::ScopedEntryPtr entry,
+ blink::mojom::FetchAPIResponse* response) {
DCHECK(blob_storage_context_);
// Create a blob with the response body data.
- response->blob_size = entry->GetDataSize(INDEX_RESPONSE_BODY);
- response->blob_uuid = base::GenerateGUID();
+ response->blob = blink::mojom::SerializedBlob::New();
+ response->blob->size = entry->GetDataSize(INDEX_RESPONSE_BODY);
+ response->blob->uuid = base::GenerateGUID();
auto blob_data =
- std::make_unique<storage::BlobDataBuilder>(response->blob_uuid);
+ std::make_unique<storage::BlobDataBuilder>(response->blob->uuid);
disk_cache::Entry* temp_entry = entry.get();
auto data_handle = base::MakeRefCounted<BlobDataHandle>(CreateCacheHandle(),
@@ -1855,10 +2019,8 @@ void CacheStorageCache::PopulateResponseBody(disk_cache::ScopedEntryPtr entry,
auto blob_handle =
blob_storage_context_->AddFinishedBlob(std::move(blob_data));
- blink::mojom::BlobPtr blob_ptr;
- storage::BlobImpl::Create(std::move(blob_handle), MakeRequest(&blob_ptr));
- response->blob =
- base::MakeRefCounted<storage::BlobHandle>(std::move(blob_ptr));
+ storage::BlobImpl::Create(std::move(blob_handle),
+ MakeRequest(&response->blob->blob));
}
CacheStorageCacheHandle CacheStorageCache::CreateCacheHandle() {
diff --git a/chromium/content/browser/cache_storage/cache_storage_cache.h b/chromium/content/browser/cache_storage/cache_storage_cache.h
index f065161eedb..d0ab8ce63db 100644
--- a/chromium/content/browser/cache_storage/cache_storage_cache.h
+++ b/chromium/content/browser/cache_storage/cache_storage_cache.h
@@ -16,6 +16,7 @@
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
+#include "base/optional.h"
#include "content/common/service_worker/service_worker_types.h"
#include "net/base/io_buffer.h"
#include "net/disk_cache/disk_cache.h"
@@ -63,13 +64,15 @@ class CONTENT_EXPORT CacheStorageCache {
public:
using ErrorCallback =
base::OnceCallback<void(blink::mojom::CacheStorageError)>;
+ using VerboseErrorCallback =
+ base::OnceCallback<void(blink::mojom::CacheStorageVerboseErrorPtr)>;
using BadMessageCallback = base::OnceCallback<void()>;
using ResponseCallback =
base::OnceCallback<void(blink::mojom::CacheStorageError,
- std::unique_ptr<ServiceWorkerResponse>)>;
+ blink::mojom::FetchAPIResponsePtr)>;
using ResponsesCallback =
base::OnceCallback<void(blink::mojom::CacheStorageError,
- std::vector<ServiceWorkerResponse>)>;
+ std::vector<blink::mojom::FetchAPIResponsePtr>)>;
using Requests = std::vector<ServiceWorkerFetchRequest>;
using RequestsCallback =
base::OnceCallback<void(blink::mojom::CacheStorageError,
@@ -101,7 +104,7 @@ class CONTENT_EXPORT CacheStorageCache {
int64_t cache_padding,
std::unique_ptr<crypto::SymmetricKey> cache_padding_key);
static int64_t CalculateResponsePadding(
- const ServiceWorkerResponse& response,
+ const blink::mojom::FetchAPIResponse& response,
const crypto::SymmetricKey* padding_key,
int side_data_size);
static int32_t GetResponsePaddingVersion();
@@ -144,12 +147,14 @@ class CONTENT_EXPORT CacheStorageCache {
// TODO(nhiroki): This function should run all operations atomically.
// http://crbug.com/486637
void BatchOperation(std::vector<blink::mojom::BatchOperationPtr> operations,
- ErrorCallback callback,
+ bool fail_on_duplicates,
+ VerboseErrorCallback callback,
BadMessageCallback bad_message_callback);
void BatchDidGetUsageAndQuota(
std::vector<blink::mojom::BatchOperationPtr> operations,
- ErrorCallback callback,
+ VerboseErrorCallback callback,
BadMessageCallback bad_message_callback,
+ base::Optional<std::string> message,
uint64_t space_required,
uint64_t side_data_size,
blink::mojom::QuotaStatusCode status_code,
@@ -159,11 +164,13 @@ class CONTENT_EXPORT CacheStorageCache {
// |error_callback|. Always invokes |completion_closure| to signal
// completion.
void BatchDidOneOperation(base::OnceClosure completion_closure,
- ErrorCallback error_callback,
+ VerboseErrorCallback error_callback,
+ base::Optional<std::string> message,
blink::mojom::CacheStorageError error);
// Callback invoked once all BatchDidOneOperation() calls have run.
// Invokes |error_callback|.
- void BatchDidAllOperations(ErrorCallback error_callback);
+ void BatchDidAllOperations(VerboseErrorCallback error_callback,
+ base::Optional<std::string> message);
// Returns blink::mojom::CacheStorageError::kSuccess and a vector of
// requests if there are no errors.
@@ -187,7 +194,7 @@ class CONTENT_EXPORT CacheStorageCache {
// by non-CacheAPI owners. The Cache Storage API uses batch operations defined
// in the dispatcher.
void Put(std::unique_ptr<ServiceWorkerFetchRequest> request,
- std::unique_ptr<ServiceWorkerResponse> response,
+ blink::mojom::FetchAPIResponsePtr response,
ErrorCallback callback);
// Async operations in progress will cancel and not run their callbacks.
@@ -288,14 +295,17 @@ class CONTENT_EXPORT CacheStorageCache {
std::unique_ptr<proto::CacheMetadata> metadata);
static bool QueryCacheResultCompare(const QueryCacheResult& lhs,
const QueryCacheResult& rhs);
+ static size_t EstimatedResponseSizeWithoutBlob(
+ const blink::mojom::FetchAPIResponse& response);
// Match callbacks
void MatchImpl(std::unique_ptr<ServiceWorkerFetchRequest> request,
blink::mojom::QueryParamsPtr match_params,
ResponseCallback callback);
- void MatchDidMatchAll(ResponseCallback callback,
- blink::mojom::CacheStorageError match_all_error,
- std::vector<ServiceWorkerResponse> match_all_responses);
+ void MatchDidMatchAll(
+ ResponseCallback callback,
+ blink::mojom::CacheStorageError match_all_error,
+ std::vector<blink::mojom::FetchAPIResponsePtr> match_all_responses);
// MatchAll callbacks
void MatchAllImpl(std::unique_ptr<ServiceWorkerFetchRequest> request,
@@ -443,7 +453,7 @@ class CONTENT_EXPORT CacheStorageCache {
void DeleteBackendCompletedIO();
void PopulateResponseBody(disk_cache::ScopedEntryPtr entry,
- ServiceWorkerResponse* response);
+ blink::mojom::FetchAPIResponse* response);
// Virtual for testing.
virtual CacheStorageCacheHandle CreateCacheHandle();
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 d20905a639a..5578dd58900 100644
--- a/chromium/content/browser/cache_storage/cache_storage_cache_unittest.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_cache_unittest.cc
@@ -53,6 +53,7 @@
#include "url/origin.h"
using blink::mojom::CacheStorageError;
+using blink::mojom::CacheStorageVerboseErrorPtr;
using storage::BlobDataItem;
namespace content {
@@ -61,6 +62,10 @@ namespace cache_storage_cache_unittest {
const char kTestData[] = "Hello World";
const char kOrigin[] = "http://example.com";
const char kCacheName[] = "test_cache";
+const GURL kBodyUrl("http://example.com/body.html");
+const GURL kBodyUrlWithQuery("http://example.com/body.html?query=test");
+const GURL kNoBodyUrl("http://example.com/no_body.html");
+const ServiceWorkerHeaderMap kHeaders({{"a", "a"}, {"b", "b"}});
// Returns a BlobProtocolHandler that uses |blob_storage_context|. Caller owns
// the memory.
@@ -70,6 +75,16 @@ std::unique_ptr<storage::BlobProtocolHandler> CreateMockBlobProtocolHandler(
new storage::BlobProtocolHandler(blob_storage_context));
}
+void SizeCallback(base::RunLoop* run_loop,
+ bool* callback_called,
+ int64_t* out_size,
+ int64_t size) {
+ *callback_called = true;
+ *out_size = size;
+ if (run_loop)
+ run_loop->Quit();
+}
+
// A disk_cache::Backend wrapper that can delay operations.
class DelayableBackend : public disk_cache::Backend {
public:
@@ -204,8 +219,8 @@ std::string CopySideData(blink::mojom::Blob* actual_blob) {
return output;
}
-bool ResponseMetadataEqual(const ServiceWorkerResponse& expected,
- const ServiceWorkerResponse& actual) {
+bool ResponseMetadataEqual(const blink::mojom::FetchAPIResponse& expected,
+ const blink::mojom::FetchAPIResponse& actual) {
EXPECT_EQ(expected.status_code, actual.status_code);
if (expected.status_code != actual.status_code)
return false;
@@ -220,18 +235,20 @@ bool ResponseMetadataEqual(const ServiceWorkerResponse& expected,
if (expected.url_list[i] != actual.url_list[i])
return false;
}
- EXPECT_EQ(expected.blob_size, actual.blob_size);
- if (expected.blob_size != actual.blob_size)
+ EXPECT_EQ(!expected.blob, !actual.blob);
+ if (!expected.blob != !actual.blob)
return false;
- if (expected.blob_size == 0) {
- EXPECT_STREQ("", actual.blob_uuid.c_str());
- if (!actual.blob_uuid.empty())
- return false;
- } else {
- EXPECT_STRNE("", actual.blob_uuid.c_str());
- if (actual.blob_uuid.empty())
- return false;
+ if (expected.blob) {
+ if (expected.blob->size == 0) {
+ EXPECT_STREQ("", actual.blob->uuid.c_str());
+ if (!actual.blob->uuid.empty())
+ return false;
+ } else {
+ EXPECT_STRNE("", actual.blob->uuid.c_str());
+ if (actual.blob->uuid.empty())
+ return false;
+ }
}
EXPECT_EQ(expected.response_time, actual.response_time);
@@ -262,11 +279,11 @@ bool ResponseSideDataEqual(const std::string& expected_side_data,
return expected_side_data == actual_body;
}
-ServiceWorkerResponse SetCacheName(const ServiceWorkerResponse& original) {
- ServiceWorkerResponse result(original);
- result.is_in_cache_storage = true;
- result.cache_storage_cache_name = kCacheName;
- return result;
+blink::mojom::FetchAPIResponsePtr SetCacheName(
+ blink::mojom::FetchAPIResponsePtr response) {
+ response->is_in_cache_storage = true;
+ response->cache_storage_cache_name = kCacheName;
+ return response;
}
std::unique_ptr<crypto::SymmetricKey> CreateTestPaddingKey() {
@@ -386,6 +403,14 @@ class CacheStorageCacheTest : public testing::Test {
CreateRequests(blob_storage_context);
+ response_time_ = base::Time::Now();
+ for (int i = 0; i < 100; ++i)
+ expected_blob_data_ += kTestData;
+ blob_handle_ = BuildBlobHandle("blob-id:myblob", expected_blob_data_);
+ storage::BlobImpl::Create(
+ std::make_unique<storage::BlobDataHandle>(*blob_handle_),
+ MakeRequest(&blob_ptr_));
+
cache_ = std::make_unique<TestCacheStorageCache>(
url::Origin::Create(GURL(kOrigin)), kCacheName, temp_dir_path,
nullptr /* CacheStorage */,
@@ -402,71 +427,46 @@ class CacheStorageCacheTest : public testing::Test {
}
void CreateRequests(ChromeBlobStorageContext* blob_storage_context) {
- ServiceWorkerHeaderMap headers;
- headers.insert(std::make_pair("a", "a"));
- headers.insert(std::make_pair("b", "b"));
body_request_ =
- ServiceWorkerFetchRequest(GURL("http://example.com/body.html"), "GET",
- headers, Referrer(), false);
+ ServiceWorkerFetchRequest(kBodyUrl, "GET", kHeaders, Referrer(), false);
body_request_with_query_ = ServiceWorkerFetchRequest(
- GURL("http://example.com/body.html?query=test"), "GET", headers,
- Referrer(), false);
- no_body_request_ =
- ServiceWorkerFetchRequest(GURL("http://example.com/no_body.html"),
- "GET", headers, Referrer(), false);
- body_head_request_ =
- ServiceWorkerFetchRequest(GURL("http://example.com/body.html"), "HEAD",
- headers, Referrer(), false);
-
- std::string expected_response;
- for (int i = 0; i < 100; ++i)
- expected_blob_data_ += kTestData;
+ kBodyUrlWithQuery, "GET", kHeaders, Referrer(), false);
+ no_body_request_ = ServiceWorkerFetchRequest(kNoBodyUrl, "GET", kHeaders,
+ Referrer(), false);
+ body_head_request_ = ServiceWorkerFetchRequest(kBodyUrl, "HEAD", kHeaders,
+ Referrer(), false);
+ }
- blob_handle_ = BuildBlobHandle("blob-id:myblob", expected_blob_data_);
+ blink::mojom::FetchAPIResponsePtr CreateBlobBodyResponse() {
+ auto blob = blink::mojom::SerializedBlob::New();
+ blob->uuid = blob_handle_->uuid();
+ blob->size = expected_blob_data_.size();
+ // Use cloned blob pointer for all responses with blob body.
+ blob_ptr_->Clone(mojo::MakeRequest(&blob->blob));
+
+ blink::mojom::FetchAPIResponsePtr response = CreateNoBodyResponse();
+ response->url_list = {kBodyUrl};
+ response->blob = std::move(blob);
+ return response;
+ }
- scoped_refptr<storage::BlobHandle> blob;
- blink::mojom::BlobPtr blob_ptr;
- storage::BlobImpl::Create(
- std::make_unique<storage::BlobDataHandle>(*blob_handle_),
- MakeRequest(&blob_ptr));
- blob = base::MakeRefCounted<storage::BlobHandle>(std::move(blob_ptr));
-
- body_response_ = CreateResponse(
- "http://example.com/body.html",
- std::make_unique<ServiceWorkerHeaderMap>(headers), blob_handle_->uuid(),
- expected_blob_data_.size(), blob,
- std::make_unique<
- ServiceWorkerHeaderList>() /* cors_exposed_header_names */);
-
- body_response_with_query_ =
- CreateResponse("http://example.com/body.html?query=test",
- std::make_unique<ServiceWorkerHeaderMap>(headers),
- blob_handle_->uuid(), expected_blob_data_.size(), blob,
- std::make_unique<ServiceWorkerHeaderList>(
- 1, "a") /* cors_exposed_header_names */);
-
- no_body_response_ = CreateResponse(
- "http://example.com/no_body.html",
- std::make_unique<ServiceWorkerHeaderMap>(headers), "", 0, nullptr,
- std::make_unique<
- ServiceWorkerHeaderList>() /* cors_exposed_header_names */);
+ blink::mojom::FetchAPIResponsePtr CreateBlobBodyResponseWithQuery() {
+ blink::mojom::FetchAPIResponsePtr response = CreateBlobBodyResponse();
+ response->url_list = {kBodyUrlWithQuery};
+ response->cors_exposed_header_names = {"a"};
+ return response;
}
- static ServiceWorkerResponse CreateResponse(
- const std::string& url,
- std::unique_ptr<ServiceWorkerHeaderMap> headers,
- const std::string& blob_uuid,
- uint64_t blob_size,
- scoped_refptr<storage::BlobHandle> blob_handle,
- std::unique_ptr<ServiceWorkerHeaderList> cors_exposed_header_names) {
- return ServiceWorkerResponse(
- std::make_unique<std::vector<GURL>>(1, GURL(url)), 200, "OK",
- network::mojom::FetchResponseType::kDefault, std::move(headers),
- blob_uuid, blob_size, std::move(blob_handle),
- blink::mojom::ServiceWorkerResponseError::kUnknown, base::Time::Now(),
- false /* is_in_cache_storage */,
- std::string() /* cache_storage_cache_name */,
- std::move(cors_exposed_header_names));
+ blink::mojom::FetchAPIResponsePtr CreateNoBodyResponse() {
+ return blink::mojom::FetchAPIResponse::New(
+ std::vector<GURL>({kNoBodyUrl}), 200, "OK",
+ network::mojom::FetchResponseType::kDefault,
+ base::flat_map<std::string, std::string>(kHeaders.cbegin(),
+ kHeaders.cend()),
+ nullptr /* blob */, blink::mojom::ServiceWorkerResponseError::kUnknown,
+ response_time_, std::string() /* cache_storage_cache_name */,
+ std::vector<std::string>() /* cors_exposed_header_names */,
+ false /* is_in_cache_storage */, nullptr /* side_data_blob */);
}
std::unique_ptr<storage::BlobDataHandle> BuildBlobHandle(
@@ -479,15 +479,13 @@ class CacheStorageCacheTest : public testing::Test {
}
void CopySideDataToResponse(storage::BlobDataHandle* side_data_blob_handle,
- ServiceWorkerResponse* response) {
- response->side_data_blob_uuid = side_data_blob_handle->uuid();
- response->side_data_blob_size = side_data_blob_handle->size();
- blink::mojom::BlobPtr blob_ptr;
+ blink::mojom::FetchAPIResponse* response) {
+ response->side_data_blob = blink::mojom::SerializedBlob::New();
+ response->side_data_blob->uuid = side_data_blob_handle->uuid();
+ response->side_data_blob->size = side_data_blob_handle->size();
storage::BlobImpl::Create(
std::make_unique<storage::BlobDataHandle>(*side_data_blob_handle),
- MakeRequest(&blob_ptr));
- response->side_data_blob =
- base::MakeRefCounted<storage::BlobHandle>(std::move(blob_ptr));
+ MakeRequest(&response->side_data_blob->blob));
}
std::unique_ptr<ServiceWorkerFetchRequest> CopyFetchRequest(
@@ -498,12 +496,13 @@ class CacheStorageCacheTest : public testing::Test {
}
CacheStorageError BatchOperation(
- std::vector<blink::mojom::BatchOperationPtr> operations) {
+ std::vector<blink::mojom::BatchOperationPtr> operations,
+ bool fail_on_duplicates = true) {
std::unique_ptr<base::RunLoop> loop(new base::RunLoop());
cache_->BatchOperation(
- std::move(operations),
- base::BindOnce(&CacheStorageCacheTest::ErrorTypeCallback,
+ std::move(operations), fail_on_duplicates,
+ base::BindOnce(&CacheStorageCacheTest::VerboseErrorTypeCallback,
base::Unretained(this), base::Unretained(loop.get())),
base::BindOnce(&OnBadMessage, base::Unretained(&bad_message_reason_)));
// TODO(jkarlin): These functions should use base::RunLoop().RunUntilIdle()
@@ -514,12 +513,12 @@ class CacheStorageCacheTest : public testing::Test {
}
bool Put(const ServiceWorkerFetchRequest& request,
- const ServiceWorkerResponse& response) {
+ blink::mojom::FetchAPIResponsePtr response) {
blink::mojom::BatchOperationPtr operation =
blink::mojom::BatchOperation::New();
operation->operation_type = blink::mojom::OperationType::kPut;
operation->request = request;
- operation->response = response;
+ operation->response = std::move(response);
std::vector<blink::mojom::BatchOperationPtr> operations;
operations.emplace_back(std::move(operation));
@@ -542,7 +541,7 @@ class CacheStorageCacheTest : public testing::Test {
bool MatchAll(const ServiceWorkerFetchRequest& request,
blink::mojom::QueryParamsPtr match_params,
- std::vector<ServiceWorkerResponse>* responses) {
+ std::vector<blink::mojom::FetchAPIResponsePtr>* responses) {
base::RunLoop loop;
cache_->MatchAll(
CopyFetchRequest(request), std::move(match_params),
@@ -552,7 +551,7 @@ class CacheStorageCacheTest : public testing::Test {
return callback_error_ == CacheStorageError::kSuccess;
}
- bool MatchAll(std::vector<ServiceWorkerResponse>* responses) {
+ bool MatchAll(std::vector<blink::mojom::FetchAPIResponsePtr>* responses) {
return MatchAll(ServiceWorkerFetchRequest(), nullptr, responses);
}
@@ -615,23 +614,23 @@ class CacheStorageCacheTest : public testing::Test {
base::RunLoop run_loop;
bool callback_called = false;
- cache_->Size(base::BindOnce(&CacheStorageCacheTest::SizeCallback,
- base::Unretained(this), &run_loop,
- &callback_called));
+ int64_t result = 0;
+ cache_->Size(
+ base::BindOnce(&SizeCallback, &run_loop, &callback_called, &result));
run_loop.Run();
EXPECT_TRUE(callback_called);
- return callback_size_;
+ return result;
}
int64_t GetSizeThenClose() {
base::RunLoop run_loop;
bool callback_called = false;
+ int64_t result = 0;
cache_->GetSizeThenClose(
- base::BindOnce(&CacheStorageCacheTest::SizeCallback,
- base::Unretained(this), &run_loop, &callback_called));
+ base::BindOnce(&SizeCallback, &run_loop, &callback_called, &result));
run_loop.Run();
EXPECT_TRUE(callback_called);
- return callback_size_;
+ return result;
}
void RequestsCallback(base::RunLoop* run_loop,
@@ -647,7 +646,14 @@ class CacheStorageCacheTest : public testing::Test {
run_loop->Quit();
}
+ void VerboseErrorTypeCallback(base::RunLoop* run_loop,
+ CacheStorageVerboseErrorPtr error) {
+ ErrorTypeCallback(run_loop, error->value);
+ callback_message_ = error->message;
+ }
+
void ErrorTypeCallback(base::RunLoop* run_loop, CacheStorageError error) {
+ callback_message_ = base::nullopt;
callback_error_ = error;
if (run_loop)
run_loop->Quit();
@@ -656,17 +662,16 @@ class CacheStorageCacheTest : public testing::Test {
void SequenceCallback(int sequence,
int* sequence_out,
base::RunLoop* run_loop,
- CacheStorageError error) {
+ CacheStorageVerboseErrorPtr error) {
*sequence_out = sequence;
- callback_error_ = error;
+ callback_error_ = error->value;
if (run_loop)
run_loop->Quit();
}
- void ResponseAndErrorCallback(
- base::RunLoop* run_loop,
- CacheStorageError error,
- std::unique_ptr<ServiceWorkerResponse> response) {
+ void ResponseAndErrorCallback(base::RunLoop* run_loop,
+ CacheStorageError error,
+ blink::mojom::FetchAPIResponsePtr response) {
callback_error_ = error;
callback_response_ = std::move(response);
@@ -676,9 +681,9 @@ class CacheStorageCacheTest : public testing::Test {
void ResponsesAndErrorCallback(
base::OnceClosure quit_closure,
- std::vector<ServiceWorkerResponse>* responses_out,
+ std::vector<blink::mojom::FetchAPIResponsePtr>* responses_out,
CacheStorageError error,
- std::vector<ServiceWorkerResponse> responses) {
+ std::vector<blink::mojom::FetchAPIResponsePtr> responses) {
callback_error_ = error;
*responses_out = std::move(responses);
std::move(quit_closure).Run();
@@ -691,25 +696,17 @@ class CacheStorageCacheTest : public testing::Test {
run_loop->Quit();
}
- void SizeCallback(base::RunLoop* run_loop,
- bool* callback_called,
- int64_t size) {
- *callback_called = true;
- callback_size_ = size;
- if (run_loop)
- run_loop->Quit();
- }
-
bool TestResponseType(network::mojom::FetchResponseType response_type) {
- body_response_.response_type = response_type;
- EXPECT_TRUE(Put(body_request_, body_response_));
+ blink::mojom::FetchAPIResponsePtr body_response = CreateBlobBodyResponse();
+ body_response->response_type = response_type;
+ EXPECT_TRUE(Put(body_request_, std::move(body_response)));
EXPECT_TRUE(Match(body_request_));
EXPECT_TRUE(Delete(body_request_));
return response_type == callback_response_->response_type;
}
void VerifyAllOpsFail() {
- EXPECT_FALSE(Put(no_body_request_, no_body_response_));
+ EXPECT_FALSE(Put(no_body_request_, CreateNoBodyResponse()));
EXPECT_FALSE(Match(no_body_request_));
EXPECT_FALSE(Delete(body_request_));
EXPECT_FALSE(Keys());
@@ -721,6 +718,11 @@ class CacheStorageCacheTest : public testing::Test {
cache_->max_query_size_bytes_ = max_bytes;
}
+ size_t EstimatedResponseSizeWithoutBlob(
+ const blink::mojom::FetchAPIResponse& response) {
+ return CacheStorageCache::EstimatedResponseSizeWithoutBlob(response);
+ }
+
protected:
base::ScopedTempDir temp_dir_;
TestBrowserThreadBundle browser_thread_bundle_;
@@ -734,21 +736,21 @@ class CacheStorageCacheTest : public testing::Test {
std::unique_ptr<TestCacheStorageCache> cache_;
ServiceWorkerFetchRequest body_request_;
- ServiceWorkerResponse body_response_;
ServiceWorkerFetchRequest body_request_with_query_;
- ServiceWorkerResponse body_response_with_query_;
ServiceWorkerFetchRequest no_body_request_;
- ServiceWorkerResponse no_body_response_;
ServiceWorkerFetchRequest body_head_request_;
std::unique_ptr<storage::BlobDataHandle> blob_handle_;
+ // Holds a Mojo connection to the BlobImpl containing |blob_handle_|.
+ blink::mojom::BlobPtr blob_ptr_;
+ base::Time response_time_;
std::string expected_blob_data_;
CacheStorageError callback_error_ = CacheStorageError::kSuccess;
- std::unique_ptr<ServiceWorkerResponse> callback_response_;
+ base::Optional<std::string> callback_message_ = base::nullopt;
+ blink::mojom::FetchAPIResponsePtr callback_response_;
std::vector<std::string> callback_strings_;
std::string bad_message_reason_;
bool callback_closed_ = false;
- int64_t callback_size_ = 0;
};
class CacheStorageCacheTestP : public CacheStorageCacheTest,
@@ -758,11 +760,11 @@ class CacheStorageCacheTestP : public CacheStorageCacheTest,
};
TEST_P(CacheStorageCacheTestP, PutNoBody) {
- EXPECT_TRUE(Put(no_body_request_, no_body_response_));
+ EXPECT_TRUE(Put(no_body_request_, CreateNoBodyResponse()));
}
TEST_P(CacheStorageCacheTestP, PutBody) {
- EXPECT_TRUE(Put(body_request_, body_response_));
+ EXPECT_TRUE(Put(body_request_, CreateBlobBodyResponse()));
}
TEST_P(CacheStorageCacheTestP, PutBody_Multiple) {
@@ -771,42 +773,45 @@ TEST_P(CacheStorageCacheTestP, PutBody_Multiple) {
operation1->operation_type = blink::mojom::OperationType::kPut;
operation1->request = body_request_;
operation1->request.url = GURL("http://example.com/1");
- operation1->response = body_response_;
+ operation1->response = CreateBlobBodyResponse();
operation1->response->url_list.push_back(GURL("http://example.com/1"));
+ ServiceWorkerFetchRequest request1 = operation1->request;
blink::mojom::BatchOperationPtr operation2 =
blink::mojom::BatchOperation::New();
operation2->operation_type = blink::mojom::OperationType::kPut;
operation2->request = body_request_;
operation2->request.url = GURL("http://example.com/2");
- operation2->response = body_response_;
+ operation2->response = CreateBlobBodyResponse();
operation2->response->url_list.push_back(GURL("http://example.com/2"));
+ ServiceWorkerFetchRequest request2 = operation2->request;
blink::mojom::BatchOperationPtr operation3 =
blink::mojom::BatchOperation::New();
operation3->operation_type = blink::mojom::OperationType::kPut;
operation3->request = body_request_;
operation3->request.url = GURL("http://example.com/3");
- operation3->response = body_response_;
+ operation3->response = CreateBlobBodyResponse();
operation3->response->url_list.push_back(GURL("http://example.com/3"));
+ ServiceWorkerFetchRequest request3 = operation3->request;
std::vector<blink::mojom::BatchOperationPtr> operations;
- operations.push_back(operation1->Clone());
- operations.push_back(operation2->Clone());
- operations.push_back(operation3->Clone());
+ operations.push_back(std::move(operation1));
+ operations.push_back(std::move(operation2));
+ operations.push_back(std::move(operation3));
EXPECT_EQ(CacheStorageError::kSuccess, BatchOperation(std::move(operations)));
- EXPECT_TRUE(Match(operation1->request));
- EXPECT_TRUE(Match(operation2->request));
- EXPECT_TRUE(Match(operation3->request));
+ EXPECT_TRUE(Match(request1));
+ EXPECT_TRUE(Match(request2));
+ EXPECT_TRUE(Match(request3));
}
TEST_P(CacheStorageCacheTestP, MatchLimit) {
- EXPECT_TRUE(Put(no_body_request_, no_body_response_));
+ EXPECT_TRUE(Put(no_body_request_, CreateNoBodyResponse()));
EXPECT_TRUE(Match(no_body_request_));
size_t max_size = no_body_request_.EstimatedStructSize() +
- callback_response_->EstimatedStructSize();
+ EstimatedResponseSizeWithoutBlob(*callback_response_);
SetMaxQuerySizeBytes(max_size);
EXPECT_TRUE(Match(no_body_request_));
@@ -816,16 +821,18 @@ TEST_P(CacheStorageCacheTestP, MatchLimit) {
}
TEST_P(CacheStorageCacheTestP, MatchAllLimit) {
- EXPECT_TRUE(Put(body_request_, no_body_response_));
- EXPECT_TRUE(Put(body_request_with_query_, no_body_response_));
+ EXPECT_TRUE(Put(body_request_, CreateNoBodyResponse()));
+ EXPECT_TRUE(Put(body_request_with_query_, CreateNoBodyResponse()));
EXPECT_TRUE(Match(body_request_));
- size_t body_request_size = body_request_.EstimatedStructSize() +
- callback_response_->EstimatedStructSize();
- size_t query_request_size = body_request_with_query_.EstimatedStructSize() +
- callback_response_->EstimatedStructSize();
+ size_t body_request_size =
+ body_request_.EstimatedStructSize() +
+ EstimatedResponseSizeWithoutBlob(*callback_response_);
+ size_t query_request_size =
+ body_request_with_query_.EstimatedStructSize() +
+ EstimatedResponseSizeWithoutBlob(*callback_response_);
- std::vector<ServiceWorkerResponse> responses;
+ std::vector<blink::mojom::FetchAPIResponsePtr> responses;
blink::mojom::QueryParamsPtr match_params = blink::mojom::QueryParams::New();
// There is enough room for both requests and responses
@@ -849,8 +856,8 @@ TEST_P(CacheStorageCacheTestP, MatchAllLimit) {
}
TEST_P(CacheStorageCacheTestP, KeysLimit) {
- EXPECT_TRUE(Put(no_body_request_, no_body_response_));
- EXPECT_TRUE(Put(body_request_, body_response_));
+ EXPECT_TRUE(Put(no_body_request_, CreateNoBodyResponse()));
+ EXPECT_TRUE(Put(body_request_, CreateBlobBodyResponse()));
size_t max_size = no_body_request_.EstimatedStructSize() +
body_request_.EstimatedStructSize();
@@ -868,11 +875,12 @@ TEST_P(CacheStorageCacheTestP, KeysLimit) {
// browser side (http://crbug.com/425505).
TEST_P(CacheStorageCacheTestP, ResponseURLDiffersFromRequestURL) {
- no_body_response_.url_list.clear();
- no_body_response_.url_list.push_back(GURL("http://example.com/foobar"));
+ blink::mojom::FetchAPIResponsePtr no_body_response = CreateNoBodyResponse();
+ no_body_response->url_list.clear();
+ no_body_response->url_list.push_back(GURL("http://example.com/foobar"));
EXPECT_STRNE("http://example.com/foobar",
no_body_request_.url.spec().c_str());
- EXPECT_TRUE(Put(no_body_request_, no_body_response_));
+ EXPECT_TRUE(Put(no_body_request_, std::move(no_body_response)));
EXPECT_TRUE(Match(no_body_request_));
ASSERT_EQ(1u, callback_response_->url_list.size());
EXPECT_STREQ("http://example.com/foobar",
@@ -880,9 +888,10 @@ TEST_P(CacheStorageCacheTestP, ResponseURLDiffersFromRequestURL) {
}
TEST_P(CacheStorageCacheTestP, ResponseURLEmpty) {
- no_body_response_.url_list.clear();
+ blink::mojom::FetchAPIResponsePtr no_body_response = CreateNoBodyResponse();
+ no_body_response->url_list.clear();
EXPECT_STRNE("", no_body_request_.url.spec().c_str());
- EXPECT_TRUE(Put(no_body_request_, no_body_response_));
+ EXPECT_TRUE(Put(no_body_request_, std::move(no_body_response)));
EXPECT_TRUE(Match(no_body_request_));
EXPECT_EQ(0u, callback_response_->url_list.size());
}
@@ -892,14 +901,14 @@ TEST_P(CacheStorageCacheTestP, PutBodyDropBlobRef) {
blink::mojom::BatchOperation::New();
operation->operation_type = blink::mojom::OperationType::kPut;
operation->request = body_request_;
- operation->response = body_response_;
+ operation->response = CreateBlobBodyResponse();
std::vector<blink::mojom::BatchOperationPtr> operations;
operations.emplace_back(std::move(operation));
std::unique_ptr<base::RunLoop> loop(new base::RunLoop());
cache_->BatchOperation(
- std::move(operations),
- base::BindOnce(&CacheStorageCacheTestP::ErrorTypeCallback,
+ std::move(operations), true /* fail_on_duplicate */,
+ base::BindOnce(&CacheStorageCacheTestP::VerboseErrorTypeCallback,
base::Unretained(this), base::Unretained(loop.get())),
CacheStorageCache::BadMessageCallback());
// The handle should be held by the cache now so the deref here should be
@@ -911,16 +920,22 @@ TEST_P(CacheStorageCacheTestP, PutBodyDropBlobRef) {
}
TEST_P(CacheStorageCacheTestP, PutBadMessage) {
- blink::mojom::BatchOperationPtr operation =
- blink::mojom::BatchOperation::New();
- operation->operation_type = blink::mojom::OperationType::kPut;
- operation->request = body_request_;
- operation->response = body_response_;
- operation->response->blob_size = UINT64_MAX;
+ // Two unique puts that will collectively overflow unit64_t size of the
+ // batch operation.
+ blink::mojom::BatchOperationPtr operation1 =
+ blink::mojom::BatchOperation::New(blink::mojom::OperationType::kPut,
+ body_request_, CreateBlobBodyResponse(),
+ nullptr /* match_params */);
+ operation1->response->blob->size = std::numeric_limits<uint64_t>::max();
+ blink::mojom::BatchOperationPtr operation2 =
+ blink::mojom::BatchOperation::New(
+ blink::mojom::OperationType::kPut, body_request_with_query_,
+ CreateBlobBodyResponse(), nullptr /* match_params */);
+ operation2->response->blob->size = std::numeric_limits<uint64_t>::max();
std::vector<blink::mojom::BatchOperationPtr> operations;
- operations.push_back(operation->Clone());
- operations.push_back(operation->Clone());
+ operations.push_back(std::move(operation1));
+ operations.push_back(std::move(operation2));
EXPECT_EQ(CacheStorageError::kErrorStorage,
BatchOperation(std::move(operations)));
EXPECT_EQ("CSDH_UNEXPECTED_OPERATION", bad_message_reason_);
@@ -929,112 +944,148 @@ TEST_P(CacheStorageCacheTestP, PutBadMessage) {
}
TEST_P(CacheStorageCacheTestP, PutReplace) {
- EXPECT_TRUE(Put(body_request_, no_body_response_));
+ EXPECT_TRUE(Put(body_request_, CreateNoBodyResponse()));
EXPECT_TRUE(Match(body_request_));
EXPECT_FALSE(callback_response_->blob);
- EXPECT_TRUE(Put(body_request_, body_response_));
+ EXPECT_TRUE(Put(body_request_, CreateBlobBodyResponse()));
EXPECT_TRUE(Match(body_request_));
EXPECT_TRUE(callback_response_->blob);
- EXPECT_TRUE(Put(body_request_, no_body_response_));
+ EXPECT_TRUE(Put(body_request_, CreateNoBodyResponse()));
EXPECT_TRUE(Match(body_request_));
EXPECT_FALSE(callback_response_->blob);
}
-TEST_P(CacheStorageCacheTestP, PutReplaceInBatch) {
+TEST_P(CacheStorageCacheTestP, PutReplaceInBatchFails) {
blink::mojom::BatchOperationPtr operation1 =
blink::mojom::BatchOperation::New();
operation1->operation_type = blink::mojom::OperationType::kPut;
operation1->request = body_request_;
- operation1->response = no_body_response_;
+ operation1->response = CreateNoBodyResponse();
blink::mojom::BatchOperationPtr operation2 =
blink::mojom::BatchOperation::New();
operation2->operation_type = blink::mojom::OperationType::kPut;
operation2->request = body_request_;
- operation2->response = body_response_;
+ operation2->response = CreateBlobBodyResponse();
std::vector<blink::mojom::BatchOperationPtr> operations;
- operations.push_back(operation1->Clone());
- operations.push_back(operation2->Clone());
+ operations.push_back(std::move(operation1));
+ operations.push_back(std::move(operation2));
- EXPECT_EQ(CacheStorageError::kSuccess, BatchOperation(std::move(operations)));
+ EXPECT_EQ(CacheStorageError::kErrorDuplicateOperation,
+ BatchOperation(std::move(operations)));
+
+ // A duplicate operation error should provide an informative message
+ // containing the URL of the duplicate request.
+ ASSERT_TRUE(callback_message_);
+ EXPECT_NE(std::string::npos, callback_message_.value().find(kBodyUrl.spec()));
+
+ // Neither operation should have completed.
+ EXPECT_FALSE(Match(body_request_));
+}
+
+TEST_P(CacheStorageCacheTestP, PutReplaceInBatchWithDuplicateCheckingDisabled) {
+ blink::mojom::BatchOperationPtr operation1 =
+ blink::mojom::BatchOperation::New();
+ operation1->operation_type = blink::mojom::OperationType::kPut;
+ operation1->request = body_request_;
+ operation1->response = CreateNoBodyResponse();
+
+ blink::mojom::BatchOperationPtr operation2 =
+ blink::mojom::BatchOperation::New();
+ operation2->operation_type = blink::mojom::OperationType::kPut;
+ operation2->request = body_request_;
+ operation2->response = CreateBlobBodyResponse();
+
+ std::vector<blink::mojom::BatchOperationPtr> operations;
+ operations.push_back(std::move(operation1));
+ operations.push_back(std::move(operation2));
+
+ EXPECT_EQ(
+ CacheStorageError::kSuccess,
+ BatchOperation(std::move(operations), false /* fail_on_duplicates */));
+
+ // Even when we don't fail on duplicates we should still provide an
+ // informative message to the user that includes the duplicate URLs.
+ ASSERT_TRUE(callback_message_);
+ EXPECT_NE(std::string::npos, callback_message_.value().find(kBodyUrl.spec()));
// |operation2| should win.
- EXPECT_TRUE(Match(operation2->request));
+ EXPECT_TRUE(Match(body_request_));
EXPECT_TRUE(callback_response_->blob);
}
TEST_P(CacheStorageCacheTestP, MatchNoBody) {
- EXPECT_TRUE(Put(no_body_request_, no_body_response_));
+ EXPECT_TRUE(Put(no_body_request_, CreateNoBodyResponse()));
EXPECT_TRUE(Match(no_body_request_));
- EXPECT_TRUE(ResponseMetadataEqual(SetCacheName(no_body_response_),
+ EXPECT_TRUE(ResponseMetadataEqual(*SetCacheName(CreateNoBodyResponse()),
*callback_response_));
EXPECT_FALSE(callback_response_->blob);
}
TEST_P(CacheStorageCacheTestP, MatchBody) {
- EXPECT_TRUE(Put(body_request_, body_response_));
+ EXPECT_TRUE(Put(body_request_, CreateBlobBodyResponse()));
EXPECT_TRUE(Match(body_request_));
- EXPECT_TRUE(
- ResponseMetadataEqual(SetCacheName(body_response_), *callback_response_));
- EXPECT_TRUE(ResponseBodiesEqual(expected_blob_data_,
- callback_response_->blob->get()));
+ EXPECT_TRUE(ResponseMetadataEqual(*SetCacheName(CreateBlobBodyResponse()),
+ *callback_response_));
+ blink::mojom::BlobPtr blob(std::move(callback_response_->blob->blob));
+ EXPECT_TRUE(ResponseBodiesEqual(expected_blob_data_, blob.get()));
}
TEST_P(CacheStorageCacheTestP, MatchBodyHead) {
- EXPECT_TRUE(Put(body_request_, body_response_));
+ EXPECT_TRUE(Put(body_request_, CreateBlobBodyResponse()));
EXPECT_FALSE(Match(body_head_request_));
}
TEST_P(CacheStorageCacheTestP, MatchAll_Empty) {
- std::vector<ServiceWorkerResponse> responses;
+ std::vector<blink::mojom::FetchAPIResponsePtr> responses;
EXPECT_TRUE(MatchAll(&responses));
EXPECT_TRUE(responses.empty());
}
TEST_P(CacheStorageCacheTestP, MatchAll_NoBody) {
- EXPECT_TRUE(Put(no_body_request_, no_body_response_));
+ EXPECT_TRUE(Put(no_body_request_, CreateNoBodyResponse()));
- std::vector<ServiceWorkerResponse> responses;
+ std::vector<blink::mojom::FetchAPIResponsePtr> responses;
EXPECT_TRUE(MatchAll(&responses));
ASSERT_EQ(1u, responses.size());
- EXPECT_TRUE(
- ResponseMetadataEqual(SetCacheName(no_body_response_), responses[0]));
- EXPECT_FALSE(responses[0].blob);
+ EXPECT_TRUE(ResponseMetadataEqual(*SetCacheName(CreateNoBodyResponse()),
+ *responses[0]));
+ EXPECT_FALSE(responses[0]->blob);
}
TEST_P(CacheStorageCacheTestP, MatchAll_Body) {
- EXPECT_TRUE(Put(body_request_, body_response_));
+ EXPECT_TRUE(Put(body_request_, CreateBlobBodyResponse()));
- std::vector<ServiceWorkerResponse> responses;
+ std::vector<blink::mojom::FetchAPIResponsePtr> responses;
EXPECT_TRUE(MatchAll(&responses));
ASSERT_EQ(1u, responses.size());
- EXPECT_TRUE(
- ResponseMetadataEqual(SetCacheName(body_response_), responses[0]));
- EXPECT_TRUE(
- ResponseBodiesEqual(expected_blob_data_, responses[0].blob->get()));
+ EXPECT_TRUE(ResponseMetadataEqual(*SetCacheName(CreateBlobBodyResponse()),
+ *responses[0]));
+ blink::mojom::BlobPtr blob(std::move(responses[0]->blob->blob));
+ EXPECT_TRUE(ResponseBodiesEqual(expected_blob_data_, blob.get()));
}
TEST_P(CacheStorageCacheTestP, MatchAll_TwoResponsesThenOne) {
- EXPECT_TRUE(Put(no_body_request_, no_body_response_));
- EXPECT_TRUE(Put(body_request_, body_response_));
+ EXPECT_TRUE(Put(no_body_request_, CreateNoBodyResponse()));
+ EXPECT_TRUE(Put(body_request_, CreateBlobBodyResponse()));
- std::vector<ServiceWorkerResponse> responses;
+ std::vector<blink::mojom::FetchAPIResponsePtr> responses;
EXPECT_TRUE(MatchAll(&responses));
ASSERT_EQ(2u, responses.size());
- EXPECT_TRUE(responses[1].blob);
-
- EXPECT_TRUE(
- ResponseMetadataEqual(SetCacheName(no_body_response_), responses[0]));
- EXPECT_FALSE(responses[0].blob);
- EXPECT_TRUE(
- ResponseMetadataEqual(SetCacheName(body_response_), responses[1]));
- EXPECT_TRUE(
- ResponseBodiesEqual(expected_blob_data_, responses[1].blob->get()));
+ EXPECT_TRUE(responses[1]->blob);
+
+ EXPECT_TRUE(ResponseMetadataEqual(*SetCacheName(CreateNoBodyResponse()),
+ *responses[0]));
+ EXPECT_FALSE(responses[0]->blob);
+ EXPECT_TRUE(ResponseMetadataEqual(*SetCacheName(CreateBlobBodyResponse()),
+ *responses[1]));
+ blink::mojom::BlobPtr blob(std::move(responses[1]->blob->blob));
+ EXPECT_TRUE(ResponseBodiesEqual(expected_blob_data_, blob.get()));
responses.clear();
@@ -1042,13 +1093,13 @@ TEST_P(CacheStorageCacheTestP, MatchAll_TwoResponsesThenOne) {
EXPECT_TRUE(MatchAll(&responses));
ASSERT_EQ(1u, responses.size());
- EXPECT_TRUE(
- ResponseMetadataEqual(SetCacheName(no_body_response_), responses[0]));
- EXPECT_FALSE(responses[0].blob);
+ EXPECT_TRUE(ResponseMetadataEqual(*SetCacheName(CreateNoBodyResponse()),
+ *responses[0]));
+ EXPECT_FALSE(responses[0]->blob);
}
TEST_P(CacheStorageCacheTestP, Match_IgnoreSearch) {
- EXPECT_TRUE(Put(body_request_with_query_, body_response_with_query_));
+ EXPECT_TRUE(Put(body_request_with_query_, CreateBlobBodyResponseWithQuery()));
EXPECT_FALSE(Match(body_request_));
blink::mojom::QueryParamsPtr match_params = blink::mojom::QueryParams::New();
@@ -1057,7 +1108,7 @@ TEST_P(CacheStorageCacheTestP, Match_IgnoreSearch) {
}
TEST_P(CacheStorageCacheTestP, Match_IgnoreMethod) {
- EXPECT_TRUE(Put(body_request_, body_response_));
+ EXPECT_TRUE(Put(body_request_, CreateBlobBodyResponse()));
ServiceWorkerFetchRequest post_request = body_request_;
post_request.method = "POST";
@@ -1070,8 +1121,9 @@ TEST_P(CacheStorageCacheTestP, Match_IgnoreMethod) {
TEST_P(CacheStorageCacheTestP, Match_IgnoreVary) {
body_request_.headers["vary_foo"] = "foo";
- body_response_.headers["vary"] = "vary_foo";
- EXPECT_TRUE(Put(body_request_, body_response_));
+ blink::mojom::FetchAPIResponsePtr body_response = CreateBlobBodyResponse();
+ body_response->headers["vary"] = "vary_foo";
+ EXPECT_TRUE(Put(body_request_, std::move(body_response)));
EXPECT_TRUE(Match(body_request_));
body_request_.headers["vary_foo"] = "bar";
@@ -1083,7 +1135,7 @@ TEST_P(CacheStorageCacheTestP, Match_IgnoreVary) {
}
TEST_P(CacheStorageCacheTestP, Keys_IgnoreSearch) {
- EXPECT_TRUE(Put(body_request_with_query_, body_response_with_query_));
+ EXPECT_TRUE(Put(body_request_with_query_, CreateBlobBodyResponseWithQuery()));
EXPECT_TRUE(Keys(body_request_));
EXPECT_EQ(0u, callback_strings_.size());
@@ -1095,7 +1147,7 @@ TEST_P(CacheStorageCacheTestP, Keys_IgnoreSearch) {
}
TEST_P(CacheStorageCacheTestP, Keys_IgnoreMethod) {
- EXPECT_TRUE(Put(body_request_, body_response_));
+ EXPECT_TRUE(Put(body_request_, CreateBlobBodyResponse()));
ServiceWorkerFetchRequest post_request = body_request_;
post_request.method = "POST";
@@ -1110,8 +1162,9 @@ TEST_P(CacheStorageCacheTestP, Keys_IgnoreMethod) {
TEST_P(CacheStorageCacheTestP, Keys_IgnoreVary) {
body_request_.headers["vary_foo"] = "foo";
- body_response_.headers["vary"] = "vary_foo";
- EXPECT_TRUE(Put(body_request_, body_response_));
+ blink::mojom::FetchAPIResponsePtr body_response = CreateBlobBodyResponse();
+ body_response->headers["vary"] = "vary_foo";
+ EXPECT_TRUE(Put(body_request_, std::move(body_response)));
EXPECT_TRUE(Keys(body_request_));
EXPECT_EQ(1u, callback_strings_.size());
@@ -1126,7 +1179,7 @@ TEST_P(CacheStorageCacheTestP, Keys_IgnoreVary) {
}
TEST_P(CacheStorageCacheTestP, Delete_IgnoreSearch) {
- EXPECT_TRUE(Put(body_request_with_query_, body_response_with_query_));
+ EXPECT_TRUE(Put(body_request_with_query_, CreateBlobBodyResponseWithQuery()));
EXPECT_FALSE(Delete(body_request_));
blink::mojom::QueryParamsPtr match_params = blink::mojom::QueryParams::New();
@@ -1135,7 +1188,7 @@ TEST_P(CacheStorageCacheTestP, Delete_IgnoreSearch) {
}
TEST_P(CacheStorageCacheTestP, Delete_IgnoreMethod) {
- EXPECT_TRUE(Put(body_request_, body_response_));
+ EXPECT_TRUE(Put(body_request_, CreateBlobBodyResponse()));
ServiceWorkerFetchRequest post_request = body_request_;
post_request.method = "POST";
@@ -1148,8 +1201,9 @@ TEST_P(CacheStorageCacheTestP, Delete_IgnoreMethod) {
TEST_P(CacheStorageCacheTestP, Delete_IgnoreVary) {
body_request_.headers["vary_foo"] = "foo";
- body_response_.headers["vary"] = "vary_foo";
- EXPECT_TRUE(Put(body_request_, body_response_));
+ blink::mojom::FetchAPIResponsePtr body_response = CreateBlobBodyResponse();
+ body_response->headers["vary"] = "vary_foo";
+ EXPECT_TRUE(Put(body_request_, std::move(body_response)));
body_request_.headers["vary_foo"] = "bar";
EXPECT_FALSE(Delete(body_request_));
@@ -1160,11 +1214,11 @@ TEST_P(CacheStorageCacheTestP, Delete_IgnoreVary) {
}
TEST_P(CacheStorageCacheTestP, MatchAll_IgnoreMethod) {
- EXPECT_TRUE(Put(body_request_, body_response_));
+ EXPECT_TRUE(Put(body_request_, CreateBlobBodyResponse()));
ServiceWorkerFetchRequest post_request = body_request_;
post_request.method = "POST";
- std::vector<ServiceWorkerResponse> responses;
+ std::vector<blink::mojom::FetchAPIResponsePtr> responses;
EXPECT_TRUE(MatchAll(post_request, nullptr, &responses));
EXPECT_EQ(0u, responses.size());
@@ -1177,9 +1231,10 @@ TEST_P(CacheStorageCacheTestP, MatchAll_IgnoreMethod) {
TEST_P(CacheStorageCacheTestP, MatchAll_IgnoreVary) {
body_request_.headers["vary_foo"] = "foo";
- body_response_.headers["vary"] = "vary_foo";
- EXPECT_TRUE(Put(body_request_, body_response_));
- std::vector<ServiceWorkerResponse> responses;
+ blink::mojom::FetchAPIResponsePtr body_response = CreateBlobBodyResponse();
+ body_response->headers["vary"] = "vary_foo";
+ EXPECT_TRUE(Put(body_request_, std::move(body_response)));
+ std::vector<blink::mojom::FetchAPIResponsePtr> responses;
EXPECT_TRUE(MatchAll(body_request_, nullptr, &responses));
EXPECT_EQ(1u, responses.size());
@@ -1195,11 +1250,11 @@ TEST_P(CacheStorageCacheTestP, MatchAll_IgnoreVary) {
}
TEST_P(CacheStorageCacheTestP, MatchAll_IgnoreSearch) {
- EXPECT_TRUE(Put(body_request_, body_response_));
- EXPECT_TRUE(Put(body_request_with_query_, body_response_with_query_));
- EXPECT_TRUE(Put(no_body_request_, no_body_response_));
+ EXPECT_TRUE(Put(body_request_, CreateBlobBodyResponse()));
+ EXPECT_TRUE(Put(body_request_with_query_, CreateBlobBodyResponseWithQuery()));
+ EXPECT_TRUE(Put(no_body_request_, CreateNoBodyResponse()));
- std::vector<ServiceWorkerResponse> responses;
+ std::vector<blink::mojom::FetchAPIResponsePtr> responses;
blink::mojom::QueryParamsPtr match_params = blink::mojom::QueryParams::New();
match_params->ignore_search = true;
EXPECT_TRUE(MatchAll(body_request_, std::move(match_params), &responses));
@@ -1208,26 +1263,25 @@ TEST_P(CacheStorageCacheTestP, MatchAll_IgnoreSearch) {
// Order of returned responses is not guaranteed.
std::set<std::string> matched_set;
- for (const ServiceWorkerResponse& response : responses) {
- ASSERT_EQ(1u, response.url_list.size());
- if (response.url_list[0].spec() ==
- "http://example.com/body.html?query=test") {
- EXPECT_TRUE(ResponseMetadataEqual(SetCacheName(body_response_with_query_),
- response));
- matched_set.insert(response.url_list[0].spec());
- } else if (response.url_list[0].spec() == "http://example.com/body.html") {
- EXPECT_TRUE(
- ResponseMetadataEqual(SetCacheName(body_response_), response));
- matched_set.insert(response.url_list[0].spec());
+ for (const blink::mojom::FetchAPIResponsePtr& response : responses) {
+ ASSERT_EQ(1u, response->url_list.size());
+ if (response->url_list[0].spec() == kBodyUrlWithQuery.spec()) {
+ EXPECT_TRUE(ResponseMetadataEqual(
+ *SetCacheName(CreateBlobBodyResponseWithQuery()), *response));
+ matched_set.insert(response->url_list[0].spec());
+ } else if (response->url_list[0].spec() == kBodyUrl.spec()) {
+ EXPECT_TRUE(ResponseMetadataEqual(*SetCacheName(CreateBlobBodyResponse()),
+ *response));
+ matched_set.insert(response->url_list[0].spec());
}
}
EXPECT_EQ(2u, matched_set.size());
}
TEST_P(CacheStorageCacheTestP, MatchAll_Head) {
- EXPECT_TRUE(Put(body_request_, body_response_));
+ EXPECT_TRUE(Put(body_request_, CreateBlobBodyResponse()));
- std::vector<ServiceWorkerResponse> responses;
+ std::vector<blink::mojom::FetchAPIResponsePtr> responses;
blink::mojom::QueryParamsPtr match_params = blink::mojom::QueryParams::New();
match_params->ignore_search = true;
EXPECT_TRUE(MatchAll(body_head_request_, match_params->Clone(), &responses));
@@ -1236,16 +1290,17 @@ TEST_P(CacheStorageCacheTestP, MatchAll_Head) {
match_params->ignore_method = true;
EXPECT_TRUE(MatchAll(body_head_request_, match_params->Clone(), &responses));
ASSERT_EQ(1u, responses.size());
- EXPECT_TRUE(
- ResponseMetadataEqual(SetCacheName(body_response_), responses[0]));
- EXPECT_TRUE(
- ResponseBodiesEqual(expected_blob_data_, responses[0].blob->get()));
+ EXPECT_TRUE(ResponseMetadataEqual(*SetCacheName(CreateBlobBodyResponse()),
+ *responses[0]));
+ blink::mojom::BlobPtr blob(std::move(responses[0]->blob->blob));
+ EXPECT_TRUE(ResponseBodiesEqual(expected_blob_data_, blob.get()));
}
TEST_P(CacheStorageCacheTestP, Vary) {
body_request_.headers["vary_foo"] = "foo";
- body_response_.headers["vary"] = "vary_foo";
- EXPECT_TRUE(Put(body_request_, body_response_));
+ blink::mojom::FetchAPIResponsePtr body_response = CreateBlobBodyResponse();
+ body_response->headers["vary"] = "vary_foo";
+ EXPECT_TRUE(Put(body_request_, std::move(body_response)));
EXPECT_TRUE(Match(body_request_));
body_request_.headers["vary_foo"] = "bar";
@@ -1256,8 +1311,9 @@ TEST_P(CacheStorageCacheTestP, Vary) {
}
TEST_P(CacheStorageCacheTestP, EmptyVary) {
- body_response_.headers["vary"] = "";
- EXPECT_TRUE(Put(body_request_, body_response_));
+ blink::mojom::FetchAPIResponsePtr body_response = CreateBlobBodyResponse();
+ body_response->headers["vary"] = "";
+ EXPECT_TRUE(Put(body_request_, std::move(body_response)));
EXPECT_TRUE(Match(body_request_));
body_request_.headers["zoo"] = "zoo";
@@ -1265,7 +1321,7 @@ TEST_P(CacheStorageCacheTestP, EmptyVary) {
}
TEST_P(CacheStorageCacheTestP, NoVaryButDiffHeaders) {
- EXPECT_TRUE(Put(body_request_, body_response_));
+ EXPECT_TRUE(Put(body_request_, CreateBlobBodyResponse()));
EXPECT_TRUE(Match(body_request_));
body_request_.headers["zoo"] = "zoo";
@@ -1275,8 +1331,9 @@ TEST_P(CacheStorageCacheTestP, NoVaryButDiffHeaders) {
TEST_P(CacheStorageCacheTestP, VaryMultiple) {
body_request_.headers["vary_foo"] = "foo";
body_request_.headers["vary_bar"] = "bar";
- body_response_.headers["vary"] = " vary_foo , vary_bar";
- EXPECT_TRUE(Put(body_request_, body_response_));
+ blink::mojom::FetchAPIResponsePtr body_response = CreateBlobBodyResponse();
+ body_response->headers["vary"] = " vary_foo , vary_bar";
+ EXPECT_TRUE(Put(body_request_, std::move(body_response)));
EXPECT_TRUE(Match(body_request_));
body_request_.headers["vary_bar"] = "foo";
@@ -1288,8 +1345,9 @@ TEST_P(CacheStorageCacheTestP, VaryMultiple) {
TEST_P(CacheStorageCacheTestP, VaryNewHeader) {
body_request_.headers["vary_foo"] = "foo";
- body_response_.headers["vary"] = " vary_foo, vary_bar";
- EXPECT_TRUE(Put(body_request_, body_response_));
+ blink::mojom::FetchAPIResponsePtr body_response = CreateBlobBodyResponse();
+ body_response->headers["vary"] = " vary_foo, vary_bar";
+ EXPECT_TRUE(Put(body_request_, std::move(body_response)));
EXPECT_TRUE(Match(body_request_));
body_request_.headers["vary_bar"] = "bar";
@@ -1297,8 +1355,9 @@ TEST_P(CacheStorageCacheTestP, VaryNewHeader) {
}
TEST_P(CacheStorageCacheTestP, VaryStar) {
- body_response_.headers["vary"] = "*";
- EXPECT_TRUE(Put(body_request_, body_response_));
+ blink::mojom::FetchAPIResponsePtr body_response = CreateBlobBodyResponse();
+ body_response->headers["vary"] = "*";
+ EXPECT_TRUE(Put(body_request_, std::move(body_response)));
EXPECT_FALSE(Match(body_request_));
}
@@ -1308,8 +1367,8 @@ TEST_P(CacheStorageCacheTestP, EmptyKeys) {
}
TEST_P(CacheStorageCacheTestP, TwoKeys) {
- EXPECT_TRUE(Put(no_body_request_, no_body_response_));
- EXPECT_TRUE(Put(body_request_, body_response_));
+ EXPECT_TRUE(Put(no_body_request_, CreateNoBodyResponse()));
+ EXPECT_TRUE(Put(body_request_, CreateBlobBodyResponse()));
EXPECT_TRUE(Keys());
std::vector<std::string> expected_keys{no_body_request_.url.spec(),
body_request_.url.spec()};
@@ -1317,8 +1376,8 @@ TEST_P(CacheStorageCacheTestP, TwoKeys) {
}
TEST_P(CacheStorageCacheTestP, TwoKeysThenOne) {
- EXPECT_TRUE(Put(no_body_request_, no_body_response_));
- EXPECT_TRUE(Put(body_request_, body_response_));
+ EXPECT_TRUE(Put(no_body_request_, CreateNoBodyResponse()));
+ EXPECT_TRUE(Put(body_request_, CreateBlobBodyResponse()));
EXPECT_TRUE(Keys());
std::vector<std::string> expected_keys{no_body_request_.url.spec(),
body_request_.url.spec()};
@@ -1331,9 +1390,9 @@ TEST_P(CacheStorageCacheTestP, TwoKeysThenOne) {
}
TEST_P(CacheStorageCacheTestP, KeysWithIgnoreSearchTrue) {
- EXPECT_TRUE(Put(no_body_request_, no_body_response_));
- EXPECT_TRUE(Put(body_request_, body_response_));
- EXPECT_TRUE(Put(body_request_with_query_, body_response_with_query_));
+ EXPECT_TRUE(Put(no_body_request_, CreateNoBodyResponse()));
+ EXPECT_TRUE(Put(body_request_, CreateBlobBodyResponse()));
+ EXPECT_TRUE(Put(body_request_with_query_, CreateBlobBodyResponseWithQuery()));
blink::mojom::QueryParamsPtr match_params = blink::mojom::QueryParams::New();
match_params->ignore_search = true;
@@ -1345,9 +1404,9 @@ TEST_P(CacheStorageCacheTestP, KeysWithIgnoreSearchTrue) {
}
TEST_P(CacheStorageCacheTestP, KeysWithIgnoreSearchFalse) {
- EXPECT_TRUE(Put(no_body_request_, no_body_response_));
- EXPECT_TRUE(Put(body_request_, body_response_));
- EXPECT_TRUE(Put(body_request_with_query_, body_response_with_query_));
+ EXPECT_TRUE(Put(no_body_request_, CreateNoBodyResponse()));
+ EXPECT_TRUE(Put(body_request_, CreateBlobBodyResponse()));
+ EXPECT_TRUE(Put(body_request_with_query_, CreateBlobBodyResponseWithQuery()));
// Default value of ignore_search is false.
blink::mojom::QueryParamsPtr match_params = blink::mojom::QueryParams::New();
@@ -1360,31 +1419,31 @@ TEST_P(CacheStorageCacheTestP, KeysWithIgnoreSearchFalse) {
}
TEST_P(CacheStorageCacheTestP, DeleteNoBody) {
- EXPECT_TRUE(Put(no_body_request_, no_body_response_));
+ EXPECT_TRUE(Put(no_body_request_, CreateNoBodyResponse()));
EXPECT_TRUE(Match(no_body_request_));
EXPECT_TRUE(Delete(no_body_request_));
EXPECT_FALSE(Match(no_body_request_));
EXPECT_FALSE(Delete(no_body_request_));
- EXPECT_TRUE(Put(no_body_request_, no_body_response_));
+ EXPECT_TRUE(Put(no_body_request_, CreateNoBodyResponse()));
EXPECT_TRUE(Match(no_body_request_));
EXPECT_TRUE(Delete(no_body_request_));
}
TEST_P(CacheStorageCacheTestP, DeleteBody) {
- EXPECT_TRUE(Put(body_request_, body_response_));
+ EXPECT_TRUE(Put(body_request_, CreateBlobBodyResponse()));
EXPECT_TRUE(Match(body_request_));
EXPECT_TRUE(Delete(body_request_));
EXPECT_FALSE(Match(body_request_));
EXPECT_FALSE(Delete(body_request_));
- EXPECT_TRUE(Put(body_request_, body_response_));
+ EXPECT_TRUE(Put(body_request_, CreateBlobBodyResponse()));
EXPECT_TRUE(Match(body_request_));
EXPECT_TRUE(Delete(body_request_));
}
TEST_P(CacheStorageCacheTestP, DeleteWithIgnoreSearchTrue) {
- EXPECT_TRUE(Put(no_body_request_, no_body_response_));
- EXPECT_TRUE(Put(body_request_, body_response_));
- EXPECT_TRUE(Put(body_request_with_query_, body_response_with_query_));
+ EXPECT_TRUE(Put(no_body_request_, CreateNoBodyResponse()));
+ EXPECT_TRUE(Put(body_request_, CreateBlobBodyResponse()));
+ EXPECT_TRUE(Put(body_request_with_query_, CreateBlobBodyResponseWithQuery()));
EXPECT_TRUE(Keys());
std::vector<std::string> expected_keys{no_body_request_.url.spec(),
@@ -1405,9 +1464,9 @@ TEST_P(CacheStorageCacheTestP, DeleteWithIgnoreSearchTrue) {
}
TEST_P(CacheStorageCacheTestP, DeleteWithIgnoreSearchFalse) {
- EXPECT_TRUE(Put(no_body_request_, no_body_response_));
- EXPECT_TRUE(Put(body_request_, body_response_));
- EXPECT_TRUE(Put(body_request_with_query_, body_response_with_query_));
+ EXPECT_TRUE(Put(no_body_request_, CreateNoBodyResponse()));
+ EXPECT_TRUE(Put(body_request_, CreateBlobBodyResponse()));
+ EXPECT_TRUE(Put(body_request_with_query_, CreateBlobBodyResponseWithQuery()));
EXPECT_TRUE(Keys());
std::vector<std::string> expected_keys{no_body_request_.url.spec(),
@@ -1430,7 +1489,7 @@ TEST_P(CacheStorageCacheTestP, DeleteWithIgnoreSearchFalse) {
TEST_P(CacheStorageCacheTestP, QuickStressNoBody) {
for (int i = 0; i < 100; ++i) {
EXPECT_FALSE(Match(no_body_request_));
- EXPECT_TRUE(Put(no_body_request_, no_body_response_));
+ EXPECT_TRUE(Put(no_body_request_, CreateNoBodyResponse()));
EXPECT_TRUE(Match(no_body_request_));
EXPECT_TRUE(Delete(no_body_request_));
}
@@ -1439,7 +1498,7 @@ TEST_P(CacheStorageCacheTestP, QuickStressNoBody) {
TEST_P(CacheStorageCacheTestP, QuickStressBody) {
for (int i = 0; i < 100; ++i) {
ASSERT_FALSE(Match(body_request_));
- ASSERT_TRUE(Put(body_request_, body_response_));
+ ASSERT_TRUE(Put(body_request_, CreateBlobBodyResponse()));
ASSERT_TRUE(Match(body_request_));
ASSERT_TRUE(Delete(body_request_));
}
@@ -1456,36 +1515,35 @@ TEST_P(CacheStorageCacheTestP, PutResponseType) {
}
TEST_P(CacheStorageCacheTestP, PutWithSideData) {
- ServiceWorkerResponse response(body_response_);
+ blink::mojom::FetchAPIResponsePtr response = CreateBlobBodyResponse();
const std::string expected_side_data = "SideData";
std::unique_ptr<storage::BlobDataHandle> side_data_blob_handle =
BuildBlobHandle("blob-id:mysideblob", expected_side_data);
- CopySideDataToResponse(side_data_blob_handle.get(), &response);
- EXPECT_TRUE(Put(body_request_, response));
+ CopySideDataToResponse(side_data_blob_handle.get(), response.get());
+ EXPECT_TRUE(Put(body_request_, std::move(response)));
EXPECT_TRUE(Match(body_request_));
ASSERT_TRUE(callback_response_->blob);
- EXPECT_TRUE(ResponseBodiesEqual(expected_blob_data_,
- callback_response_->blob->get()));
- EXPECT_TRUE(ResponseSideDataEqual(expected_side_data,
- callback_response_->blob->get()));
+ blink::mojom::BlobPtr blob(std::move(callback_response_->blob->blob));
+ EXPECT_TRUE(ResponseBodiesEqual(expected_blob_data_, blob.get()));
+ EXPECT_TRUE(ResponseSideDataEqual(expected_side_data, blob.get()));
}
TEST_P(CacheStorageCacheTestP, PutWithSideData_QuotaExceeded) {
mock_quota_manager_->SetQuota(GURL(kOrigin),
blink::mojom::StorageType::kTemporary,
expected_blob_data_.size() - 1);
- ServiceWorkerResponse response(body_response_);
+ blink::mojom::FetchAPIResponsePtr response = CreateBlobBodyResponse();
const std::string expected_side_data = "SideData";
std::unique_ptr<storage::BlobDataHandle> side_data_blob_handle =
BuildBlobHandle("blob-id:mysideblob", expected_side_data);
- CopySideDataToResponse(side_data_blob_handle.get(), &response);
+ CopySideDataToResponse(side_data_blob_handle.get(), response.get());
// When the available space is not enough for the body, Put operation must
// fail.
- EXPECT_FALSE(Put(body_request_, response));
+ EXPECT_FALSE(Put(body_request_, std::move(response)));
EXPECT_EQ(CacheStorageError::kErrorQuotaExceeded, callback_error_);
}
@@ -1493,39 +1551,39 @@ TEST_P(CacheStorageCacheTestP, PutWithSideData_QuotaExceededSkipSideData) {
mock_quota_manager_->SetQuota(GURL(kOrigin),
blink::mojom::StorageType::kTemporary,
expected_blob_data_.size());
- ServiceWorkerResponse response(body_response_);
+ blink::mojom::FetchAPIResponsePtr response = CreateBlobBodyResponse();
const std::string expected_side_data = "SideData";
std::unique_ptr<storage::BlobDataHandle> side_data_blob_handle =
BuildBlobHandle("blob-id:mysideblob", expected_side_data);
- CopySideDataToResponse(side_data_blob_handle.get(), &response);
+ CopySideDataToResponse(side_data_blob_handle.get(), response.get());
// When the available space is enough for the body but not enough for the side
// data, Put operation must succeed.
- EXPECT_TRUE(Put(body_request_, response));
+ EXPECT_TRUE(Put(body_request_, std::move(response)));
EXPECT_TRUE(Match(body_request_));
ASSERT_TRUE(callback_response_->blob);
- EXPECT_TRUE(ResponseBodiesEqual(expected_blob_data_,
- callback_response_->blob->get()));
+ blink::mojom::BlobPtr blob(std::move(callback_response_->blob->blob));
+ EXPECT_TRUE(ResponseBodiesEqual(expected_blob_data_, blob.get()));
// The side data should not be written.
- EXPECT_TRUE(ResponseSideDataEqual("", callback_response_->blob->get()));
+ EXPECT_TRUE(ResponseSideDataEqual("", blob.get()));
}
TEST_P(CacheStorageCacheTestP, PutWithSideData_BadMessage) {
- ServiceWorkerResponse response(body_response_);
+ blink::mojom::FetchAPIResponsePtr response = CreateBlobBodyResponse();
const std::string expected_side_data = "SideData";
std::unique_ptr<storage::BlobDataHandle> side_data_blob_handle =
BuildBlobHandle("blob-id:mysideblob", expected_side_data);
- CopySideDataToResponse(side_data_blob_handle.get(), &response);
+ CopySideDataToResponse(side_data_blob_handle.get(), response.get());
blink::mojom::BatchOperationPtr operation =
blink::mojom::BatchOperation::New();
operation->operation_type = blink::mojom::OperationType::kPut;
operation->request = body_request_;
- operation->response = response;
- operation->response->blob_size = UINT64_MAX;
+ operation->response = std::move(response);
+ operation->response->blob->size = std::numeric_limits<uint64_t>::max();
std::vector<blink::mojom::BatchOperationPtr> operations;
operations.emplace_back(std::move(operation));
@@ -1538,9 +1596,9 @@ TEST_P(CacheStorageCacheTestP, PutWithSideData_BadMessage) {
TEST_P(CacheStorageCacheTestP, WriteSideData) {
base::Time response_time(base::Time::Now());
- ServiceWorkerResponse response(body_response_);
- response.response_time = response_time;
- EXPECT_TRUE(Put(body_request_, response));
+ blink::mojom::FetchAPIResponsePtr response = CreateBlobBodyResponse();
+ response->response_time = response_time;
+ EXPECT_TRUE(Put(body_request_, std::move(response)));
const std::string expected_side_data1 = "SideDataSample";
scoped_refptr<net::IOBuffer> buffer1(
@@ -1550,10 +1608,9 @@ TEST_P(CacheStorageCacheTestP, WriteSideData) {
EXPECT_TRUE(Match(body_request_));
ASSERT_TRUE(callback_response_->blob);
- EXPECT_TRUE(ResponseBodiesEqual(expected_blob_data_,
- callback_response_->blob->get()));
- EXPECT_TRUE(ResponseSideDataEqual(expected_side_data1,
- callback_response_->blob->get()));
+ blink::mojom::BlobPtr blob1(std::move(callback_response_->blob->blob));
+ EXPECT_TRUE(ResponseBodiesEqual(expected_blob_data_, blob1.get()));
+ EXPECT_TRUE(ResponseSideDataEqual(expected_side_data1, blob1.get()));
const std::string expected_side_data2 = "New data";
scoped_refptr<net::IOBuffer> buffer2(
@@ -1562,10 +1619,9 @@ TEST_P(CacheStorageCacheTestP, WriteSideData) {
expected_side_data2.length()));
EXPECT_TRUE(Match(body_request_));
ASSERT_TRUE(callback_response_->blob);
- EXPECT_TRUE(ResponseBodiesEqual(expected_blob_data_,
- callback_response_->blob->get()));
- EXPECT_TRUE(ResponseSideDataEqual(expected_side_data2,
- callback_response_->blob->get()));
+ blink::mojom::BlobPtr blob2(std::move(callback_response_->blob->blob));
+ EXPECT_TRUE(ResponseBodiesEqual(expected_blob_data_, blob2.get()));
+ EXPECT_TRUE(ResponseSideDataEqual(expected_side_data2, blob2.get()));
ASSERT_TRUE(Delete(body_request_));
}
@@ -1574,9 +1630,9 @@ TEST_P(CacheStorageCacheTestP, WriteSideData_QuotaExceeded) {
mock_quota_manager_->SetQuota(
GURL(kOrigin), blink::mojom::StorageType::kTemporary, 1024 * 1023);
base::Time response_time(base::Time::Now());
- ServiceWorkerResponse response;
- response.response_time = response_time;
- EXPECT_TRUE(Put(no_body_request_, response));
+ blink::mojom::FetchAPIResponsePtr response(CreateNoBodyResponse());
+ response->response_time = response_time;
+ EXPECT_TRUE(Put(no_body_request_, std::move(response)));
const size_t kSize = 1024 * 1024;
scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
@@ -1589,10 +1645,10 @@ TEST_P(CacheStorageCacheTestP, WriteSideData_QuotaExceeded) {
TEST_P(CacheStorageCacheTestP, WriteSideData_QuotaManagerModified) {
base::Time response_time(base::Time::Now());
- ServiceWorkerResponse response;
- response.response_time = response_time;
+ blink::mojom::FetchAPIResponsePtr response(CreateNoBodyResponse());
+ response->response_time = response_time;
EXPECT_EQ(0, quota_manager_proxy_->notify_storage_modified_count());
- EXPECT_TRUE(Put(no_body_request_, response));
+ EXPECT_TRUE(Put(no_body_request_, std::move(response)));
// Storage notification happens after the operation returns, so continue the
// event loop.
base::RunLoop().RunUntilIdle();
@@ -1610,9 +1666,9 @@ TEST_P(CacheStorageCacheTestP, WriteSideData_QuotaManagerModified) {
TEST_P(CacheStorageCacheTestP, WriteSideData_DifferentTimeStamp) {
base::Time response_time(base::Time::Now());
- ServiceWorkerResponse response;
- response.response_time = response_time;
- EXPECT_TRUE(Put(no_body_request_, response));
+ blink::mojom::FetchAPIResponsePtr response(CreateNoBodyResponse());
+ response->response_time = response_time;
+ EXPECT_TRUE(Put(no_body_request_, std::move(response)));
const size_t kSize = 10;
scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
@@ -1633,23 +1689,6 @@ TEST_P(CacheStorageCacheTestP, WriteSideData_NotFound) {
EXPECT_EQ(CacheStorageError::kErrorNotFound, callback_error_);
}
-TEST_F(CacheStorageCacheTest, CaselessServiceWorkerResponseHeaders) {
- // CacheStorageCache depends on ServiceWorkerResponse having caseless
- // headers so that it can quickly lookup vary headers.
- ServiceWorkerResponse response(
- std::make_unique<std::vector<GURL>>(), 200, "OK",
- network::mojom::FetchResponseType::kDefault,
- std::make_unique<ServiceWorkerHeaderMap>(), "", 0, nullptr /* blob */,
- blink::mojom::ServiceWorkerResponseError::kUnknown, base::Time(),
- false /* is_in_cache_storage */,
- std::string() /* cache_storage_cache_name */,
- std::make_unique<
- ServiceWorkerHeaderList>() /* cors_exposed_header_names */);
- response.headers["content-type"] = "foo";
- response.headers["Content-Type"] = "bar";
- EXPECT_EQ("bar", response.headers["content-type"]);
-}
-
TEST_F(CacheStorageCacheTest, CaselessServiceWorkerFetchRequestHeaders) {
// CacheStorageCache depends on ServiceWorkerFetchRequest having caseless
// headers so that it can quickly lookup vary headers.
@@ -1664,7 +1703,7 @@ TEST_F(CacheStorageCacheTest, CaselessServiceWorkerFetchRequestHeaders) {
TEST_P(CacheStorageCacheTestP, QuotaManagerModified) {
EXPECT_EQ(0, quota_manager_proxy_->notify_storage_modified_count());
- EXPECT_TRUE(Put(no_body_request_, no_body_response_));
+ EXPECT_TRUE(Put(no_body_request_, CreateNoBodyResponse()));
// Storage notification happens after the operation returns, so continue the
// event loop.
base::RunLoop().RunUntilIdle();
@@ -1672,7 +1711,7 @@ TEST_P(CacheStorageCacheTestP, QuotaManagerModified) {
EXPECT_LT(0, quota_manager_proxy_->last_notified_delta());
int64_t sum_delta = quota_manager_proxy_->last_notified_delta();
- EXPECT_TRUE(Put(body_request_, body_response_));
+ EXPECT_TRUE(Put(body_request_, CreateBlobBodyResponse()));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(2, quota_manager_proxy_->notify_storage_modified_count());
EXPECT_LT(sum_delta, quota_manager_proxy_->last_notified_delta());
@@ -1694,20 +1733,20 @@ TEST_P(CacheStorageCacheTestP, QuotaManagerModified) {
TEST_P(CacheStorageCacheTestP, PutObeysQuotaLimits) {
mock_quota_manager_->SetQuota(GURL(kOrigin),
blink::mojom::StorageType::kTemporary, 0);
- EXPECT_FALSE(Put(body_request_, body_response_));
+ EXPECT_FALSE(Put(body_request_, CreateBlobBodyResponse()));
EXPECT_EQ(CacheStorageError::kErrorQuotaExceeded, callback_error_);
}
TEST_P(CacheStorageCacheTestP, Size) {
EXPECT_EQ(0, Size());
- EXPECT_TRUE(Put(no_body_request_, no_body_response_));
+ EXPECT_TRUE(Put(no_body_request_, CreateNoBodyResponse()));
EXPECT_LT(0, Size());
int64_t no_body_size = Size();
EXPECT_TRUE(Delete(no_body_request_));
EXPECT_EQ(0, Size());
- EXPECT_TRUE(Put(body_request_, body_response_));
+ EXPECT_TRUE(Put(body_request_, CreateBlobBodyResponse()));
EXPECT_LT(no_body_size, Size());
EXPECT_TRUE(Delete(body_request_));
@@ -1719,12 +1758,13 @@ TEST_F(CacheStorageCacheTest, VerifyOpaqueSizePadding) {
ServiceWorkerFetchRequest non_opaque_request(body_request_);
non_opaque_request.url = GURL("http://example.com/no-pad.html");
- ServiceWorkerResponse non_opaque_response(body_response_);
- non_opaque_response.response_time = response_time;
+ blink::mojom::FetchAPIResponsePtr non_opaque_response =
+ CreateBlobBodyResponse();
+ non_opaque_response->response_time = response_time;
EXPECT_EQ(0, CacheStorageCache::CalculateResponsePadding(
- non_opaque_response, CreateTestPaddingKey().get(),
+ *non_opaque_response, CreateTestPaddingKey().get(),
0 /* side_data_size */));
- EXPECT_TRUE(Put(non_opaque_request, non_opaque_response));
+ EXPECT_TRUE(Put(non_opaque_request, std::move(non_opaque_response)));
int64_t unpadded_no_data_cache_size = Size();
// Now write some side data to that cache.
@@ -1738,8 +1778,11 @@ TEST_F(CacheStorageCacheTest, VerifyOpaqueSizePadding) {
unpadded_total_resource_size - unpadded_no_data_cache_size;
EXPECT_EQ(expected_side_data.size(),
static_cast<size_t>(unpadded_side_data_size));
+ blink::mojom::FetchAPIResponsePtr non_opaque_response_clone =
+ CreateBlobBodyResponse();
+ non_opaque_response_clone->response_time = response_time;
EXPECT_EQ(0, CacheStorageCache::CalculateResponsePadding(
- non_opaque_response, CreateTestPaddingKey().get(),
+ *non_opaque_response_clone, CreateTestPaddingKey().get(),
unpadded_side_data_size));
// Now write an identically sized opaque response.
@@ -1748,11 +1791,11 @@ TEST_F(CacheStorageCacheTest, VerifyOpaqueSizePadding) {
// Same URL length means same cache sizes (ignoring padding).
EXPECT_EQ(opaque_request.url.spec().length(),
non_opaque_request.url.spec().length());
- ServiceWorkerResponse opaque_response(non_opaque_response);
- opaque_response.response_type = network::mojom::FetchResponseType::kOpaque;
- opaque_response.response_time = response_time;
+ blink::mojom::FetchAPIResponsePtr opaque_response(CreateBlobBodyResponse());
+ opaque_response->response_type = network::mojom::FetchResponseType::kOpaque;
+ opaque_response->response_time = response_time;
- EXPECT_TRUE(Put(opaque_request, opaque_response));
+ EXPECT_TRUE(Put(opaque_request, std::move(opaque_response)));
// This test is fragile. Right now it deterministically adds non-zero padding.
// But if the url, padding key, or padding algorithm change it might become
// zero.
@@ -1784,11 +1827,11 @@ TEST_F(CacheStorageCacheTest, VerifyOpaqueSizePadding) {
TEST_F(CacheStorageCacheTest, TestDifferentOpaqueSideDataSizes) {
ServiceWorkerFetchRequest request(body_request_);
- ServiceWorkerResponse response(body_response_);
- response.response_type = network::mojom::FetchResponseType::kOpaque;
+ blink::mojom::FetchAPIResponsePtr response(CreateBlobBodyResponse());
+ response->response_type = network::mojom::FetchResponseType::kOpaque;
base::Time response_time(base::Time::Now());
- response.response_time = response_time;
- EXPECT_TRUE(Put(request, response));
+ response->response_time = response_time;
+ EXPECT_TRUE(Put(request, std::move(response)));
int64_t opaque_cache_size_no_side_data = Size();
const std::string small_side_data(1024, 'X');
@@ -1816,27 +1859,27 @@ TEST_F(CacheStorageCacheTest, TestDoubleOpaquePut) {
base::Time response_time(base::Time::Now());
- ServiceWorkerResponse response(body_response_);
- response.response_type = network::mojom::FetchResponseType::kOpaque;
- response.response_time = response_time;
- EXPECT_TRUE(Put(request, response));
+ blink::mojom::FetchAPIResponsePtr response(CreateBlobBodyResponse());
+ response->response_type = network::mojom::FetchResponseType::kOpaque;
+ response->response_time = response_time;
+ EXPECT_TRUE(Put(request, std::move(response)));
int64_t size_after_first_put = Size();
ServiceWorkerFetchRequest request2(body_request_);
- ServiceWorkerResponse response2(body_response_);
- response2.response_type = network::mojom::FetchResponseType::kOpaque;
- response2.response_time = response_time;
- EXPECT_TRUE(Put(request2, response2));
+ blink::mojom::FetchAPIResponsePtr response2(CreateBlobBodyResponse());
+ response2->response_type = network::mojom::FetchResponseType::kOpaque;
+ response2->response_time = response_time;
+ EXPECT_TRUE(Put(request2, std::move(response2)));
EXPECT_EQ(size_after_first_put, Size());
}
TEST_P(CacheStorageCacheTestP, GetSizeThenClose) {
// Create the backend and put something in it.
- EXPECT_TRUE(Put(body_request_, body_response_));
+ EXPECT_TRUE(Put(body_request_, CreateBlobBodyResponse()));
// Get a reference to the response in the cache.
EXPECT_TRUE(Match(body_request_));
- blink::mojom::BlobPtr blob = callback_response_->blob->TakeBlobPtr();
+ blink::mojom::BlobPtr blob(std::move(callback_response_->blob->blob));
callback_response_ = nullptr;
int64_t cache_size = Size();
@@ -1849,17 +1892,17 @@ TEST_P(CacheStorageCacheTestP, GetSizeThenClose) {
TEST_P(CacheStorageCacheTestP, OpsFailOnClosedBackend) {
// Create the backend and put something in it.
- EXPECT_TRUE(Put(body_request_, body_response_));
+ EXPECT_TRUE(Put(body_request_, CreateBlobBodyResponse()));
EXPECT_TRUE(Close());
VerifyAllOpsFail();
}
TEST_P(CacheStorageCacheTestP, BlobReferenceDelaysClose) {
// Create the backend and put something in it.
- EXPECT_TRUE(Put(body_request_, body_response_));
+ EXPECT_TRUE(Put(body_request_, CreateBlobBodyResponse()));
// Get a reference to the response in the cache.
EXPECT_TRUE(Match(body_request_));
- blink::mojom::BlobPtr blob = callback_response_->blob->TakeBlobPtr();
+ blink::mojom::BlobPtr blob(std::move(callback_response_->blob->blob));
callback_response_ = nullptr;
base::RunLoop loop;
@@ -1891,13 +1934,13 @@ TEST_P(CacheStorageCacheTestP, VerifySerialScheduling) {
blink::mojom::BatchOperation::New();
operation1->operation_type = blink::mojom::OperationType::kPut;
operation1->request = body_request_;
- operation1->response = body_response_;
+ operation1->response = CreateBlobBodyResponse();
std::unique_ptr<base::RunLoop> close_loop1(new base::RunLoop());
std::vector<blink::mojom::BatchOperationPtr> operations1;
operations1.emplace_back(std::move(operation1));
cache_->BatchOperation(
- std::move(operations1),
+ std::move(operations1), true /* fail_on_duplicate */,
base::BindOnce(&CacheStorageCacheTest::SequenceCallback,
base::Unretained(this), 1, &sequence_out,
close_loop1.get()),
@@ -1910,14 +1953,14 @@ TEST_P(CacheStorageCacheTestP, VerifySerialScheduling) {
blink::mojom::BatchOperation::New();
operation2->operation_type = blink::mojom::OperationType::kPut;
operation2->request = body_request_;
- operation2->response = body_response_;
+ operation2->response = CreateBlobBodyResponse();
delayable_backend->set_delay_open_entry(false);
std::unique_ptr<base::RunLoop> close_loop2(new base::RunLoop());
std::vector<blink::mojom::BatchOperationPtr> operations2;
operations2.emplace_back(std::move(operation2));
cache_->BatchOperation(
- std::move(operations2),
+ std::move(operations2), true /* fail_on_duplicate */,
base::BindOnce(&CacheStorageCacheTest::SequenceCallback,
base::Unretained(this), 2, &sequence_out,
close_loop2.get()),
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 87c836e3f98..c61cf8c1d81 100644
--- a/chromium/content/browser/cache_storage/cache_storage_context_impl.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_context_impl.cc
@@ -7,7 +7,7 @@
#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/sequenced_task_runner.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/browser/cache_storage/cache_storage_manager.h"
#include "content/public/browser/browser_context.h"
@@ -36,7 +36,7 @@ void CacheStorageContextImpl::Init(
is_incognito_ = user_data_directory.empty();
scoped_refptr<base::SequencedTaskRunner> cache_task_runner =
base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BACKGROUND,
+ {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
// This thread-hopping antipattern is needed here for some unit tests, where
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 60669ac676e..5f50ea600d4 100644
--- a/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.cc
@@ -34,6 +34,7 @@ namespace content {
namespace {
using blink::mojom::CacheStorageError;
+using blink::mojom::CacheStorageVerboseError;
const int32_t kCachePreservationSeconds = 5;
@@ -84,13 +85,14 @@ class CacheStorageDispatcherHost::CacheImpl
void OnCacheMatchCallback(
blink::mojom::CacheStorageCache::MatchCallback callback,
blink::mojom::CacheStorageError error,
- std::unique_ptr<ServiceWorkerResponse> response) {
+ blink::mojom::FetchAPIResponsePtr response) {
if (error != CacheStorageError::kSuccess) {
std::move(callback).Run(blink::mojom::MatchResult::NewStatus(error));
return;
}
- std::move(callback).Run(blink::mojom::MatchResult::NewResponse(*response));
+ std::move(callback).Run(
+ blink::mojom::MatchResult::NewResponse(std::move(response)));
}
void MatchAll(const base::Optional<ServiceWorkerFetchRequest>& request,
@@ -120,7 +122,7 @@ class CacheStorageDispatcherHost::CacheImpl
void OnCacheMatchAllCallback(
blink::mojom::CacheStorageCache::MatchAllCallback callback,
blink::mojom::CacheStorageError error,
- std::vector<ServiceWorkerResponse> responses) {
+ std::vector<blink::mojom::FetchAPIResponsePtr> responses) {
if (error != CacheStorageError::kSuccess &&
error != CacheStorageError::kErrorNotFound) {
std::move(callback).Run(blink::mojom::MatchAllResult::NewStatus(error));
@@ -167,14 +169,16 @@ class CacheStorageDispatcherHost::CacheImpl
}
void Batch(std::vector<blink::mojom::BatchOperationPtr> batch_operations,
+ bool fail_on_duplicates,
BatchCallback callback) override {
content::CacheStorageCache* cache = cache_handle_.value();
if (!cache) {
- std::move(callback).Run(CacheStorageError::kErrorNotFound);
+ std::move(callback).Run(CacheStorageVerboseError::New(
+ CacheStorageError::kErrorNotFound, base::nullopt));
return;
}
cache->BatchOperation(
- std::move(batch_operations),
+ std::move(batch_operations), fail_on_duplicates,
base::BindOnce(&CacheImpl::OnCacheBatchCallback,
weak_factory_.GetWeakPtr(), std::move(callback)),
base::BindOnce(&CacheImpl::OnBadMessage, weak_factory_.GetWeakPtr(),
@@ -183,8 +187,8 @@ class CacheStorageDispatcherHost::CacheImpl
void OnCacheBatchCallback(
blink::mojom::CacheStorageCache::BatchCallback callback,
- blink::mojom::CacheStorageError error) {
- std::move(callback).Run(error);
+ blink::mojom::CacheStorageVerboseErrorPtr error) {
+ std::move(callback).Run(std::move(error));
}
void OnBadMessage(mojo::ReportBadMessageCallback bad_message_callback) {
@@ -371,14 +375,14 @@ void CacheStorageDispatcherHost::OnKeysCallback(
void CacheStorageDispatcherHost::OnMatchCallback(
blink::mojom::CacheStorage::MatchCallback callback,
CacheStorageError error,
- std::unique_ptr<ServiceWorkerResponse> response) {
+ blink::mojom::FetchAPIResponsePtr response) {
if (error != CacheStorageError::kSuccess) {
std::move(callback).Run(blink::mojom::MatchResult::NewStatus(error));
return;
}
std::move(callback).Run(
- blink::mojom::MatchResult::NewResponse(std::move(*response)));
+ blink::mojom::MatchResult::NewResponse(std::move(response)));
}
void CacheStorageDispatcherHost::AddBinding(
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 f4f99042e39..ade31c52d76 100644
--- a/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.h
+++ b/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.h
@@ -83,7 +83,7 @@ class CONTENT_EXPORT CacheStorageDispatcherHost
blink::mojom::CacheStorageError error);
void OnMatchCallback(blink::mojom::CacheStorage::MatchCallback callback,
blink::mojom::CacheStorageError error,
- std::unique_ptr<ServiceWorkerResponse> response);
+ blink::mojom::FetchAPIResponsePtr response);
void OnOpenCallback(url::Origin origin,
blink::mojom::CacheStorage::OpenCallback callback,
CacheStorageCacheHandle cache_handle,
diff --git a/chromium/content/browser/cache_storage/cache_storage_manager.cc b/chromium/content/browser/cache_storage/cache_storage_manager.cc
index be479cf1d69..6eab90f4d1e 100644
--- a/chromium/content/browser/cache_storage/cache_storage_manager.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_manager.cc
@@ -255,7 +255,7 @@ void CacheStorageManager::WriteToCache(
CacheStorageOwner owner,
const std::string& cache_name,
std::unique_ptr<ServiceWorkerFetchRequest> request,
- std::unique_ptr<ServiceWorkerResponse> response,
+ blink::mojom::FetchAPIResponsePtr response,
CacheStorage::ErrorCallback callback) {
// Cache API should write through the dispatcher.
DCHECK_NE(owner, CacheStorageOwner::kCacheAPI);
diff --git a/chromium/content/browser/cache_storage/cache_storage_manager.h b/chromium/content/browser/cache_storage/cache_storage_manager.h
index e7460ce34f8..d08b84a5e3e 100644
--- a/chromium/content/browser/cache_storage/cache_storage_manager.h
+++ b/chromium/content/browser/cache_storage/cache_storage_manager.h
@@ -110,7 +110,7 @@ class CONTENT_EXPORT CacheStorageManager
CacheStorageOwner owner,
const std::string& cache_name,
std::unique_ptr<ServiceWorkerFetchRequest> request,
- std::unique_ptr<ServiceWorkerResponse> response,
+ blink::mojom::FetchAPIResponsePtr response,
CacheStorage::ErrorCallback callback);
// This must be called before creating any of the public *Cache functions
@@ -204,7 +204,7 @@ class CONTENT_EXPORT CacheStorageManager
// |cache_task_runner_|.
CacheStorageMap cache_storage_map_;
- base::ObserverList<CacheStorageContextImpl::Observer> observers_;
+ base::ObserverList<CacheStorageContextImpl::Observer>::Unchecked observers_;
scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
base::WeakPtr<storage::BlobStorageContext> blob_context_;
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 d62569b7672..c9aa9486f41 100644
--- a/chromium/content/browser/cache_storage/cache_storage_manager_unittest.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_manager_unittest.cc
@@ -11,6 +11,7 @@
#include <set>
#include <utility>
+#include "base/containers/flat_map.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
@@ -56,12 +57,14 @@
#include "url/origin.h"
using blink::mojom::CacheStorageError;
+using blink::mojom::CacheStorageVerboseErrorPtr;
using network::mojom::FetchResponseType;
namespace content {
namespace cache_storage_manager_unittest {
using blink::mojom::StorageType;
+using ResponseHeaderMap = base::flat_map<std::string, std::string>;
class MockCacheStorageQuotaManagerProxy : public MockQuotaManagerProxy {
public:
@@ -210,19 +213,21 @@ class CacheStorageManagerTest : public testing::Test {
return cache_names;
}
- void CachePutCallback(base::RunLoop* run_loop, CacheStorageError error) {
- callback_error_ = error;
+ void CachePutCallback(base::RunLoop* run_loop,
+ CacheStorageVerboseErrorPtr error) {
+ callback_error_ = error->value;
run_loop->Quit();
}
- void CacheDeleteCallback(base::RunLoop* run_loop, CacheStorageError error) {
- callback_error_ = error;
+ void CacheDeleteCallback(base::RunLoop* run_loop,
+ CacheStorageVerboseErrorPtr error) {
+ callback_error_ = error->value;
run_loop->Quit();
}
void CacheMatchCallback(base::RunLoop* run_loop,
CacheStorageError error,
- std::unique_ptr<ServiceWorkerResponse> response) {
+ blink::mojom::FetchAPIResponsePtr response) {
callback_error_ = error;
callback_cache_handle_response_ = std::move(response);
run_loop->Quit();
@@ -424,11 +429,10 @@ class CacheStorageManagerTest : public testing::Test {
auto request = std::make_unique<ServiceWorkerFetchRequest>();
request->url = GURL(request_url);
- auto response = std::make_unique<ServiceWorkerResponse>();
-
base::RunLoop loop;
cache_manager_->WriteToCache(
- origin, owner, cache_name, std::move(request), std::move(response),
+ origin, owner, cache_name, std::move(request),
+ blink::mojom::FetchAPIResponse::New(),
base::BindOnce(&CacheStorageManagerTest::ErrorCallback,
base::Unretained(this), base::Unretained(&loop)));
loop.Run();
@@ -447,10 +451,10 @@ class CacheStorageManagerTest : public testing::Test {
bool CachePutWithRequestAndHeaders(
CacheStorageCache* cache,
const ServiceWorkerFetchRequest& request,
- const ServiceWorkerHeaderMap& response_headers,
+ ResponseHeaderMap response_headers,
FetchResponseType response_type = FetchResponseType::kDefault) {
return CachePutWithStatusCode(cache, request, 200, response_type,
- response_headers);
+ std::move(response_headers));
}
bool CachePutWithStatusCode(
@@ -458,8 +462,7 @@ class CacheStorageManagerTest : public testing::Test {
const ServiceWorkerFetchRequest& request,
int status_code,
FetchResponseType response_type = FetchResponseType::kDefault,
- const ServiceWorkerHeaderMap& response_headers =
- ServiceWorkerHeaderMap()) {
+ ResponseHeaderMap response_headers = ResponseHeaderMap()) {
std::string blob_uuid = base::GenerateGUID();
std::unique_ptr<storage::BlobDataBuilder> blob_data(
new storage::BlobDataBuilder(blob_uuid));
@@ -468,35 +471,34 @@ class CacheStorageManagerTest : public testing::Test {
std::unique_ptr<storage::BlobDataHandle> blob_data_handle =
blob_storage_context_->AddFinishedBlob(std::move(blob_data));
- scoped_refptr<storage::BlobHandle> blob_handle;
- blink::mojom::BlobPtr blob;
- storage::BlobImpl::Create(std::move(blob_data_handle), MakeRequest(&blob));
- blob_handle = base::MakeRefCounted<storage::BlobHandle>(std::move(blob));
-
- std::unique_ptr<std::vector<GURL>> url_list =
- std::make_unique<std::vector<GURL>>();
- url_list->push_back(request.url);
- ServiceWorkerResponse response(
- std::move(url_list), status_code, "OK", response_type,
- std::make_unique<ServiceWorkerHeaderMap>(response_headers), blob_uuid,
- request.url.spec().size(), blob_handle,
+ blink::mojom::BlobPtrInfo blob_ptr_info;
+ storage::BlobImpl::Create(std::move(blob_data_handle),
+ MakeRequest(&blob_ptr_info));
+
+ auto blob = blink::mojom::SerializedBlob::New();
+ blob->uuid = blob_uuid;
+ blob->size = request.url.spec().size();
+ blob->blob = std::move(blob_ptr_info);
+
+ auto response = blink::mojom::FetchAPIResponse::New(
+ std::vector<GURL>({request.url}), status_code, "OK", response_type,
+ response_headers, std::move(blob),
blink::mojom::ServiceWorkerResponseError::kUnknown, base::Time(),
- false /* is_in_cache_storage */,
std::string() /* cache_storage_cache_name */,
- std::make_unique<
- ServiceWorkerHeaderList>() /* cors_exposed_header_names */);
+ std::vector<std::string>() /* cors_exposed_header_names */,
+ false /* is_in_cache_storage */, nullptr /* side_data_blob */);
blink::mojom::BatchOperationPtr operation =
blink::mojom::BatchOperation::New();
operation->operation_type = blink::mojom::OperationType::kPut;
operation->request = request;
- operation->response = response;
+ operation->response = std::move(response);
std::vector<blink::mojom::BatchOperationPtr> operations;
operations.emplace_back(std::move(operation));
base::RunLoop loop;
cache->BatchOperation(
- std::move(operations),
+ std::move(operations), true /* fail_on_duplicate */,
base::BindOnce(&CacheStorageManagerTest::CachePutCallback,
base::Unretained(this), base::Unretained(&loop)),
CacheStorageCache::BadMessageCallback());
@@ -508,19 +510,18 @@ class CacheStorageManagerTest : public testing::Test {
bool CacheDelete(CacheStorageCache* cache, const GURL& url) {
ServiceWorkerFetchRequest request;
request.url = url;
- ServiceWorkerResponse response;
blink::mojom::BatchOperationPtr operation =
blink::mojom::BatchOperation::New();
operation->operation_type = blink::mojom::OperationType::kDelete;
operation->request = request;
- operation->response = response;
+ operation->response = blink::mojom::FetchAPIResponse::New();
std::vector<blink::mojom::BatchOperationPtr> operations;
operations.emplace_back(std::move(operation));
base::RunLoop loop;
cache->BatchOperation(
- std::move(operations),
+ std::move(operations), true /* fail_on_duplicate */,
base::BindOnce(&CacheStorageManagerTest::CacheDeleteCallback,
base::Unretained(this), base::Unretained(&loop)),
CacheStorageCache::BadMessageCallback());
@@ -641,7 +642,7 @@ class CacheStorageManagerTest : public testing::Test {
CacheStorageCacheHandle callback_cache_handle_;
int callback_bool_;
CacheStorageError callback_error_;
- std::unique_ptr<ServiceWorkerResponse> callback_cache_handle_response_;
+ blink::mojom::FetchAPIResponsePtr callback_cache_handle_response_;
std::unique_ptr<storage::BlobDataHandle> callback_data_handle_;
CacheStorageIndex callback_cache_index_;
@@ -1794,11 +1795,11 @@ TEST_P(CacheStorageManagerTestP, StorageMatch_IgnoreVary) {
request.url = url;
request.headers["vary_foo"] = "foo";
- ServiceWorkerHeaderMap response_headers;
+ ResponseHeaderMap response_headers;
response_headers["vary"] = "vary_foo";
- EXPECT_TRUE(CachePutWithRequestAndHeaders(callback_cache_handle_.value(),
- request, response_headers));
+ EXPECT_TRUE(CachePutWithRequestAndHeaders(
+ callback_cache_handle_.value(), request, std::move(response_headers)));
EXPECT_TRUE(StorageMatchWithRequest(origin1_, "foo", request));
request.headers["vary_foo"] = "bar";
@@ -1847,7 +1848,7 @@ TEST_P(CacheStorageManagerTestP, StorageMatchAll_IgnoreVary) {
request.url = url;
request.headers["vary_foo"] = "foo";
- ServiceWorkerHeaderMap response_headers;
+ ResponseHeaderMap response_headers;
response_headers["vary"] = "vary_foo";
EXPECT_TRUE(CachePutWithRequestAndHeaders(callback_cache_handle_.value(),
diff --git a/chromium/content/browser/child_process_launcher.cc b/chromium/content/browser/child_process_launcher.cc
index f071c1d5c05..bd16e1b1080 100644
--- a/chromium/content/browser/child_process_launcher.cc
+++ b/chromium/content/browser/child_process_launcher.cc
@@ -175,6 +175,7 @@ bool ChildProcessLauncherPriority::operator==(
return visible == other.visible &&
has_media_stream == other.has_media_stream &&
frame_depth == other.frame_depth &&
+ intersects_viewport == other.intersects_viewport &&
boost_for_pending_views == other.boost_for_pending_views
#if defined(OS_ANDROID)
&& importance == other.importance
diff --git a/chromium/content/browser/child_process_launcher.h b/chromium/content/browser/child_process_launcher.h
index 190ee370186..26f1376d45c 100644
--- a/chromium/content/browser/child_process_launcher.h
+++ b/chromium/content/browser/child_process_launcher.h
@@ -59,6 +59,7 @@ struct ChildProcessLauncherPriority {
ChildProcessLauncherPriority(bool visible,
bool has_media_stream,
unsigned int frame_depth,
+ bool intersects_viewport,
bool boost_for_pending_views,
bool should_boost_for_pending_views
#if defined(OS_ANDROID)
@@ -69,6 +70,7 @@ struct ChildProcessLauncherPriority {
: visible(visible),
has_media_stream(has_media_stream),
frame_depth(frame_depth),
+ intersects_viewport(intersects_viewport),
boost_for_pending_views(boost_for_pending_views),
should_boost_for_pending_views(should_boost_for_pending_views)
#if defined(OS_ANDROID)
@@ -108,6 +110,12 @@ struct ChildProcessLauncherPriority {
// matching |visible| properties.
unsigned int frame_depth;
+ // |intersects_viewport| is true if this process is responsible for a frame
+ // which intersects a viewport which has |visible| visibility. It only makes
+ // sense to compare this property for two ChildProcessLauncherPriority
+ // instances with matching |visible| properties.
+ bool intersects_viewport;
+
// |boost_for_pending_views| is true if this process is responsible for a
// pending view (this is used to boost priority of a process responsible for
// foreground content which hasn't yet been added as a visible widget -- i.e.
diff --git a/chromium/content/browser/child_process_launcher_helper.cc b/chromium/content/browser/child_process_launcher_helper.cc
index d4272efe0e4..6e0eebe2361 100644
--- a/chromium/content/browser/child_process_launcher_helper.cc
+++ b/chromium/content/browser/child_process_launcher_helper.cc
@@ -8,10 +8,10 @@
#include "base/metrics/histogram_macros.h"
#include "base/no_destructor.h"
#include "base/single_thread_task_runner.h"
-#include "base/task_scheduler/lazy_task_runner.h"
-#include "base/task_scheduler/post_task.h"
-#include "base/task_scheduler/single_thread_task_runner_thread_mode.h"
-#include "base/task_scheduler/task_traits.h"
+#include "base/task/lazy_task_runner.h"
+#include "base/task/post_task.h"
+#include "base/task/single_thread_task_runner_thread_mode.h"
+#include "base/task/task_traits.h"
#include "content/browser/child_process_launcher.h"
#include "content/public/browser/child_process_launcher_utils.h"
#include "content/public/common/content_switches.h"
diff --git a/chromium/content/browser/child_process_launcher_helper_android.cc b/chromium/content/browser/child_process_launcher_helper_android.cc
index 2115d7f830c..83be7e6bbb4 100644
--- a/chromium/content/browser/child_process_launcher_helper_android.cc
+++ b/chromium/content/browser/child_process_launcher_helper_android.cc
@@ -223,7 +223,8 @@ void ChildProcessLauncherHelper::SetProcessPriorityOnLauncherThread(
return Java_ChildProcessLauncherHelperImpl_setPriority(
env, java_peer_, process.Handle(), priority.visible,
priority.has_media_stream, priority.frame_depth,
- priority.boost_for_pending_views, static_cast<jint>(priority.importance));
+ priority.intersects_viewport, priority.boost_for_pending_views,
+ static_cast<jint>(priority.importance));
}
// static
diff --git a/chromium/content/browser/child_process_launcher_helper_mac.cc b/chromium/content/browser/child_process_launcher_helper_mac.cc
index 3fd28bf7589..c1b02ef4855 100644
--- a/chromium/content/browser/child_process_launcher_helper_mac.cc
+++ b/chromium/content/browser/child_process_launcher_helper_mac.cc
@@ -22,6 +22,7 @@
#include "content/public/common/sandboxed_process_launcher_delegate.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_v2.sb.h"
#include "services/service_manager/sandbox/mac/gpu_v2.sb.h"
@@ -73,7 +74,8 @@ bool ChildProcessLauncherHelper::BeforeLaunchOnLauncherThread(
service_manager::IsUnsandboxedSandboxType(sandbox_type);
// TODO(kerrnel): Delete this switch once the V2 sandbox is always enabled.
- bool v2_process = false;
+ bool use_v2 = base::FeatureList::IsEnabled(features::kMacV2Sandbox);
+
switch (sandbox_type) {
case service_manager::SANDBOX_TYPE_NO_SANDBOX:
break;
@@ -84,18 +86,22 @@ bool ChildProcessLauncherHelper::BeforeLaunchOnLauncherThread(
case service_manager::SANDBOX_TYPE_NACL_LOADER:
case service_manager::SANDBOX_TYPE_PDF_COMPOSITOR:
case service_manager::SANDBOX_TYPE_PROFILING:
- v2_process = true;
+ // If the feature experiment is enabled and this process type supports
+ // the v2 sandbox, use it.
+ use_v2 &= true;
+ break;
+ case service_manager::SANDBOX_TYPE_AUDIO:
+ // The audio service only exists with the v2 sandbox.
+ use_v2 |= true;
break;
default:
// This is a 'break' because the V2 sandbox is not enabled for all
// processes yet, and so there are sandbox types like NETWORK that
// should not be run under the V2 sandbox.
+ use_v2 = false;
break;
}
- bool use_v2 =
- v2_process && base::FeatureList::IsEnabled(features::kMacV2Sandbox);
-
if (use_v2 && !no_sandbox) {
// Generate the profile string.
std::string profile =
@@ -120,6 +126,9 @@ bool ChildProcessLauncherHelper::BeforeLaunchOnLauncherThread(
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_UTILITY:
case service_manager::SANDBOX_TYPE_PROFILING:
profile += service_manager::kSeatbeltPolicyString_utility;
@@ -143,6 +152,7 @@ bool ChildProcessLauncherHelper::BeforeLaunchOnLauncherThread(
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_PPAPI:
diff --git a/chromium/content/browser/child_process_security_policy_impl.cc b/chromium/content/browser/child_process_security_policy_impl.cc
index 1272be30040..bd757e4fdef 100644
--- a/chromium/content/browser/child_process_security_policy_impl.cc
+++ b/chromium/content/browser/child_process_security_policy_impl.cc
@@ -1120,7 +1120,7 @@ bool ChildProcessSecurityPolicyImpl::CanAccessDataForOrigin(int child_id,
// TODO(creis): We must pass the valid browser_context to convert hosted apps
// URLs. Currently, hosted apps cannot set cookies in this mode. See
// http://crbug.com/160576.
- GURL site_url = SiteInstanceImpl::GetSiteForURL(nullptr, url);
+ GURL site_url = SiteInstance::GetSiteForURL(nullptr, url);
base::AutoLock lock(lock_);
SecurityStateMap::iterator state = security_state_.find(child_id);
@@ -1153,7 +1153,7 @@ void ChildProcessSecurityPolicyImpl::LockToOrigin(int child_id,
DCHECK_CURRENTLY_ON(BrowserThread::UI);
// "gurl" can be currently empty in some cases, such as file://blah.
- DCHECK(SiteInstanceImpl::GetSiteForURL(nullptr, gurl) == gurl);
+ DCHECK_EQ(SiteInstanceImpl::DetermineProcessLockURL(nullptr, gurl), gurl);
base::AutoLock lock(lock_);
SecurityStateMap::iterator state = security_state_.find(child_id);
DCHECK(state != security_state_.end());
diff --git a/chromium/content/browser/cocoa/system_hotkey_helper_mac.mm b/chromium/content/browser/cocoa/system_hotkey_helper_mac.mm
index 36a0ee2f3bc..0a26a48fd62 100644
--- a/chromium/content/browser/cocoa/system_hotkey_helper_mac.mm
+++ b/chromium/content/browser/cocoa/system_hotkey_helper_mac.mm
@@ -8,9 +8,9 @@
#include "base/files/file_path.h"
#include "base/mac/foundation_util.h"
#include "base/metrics/histogram_macros.h"
-#include "base/task_scheduler/post_task.h"
-#include "base/task_scheduler/task_traits.h"
-#include "base/threading/thread_restrictions.h"
+#include "base/task/post_task.h"
+#include "base/task/task_traits.h"
+#include "base/threading/scoped_blocking_call.h"
#include "content/browser/cocoa/system_hotkey_map.h"
#include "content/public/browser/browser_thread.h"
@@ -48,7 +48,7 @@ SystemHotkeyHelperMac::~SystemHotkeyHelperMac() {
}
void SystemHotkeyHelperMac::LoadSystemHotkeys() {
- base::AssertBlockingAllowed();
+ base::ScopedBlockingCall scoped_blocking_call(base::BlockingType::MAY_BLOCK);
std::string library_path(base::mac::GetUserLibraryPath().value());
NSString* expanded_file_path =
diff --git a/chromium/content/browser/code_cache/generated_code_cache.cc b/chromium/content/browser/code_cache/generated_code_cache.cc
index c74c9a32d40..f1f3ec32393 100644
--- a/chromium/content/browser/code_cache/generated_code_cache.cc
+++ b/chromium/content/browser/code_cache/generated_code_cache.cc
@@ -58,66 +58,103 @@ std::string GetCacheKey(const GURL& resource_url,
// being initialized.
class GeneratedCodeCache::PendingOperation {
public:
- PendingOperation(Operation op,
- std::string key,
- scoped_refptr<net::IOBufferWithSize>);
- PendingOperation(Operation op, std::string key, const ReadDataCallback&);
- PendingOperation(Operation op, std::string key);
+ static std::unique_ptr<PendingOperation> CreateWritePendingOp(
+ std::string key,
+ scoped_refptr<net::IOBufferWithSize>);
+ static std::unique_ptr<PendingOperation> CreateFetchPendingOp(
+ std::string key,
+ const ReadDataCallback&);
+ static std::unique_ptr<PendingOperation> CreateDeletePendingOp(
+ std::string key);
+ static std::unique_ptr<PendingOperation> CreateClearCachePendingOp(
+ net::CompletionCallback callback);
~PendingOperation();
Operation operation() const { return op_; }
const std::string& key() const { return key_; }
const scoped_refptr<net::IOBufferWithSize> data() const { return data_; }
- const ReadDataCallback& callback() const { return callback_; }
+ ReadDataCallback ReleaseReadCallback() { return std::move(read_callback_); }
+ net::CompletionCallback ReleaseCallback() { return std::move(callback_); }
private:
+ PendingOperation(Operation op,
+ std::string key,
+ scoped_refptr<net::IOBufferWithSize>,
+ const ReadDataCallback&,
+ net::CompletionCallback);
+
const Operation op_;
const std::string key_;
const scoped_refptr<net::IOBufferWithSize> data_;
- const ReadDataCallback callback_;
+ ReadDataCallback read_callback_;
+ net::CompletionCallback callback_;
};
-GeneratedCodeCache::PendingOperation::PendingOperation(
- Operation op,
+std::unique_ptr<GeneratedCodeCache::PendingOperation>
+GeneratedCodeCache::PendingOperation::CreateWritePendingOp(
std::string key,
- scoped_refptr<net::IOBufferWithSize> buffer)
- : op_(op),
- key_(std::move(key)),
- data_(buffer),
- callback_(ReadDataCallback()) {}
+ scoped_refptr<net::IOBufferWithSize> buffer) {
+ return base::WrapUnique(
+ new PendingOperation(Operation::kWrite, std::move(key), buffer,
+ ReadDataCallback(), net::CompletionCallback()));
+}
+
+std::unique_ptr<GeneratedCodeCache::PendingOperation>
+GeneratedCodeCache::PendingOperation::CreateFetchPendingOp(
+ std::string key,
+ const ReadDataCallback& read_callback) {
+ return base::WrapUnique(new PendingOperation(
+ Operation::kFetch, std::move(key), scoped_refptr<net::IOBufferWithSize>(),
+ read_callback, net::CompletionCallback()));
+}
+
+std::unique_ptr<GeneratedCodeCache::PendingOperation>
+GeneratedCodeCache::PendingOperation::CreateDeletePendingOp(std::string key) {
+ return base::WrapUnique(
+ new PendingOperation(Operation::kDelete, std::move(key),
+ scoped_refptr<net::IOBufferWithSize>(),
+ ReadDataCallback(), net::CompletionCallback()));
+}
+
+std::unique_ptr<GeneratedCodeCache::PendingOperation>
+GeneratedCodeCache::PendingOperation::CreateClearCachePendingOp(
+ net::CompletionCallback callback) {
+ return base::WrapUnique(
+ new PendingOperation(Operation::kClearCache, std::string(),
+ scoped_refptr<net::IOBufferWithSize>(),
+ ReadDataCallback(), std::move(callback)));
+}
GeneratedCodeCache::PendingOperation::PendingOperation(
Operation op,
std::string key,
- const ReadDataCallback& callback)
- : op_(op),
- key_(std::move(key)),
- data_(scoped_refptr<net::IOBufferWithSize>()),
- callback_(callback) {}
-
-GeneratedCodeCache::PendingOperation::PendingOperation(Operation op,
- std::string key)
+ scoped_refptr<net::IOBufferWithSize> buffer,
+ const ReadDataCallback& read_callback,
+ net::CompletionCallback callback)
: op_(op),
key_(std::move(key)),
- data_(scoped_refptr<net::IOBufferWithSize>()),
- callback_(ReadDataCallback()) {}
+ data_(buffer),
+ read_callback_(read_callback),
+ callback_(std::move(callback)) {}
GeneratedCodeCache::PendingOperation::~PendingOperation() = default;
-// Static factory method.
-std::unique_ptr<GeneratedCodeCache> GeneratedCodeCache::Create(
- const base::FilePath& path,
- int max_size_bytes) {
- return base::WrapUnique(new GeneratedCodeCache(path, max_size_bytes));
+GeneratedCodeCache::GeneratedCodeCache(const base::FilePath& path,
+ int max_size_bytes)
+ : backend_state_(kUnInitialized),
+ path_(path),
+ max_size_bytes_(max_size_bytes),
+ weak_ptr_factory_(this) {
+ CreateBackend();
}
GeneratedCodeCache::~GeneratedCodeCache() = default;
-void GeneratedCodeCache::WriteData(
- const GURL& url,
- const url::Origin& origin,
- scoped_refptr<net::IOBufferWithSize> buffer) {
+void GeneratedCodeCache::WriteData(const GURL& url,
+ const url::Origin& origin,
+ const base::Time& response_time,
+ const std::vector<uint8_t>& data) {
// Silently ignore the requests.
if (backend_state_ == kFailed)
return;
@@ -127,12 +164,24 @@ void GeneratedCodeCache::WriteData(
if (!IsAllowedToCache(url, origin))
return;
+ // Append the response time to the metadata. Code caches store
+ // response_time + generated code as a single entry.
+ scoped_refptr<net::IOBufferWithSize> buffer(
+ new net::IOBufferWithSize(data.size() + kResponseTimeSizeInBytes));
+ int64_t serialized_time =
+ response_time.ToDeltaSinceWindowsEpoch().InMicroseconds();
+ memcpy(buffer->data(), &serialized_time, kResponseTimeSizeInBytes);
+ if (!data.empty())
+ memcpy(buffer->data() + kResponseTimeSizeInBytes, &data.front(),
+ data.size());
+
std::string key = GetCacheKey(url, origin);
if (backend_state_ != kInitialized) {
// Insert it into the list of pending operations while the backend is
// still being opened.
- pending_ops_.push_back(std::make_unique<PendingOperation>(
- Operation::kWrite, std::move(key), buffer));
+ pending_ops_.push_back(
+ GeneratedCodeCache::PendingOperation::CreateWritePendingOp(
+ std::move(key), buffer));
return;
}
@@ -144,14 +193,14 @@ void GeneratedCodeCache::FetchEntry(const GURL& url,
ReadDataCallback read_data_callback) {
if (backend_state_ == kFailed) {
// Silently ignore the requests.
- std::move(read_data_callback).Run(scoped_refptr<net::IOBufferWithSize>());
+ std::move(read_data_callback).Run(base::Time(), std::vector<uint8_t>());
return;
}
// If the url is invalid or if it is from a unique origin, we should not
// cache the code.
if (!IsAllowedToCache(url, origin)) {
- std::move(read_data_callback).Run(scoped_refptr<net::IOBufferWithSize>());
+ std::move(read_data_callback).Run(base::Time(), std::vector<uint8_t>());
return;
}
@@ -159,8 +208,9 @@ void GeneratedCodeCache::FetchEntry(const GURL& url,
if (backend_state_ != kInitialized) {
// Insert it into the list of pending operations while the backend is
// still being opened.
- pending_ops_.push_back(std::make_unique<PendingOperation>(
- Operation::kFetch, std::move(key), read_data_callback));
+ pending_ops_.push_back(
+ GeneratedCodeCache::PendingOperation::CreateFetchPendingOp(
+ std::move(key), read_data_callback));
return;
}
@@ -183,20 +233,27 @@ void GeneratedCodeCache::DeleteEntry(const GURL& url,
// Insert it into the list of pending operations while the backend is
// still being opened.
pending_ops_.push_back(
- std::make_unique<PendingOperation>(Operation::kDelete, std::move(key)));
+ GeneratedCodeCache::PendingOperation::CreateDeletePendingOp(
+ std::move(key)));
return;
}
DeleteEntryImpl(key);
}
-GeneratedCodeCache::GeneratedCodeCache(const base::FilePath& path,
- int max_size_bytes)
- : backend_state_(kUnInitialized),
- path_(path),
- max_size_bytes_(max_size_bytes),
- weak_ptr_factory_(this) {
- CreateBackend();
+int GeneratedCodeCache::ClearCache(net::CompletionCallback callback) {
+ if (backend_state_ == kFailed) {
+ return net::ERR_FAILED;
+ }
+
+ if (backend_state_ != kInitialized) {
+ pending_ops_.push_back(
+ GeneratedCodeCache::PendingOperation::CreateClearCachePendingOp(
+ std::move(callback)));
+ return net::ERR_IO_PENDING;
+ }
+
+ return backend_->DoomAllEntries(std::move(callback));
}
void GeneratedCodeCache::CreateBackend() {
@@ -242,7 +299,7 @@ void GeneratedCodeCache::IssuePendingOperations() {
for (auto const& op : pending_ops_) {
switch (op->operation()) {
case kFetch:
- FetchEntryImpl(op->key(), op->callback());
+ FetchEntryImpl(op->key(), op->ReleaseReadCallback());
break;
case kWrite:
WriteDataImpl(op->key(), op->data());
@@ -250,6 +307,9 @@ void GeneratedCodeCache::IssuePendingOperations() {
case kDelete:
DeleteEntryImpl(op->key());
break;
+ case kClearCache:
+ DoPendingClearCache(op->ReleaseCallback());
+ break;
}
}
pending_ops_.clear();
@@ -318,7 +378,7 @@ void GeneratedCodeCache::CreateCompleteForWriteData(
void GeneratedCodeCache::FetchEntryImpl(const std::string& key,
ReadDataCallback read_data_callback) {
if (backend_state_ != kInitialized) {
- std::move(read_data_callback).Run(scoped_refptr<net::IOBufferWithSize>());
+ std::move(read_data_callback).Run(base::Time(), std::vector<uint8_t>());
return;
}
@@ -342,7 +402,7 @@ void GeneratedCodeCache::OpenCompleteForReadData(
scoped_refptr<base::RefCountedData<disk_cache::Entry*>> entry,
int rv) {
if (rv != net::OK) {
- std::move(read_data_callback).Run(scoped_refptr<net::IOBufferWithSize>());
+ std::move(read_data_callback).Run(base::Time(), std::vector<uint8_t>());
return;
}
@@ -367,9 +427,14 @@ void GeneratedCodeCache::ReadDataComplete(
scoped_refptr<net::IOBufferWithSize> buffer,
int rv) {
if (rv != buffer->size()) {
- std::move(callback).Run(scoped_refptr<net::IOBufferWithSize>());
+ std::move(callback).Run(base::Time(), std::vector<uint8_t>());
} else {
- std::move(callback).Run(buffer);
+ int64_t raw_response_time = *(reinterpret_cast<int64_t*>(buffer->data()));
+ base::Time response_time = base::Time::FromDeltaSinceWindowsEpoch(
+ base::TimeDelta::FromMicroseconds(raw_response_time));
+ std::vector<uint8_t> data(buffer->data() + kResponseTimeSizeInBytes,
+ buffer->data() + buffer->size());
+ std::move(callback).Run(response_time, data);
}
}
@@ -380,4 +445,14 @@ void GeneratedCodeCache::DeleteEntryImpl(const std::string& key) {
backend_->DoomEntry(key, net::LOWEST, net::CompletionOnceCallback());
}
+void GeneratedCodeCache::DoPendingClearCache(
+ net::CompletionCallback user_callback) {
+ int result = backend_->DoomAllEntries(user_callback);
+ if (result != net::ERR_IO_PENDING) {
+ // Call the callback here because we returned ERR_IO_PENDING for initial
+ // request.
+ std::move(user_callback).Run(result);
+ }
+}
+
} // namespace content
diff --git a/chromium/content/browser/code_cache/generated_code_cache.h b/chromium/content/browser/code_cache/generated_code_cache.h
index 57e92b76946..58e735b447d 100644
--- a/chromium/content/browser/code_cache/generated_code_cache.h
+++ b/chromium/content/browser/code_cache/generated_code_cache.h
@@ -9,6 +9,7 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "content/common/content_export.h"
+#include "net/base/completion_callback.h"
#include "net/base/io_buffer.h"
#include "net/disk_cache/disk_cache.h"
#include "url/origin.h"
@@ -31,11 +32,14 @@ namespace content {
class CONTENT_EXPORT GeneratedCodeCache {
public:
using ReadDataCallback =
- base::RepeatingCallback<void(scoped_refptr<net::IOBufferWithSize>)>;
+ base::RepeatingCallback<void(const base::Time&,
+ const std::vector<uint8_t>&)>;
+ static const int kResponseTimeSizeInBytes = sizeof(int64_t);
// Creates a GeneratedCodeCache with the specified path and the maximum size.
- static std::unique_ptr<GeneratedCodeCache> Create(const base::FilePath& path,
- int max_size);
+ // If |max_size_bytes| is 0, then disk_cache picks a default size based on
+ // some heuristics.
+ GeneratedCodeCache(const base::FilePath& path, int max_size_bytes);
~GeneratedCodeCache();
@@ -44,7 +48,8 @@ class CONTENT_EXPORT GeneratedCodeCache {
// it creates a new one.
void WriteData(const GURL& url,
const url::Origin& origin,
- scoped_refptr<net::IOBufferWithSize>);
+ const base::Time& response_time,
+ const std::vector<uint8_t>& data);
// Fetch entry corresponding to <url, origin> from the cache and pass
// it using the ReadDataCallback.
@@ -53,6 +58,13 @@ class CONTENT_EXPORT GeneratedCodeCache {
// Delete the entry corresponding to <url, origin>
void DeleteEntry(const GURL& url, const url::Origin& origin);
+ // Clear code cache.
+ // TODO(mythria): Add support to conditional clearing based on URL
+ // and time range.
+ // TODO(mythria): Also check if we can avoid retruning an error code and
+ // always call the callback to be consistent with other methods.
+ int ClearCache(net::CompletionCallback callback);
+
const base::FilePath& path() const { return path_; }
private:
@@ -63,13 +75,11 @@ class CONTENT_EXPORT GeneratedCodeCache {
enum BackendState { kUnInitialized, kInitializing, kInitialized, kFailed };
// The operation requested.
- enum Operation { kFetch, kWrite, kDelete };
+ enum Operation { kFetch, kWrite, kDelete, kClearCache };
// Data streams corresponding to each entry.
enum { kDataIndex = 1 };
- GeneratedCodeCache(const base::FilePath& path, int max_size_bytes);
-
// Creates a simple_disk_cache backend.
void CreateBackend();
void DidCreateBackend(
@@ -107,6 +117,9 @@ class CONTENT_EXPORT GeneratedCodeCache {
// Delete entry from cache
void DeleteEntryImpl(const std::string& key);
+ void DoPendingClearCache(net::CompletionCallback callback);
+ void PendingClearComplete(net::CompletionCallback callback, int rv);
+
std::unique_ptr<disk_cache::Backend> backend_;
BackendState backend_state_;
diff --git a/chromium/content/browser/code_cache/generated_code_cache_context.cc b/chromium/content/browser/code_cache/generated_code_cache_context.cc
new file mode 100644
index 00000000000..9aa1621fce3
--- /dev/null
+++ b/chromium/content/browser/code_cache/generated_code_cache_context.cc
@@ -0,0 +1,37 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#include "content/browser/code_cache/generated_code_cache_context.h"
+#include "base/files/file_path.h"
+#include "content/browser/code_cache/generated_code_cache.h"
+#include "content/public/browser/browser_thread.h"
+
+namespace content {
+
+GeneratedCodeCacheContext::GeneratedCodeCacheContext() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+}
+
+void GeneratedCodeCacheContext::Initialize(const base::FilePath& path,
+ int max_bytes) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&GeneratedCodeCacheContext::InitializeOnIO, this, path,
+ max_bytes));
+}
+
+void GeneratedCodeCacheContext::InitializeOnIO(const base::FilePath& path,
+ int max_bytes) {
+ generated_code_cache_.reset(new GeneratedCodeCache(path, max_bytes));
+}
+
+GeneratedCodeCache* GeneratedCodeCacheContext::generated_code_cache() const {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ return generated_code_cache_.get();
+}
+
+GeneratedCodeCacheContext::~GeneratedCodeCacheContext() = default;
+
+} // namespace content
diff --git a/chromium/content/browser/code_cache/generated_code_cache_context.h b/chromium/content/browser/code_cache/generated_code_cache_context.h
new file mode 100644
index 00000000000..4a42bebef7b
--- /dev/null
+++ b/chromium/content/browser/code_cache/generated_code_cache_context.h
@@ -0,0 +1,51 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_CODE_CACHE_GENERATED_CODE_CACHE_CONTEXT_H_
+#define CONTENT_BROWSER_CODE_CACHE_GENERATED_CODE_CACHE_CONTEXT_H_
+
+#include "base/files/file_path.h"
+#include "base/memory/ref_counted.h"
+#include "content/common/content_export.h"
+#include "content/public/browser/browser_thread.h"
+
+namespace content {
+
+class GeneratedCodeCache;
+
+// One instance exists per disk-backed (non in-memory) storage contexts. This
+// owns the instance of GeneratedCodeCache that is used to store the data
+// generated by the renderer (for ex: code caches for script resources). This
+// initializes and closes the code cache on the I/O thread. The instance of
+// this class (|this|) itself is constructed on the UI thread.
+class CONTENT_EXPORT GeneratedCodeCacheContext
+ : public base::RefCountedThreadSafe<GeneratedCodeCacheContext> {
+ public:
+ REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE();
+
+ GeneratedCodeCacheContext();
+
+ // Initialize is called on the UI thread when the StoragePartition is
+ // being setup.
+ void Initialize(const base::FilePath& path, int max_bytes);
+
+ // Call on the IO thread to get the code cache instance.
+ GeneratedCodeCache* generated_code_cache() const;
+
+ private:
+ friend class base::RefCountedThreadSafe<GeneratedCodeCacheContext>;
+ ~GeneratedCodeCacheContext();
+
+ void InitializeOnIO(const base::FilePath& path, int max_bytes);
+
+ // Created, used and deleted on the IO thread.
+ std::unique_ptr<GeneratedCodeCache, BrowserThread::DeleteOnIOThread>
+ generated_code_cache_;
+
+ DISALLOW_COPY_AND_ASSIGN(GeneratedCodeCacheContext);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_CODE_CACHE_GENERATED_CACHE_CONTEXT_H_
diff --git a/chromium/content/browser/code_cache/generated_code_cache_unittest.cc b/chromium/content/browser/code_cache/generated_code_cache_unittest.cc
index 45ea2246f85..4f005c89c9a 100644
--- a/chromium/content/browser/code_cache/generated_code_cache_unittest.cc
+++ b/chromium/content/browser/code_cache/generated_code_cache_unittest.cc
@@ -26,7 +26,7 @@ class GeneratedCodeCacheTest : public testing::Test {
ASSERT_TRUE(cache_dir_.CreateUniqueTempDir());
cache_path_ = cache_dir_.GetPath();
generated_code_cache_ =
- GeneratedCodeCache::Create(cache_path_, kMaxSizeInBytes);
+ std::make_unique<GeneratedCodeCache>(cache_path_, kMaxSizeInBytes);
}
void TearDown() override {
@@ -39,7 +39,7 @@ class GeneratedCodeCacheTest : public testing::Test {
void InitializeCache() {
GURL url(kInitialUrl);
url::Origin origin = url::Origin::Create(GURL(kInitialOrigin));
- WriteToCache(url, origin, kInitialData);
+ WriteToCache(url, origin, kInitialData, base::Time::Now());
scoped_task_environment_.RunUntilIdle();
}
@@ -48,18 +48,16 @@ class GeneratedCodeCacheTest : public testing::Test {
// to test the pending operaions path.
void InitializeCacheAndReOpen() {
InitializeCache();
- generated_code_cache_.reset();
- generated_code_cache_ =
- GeneratedCodeCache::Create(cache_path_, kMaxSizeInBytes);
+ generated_code_cache_.reset(
+ new GeneratedCodeCache(cache_path_, kMaxSizeInBytes));
}
void WriteToCache(const GURL& url,
const url::Origin& origin,
- const std::string& data) {
- scoped_refptr<net::IOBufferWithSize> buffer(
- new net::IOBufferWithSize(data.length()));
- memcpy(buffer->data(), data.c_str(), data.length());
- generated_code_cache_->WriteData(url, origin, buffer);
+ const std::string& data,
+ base::Time response_time) {
+ std::vector<uint8_t> vector_data(data.begin(), data.end());
+ generated_code_cache_->WriteData(url, origin, response_time, vector_data);
}
void DeleteFromCache(const GURL& url, const url::Origin& origin) {
@@ -73,16 +71,26 @@ class GeneratedCodeCacheTest : public testing::Test {
generated_code_cache_->FetchEntry(url, origin, callback);
}
- void FetchEntryCallback(scoped_refptr<net::IOBufferWithSize> buffer) {
- if (!buffer || !buffer->data()) {
+ void ClearCache() {
+ generated_code_cache_->ClearCache(base::BindRepeating(
+ &GeneratedCodeCacheTest::ClearCacheComplete, base::Unretained(this)));
+ }
+
+ void ClearCacheComplete(int rv) {}
+
+ void FetchEntryCallback(const base::Time& response_time,
+ const std::vector<uint8_t>& data) {
+ if (data.size() == 0) {
received_ = true;
received_null_ = true;
+ received_response_time_ = response_time;
return;
}
- std::string str(buffer->data(), buffer->size());
+ std::string str(data.begin(), data.end());
received_ = true;
received_null_ = false;
received_data_ = str;
+ received_response_time_ = response_time;
}
protected:
@@ -90,6 +98,7 @@ class GeneratedCodeCacheTest : public testing::Test {
std::unique_ptr<GeneratedCodeCache> generated_code_cache_;
base::ScopedTempDir cache_dir_;
std::string received_data_;
+ base::Time received_response_time_;
bool received_;
bool received_null_;
base::FilePath cache_path_;
@@ -98,6 +107,23 @@ class GeneratedCodeCacheTest : public testing::Test {
constexpr char GeneratedCodeCacheTest::kInitialUrl[];
constexpr char GeneratedCodeCacheTest::kInitialOrigin[];
constexpr char GeneratedCodeCacheTest::kInitialData[];
+const int GeneratedCodeCacheTest::kMaxSizeInBytes;
+
+TEST_F(GeneratedCodeCacheTest, CheckResponseTime) {
+ GURL url(kInitialUrl);
+ url::Origin origin = url::Origin::Create(GURL(kInitialOrigin));
+
+ std::string data = "SerializedCodeForScript";
+ base::Time response_time = base::Time::Now();
+ WriteToCache(url, origin, data, response_time);
+ scoped_task_environment_.RunUntilIdle();
+ FetchFromCache(url, origin);
+ scoped_task_environment_.RunUntilIdle();
+
+ ASSERT_TRUE(received_);
+ EXPECT_EQ(data, received_data_);
+ EXPECT_EQ(response_time, received_response_time_);
+}
TEST_F(GeneratedCodeCacheTest, FetchEntry) {
GURL url(kInitialUrl);
@@ -117,12 +143,15 @@ TEST_F(GeneratedCodeCacheTest, WriteEntry) {
InitializeCache();
std::string data = "SerializedCodeForScript";
- WriteToCache(new_url, origin, data);
+ base::Time response_time = base::Time::Now();
+ WriteToCache(new_url, origin, data, response_time);
+ scoped_task_environment_.RunUntilIdle();
FetchFromCache(new_url, origin);
scoped_task_environment_.RunUntilIdle();
ASSERT_TRUE(received_);
EXPECT_EQ(data, received_data_);
+ EXPECT_EQ(response_time, received_response_time_);
}
TEST_F(GeneratedCodeCacheTest, DeleteEntry) {
@@ -156,13 +185,15 @@ TEST_F(GeneratedCodeCacheTest, WriteEntryPendingOp) {
InitializeCache();
std::string data = "SerializedCodeForScript";
- WriteToCache(new_url, origin, data);
+ base::Time response_time = base::Time::Now();
+ WriteToCache(new_url, origin, data, response_time);
scoped_task_environment_.RunUntilIdle();
FetchFromCache(new_url, origin);
scoped_task_environment_.RunUntilIdle();
ASSERT_TRUE(received_);
EXPECT_EQ(data, received_data_);
+ EXPECT_EQ(response_time, received_response_time_);
}
TEST_F(GeneratedCodeCacheTest, DeleteEntryPendingOp) {
@@ -184,12 +215,15 @@ TEST_F(GeneratedCodeCacheTest, UpdateDataOfExistingEntry) {
InitializeCache();
std::string new_data = "SerializedCodeForScriptOverwrite";
- WriteToCache(url, origin, new_data);
+ base::Time response_time = base::Time::Now();
+ WriteToCache(url, origin, new_data, response_time);
+ scoped_task_environment_.RunUntilIdle();
FetchFromCache(url, origin);
scoped_task_environment_.RunUntilIdle();
ASSERT_TRUE(received_);
EXPECT_EQ(new_data, received_data_);
+ EXPECT_EQ(response_time, received_response_time_);
}
TEST_F(GeneratedCodeCacheTest, FetchFailsForNonexistingOrigin) {
@@ -208,10 +242,10 @@ TEST_F(GeneratedCodeCacheTest, FetchEntriesFromSameOrigin) {
url::Origin origin = url::Origin::Create(GURL(kInitialOrigin));
std::string data_first_resource = "SerializedCodeForFirstResource";
- WriteToCache(url, origin, data_first_resource);
+ WriteToCache(url, origin, data_first_resource, base::Time());
std::string data_second_resource = "SerializedCodeForSecondResource";
- WriteToCache(second_url, origin, data_second_resource);
+ WriteToCache(second_url, origin, data_second_resource, base::Time());
scoped_task_environment_.RunUntilIdle();
FetchFromCache(url, origin);
@@ -231,10 +265,10 @@ TEST_F(GeneratedCodeCacheTest, FetchSucceedsFromDifferentOrigins) {
url::Origin origin1 = url::Origin::Create(GURL("http://example1.com"));
std::string data_origin = "SerializedCodeForFirstOrigin";
- WriteToCache(url, origin, data_origin);
+ WriteToCache(url, origin, data_origin, base::Time());
std::string data_origin1 = "SerializedCodeForSecondOrigin";
- WriteToCache(url, origin1, data_origin1);
+ WriteToCache(url, origin1, data_origin1, base::Time());
scoped_task_environment_.RunUntilIdle();
FetchFromCache(url, origin);
@@ -254,7 +288,7 @@ TEST_F(GeneratedCodeCacheTest, FetchFailsForUniqueOrigin) {
url::Origin::Create(GURL("data:text/html,<script></script>"));
std::string data = "SerializedCodeForUniqueOrigin";
- WriteToCache(url, origin, data);
+ WriteToCache(url, origin, data, base::Time());
scoped_task_environment_.RunUntilIdle();
FetchFromCache(url, origin);
@@ -268,11 +302,12 @@ TEST_F(GeneratedCodeCacheTest, FetchFailsForInvalidOrigin) {
url::Origin origin = url::Origin::Create(GURL("invalidURL"));
std::string data = "SerializedCodeForInvalidOrigin";
- WriteToCache(url, origin, data);
+ WriteToCache(url, origin, data, base::Time());
scoped_task_environment_.RunUntilIdle();
FetchFromCache(url, origin);
scoped_task_environment_.RunUntilIdle();
+
ASSERT_TRUE(received_);
ASSERT_TRUE(received_null_);
}
@@ -282,7 +317,7 @@ TEST_F(GeneratedCodeCacheTest, FetchFailsForInvalidURL) {
url::Origin origin = url::Origin::Create(GURL("http://example.com"));
std::string data = "SerializedCodeForInvalidURL";
- WriteToCache(url, origin, data);
+ WriteToCache(url, origin, data, base::Time());
scoped_task_environment_.RunUntilIdle();
FetchFromCache(url, origin);
@@ -290,4 +325,18 @@ TEST_F(GeneratedCodeCacheTest, FetchFailsForInvalidURL) {
ASSERT_TRUE(received_);
ASSERT_TRUE(received_null_);
}
+
+TEST_F(GeneratedCodeCacheTest, ClearCache) {
+ GURL url("http://example.com/script.js");
+ url::Origin origin = url::Origin::Create(GURL("http://example.com"));
+
+ InitializeCache();
+ ClearCache();
+ scoped_task_environment_.RunUntilIdle();
+ FetchFromCache(url, origin);
+ scoped_task_environment_.RunUntilIdle();
+
+ ASSERT_TRUE(received_);
+ ASSERT_TRUE(received_null_);
+}
} // namespace content
diff --git a/chromium/content/browser/compositor/DEPS b/chromium/content/browser/compositor/DEPS
index 1b482fbe5b9..91404304090 100644
--- a/chromium/content/browser/compositor/DEPS
+++ b/chromium/content/browser/compositor/DEPS
@@ -2,7 +2,7 @@ include_rules = [
"+components/viz/common",
"+components/viz/host",
"+components/viz/service",
- "+services/ui/public/cpp",
+ "+services/ws/public/cpp",
"+ui/platform_window",
]
diff --git a/chromium/content/browser/compositor/browser_compositor_output_surface.cc b/chromium/content/browser/compositor/browser_compositor_output_surface.cc
index 924e82dadab..d96efe91eea 100644
--- a/chromium/content/browser/compositor/browser_compositor_output_surface.cc
+++ b/chromium/content/browser/compositor/browser_compositor_output_surface.cc
@@ -14,7 +14,7 @@
#include "components/viz/service/display/output_surface_client.h"
#include "components/viz/service/display_embedder/compositor_overlay_candidate_validator.h"
#include "content/browser/compositor/reflector_impl.h"
-#include "services/ui/public/cpp/gpu/context_provider_command_buffer.h"
+#include "services/ws/public/cpp/gpu/context_provider_command_buffer.h"
namespace content {
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 15226b0f4d7..d6bcbc3b922 100644
--- a/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.cc
+++ b/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.cc
@@ -18,13 +18,13 @@
#include "gpu/command_buffer/common/swap_buffers_complete_params.h"
#include "gpu/command_buffer/common/swap_buffers_flags.h"
#include "gpu/ipc/client/command_buffer_proxy_impl.h"
-#include "services/ui/public/cpp/gpu/context_provider_command_buffer.h"
+#include "services/ws/public/cpp/gpu/context_provider_command_buffer.h"
#include "ui/gl/gl_utils.h"
namespace content {
GpuBrowserCompositorOutputSurface::GpuBrowserCompositorOutputSurface(
- scoped_refptr<ui::ContextProviderCommandBuffer> context,
+ scoped_refptr<ws::ContextProviderCommandBuffer> context,
const UpdateVSyncParametersCallback& update_vsync_parameters_callback,
std::unique_ptr<viz::CompositorOverlayCandidateValidator>
overlay_candidate_validator)
@@ -147,7 +147,7 @@ void GpuBrowserCompositorOutputSurface::SwapBuffers(
}
uint32_t GpuBrowserCompositorOutputSurface::GetFramebufferCopyTextureFormat() {
- auto* gl = static_cast<ui::ContextProviderCommandBuffer*>(context_provider());
+ auto* gl = static_cast<ws::ContextProviderCommandBuffer*>(context_provider());
return gl->GetCopyTextureInternalFormat();
}
@@ -192,8 +192,8 @@ void GpuBrowserCompositorOutputSurface::OnUpdateVSyncParameters(
gpu::CommandBufferProxyImpl*
GpuBrowserCompositorOutputSurface::GetCommandBufferProxy() {
- ui::ContextProviderCommandBuffer* provider_command_buffer =
- static_cast<ui::ContextProviderCommandBuffer*>(context_provider_.get());
+ ws::ContextProviderCommandBuffer* provider_command_buffer =
+ static_cast<ws::ContextProviderCommandBuffer*>(context_provider_.get());
gpu::CommandBufferProxyImpl* command_buffer_proxy =
provider_command_buffer->GetCommandBufferProxy();
DCHECK(command_buffer_proxy);
diff --git a/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.h b/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.h
index 67ef5d40f1c..a7153104e1c 100644
--- a/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.h
+++ b/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.h
@@ -27,7 +27,7 @@ class CommandBufferProxyImpl;
struct SwapBuffersCompleteParams;
}
-namespace ui {
+namespace ws {
class ContextProviderCommandBuffer;
}
@@ -41,7 +41,7 @@ class GpuBrowserCompositorOutputSurface
: public BrowserCompositorOutputSurface {
public:
GpuBrowserCompositorOutputSurface(
- scoped_refptr<ui::ContextProviderCommandBuffer> context,
+ scoped_refptr<ws::ContextProviderCommandBuffer> context,
const UpdateVSyncParametersCallback& update_vsync_parameters_callback,
std::unique_ptr<viz::CompositorOverlayCandidateValidator>
overlay_candidate_validator);
diff --git a/chromium/content/browser/compositor/gpu_output_surface_mac.cc b/chromium/content/browser/compositor/gpu_output_surface_mac.cc
index 7c5b22d9df7..1a8833894fd 100644
--- a/chromium/content/browser/compositor/gpu_output_surface_mac.cc
+++ b/chromium/content/browser/compositor/gpu_output_surface_mac.cc
@@ -8,12 +8,12 @@
#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/ui/public/cpp/gpu/context_provider_command_buffer.h"
+#include "services/ws/public/cpp/gpu/context_provider_command_buffer.h"
namespace content {
GpuOutputSurfaceMac::GpuOutputSurfaceMac(
- scoped_refptr<ui::ContextProviderCommandBuffer> context,
+ scoped_refptr<ws::ContextProviderCommandBuffer> context,
gpu::SurfaceHandle surface_handle,
const UpdateVSyncParametersCallback& update_vsync_parameters_callback,
std::unique_ptr<viz::CompositorOverlayCandidateValidator>
diff --git a/chromium/content/browser/compositor/gpu_output_surface_mac.h b/chromium/content/browser/compositor/gpu_output_surface_mac.h
index 73ad778a50a..0fe8986a17b 100644
--- a/chromium/content/browser/compositor/gpu_output_surface_mac.h
+++ b/chromium/content/browser/compositor/gpu_output_surface_mac.h
@@ -15,7 +15,7 @@ class GpuOutputSurfaceMac
: public GpuSurfacelessBrowserCompositorOutputSurface {
public:
GpuOutputSurfaceMac(
- scoped_refptr<ui::ContextProviderCommandBuffer> context,
+ scoped_refptr<ws::ContextProviderCommandBuffer> context,
gpu::SurfaceHandle surface_handle,
const UpdateVSyncParametersCallback& update_vsync_parameters_callback,
std::unique_ptr<viz::CompositorOverlayCandidateValidator>
diff --git a/chromium/content/browser/compositor/gpu_process_transport_factory.cc b/chromium/content/browser/compositor/gpu_process_transport_factory.cc
index 511d805187b..642fff3b436 100644
--- a/chromium/content/browser/compositor/gpu_process_transport_factory.cc
+++ b/chromium/content/browser/compositor/gpu_process_transport_factory.cc
@@ -26,7 +26,6 @@
#include "components/viz/common/frame_sinks/begin_frame_args.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/common/gl_helper.h"
#include "components/viz/common/switches.h"
#include "components/viz/host/host_display_client.h"
#include "components/viz/host/host_frame_sink_manager.h"
@@ -63,7 +62,7 @@
#include "gpu/ipc/host/gpu_memory_buffer_support.h"
#include "gpu/vulkan/buildflags.h"
#include "services/service_manager/runner/common/client_util.h"
-#include "services/ui/public/cpp/gpu/context_provider_command_buffer.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"
@@ -218,7 +217,7 @@ GpuProcessTransportFactory::CreateSoftwareOutputDevice(
return base::WrapUnique(new viz::SoftwareOutputDevice);
#if defined(USE_AURA)
- if (!features::IsAshInBrowserProcess()) {
+ if (features::IsUsingWindowService()) {
NOTREACHED();
return nullptr;
}
@@ -266,7 +265,7 @@ CreateOverlayCandidateValidator(
ozone_platform->GetOverlayManager();
if (!command_line->HasSwitch(switches::kEnableHardwareOverlays) &&
overlay_manager->SupportsOverlays()) {
- enable_overlay_flag = "single-fullscreen,single-on-top";
+ enable_overlay_flag = "single-fullscreen,single-on-top,underlay";
}
if (!enable_overlay_flag.empty()) {
std::unique_ptr<ui::OverlayCandidatesOzone> overlay_candidates =
@@ -375,7 +374,7 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
#else
bool use_vulkan = false;
#endif
- scoped_refptr<ui::ContextProviderCommandBuffer> context_provider;
+ scoped_refptr<ws::ContextProviderCommandBuffer> context_provider;
if (!use_gpu_compositing || use_vulkan) {
// If not using GL compositing, don't keep the old shared worker context.
@@ -401,7 +400,7 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
gpu_channel_host, gpu::kNullSurfaceHandle, need_alpha_channel,
false /* support_stencil */, support_locking, support_gles2_interface,
support_raster_interface, support_grcontext,
- ui::command_buffer_metrics::ContextType::BROWSER_WORKER);
+ ws::command_buffer_metrics::ContextType::BROWSER_WORKER);
auto result = shared_worker_context_provider_->BindToCurrentThread();
if (result != gpu::ContextResult::kSuccess) {
shared_worker_context_provider_ = nullptr;
@@ -428,7 +427,7 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
std::move(gpu_channel_host), surface_handle, need_alpha_channel,
support_stencil, support_locking, support_gles2_interface,
support_raster_interface, support_grcontext,
- ui::command_buffer_metrics::ContextType::BROWSER_COMPOSITOR);
+ ws::command_buffer_metrics::ContextType::BROWSER_COMPOSITOR);
// On Mac, GpuCommandBufferMsg_SwapBuffersCompleted must be handled in
// a nested run loop during resize.
context_provider->SetDefaultTaskRunner(resize_task_runner_);
@@ -569,7 +568,8 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
external_begin_frame_source_mojo =
std::make_unique<viz::ExternalBeginFrameSourceMojo>(
std::move(request),
- external_begin_frame_controller_client->GetBoundPtr());
+ external_begin_frame_controller_client->GetBoundPtr(),
+ viz::BeginFrameSource::kNotRestartableId);
begin_frame_source = external_begin_frame_source_mojo.get();
} else if (disable_frame_rate_limit_) {
synthetic_begin_frame_source =
@@ -586,10 +586,6 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
begin_frame_source = synthetic_begin_frame_source.get();
}
-#if defined(OS_WIN)
- gfx::RenderingWindowManager::GetInstance()->DoSetParentOnChild(
- compositor->widget());
-#endif
if (data->synthetic_begin_frame_source) {
GetFrameSinkManager()->UnregisterBeginFrameSource(
data->synthetic_begin_frame_source.get());
@@ -731,21 +727,10 @@ void GpuProcessTransportFactory::RemoveCompositor(ui::Compositor* compositor) {
}
per_compositor_data_.erase(it);
if (per_compositor_data_.empty()) {
- // Destroying the GLHelper may cause some async actions to be cancelled,
- // causing things to request a new GLHelper. Due to crbug.com/176091 the
- // GLHelper created in this case would be lost/leaked if we just reset()
- // on the |gl_helper_| variable directly. So instead we call reset() on a
- // local std::unique_ptr.
- std::unique_ptr<viz::GLHelper> helper = std::move(gl_helper_);
-
- // If there are any observer left at this point, make sure they clean up
- // before we destroy the GLHelper.
+ // If there are any observers left at this point, notify them that the
+ // context has been lost.
for (auto& observer : observer_list_)
observer.OnLostSharedContext();
-
- helper.reset();
- DCHECK(!gl_helper_) << "Destroying the GLHelper should not cause a new "
- "GLHelper to be created.";
}
#if defined(OS_WIN)
gfx::RenderingWindowManager::GetInstance()->UnregisterParent(
@@ -927,16 +912,6 @@ viz::FrameSinkManagerImpl* GpuProcessTransportFactory::GetFrameSinkManager() {
return BrowserMainLoop::GetInstance()->GetFrameSinkManager();
}
-viz::GLHelper* GpuProcessTransportFactory::GetGLHelper() {
- if (!gl_helper_ && !per_compositor_data_.empty()) {
- scoped_refptr<ContextProvider> provider = SharedMainThreadContextProvider();
- if (provider.get())
- gl_helper_.reset(
- new viz::GLHelper(provider->ContextGL(), provider->ContextSupport()));
- }
- return gl_helper_.get();
-}
-
scoped_refptr<ContextProvider>
GpuProcessTransportFactory::SharedMainThreadContextProvider() {
if (is_gpu_compositing_disabled_)
@@ -957,8 +932,6 @@ GpuProcessTransportFactory::SharedMainThreadContextProvider() {
return nullptr;
}
- // We need a separate context from the compositor's so that skia and gl_helper
- // don't step on each other.
bool need_alpha_channel = false;
bool support_locking = false;
bool support_gles2_interface = true;
@@ -968,7 +941,7 @@ GpuProcessTransportFactory::SharedMainThreadContextProvider() {
std::move(gpu_channel_host), gpu::kNullSurfaceHandle, need_alpha_channel,
false, support_locking, support_gles2_interface, support_raster_interface,
support_grcontext,
- ui::command_buffer_metrics::ContextType::BROWSER_MAIN_THREAD);
+ ws::command_buffer_metrics::ContextType::BROWSER_MAIN_THREAD);
shared_main_thread_contexts_->AddObserver(this);
auto result = shared_main_thread_contexts_->BindToCurrentThread();
if (result != gpu::ContextResult::kSuccess) {
@@ -1016,13 +989,10 @@ void GpuProcessTransportFactory::OnLostMainThreadSharedContext() {
shared_main_thread_contexts_;
shared_main_thread_contexts_ = nullptr;
- std::unique_ptr<viz::GLHelper> lost_gl_helper = std::move(gl_helper_);
-
for (auto& observer : observer_list_)
observer.OnLostSharedContext();
// Kill things that use the shared context before killing the shared context.
- lost_gl_helper.reset();
lost_shared_main_thread_contexts = nullptr;
}
@@ -1057,7 +1027,7 @@ void GpuProcessTransportFactory::OnContextLost() {
callback_factory_.GetWeakPtr()));
}
-scoped_refptr<ui::ContextProviderCommandBuffer>
+scoped_refptr<ws::ContextProviderCommandBuffer>
GpuProcessTransportFactory::CreateContextCommon(
scoped_refptr<gpu::GpuChannelHost> gpu_channel_host,
gpu::SurfaceHandle surface_handle,
@@ -1067,7 +1037,7 @@ GpuProcessTransportFactory::CreateContextCommon(
bool support_gles2_interface,
bool support_raster_interface,
bool support_grcontext,
- ui::command_buffer_metrics::ContextType type) {
+ ws::command_buffer_metrics::ContextType type) {
DCHECK(gpu_channel_host);
DCHECK(!is_gpu_compositing_disabled_);
@@ -1104,7 +1074,7 @@ GpuProcessTransportFactory::CreateContextCommon(
constexpr bool automatic_flushes = false;
GURL url("chrome://gpu/GpuProcessTransportFactory::CreateContextCommon");
- return base::MakeRefCounted<ui::ContextProviderCommandBuffer>(
+ return base::MakeRefCounted<ws::ContextProviderCommandBuffer>(
std::move(gpu_channel_host), GetGpuMemoryBufferManager(), stream_id,
stream_priority, surface_handle, url, automatic_flushes, support_locking,
support_grcontext, gpu::SharedMemoryLimits(), attributes, type);
diff --git a/chromium/content/browser/compositor/gpu_process_transport_factory.h b/chromium/content/browser/compositor/gpu_process_transport_factory.h
index 6704fa4bb4c..08384de8696 100644
--- a/chromium/content/browser/compositor/gpu_process_transport_factory.h
+++ b/chromium/content/browser/compositor/gpu_process_transport_factory.h
@@ -23,7 +23,7 @@
#include "content/browser/compositor/image_transport_factory.h"
#include "gpu/ipc/client/gpu_channel_host.h"
#include "gpu/vulkan/buildflags.h"
-#include "services/ui/public/cpp/gpu/command_buffer_metrics.h"
+#include "services/ws/public/cpp/gpu/command_buffer_metrics.h"
#include "ui/compositor/compositor.h"
namespace base {
@@ -40,10 +40,6 @@ class GpuChannelEstablishFactory;
class VulkanImplementation;
}
-namespace ui {
-class ContextProviderCommandBuffer;
-}
-
namespace viz {
class CompositingModeReporterImpl;
class OutputDeviceBacking;
@@ -53,6 +49,10 @@ class VulkanInProcessContextProvider;
class RasterContextProvider;
}
+namespace ws {
+class ContextProviderCommandBuffer;
+}
+
namespace content {
class GpuProcessTransportFactory : public ui::ContextFactory,
@@ -111,7 +111,6 @@ class GpuProcessTransportFactory : public ui::ContextFactory,
ui::ContextFactory* GetContextFactory() override;
ui::ContextFactoryPrivate* GetContextFactoryPrivate() override;
viz::FrameSinkManagerImpl* GetFrameSinkManager() override;
- viz::GLHelper* GetGLHelper() override;
private:
struct PerCompositorData;
@@ -137,7 +136,7 @@ class GpuProcessTransportFactory : public ui::ContextFactory,
// viz::ContextLostObserver implementation.
void OnContextLost() override;
- scoped_refptr<ui::ContextProviderCommandBuffer> CreateContextCommon(
+ scoped_refptr<ws::ContextProviderCommandBuffer> CreateContextCommon(
scoped_refptr<gpu::GpuChannelHost> gpu_channel_host,
gpu::SurfaceHandle surface_handle,
bool need_alpha_channel,
@@ -146,7 +145,7 @@ class GpuProcessTransportFactory : public ui::ContextFactory,
bool support_gles2_interface,
bool support_raster_interface,
bool support_grcontext,
- ui::command_buffer_metrics::ContextType type);
+ ws::command_buffer_metrics::ContextType type);
viz::FrameSinkIdAllocator frame_sink_id_allocator_;
@@ -165,9 +164,8 @@ class GpuProcessTransportFactory : public ui::ContextFactory,
PerCompositorDataMap per_compositor_data_;
const viz::RendererSettings renderer_settings_;
- scoped_refptr<ui::ContextProviderCommandBuffer> shared_main_thread_contexts_;
- std::unique_ptr<viz::GLHelper> gl_helper_;
- base::ObserverList<ui::ContextFactoryObserver> observer_list_;
+ scoped_refptr<ws::ContextProviderCommandBuffer> shared_main_thread_contexts_;
+ base::ObserverList<ui::ContextFactoryObserver>::Unchecked observer_list_;
scoped_refptr<base::SingleThreadTaskRunner> resize_task_runner_;
std::unique_ptr<cc::SingleThreadTaskGraphRunner> task_graph_runner_;
scoped_refptr<viz::RasterContextProvider> shared_worker_context_provider_;
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 c2a3a8d7b5e..dda311477dc 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
@@ -6,7 +6,6 @@
#include <utility>
-#include "components/viz/common/gl_helper.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/buffer_queue.h"
@@ -15,13 +14,13 @@
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/common/swap_buffers_complete_params.h"
-#include "services/ui/public/cpp/gpu/context_provider_command_buffer.h"
+#include "services/ws/public/cpp/gpu/context_provider_command_buffer.h"
namespace content {
GpuSurfacelessBrowserCompositorOutputSurface::
GpuSurfacelessBrowserCompositorOutputSurface(
- scoped_refptr<ui::ContextProviderCommandBuffer> context,
+ scoped_refptr<ws::ContextProviderCommandBuffer> context,
gpu::SurfaceHandle surface_handle,
const UpdateVSyncParametersCallback& update_vsync_parameters_callback,
std::unique_ptr<viz::CompositorOverlayCandidateValidator>
@@ -50,11 +49,9 @@ GpuSurfacelessBrowserCompositorOutputSurface::
// implementation.
capabilities_.max_frames_pending = 2;
- gl_helper_.reset(new viz::GLHelper(context_provider_->ContextGL(),
- context_provider_->ContextSupport()));
buffer_queue_.reset(new viz::BufferQueue(
context_provider_->ContextGL(), target, internalformat, format,
- gl_helper_.get(), gpu_memory_buffer_manager_, surface_handle));
+ gpu_memory_buffer_manager_, surface_handle));
buffer_queue_->Initialize();
}
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 439c8553ab1..a457be1d4af 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
@@ -6,6 +6,7 @@
#define CONTENT_BROWSER_COMPOSITOR_GPU_SURFACELESS_BROWSER_COMPOSITOR_OUTPUT_SURFACE_H_
#include <memory>
+#include <vector>
#include "content/browser/compositor/gpu_browser_compositor_output_surface.h"
#include "gpu/ipc/common/surface_handle.h"
@@ -16,7 +17,6 @@ class GpuMemoryBufferManager;
namespace viz {
class BufferQueue;
-class GLHelper;
}
namespace content {
@@ -25,7 +25,7 @@ class GpuSurfacelessBrowserCompositorOutputSurface
: public GpuBrowserCompositorOutputSurface {
public:
GpuSurfacelessBrowserCompositorOutputSurface(
- scoped_refptr<ui::ContextProviderCommandBuffer> context,
+ scoped_refptr<ws::ContextProviderCommandBuffer> context,
gpu::SurfaceHandle surface_handle,
const UpdateVSyncParametersCallback& update_vsync_parameters_callback,
std::unique_ptr<viz::CompositorOverlayCandidateValidator>
@@ -61,7 +61,6 @@ class GpuSurfacelessBrowserCompositorOutputSurface
bool use_gpu_fence_;
unsigned gpu_fence_id_;
- std::unique_ptr<viz::GLHelper> gl_helper_;
std::unique_ptr<viz::BufferQueue> buffer_queue_;
gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager_;
};
diff --git a/chromium/content/browser/compositor/image_transport_factory.h b/chromium/content/browser/compositor/image_transport_factory.h
index 9dba97fe029..2d093e64347 100644
--- a/chromium/content/browser/compositor/image_transport_factory.h
+++ b/chromium/content/browser/compositor/image_transport_factory.h
@@ -15,10 +15,6 @@ class ContextFactory;
class ContextFactoryPrivate;
}
-namespace viz {
-class GLHelper;
-}
-
namespace content {
// This class provides the interface for creating the support for the
@@ -54,11 +50,6 @@ class CONTENT_EXPORT ImageTransportFactory {
// compositor. TODO(fsamuel): This interface should eventually go away once
// Mus subsumes this functionality.
virtual ui::ContextFactoryPrivate* GetContextFactoryPrivate() = 0;
-
- // Gets a GLHelper instance, associated with the shared context. This
- // GLHelper will get destroyed whenever the shared context is lost
- // (ImageTransportFactoryObserver::OnLostResources is called).
- virtual viz::GLHelper* GetGLHelper() = 0;
};
} // namespace content
diff --git a/chromium/content/browser/compositor/image_transport_factory_browsertest.cc b/chromium/content/browser/compositor/image_transport_factory_browsertest.cc
index 659533c687d..95f86bfa8c9 100644
--- a/chromium/content/browser/compositor/image_transport_factory_browsertest.cc
+++ b/chromium/content/browser/compositor/image_transport_factory_browsertest.cc
@@ -6,9 +6,7 @@
#include "base/run_loop.h"
#include "build/build_config.h"
-#include "components/viz/common/features.h"
#include "components/viz/common/gpu/context_provider.h"
-#include "content/browser/compositor/owned_mailbox.h"
#include "content/public/test/content_browser_test.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/gles2_interface.h"
@@ -63,41 +61,5 @@ IN_PROC_BROWSER_TEST_F(ImageTransportFactoryBrowserTest,
factory->GetContextFactory()->RemoveObserver(&observer);
}
-class ImageTransportFactoryTearDownBrowserTest : public ContentBrowserTest {
- public:
- void TearDown() override {
- // Mailbox is null if the test exited early.
- if (mailbox_.get())
- EXPECT_TRUE(mailbox_->mailbox().IsZero());
- ContentBrowserTest::TearDown();
- }
-
- protected:
- scoped_refptr<OwnedMailbox> mailbox_;
-};
-
-// Checks that upon destruction of the ImageTransportFactory, the observer is
-// called and the created resources are reset.
-IN_PROC_BROWSER_TEST_F(ImageTransportFactoryTearDownBrowserTest,
- LoseOnTearDown) {
- ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
-
- // TODO(crbug.com/844469): Delete after OOP-D is launched because GLHelper
- // and OwnedMailbox aren't used.
- if (base::FeatureList::IsEnabled(features::kVizDisplayCompositor))
- return;
-
- // This test doesn't make sense in software compositing mode.
- if (factory->IsGpuCompositingDisabled())
- return;
-
- viz::GLHelper* helper = factory->GetGLHelper();
- ASSERT_TRUE(helper);
- mailbox_ = base::MakeRefCounted<OwnedMailbox>(helper);
- EXPECT_FALSE(mailbox_->mailbox().IsZero());
-
- // See TearDown() for the test expectation that |mailbox_| has been reset.
-}
-
} // anonymous namespace
} // namespace content
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 3b3dc6943a6..b5f5874e8fa 100644
--- a/chromium/content/browser/compositor/offscreen_browser_compositor_output_surface.cc
+++ b/chromium/content/browser/compositor/offscreen_browser_compositor_output_surface.cc
@@ -18,7 +18,7 @@
#include "content/public/browser/browser_thread.h"
#include "gpu/command_buffer/client/context_support.h"
#include "gpu/command_buffer/client/gles2_interface.h"
-#include "services/ui/public/cpp/gpu/context_provider_command_buffer.h"
+#include "services/ws/public/cpp/gpu/context_provider_command_buffer.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "third_party/khronos/GLES2/gl2ext.h"
@@ -30,7 +30,7 @@ static viz::ResourceFormat kFboTextureFormat = viz::RGBA_8888;
OffscreenBrowserCompositorOutputSurface::
OffscreenBrowserCompositorOutputSurface(
- scoped_refptr<ui::ContextProviderCommandBuffer> context,
+ scoped_refptr<ws::ContextProviderCommandBuffer> context,
const UpdateVSyncParametersCallback& update_vsync_parameters_callback,
std::unique_ptr<viz::CompositorOverlayCandidateValidator>
overlay_candidate_validator)
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 f123692aebb..582388dd576 100644
--- a/chromium/content/browser/compositor/offscreen_browser_compositor_output_surface.h
+++ b/chromium/content/browser/compositor/offscreen_browser_compositor_output_surface.h
@@ -18,7 +18,7 @@
#include "ui/latency/latency_info.h"
#include "ui/latency/latency_tracker.h"
-namespace ui {
+namespace ws {
class ContextProviderCommandBuffer;
}
@@ -29,7 +29,7 @@ class OffscreenBrowserCompositorOutputSurface
: public BrowserCompositorOutputSurface {
public:
OffscreenBrowserCompositorOutputSurface(
- scoped_refptr<ui::ContextProviderCommandBuffer> context,
+ scoped_refptr<ws::ContextProviderCommandBuffer> context,
const UpdateVSyncParametersCallback& update_vsync_parameters_callback,
std::unique_ptr<viz::CompositorOverlayCandidateValidator>
overlay_candidate_validator);
diff --git a/chromium/content/browser/compositor/owned_mailbox.cc b/chromium/content/browser/compositor/owned_mailbox.cc
index f1eddad0fbc..0969ecaad96 100644
--- a/chromium/content/browser/compositor/owned_mailbox.cc
+++ b/chromium/content/browser/compositor/owned_mailbox.cc
@@ -4,48 +4,47 @@
#include "content/browser/compositor/owned_mailbox.h"
-#include "base/logging.h"
-#include "components/viz/common/gl_helper.h"
-#include "content/browser/compositor/image_transport_factory.h"
+#include "base/bind.h"
+#include "gpu/command_buffer/client/gles2_interface.h"
namespace content {
-OwnedMailbox::OwnedMailbox(viz::GLHelper* gl_helper)
- : texture_id_(0), gl_helper_(gl_helper) {
- texture_id_ = gl_helper_->CreateTexture();
- mailbox_holder_ = gl_helper_->ProduceMailboxHolderFromTexture(texture_id_);
- // The texture target is not exposed on this class, as GLHelper assumes
- // GL_TEXTURE_2D.
- DCHECK_EQ(mailbox_holder_.texture_target,
- static_cast<uint32_t>(GL_TEXTURE_2D));
- ImageTransportFactory::GetInstance()->GetContextFactory()->AddObserver(this);
+OwnedMailbox::OwnedMailbox(gpu::gles2::GLES2Interface* gl)
+ : gl_(gl), texture_id_(0), weak_ptr_factory_(this) {
+ DCHECK(gl_);
+
+ // Create the texture.
+ static_assert(sizeof(texture_id_) == sizeof(GLuint),
+ "need to adjust type of texture_id_ in its declaration");
+ gl_->GenTextures(1, &texture_id_);
+ gl_->BindTexture(GL_TEXTURE_2D, texture_id_);
+ gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ gl_->BindTexture(GL_TEXTURE_2D, 0);
+
+ // Initialize the MailboxHolder for the texture.
+ gl_->ProduceTextureDirectCHROMIUM(texture_id_, mailbox_holder_.mailbox.name);
+ gl_->GenSyncTokenCHROMIUM(mailbox_holder_.sync_token.GetData());
+ mailbox_holder_.texture_target = GL_TEXTURE_2D;
}
OwnedMailbox::~OwnedMailbox() {
- if (gl_helper_)
- Destroy();
+ gl_->WaitSyncTokenCHROMIUM(mailbox_holder_.sync_token.GetConstData());
+ gl_->DeleteTextures(1, &texture_id_);
}
-void OwnedMailbox::UpdateSyncToken(const gpu::SyncToken& sync_token) {
- if (sync_token.HasData())
- mailbox_holder_.sync_token = sync_token;
-}
-
-void OwnedMailbox::Destroy() {
- ImageTransportFactory::GetInstance()->GetContextFactory()->RemoveObserver(
- this);
- gl_helper_->WaitSyncToken(mailbox_holder_.sync_token);
- gl_helper_->DeleteTexture(texture_id_);
- texture_id_ = 0;
- mailbox_holder_ = gpu::MailboxHolder();
- gl_helper_ = nullptr;
+std::unique_ptr<viz::SingleReleaseCallback>
+OwnedMailbox::GetSingleReleaseCallback() {
+ return viz::SingleReleaseCallback::Create(base::BindOnce(
+ &OwnedMailbox::UpdateSyncToken, weak_ptr_factory_.GetWeakPtr()));
}
-void OwnedMailbox::OnLostSharedContext() {
- if (gl_helper_)
- Destroy();
+void OwnedMailbox::UpdateSyncToken(const gpu::SyncToken& sync_token,
+ bool is_lost) {
+ if (sync_token.HasData())
+ mailbox_holder_.sync_token = sync_token;
}
-void OwnedMailbox::OnLostVizProcess() {}
-
} // namespace content
diff --git a/chromium/content/browser/compositor/owned_mailbox.h b/chromium/content/browser/compositor/owned_mailbox.h
index 9880759f4c6..084e28f4653 100644
--- a/chromium/content/browser/compositor/owned_mailbox.h
+++ b/chromium/content/browser/compositor/owned_mailbox.h
@@ -7,26 +7,28 @@
#include <stdint.h>
+#include <memory>
+
#include "base/memory/ref_counted.h"
-#include "content/browser/compositor/image_transport_factory.h"
+#include "base/memory/weak_ptr.h"
+#include "components/viz/common/resources/single_release_callback.h"
#include "content/common/content_export.h"
#include "gpu/command_buffer/common/mailbox_holder.h"
#include "ui/compositor/compositor.h"
-namespace viz {
-class GLHelper;
+namespace gpu {
+namespace gles2 {
+class GLES2Interface;
+}
}
namespace content {
-
// This class holds a texture id and gpu::Mailbox, and deletes the texture
-// id when the object itself is destroyed. Should only be created if a GLHelper
-// exists on the ImageTransportFactory.
-class CONTENT_EXPORT OwnedMailbox : public base::RefCounted<OwnedMailbox>,
- public ui::ContextFactoryObserver {
+// id when the object itself is destroyed.
+class CONTENT_EXPORT OwnedMailbox : public base::RefCounted<OwnedMailbox> {
public:
- explicit OwnedMailbox(viz::GLHelper* gl_helper);
+ explicit OwnedMailbox(gpu::gles2::GLES2Interface* gl);
const gpu::MailboxHolder& holder() const { return mailbox_holder_; }
const gpu::Mailbox& mailbox() const { return mailbox_holder_.mailbox; }
@@ -34,22 +36,21 @@ class CONTENT_EXPORT OwnedMailbox : public base::RefCounted<OwnedMailbox>,
return mailbox_holder_.sync_token;
}
uint32_t texture_id() const { return texture_id_; }
- void UpdateSyncToken(const gpu::SyncToken& sync_token);
- void Destroy();
- protected:
- ~OwnedMailbox() override;
-
- // ImageTransportFactoryObserver implementation.
- void OnLostSharedContext() override;
- void OnLostVizProcess() override;
+ // Returns a SingleReleaseCallback for TextureLayer.
+ std::unique_ptr<viz::SingleReleaseCallback> GetSingleReleaseCallback();
private:
friend class base::RefCounted<OwnedMailbox>;
+ ~OwnedMailbox();
+
+ void UpdateSyncToken(const gpu::SyncToken& sync_token, bool is_lost);
+
+ gpu::gles2::GLES2Interface* const gl_;
uint32_t texture_id_;
gpu::MailboxHolder mailbox_holder_;
- viz::GLHelper* gl_helper_;
+ base::WeakPtrFactory<OwnedMailbox> weak_ptr_factory_;
};
} // namespace content
diff --git a/chromium/content/browser/compositor/reflector_impl.cc b/chromium/content/browser/compositor/reflector_impl.cc
index a0a54c0d450..b41cb5b429a 100644
--- a/chromium/content/browser/compositor/reflector_impl.cc
+++ b/chromium/content/browser/compositor/reflector_impl.cc
@@ -4,7 +4,6 @@
#include "content/browser/compositor/reflector_impl.h"
-#include "base/bind.h"
#include "base/location.h"
#include "components/viz/common/resources/transferable_resource.h"
#include "content/browser/compositor/browser_compositor_output_surface.h"
@@ -30,8 +29,7 @@ ReflectorImpl::ReflectorImpl(ui::Compositor* mirrored_compositor,
AddMirroringLayer(mirroring_layer);
}
-ReflectorImpl::~ReflectorImpl() {
-}
+ReflectorImpl::~ReflectorImpl() = default;
void ReflectorImpl::Shutdown() {
if (output_surface_)
@@ -43,8 +41,8 @@ void ReflectorImpl::Shutdown() {
void ReflectorImpl::DetachFromOutputSurface() {
DCHECK(output_surface_);
output_surface_->SetReflector(nullptr);
- DCHECK(mailbox_.get());
- mailbox_ = nullptr;
+ DCHECK(mailbox_);
+ mailbox_.reset();
output_surface_ = nullptr;
for (const auto& layer_data : mirroring_layers_)
layer_data->layer->SetShowSolidColorContent();
@@ -140,12 +138,6 @@ void ReflectorImpl::OnSourcePostSubBuffer(const gfx::Rect& swap_rect,
UpdateTexture(layer_data.get(), surface_size, mirroring_rect);
}
-static void ReleaseMailbox(scoped_refptr<OwnedMailbox> mailbox,
- const gpu::SyncToken& sync_token,
- bool is_lost) {
- mailbox->UpdateSyncToken(sync_token);
-}
-
std::vector<std::unique_ptr<ReflectorImpl::LayerData>>::iterator
ReflectorImpl::FindLayerData(ui::Layer* layer) {
return std::find_if(mirroring_layers_.begin(), mirroring_layers_.end(),
@@ -162,9 +154,7 @@ void ReflectorImpl::UpdateTexture(ReflectorImpl::LayerData* layer_data,
viz::TransferableResource::MakeGL(mailbox_->holder().mailbox, GL_LINEAR,
mailbox_->holder().texture_target,
mailbox_->holder().sync_token),
- viz::SingleReleaseCallback::Create(
- base::BindOnce(ReleaseMailbox, mailbox_)),
- source_size);
+ mailbox_->GetSingleReleaseCallback(), source_size);
layer_data->needs_set_mailbox = false;
} else {
layer_data->layer->SetTextureSize(source_size);
diff --git a/chromium/content/browser/compositor/reflector_impl_unittest.cc b/chromium/content/browser/compositor/reflector_impl_unittest.cc
index fd673e054bd..40a83a865a1 100644
--- a/chromium/content/browser/compositor/reflector_impl_unittest.cc
+++ b/chromium/content/browser/compositor/reflector_impl_unittest.cc
@@ -5,10 +5,12 @@
#include "content/browser/compositor/reflector_impl.h"
#include "base/callback.h"
+#include "base/feature_list.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "build/build_config.h"
+#include "components/viz/common/features.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"
@@ -202,6 +204,10 @@ class ReflectorImplTest : public testing::Test {
namespace {
TEST_F(ReflectorImplTest, CheckNormalOutputSurface) {
+ // TODO(jonross): Re-enable once Reflector is re-written to work with
+ // VizDisplayCompositor. https://crbug.com/601869
+ if (base::FeatureList::IsEnabled(features::kVizDisplayCompositor))
+ return;
output_surface_->SetFlip(false);
SetUpReflector();
UpdateTexture();
@@ -212,6 +218,10 @@ TEST_F(ReflectorImplTest, CheckNormalOutputSurface) {
}
TEST_F(ReflectorImplTest, CheckInvertedOutputSurface) {
+ // TODO(jonross): Re-enable once Reflector is re-written to work with
+ // VizDisplayCompositor. https://crbug.com/601869
+ if (base::FeatureList::IsEnabled(features::kVizDisplayCompositor))
+ return;
output_surface_->SetFlip(true);
SetUpReflector();
UpdateTexture();
@@ -221,6 +231,10 @@ TEST_F(ReflectorImplTest, CheckInvertedOutputSurface) {
#if defined(USE_OZONE)
TEST_F(ReflectorImplTest, CheckOverlayNoReflector) {
+ // TODO(jonross): Re-enable once Reflector is re-written to work with
+ // VizDisplayCompositor. https://crbug.com/601869
+ if (base::FeatureList::IsEnabled(features::kVizDisplayCompositor))
+ return;
viz::OverlayCandidateList list;
viz::OverlayCandidate plane_1, plane_2;
plane_1.plane_z_order = 0;
@@ -232,6 +246,10 @@ TEST_F(ReflectorImplTest, CheckOverlayNoReflector) {
}
TEST_F(ReflectorImplTest, CheckOverlaySWMirroring) {
+ // TODO(jonross): Re-enable once Reflector is re-written to work with
+ // VizDisplayCompositor. https://crbug.com/601869
+ if (base::FeatureList::IsEnabled(features::kVizDisplayCompositor))
+ return;
SetUpReflector();
viz::OverlayCandidateList list;
viz::OverlayCandidate plane_1, plane_2;
diff --git a/chromium/content/browser/compositor/reflector_texture.cc b/chromium/content/browser/compositor/reflector_texture.cc
index 35dcfffbb68..cc6de8be58d 100644
--- a/chromium/content/browser/compositor/reflector_texture.cc
+++ b/chromium/content/browser/compositor/reflector_texture.cc
@@ -4,45 +4,51 @@
#include "content/browser/compositor/reflector_texture.h"
-#include "components/viz/common/gl_helper.h"
#include "content/browser/compositor/owned_mailbox.h"
#include "gpu/command_buffer/client/context_support.h"
#include "gpu/command_buffer/client/gles2_interface.h"
-#include "services/ui/public/cpp/gpu/context_provider_command_buffer.h"
+#include "services/ws/public/cpp/gpu/context_provider_command_buffer.h"
namespace content {
ReflectorTexture::ReflectorTexture(viz::ContextProvider* context_provider)
- : texture_id_(0) {
- viz::GLHelper* shared_helper =
- ImageTransportFactory::GetInstance()->GetGLHelper();
- mailbox_ = new OwnedMailbox(shared_helper);
- gpu::gles2::GLES2Interface* gl = context_provider->ContextGL();
-
- gl_helper_.reset(new viz::GLHelper(gl, context_provider->ContextSupport()));
-
- texture_id_ = gl_helper_->ConsumeMailboxToTexture(mailbox_->mailbox(),
- mailbox_->sync_token());
+ : gl_(context_provider->ContextGL()), texture_id_(0) {
+ mailbox_ = new OwnedMailbox(gl_);
+
+ if (!mailbox_->mailbox().IsZero()) {
+ if (mailbox_->sync_token().HasData())
+ gl_->WaitSyncTokenCHROMIUM(mailbox_->sync_token().GetConstData());
+ texture_id_ =
+ gl_->CreateAndConsumeTextureCHROMIUM(mailbox_->mailbox().name);
+ }
}
ReflectorTexture::~ReflectorTexture() {
- gl_helper_->DeleteTexture(texture_id_);
+ if (texture_id_ != 0)
+ gl_->DeleteTextures(1, &texture_id_);
}
void ReflectorTexture::CopyTextureFullImage(const gfx::Size& size) {
- gl_helper_->CopyTextureFullImage(texture_id_, size);
+ gl_->BindTexture(GL_TEXTURE_2D, texture_id_);
+ gl_->CopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, size.width(),
+ size.height(), 0);
+ gl_->BindTexture(GL_TEXTURE_2D, 0);
+
// Insert a barrier to make the copy show up in the mirroring compositor's
- // mailbox. Since the the compositor contexts and the
- // ImageTransportFactory's
- // GLHelper are all on the same GPU channel, this is sufficient instead of
+ // mailbox. Since the the compositor contexts and the ImageTransportFactory's
+ // GL context are all on the same GPU channel, this is sufficient instead of
// plumbing through a sync point.
- gl_helper_->InsertOrderingBarrier();
+ gl_->OrderingBarrierCHROMIUM();
}
void ReflectorTexture::CopyTextureSubImage(const gfx::Rect& rect) {
- gl_helper_->CopyTextureSubImage(texture_id_, rect);
+ gl_->BindTexture(GL_TEXTURE_2D, texture_id_);
+ gl_->CopyTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.x(),
+ rect.y(), rect.width(), rect.height());
+ gl_->BindTexture(GL_TEXTURE_2D, 0);
+
// Insert a barrier for the same reason above.
- gl_helper_->InsertOrderingBarrier();
+ gl_->OrderingBarrierCHROMIUM();
}
} // namespace content
diff --git a/chromium/content/browser/compositor/reflector_texture.h b/chromium/content/browser/compositor/reflector_texture.h
index d5531a362b3..ae1a3d7f08c 100644
--- a/chromium/content/browser/compositor/reflector_texture.h
+++ b/chromium/content/browser/compositor/reflector_texture.h
@@ -19,9 +19,14 @@ class Rect;
class Size;
}
+namespace gpu {
+namespace gles2 {
+class GLES2Interface;
+}
+} // namespace gpu
+
namespace viz {
class ContextProvider;
-class GLHelper;
}
namespace content {
@@ -39,8 +44,8 @@ class CONTENT_EXPORT ReflectorTexture {
scoped_refptr<OwnedMailbox> mailbox() { return mailbox_; }
private:
+ gpu::gles2::GLES2Interface* const gl_;
scoped_refptr<OwnedMailbox> mailbox_;
- std::unique_ptr<viz::GLHelper> gl_helper_;
uint32_t texture_id_;
DISALLOW_COPY_AND_ASSIGN(ReflectorTexture);
@@ -48,4 +53,4 @@ class CONTENT_EXPORT ReflectorTexture {
} // namespace content
-#endif
+#endif // CONTENT_BROWSER_COMPOSITOR_REFLECTOR_TEXTURE_H_
diff --git a/chromium/content/browser/compositor/viz_process_transport_factory.cc b/chromium/content/browser/compositor/viz_process_transport_factory.cc
index af692aeb080..07fe6eeaf90 100644
--- a/chromium/content/browser/compositor/viz_process_transport_factory.cc
+++ b/chromium/content/browser/compositor/viz_process_transport_factory.cc
@@ -17,6 +17,7 @@
#include "components/viz/common/gpu/context_provider.h"
#include "components/viz/common/gpu/raster_context_provider.h"
#include "components/viz/common/switches.h"
+#include "components/viz/host/gpu_host_impl.h"
#include "components/viz/host/host_frame_sink_manager.h"
#include "components/viz/service/display_embedder/compositing_mode_reporter_impl.h"
#include "components/viz/service/display_embedder/server_shared_bitmap_manager.h"
@@ -31,7 +32,7 @@
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/client/raster_interface.h"
#include "gpu/ipc/client/gpu_channel_host.h"
-#include "services/ui/public/cpp/gpu/context_provider_command_buffer.h"
+#include "services/ws/public/cpp/gpu/context_provider_command_buffer.h"
#include "ui/base/ui_base_features.h"
#include "ui/compositor/reflector.h"
@@ -46,14 +47,14 @@ namespace {
// child process client id.
constexpr uint32_t kBrowserClientId = 0u;
-scoped_refptr<ui::ContextProviderCommandBuffer> CreateContextProviderImpl(
+scoped_refptr<ws::ContextProviderCommandBuffer> CreateContextProviderImpl(
scoped_refptr<gpu::GpuChannelHost> gpu_channel_host,
gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
bool support_locking,
bool support_gles2_interface,
bool support_raster_interface,
bool support_grcontext,
- ui::command_buffer_metrics::ContextType type) {
+ ws::command_buffer_metrics::ContextType type) {
constexpr bool kAutomaticFlushes = false;
gpu::ContextCreationAttribs attributes;
@@ -69,7 +70,7 @@ scoped_refptr<ui::ContextProviderCommandBuffer> CreateContextProviderImpl(
attributes.enable_raster_interface = support_raster_interface;
GURL url("chrome://gpu/VizProcessTransportFactory::CreateContextProvider");
- return base::MakeRefCounted<ui::ContextProviderCommandBuffer>(
+ return base::MakeRefCounted<ws::ContextProviderCommandBuffer>(
std::move(gpu_channel_host), gpu_memory_buffer_manager,
kGpuStreamIdDefault, kGpuStreamPriorityUI, gpu::kNullSurfaceHandle,
std::move(url), kAutomaticFlushes, support_locking, support_grcontext,
@@ -165,8 +166,8 @@ void VizProcessTransportFactory::ConnectHostFrameSinkManager() {
// return null.
auto* gpu_process_host = GpuProcessHost::Get();
if (gpu_process_host) {
- gpu_process_host->ConnectFrameSinkManager(std::move(request),
- std::move(client));
+ gpu_process_host->gpu_host()->ConnectFrameSinkManager(
+ std::move(request), std::move(client));
}
};
BrowserThread::PostTask(
@@ -285,12 +286,9 @@ VizProcessTransportFactory::GetContextFactoryPrivate() {
return this;
}
-viz::GLHelper* VizProcessTransportFactory::GetGLHelper() {
- NOTREACHED(); // Readback happens in the GPU process and this isn't used.
- return nullptr;
-}
-
void VizProcessTransportFactory::OnContextLost() {
+ // PostTask to avoid destroying |main_context_provider_| while it's still
+ // informing observers about the context loss.
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(&VizProcessTransportFactory::OnLostMainThreadSharedContext,
@@ -306,19 +304,18 @@ void VizProcessTransportFactory::DisableGpuCompositing(
compositing_mode_reporter_->SetUsingSoftwareCompositing();
- // Consumers of the shared main thread context aren't CompositingModeWatchers,
- // so inform them about the compositing mode switch by acting like the context
- // was lost. This also destroys the contexts since they aren't created when
- // gpu compositing isn't being used.
- OnLostMainThreadSharedContext();
-
// Drop our reference on the gpu contexts for the compositors.
- worker_context_provider_ = nullptr;
+ worker_context_provider_.reset();
if (main_context_provider_) {
main_context_provider_->RemoveObserver(this);
- main_context_provider_ = nullptr;
+ main_context_provider_.reset();
}
+ // Consumers of the shared main thread context aren't CompositingModeWatchers,
+ // so inform them about the context loss due to switching to software
+ // compositing.
+ OnLostMainThreadSharedContext();
+
// Reemove the FrameSink from every compositor that needs to fall back to
// software compositing.
for (ui::Compositor* compositor : GetAllCompositors()) {
@@ -405,7 +402,7 @@ VizProcessTransportFactory::TryCreateContextsForGpuCompositing(
if (worker_context_provider_ &&
IsWorkerContextLost(worker_context_provider_.get()))
- worker_context_provider_ = nullptr;
+ worker_context_provider_.reset();
if (!worker_context_provider_) {
constexpr bool kSharedWorkerContextSupportsLocking = true;
@@ -420,21 +417,21 @@ VizProcessTransportFactory::TryCreateContextsForGpuCompositing(
kSharedWorkerContextSupportsLocking, kSharedWorkerContextSupportsGLES2,
kSharedWorkerContextSupportsRaster,
kSharedWorkerContextSupportsGrContext,
- ui::command_buffer_metrics::ContextType::BROWSER_WORKER);
+ ws::command_buffer_metrics::ContextType::BROWSER_WORKER);
// Don't observer context loss on |worker_context_provider_| here, that is
// already observered by LayerTreeFrameSink. The lost context will be caught
// when recreating LayerTreeFrameSink(s).
auto context_result = worker_context_provider_->BindToCurrentThread();
if (context_result != gpu::ContextResult::kSuccess) {
- worker_context_provider_ = nullptr;
+ worker_context_provider_.reset();
return context_result;
}
}
if (main_context_provider_ && IsContextLost(main_context_provider_.get())) {
main_context_provider_->RemoveObserver(this);
- main_context_provider_ = nullptr;
+ main_context_provider_.reset();
}
if (!main_context_provider_) {
@@ -447,13 +444,12 @@ VizProcessTransportFactory::TryCreateContextsForGpuCompositing(
std::move(gpu_channel_host), GetGpuMemoryBufferManager(),
kCompositorContextSupportsLocking, kCompositorContextSupportsGLES2,
kCompositorContextSupportsRaster, kCompositorContextSupportsGrContext,
- ui::command_buffer_metrics::ContextType::BROWSER_MAIN_THREAD);
+ ws::command_buffer_metrics::ContextType::BROWSER_MAIN_THREAD);
main_context_provider_->SetDefaultTaskRunner(resize_task_runner());
auto context_result = main_context_provider_->BindToCurrentThread();
if (context_result != gpu::ContextResult::kSuccess) {
- worker_context_provider_ = nullptr;
- main_context_provider_ = nullptr;
+ main_context_provider_.reset();
return context_result;
}
@@ -468,7 +464,7 @@ void VizProcessTransportFactory::OnLostMainThreadSharedContext() {
// OnEstablishedGpuChannel(), so check if it's lost before resetting here.
if (main_context_provider_ && IsContextLost(main_context_provider_.get())) {
main_context_provider_->RemoveObserver(this);
- main_context_provider_ = nullptr;
+ main_context_provider_.reset();
}
for (auto& observer : observer_list_)
diff --git a/chromium/content/browser/compositor/viz_process_transport_factory.h b/chromium/content/browser/compositor/viz_process_transport_factory.h
index 731a309d53a..41619afe58d 100644
--- a/chromium/content/browser/compositor/viz_process_transport_factory.h
+++ b/chromium/content/browser/compositor/viz_process_transport_factory.h
@@ -31,15 +31,15 @@ namespace gpu {
class GpuChannelEstablishFactory;
}
-namespace ui {
-class ContextProviderCommandBuffer;
-}
-
namespace viz {
class CompositingModeReporterImpl;
class RasterContextProvider;
}
+namespace ws {
+class ContextProviderCommandBuffer;
+}
+
namespace content {
// A replacement for GpuProcessTransportFactory to be used when running viz. In
@@ -78,7 +78,6 @@ class VizProcessTransportFactory : public ui::ContextFactory,
bool IsGpuCompositingDisabled() override;
ui::ContextFactory* GetContextFactory() override;
ui::ContextFactoryPrivate* GetContextFactoryPrivate() override;
- viz::GLHelper* GetGLHelper() override;
// viz::ContextLostObserver implementation.
void OnContextLost() override;
@@ -118,14 +117,14 @@ class VizProcessTransportFactory : public ui::ContextFactory,
// are using.
viz::CompositingModeReporterImpl* const compositing_mode_reporter_;
- base::ObserverList<ui::ContextFactoryObserver> observer_list_;
+ base::ObserverList<ui::ContextFactoryObserver>::Unchecked observer_list_;
// ContextProvider used on worker threads for rasterization.
scoped_refptr<viz::RasterContextProvider> worker_context_provider_;
// ContextProvider used on the main thread. Shared by ui::Compositors and also
// returned from GetSharedMainThreadContextProvider().
- scoped_refptr<ui::ContextProviderCommandBuffer> main_context_provider_;
+ scoped_refptr<ws::ContextProviderCommandBuffer> main_context_provider_;
std::unique_ptr<cc::SingleThreadTaskGraphRunner> task_graph_runner_;
diff --git a/chromium/content/browser/compositor/vulkan_browser_compositor_output_surface.cc b/chromium/content/browser/compositor/vulkan_browser_compositor_output_surface.cc
index 8637358c8e2..7d4b39a2e2f 100644
--- a/chromium/content/browser/compositor/vulkan_browser_compositor_output_surface.cc
+++ b/chromium/content/browser/compositor/vulkan_browser_compositor_output_surface.cc
@@ -86,7 +86,7 @@ void VulkanBrowserCompositorOutputSurface::Reshape(
const gfx::ColorSpace& color_space,
bool has_alpha,
bool use_stencil) {
- NOTIMPLEMENTED();
+ surface_->SetSize(size);
}
void VulkanBrowserCompositorOutputSurface::SetDrawRectangle(
diff --git a/chromium/content/browser/cross_site_transfer_browsertest.cc b/chromium/content/browser/cross_site_transfer_browsertest.cc
index bc1b974fb45..28626c314a7 100644
--- a/chromium/content/browser/cross_site_transfer_browsertest.cc
+++ b/chromium/content/browser/cross_site_transfer_browsertest.cc
@@ -288,7 +288,7 @@ IN_PROC_BROWSER_TEST_F(CrossSiteTransferTest, PostWithFileData) {
EXPECT_TRUE(NavigateToURL(shell(), form_url));
// Prepare a file to upload.
- base::ThreadRestrictions::ScopedAllowIO allow_io_for_temp_dir;
+ base::ScopedAllowBlockingForTesting allow_blocking;
base::ScopedTempDir temp_dir;
base::FilePath file_path;
std::string file_content("test-file-content");
@@ -381,7 +381,7 @@ IN_PROC_BROWSER_TEST_F(CrossSiteTransferTest, MaliciousPostWithFileData) {
form_contents->GetMainFrame()->GetProcess()->GetID());
// Prepare a file to upload.
- base::ThreadRestrictions::ScopedAllowIO allow_io_for_temp_dir;
+ base::ScopedAllowBlockingForTesting allow_blocking;
base::ScopedTempDir temp_dir;
base::FilePath file_path;
std::string file_content("test-file-content");
@@ -472,24 +472,4 @@ IN_PROC_BROWSER_TEST_F(CrossSiteTransferTest, NoDeliveryToDetachedFrame) {
<< "Request should have been cancelled before reaching the renderer.";
}
-// Ensure that we don't send a referrer if a site tries to trigger the forking
-// heuristic, even if we would have forked anyways.
-IN_PROC_BROWSER_TEST_F(CrossSiteTransferTest, NoReferrerOnFork) {
- base::CommandLine::ForCurrentProcess()->AppendSwitch(
- switches::kContentShellAlwaysFork);
-
- GURL start_url(embedded_test_server()->GetURL("a.com", "/fork-popup.html"));
- EXPECT_TRUE(NavigateToURL(shell(), start_url));
- EXPECT_EQ(2u, shell()->windows().size());
- Shell* popup = shell()->windows().back();
- EXPECT_NE(popup, shell());
-
- base::string16 expected_title = base::ASCIIToUTF16("Referrer = ''");
- base::string16 failed_title = base::ASCIIToUTF16(
- base::StringPrintf("Referrer = '%s'", start_url.spec().c_str()));
- TitleWatcher watcher(popup->web_contents(), expected_title);
- watcher.AlsoWaitForTitle(failed_title);
- EXPECT_EQ(expected_title, watcher.WaitAndGetTitle());
-}
-
} // namespace content
diff --git a/chromium/content/browser/dedicated_worker/dedicated_worker_host.cc b/chromium/content/browser/dedicated_worker/dedicated_worker_host.cc
index 7eccbe6db70..9c9271b5631 100644
--- a/chromium/content/browser/dedicated_worker/dedicated_worker_host.cc
+++ b/chromium/content/browser/dedicated_worker/dedicated_worker_host.cc
@@ -17,6 +17,7 @@
#include "mojo/public/cpp/system/message_pipe.h"
#include "services/service_manager/public/cpp/binder_registry.h"
#include "services/service_manager/public/mojom/interface_provider.mojom.h"
+#include "third_party/blink/public/mojom/usb/web_usb_service.mojom.h"
#include "url/origin.h"
namespace content {
@@ -57,16 +58,16 @@ class DedicatedWorkerHost : public service_manager::mojom::InterfaceProvider {
registry_.AddInterface(base::BindRepeating(
&DedicatedWorkerHost::CreateWebSocket, base::Unretained(this)));
registry_.AddInterface(base::BindRepeating(
- &DedicatedWorkerHost::CreateUsbDeviceManager, base::Unretained(this)));
+ &DedicatedWorkerHost::CreateWebUsbService, base::Unretained(this)));
registry_.AddInterface(base::BindRepeating(
&DedicatedWorkerHost::CreateDedicatedWorker, base::Unretained(this)));
}
- void CreateUsbDeviceManager(device::mojom::UsbDeviceManagerRequest request) {
+ void CreateWebUsbService(blink::mojom::WebUsbServiceRequest request) {
auto* host =
RenderFrameHostImpl::FromID(process_id_, ancestor_render_frame_id_);
- GetContentClient()->browser()->CreateUsbDeviceManager(host,
- std::move(request));
+ GetContentClient()->browser()->CreateWebUsbService(host,
+ std::move(request));
}
void CreateWebSocket(network::mojom::WebSocketRequest request) {
diff --git a/chromium/content/browser/devtools/DEPS b/chromium/content/browser/devtools/DEPS
index 28ece8ad732..93bf7150a33 100644
--- a/chromium/content/browser/devtools/DEPS
+++ b/chromium/content/browser/devtools/DEPS
@@ -1,5 +1,6 @@
include_rules = [
"+third_party/brotli", # For compressed protocol.json.
+ "+content/shell/browser/shell.h", # for access to web contents from devtools_protocol_test_support.cc
# V8 version info
"+v8/include/v8-version-string.h",
]
diff --git a/chromium/content/browser/devtools/browser_devtools_agent_host.cc b/chromium/content/browser/devtools/browser_devtools_agent_host.cc
index 5bdec4f820f..a83315a158b 100644
--- a/chromium/content/browser/devtools/browser_devtools_agent_host.cc
+++ b/chromium/content/browser/devtools/browser_devtools_agent_host.cc
@@ -111,14 +111,15 @@ void BrowserDevToolsAgentHost::Reload() {
bool BrowserDevToolsAgentHost::DispatchProtocolMessage(
DevToolsAgentHostClient* client,
const std::string& message,
- base::DictionaryValue* parsed_message) {
+ std::unique_ptr<base::DictionaryValue> parsed_message) {
auto it = target_registries_.find(client);
if (it != target_registries_.end() &&
- it->second->DispatchMessageOnAgentHost(message, parsed_message)) {
+ it->second->CanDispatchMessageOnAgentHost(parsed_message.get())) {
+ it->second->DispatchMessageOnAgentHost(message, std::move(parsed_message));
return true;
}
- return DevToolsAgentHostImpl::DispatchProtocolMessage(client, message,
- parsed_message);
+ return DevToolsAgentHostImpl::DispatchProtocolMessage(
+ client, message, std::move(parsed_message));
}
} // content
diff --git a/chromium/content/browser/devtools/browser_devtools_agent_host.h b/chromium/content/browser/devtools/browser_devtools_agent_host.h
index 29963484035..0bdd0bc36f1 100644
--- a/chromium/content/browser/devtools/browser_devtools_agent_host.h
+++ b/chromium/content/browser/devtools/browser_devtools_agent_host.h
@@ -25,9 +25,10 @@ class BrowserDevToolsAgentHost : public DevToolsAgentHostImpl {
bool AttachSession(DevToolsSession* session,
TargetRegistry* registry) override;
void DetachSession(DevToolsSession* session) override;
- bool DispatchProtocolMessage(DevToolsAgentHostClient* client,
- const std::string& message,
- base::DictionaryValue* parsed_message) override;
+ bool DispatchProtocolMessage(
+ DevToolsAgentHostClient* client,
+ const std::string& message,
+ std::unique_ptr<base::DictionaryValue> parsed_message) override;
// DevToolsAgentHost implementation.
std::string GetType() override;
diff --git a/chromium/content/browser/devtools/devtools_agent_host_impl.cc b/chromium/content/browser/devtools/devtools_agent_host_impl.cc
index 273ca40034c..d32bd45d916 100644
--- a/chromium/content/browser/devtools/devtools_agent_host_impl.cc
+++ b/chromium/content/browser/devtools/devtools_agent_host_impl.cc
@@ -35,8 +35,8 @@ typedef std::map<std::string, DevToolsAgentHostImpl*> DevToolsMap;
base::LazyInstance<DevToolsMap>::Leaky g_devtools_instances =
LAZY_INSTANCE_INITIALIZER;
-base::LazyInstance<base::ObserverList<DevToolsAgentHostObserver>>::Leaky
- g_devtools_observers = LAZY_INSTANCE_INITIALIZER;
+base::LazyInstance<base::ObserverList<DevToolsAgentHostObserver>::Unchecked>::
+ Leaky g_devtools_observers = LAZY_INSTANCE_INITIALIZER;
// Returns a list of all active hosts on browser targets.
DevToolsAgentHost::List GetBrowserAgentHosts() {
@@ -231,20 +231,18 @@ bool DevToolsAgentHostImpl::DispatchProtocolMessage(
DevToolsAgentHostClient* client,
const std::string& message) {
std::unique_ptr<base::Value> value = base::JSONReader::Read(message);
- if (value && !value->is_dict())
- value.reset();
- return DispatchProtocolMessage(
- client, message, static_cast<base::DictionaryValue*>(value.get()));
+ return DispatchProtocolMessage(client, message,
+ base::DictionaryValue::From(std::move(value)));
}
bool DevToolsAgentHostImpl::DispatchProtocolMessage(
DevToolsAgentHostClient* client,
const std::string& message,
- base::DictionaryValue* parsed_message) {
+ std::unique_ptr<base::DictionaryValue> parsed_message) {
DevToolsSession* session = SessionByClient(client);
if (!session)
return false;
- session->DispatchProtocolMessage(message, parsed_message);
+ session->DispatchProtocolMessage(message, std::move(parsed_message));
return true;
}
diff --git a/chromium/content/browser/devtools/devtools_agent_host_impl.h b/chromium/content/browser/devtools/devtools_agent_host_impl.h
index b258f840c9b..0910548167e 100644
--- a/chromium/content/browser/devtools/devtools_agent_host_impl.h
+++ b/chromium/content/browser/devtools/devtools_agent_host_impl.h
@@ -70,9 +70,10 @@ class CONTENT_EXPORT DevToolsAgentHostImpl : public DevToolsAgentHost {
TargetRegistry* registry);
virtual void DetachSession(DevToolsSession* session);
- virtual bool DispatchProtocolMessage(DevToolsAgentHostClient* client,
- const std::string& message,
- base::DictionaryValue* parsed_message);
+ virtual bool DispatchProtocolMessage(
+ DevToolsAgentHostClient* client,
+ const std::string& message,
+ std::unique_ptr<base::DictionaryValue> parsed_message);
void NotifyCreated();
void NotifyNavigated();
diff --git a/chromium/content/browser/devtools/devtools_frame_trace_recorder.cc b/chromium/content/browser/devtools/devtools_frame_trace_recorder.cc
index 9f8da6cf237..4c8f6b249c3 100644
--- a/chromium/content/browser/devtools/devtools_frame_trace_recorder.cc
+++ b/chromium/content/browser/devtools/devtools_frame_trace_recorder.cc
@@ -80,14 +80,6 @@ DevToolsFrameTraceRecorder::DevToolsFrameTraceRecorder() { }
DevToolsFrameTraceRecorder::~DevToolsFrameTraceRecorder() { }
-void DevToolsFrameTraceRecorder::OnSwapCompositorFrame(
- RenderFrameHostImpl* host,
- const viz::CompositorFrameMetadata& frame_metadata) {
- if (!host || !ScreenshotCategoryEnabled())
- return;
- CaptureFrame(host, frame_metadata);
-}
-
void DevToolsFrameTraceRecorder::OnSynchronousSwapCompositorFrame(
RenderFrameHostImpl* host,
const viz::CompositorFrameMetadata& frame_metadata) {
diff --git a/chromium/content/browser/devtools/devtools_frame_trace_recorder.h b/chromium/content/browser/devtools/devtools_frame_trace_recorder.h
index a80afc02a26..ed1d52f1152 100644
--- a/chromium/content/browser/devtools/devtools_frame_trace_recorder.h
+++ b/chromium/content/browser/devtools/devtools_frame_trace_recorder.h
@@ -24,10 +24,6 @@ class DevToolsFrameTraceRecorder {
DevToolsFrameTraceRecorder();
~DevToolsFrameTraceRecorder();
- void OnSwapCompositorFrame(
- RenderFrameHostImpl* host,
- const viz::CompositorFrameMetadata& frame_metadata);
-
void OnSynchronousSwapCompositorFrame(
RenderFrameHostImpl* host,
const viz::CompositorFrameMetadata& frame_metadata);
diff --git a/chromium/content/browser/devtools/devtools_http_handler.cc b/chromium/content/browser/devtools/devtools_http_handler.cc
index eaf44246e9e..a0ce6d621d8 100644
--- a/chromium/content/browser/devtools/devtools_http_handler.cc
+++ b/chromium/content/browser/devtools/devtools_http_handler.cc
@@ -22,7 +22,7 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "base/threading/thread.h"
#include "base/values.h"
#include "build/build_config.h"
@@ -222,7 +222,7 @@ void TerminateOnUI(std::unique_ptr<base::Thread> thread,
thread->task_runner()->DeleteSoon(FROM_HERE, std::move(socket_factory));
if (thread) {
base::PostTaskWithTraits(
- FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND},
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
BindOnce([](std::unique_ptr<base::Thread>) {}, std::move(thread)));
}
}
diff --git a/chromium/content/browser/devtools/devtools_http_handler_unittest.cc b/chromium/content/browser/devtools/devtools_http_handler_unittest.cc
index 3222803c84e..97ac6d57e1d 100644
--- a/chromium/content/browser/devtools/devtools_http_handler_unittest.cc
+++ b/chromium/content/browser/devtools/devtools_http_handler_unittest.cc
@@ -24,6 +24,7 @@
#include "content/public/browser/devtools_socket_factory.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_utils.h"
+#include "net/base/completion_once_callback.h"
#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
@@ -52,7 +53,7 @@ class DummyServerSocket : public net::ServerSocket {
}
int Accept(std::unique_ptr<net::StreamSocket>* socket,
- const net::CompletionCallback& callback) override {
+ net::CompletionOnceCallback callback) override {
return net::ERR_IO_PENDING;
}
};
diff --git a/chromium/content/browser/devtools/devtools_pipe_handler.cc b/chromium/content/browser/devtools/devtools_pipe_handler.cc
index dcdce1fe0ef..8552cf21711 100644
--- a/chromium/content/browser/devtools/devtools_pipe_handler.cc
+++ b/chromium/content/browser/devtools/devtools_pipe_handler.cc
@@ -20,7 +20,7 @@
#include "base/message_loop/message_loop.h"
#include "base/sequenced_task_runner.h"
#include "base/single_thread_task_runner.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "base/threading/thread.h"
#include "build/build_config.h"
#include "content/public/browser/browser_thread.h"
@@ -209,7 +209,7 @@ void DevToolsPipeHandler::Shutdown() {
// If there is no write thread, only take care of the read thread.
if (!write_thread_) {
base::PostTaskWithTraits(
- FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND},
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
base::BindOnce([](base::Thread* rthread) { delete rthread; },
read_thread_.release()));
return;
@@ -236,7 +236,7 @@ void DevToolsPipeHandler::Shutdown() {
// Post background task that would join and destroy the threads.
base::PostTaskWithTraits(
- FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND},
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
base::BindOnce(
[](base::Thread* rthread, base::Thread* wthread) {
delete rthread;
diff --git a/chromium/content/browser/devtools/devtools_session.cc b/chromium/content/browser/devtools/devtools_session.cc
index a82213afc24..0d91850d5e7 100644
--- a/chromium/content/browser/devtools/devtools_session.cc
+++ b/chromium/content/browser/devtools/devtools_session.cc
@@ -42,7 +42,6 @@ DevToolsSession::DevToolsSession(DevToolsAgentHostImpl* agent_host,
host_(nullptr),
dispatcher_(new protocol::UberDispatcher(this)),
weak_factory_(this) {
- dispatcher_->setFallThroughForNotFound(true);
}
DevToolsSession::~DevToolsSession() {
@@ -76,7 +75,6 @@ void DevToolsSession::SetRenderer(int process_host_id,
void DevToolsSession::SetBrowserOnly(bool browser_only) {
browser_only_ = browser_only;
- dispatcher_->setFallThroughForNotFound(!browser_only);
}
void DevToolsSession::AttachToAgent(
@@ -85,7 +83,7 @@ void DevToolsSession::AttachToAgent(
binding_.Bind(mojo::MakeRequest(&host_ptr_info));
agent->AttachDevToolsSession(
std::move(host_ptr_info), mojo::MakeRequest(&session_ptr_),
- mojo::MakeRequest(&io_session_ptr_), state_cookie_);
+ mojo::MakeRequest(&io_session_ptr_), session_state_cookie_.Clone());
session_ptr_.set_connection_error_handler(base::BindOnce(
&DevToolsSession::MojoConnectionDestroyed, base::Unretained(this)));
@@ -104,9 +102,9 @@ void DevToolsSession::AttachToAgent(
waiting_for_response_messages_.clear();
}
- // Set cookie to an empty string to reattach next time instead of attaching.
- if (!state_cookie_.has_value())
- state_cookie_ = std::string();
+ // Set cookie to an empty struct to reattach next time instead of attaching.
+ if (!session_state_cookie_)
+ session_state_cookie_ = blink::mojom::DevToolsSessionState::New();
}
void DevToolsSession::SendResponse(
@@ -125,22 +123,39 @@ void DevToolsSession::MojoConnectionDestroyed() {
void DevToolsSession::DispatchProtocolMessage(
const std::string& message,
- base::DictionaryValue* parsed_message) {
+ std::unique_ptr<base::DictionaryValue> parsed_message) {
DevToolsManagerDelegate* delegate =
DevToolsManager::GetInstance()->delegate();
- if (delegate && parsed_message &&
- delegate->HandleCommand(agent_host_, client_, parsed_message)) {
- return;
+ if (delegate && parsed_message) {
+ delegate->HandleCommand(agent_host_, client_, std::move(parsed_message),
+ message,
+ base::BindOnce(&DevToolsSession::HandleCommand,
+ weak_factory_.GetWeakPtr()));
+ } else {
+ HandleCommand(std::move(parsed_message), message);
}
+}
+void DevToolsSession::HandleCommand(
+ std::unique_ptr<base::DictionaryValue> parsed_message,
+ const std::string& message) {
+ std::unique_ptr<protocol::Value> protocol_command =
+ protocol::toProtocolValue(parsed_message.get(), 1000);
int call_id;
std::string method;
- if (dispatcher_->dispatch(protocol::toProtocolValue(parsed_message, 1000),
- &call_id,
- &method) != protocol::Response::kFallThrough) {
+ if (!dispatcher_->parseCommand(protocol_command.get(), &call_id, &method))
return;
+ if (browser_only_ || dispatcher_->canDispatch(method)) {
+ dispatcher_->dispatch(call_id, method, std::move(protocol_command),
+ message);
+ } else {
+ fallThrough(call_id, method, message);
}
+}
+void DevToolsSession::fallThrough(int call_id,
+ const std::string& method,
+ const std::string& message) {
// In browser-only mode, we should've handled everything in dispatcher.
DCHECK(!browser_only_);
@@ -203,9 +218,8 @@ void DevToolsSession::flushProtocolNotifications() {
void DevToolsSession::DispatchProtocolResponse(
const std::string& message,
int call_id,
- const base::Optional<std::string>& state) {
- if (state.has_value())
- state_cookie_ = state.value();
+ blink::mojom::DevToolsSessionStatePtr updates) {
+ ApplySessionStateUpdates(std::move(updates));
waiting_for_response_messages_.erase(call_id);
client_->DispatchProtocolMessage(agent_host_, message);
// |this| may be deleted at this point.
@@ -213,11 +227,23 @@ void DevToolsSession::DispatchProtocolResponse(
void DevToolsSession::DispatchProtocolNotification(
const std::string& message,
- const base::Optional<std::string>& state) {
- if (state.has_value())
- state_cookie_ = state.value();
+ blink::mojom::DevToolsSessionStatePtr updates) {
+ ApplySessionStateUpdates(std::move(updates));
client_->DispatchProtocolMessage(agent_host_, message);
// |this| may be deleted at this point.
}
+void DevToolsSession::ApplySessionStateUpdates(
+ blink::mojom::DevToolsSessionStatePtr updates) {
+ if (!updates)
+ return;
+ if (!session_state_cookie_)
+ 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);
+ else
+ session_state_cookie_->entries.erase(entry.first);
+ }
+}
} // namespace content
diff --git a/chromium/content/browser/devtools/devtools_session.h b/chromium/content/browser/devtools/devtools_session.h
index 2b2bccf785b..467edb43869 100644
--- a/chromium/content/browser/devtools/devtools_session.h
+++ b/chromium/content/browser/devtools/devtools_session.h
@@ -43,8 +43,9 @@ class DevToolsSession : public protocol::FrontendChannel,
void SetRenderer(int process_host_id, RenderFrameHostImpl* frame_host);
void AttachToAgent(const blink::mojom::DevToolsAgentAssociatedPtr& agent);
- void DispatchProtocolMessage(const std::string& message,
- base::DictionaryValue* parsed_message);
+ void DispatchProtocolMessage(
+ const std::string& message,
+ std::unique_ptr<base::DictionaryValue> parsed_message);
void SuspendSendingMessagesToAgent();
void ResumeSendingMessagesToAgent();
@@ -69,6 +70,8 @@ class DevToolsSession : public protocol::FrontendChannel,
void DispatchProtocolMessageToAgent(int call_id,
const std::string& method,
const std::string& message);
+ void HandleCommand(std::unique_ptr<base::DictionaryValue> parsed_message,
+ const std::string& message);
// protocol::FrontendChannel implementation.
void sendProtocolResponse(
@@ -77,15 +80,21 @@ class DevToolsSession : public protocol::FrontendChannel,
void sendProtocolNotification(
std::unique_ptr<protocol::Serializable> message) override;
void flushProtocolNotifications() override;
+ void fallThrough(int call_id,
+ const std::string& method,
+ const std::string& message) override;
// blink::mojom::DevToolsSessionHost implementation.
void DispatchProtocolResponse(
const std::string& message,
int call_id,
- const base::Optional<std::string>& state) override;
+ blink::mojom::DevToolsSessionStatePtr updates) override;
void DispatchProtocolNotification(
const std::string& message,
- const base::Optional<std::string>& state) override;
+ blink::mojom::DevToolsSessionStatePtr updates) override;
+
+ // Merges the |updates| received from the renderer into session_state_cookie_.
+ void ApplySessionStateUpdates(blink::mojom::DevToolsSessionStatePtr updates);
mojo::AssociatedBinding<blink::mojom::DevToolsSessionHost> binding_;
blink::mojom::DevToolsSessionAssociatedPtr session_ptr_;
@@ -117,10 +126,10 @@ class DevToolsSession : public protocol::FrontendChannel,
};
std::map<int, WaitingMessage> waiting_for_response_messages_;
- // |state_cookie_| always corresponds to a state before
+ // |session_state_cookie_| always corresponds to a state before
// any of the waiting for response messages have been handled.
- // Note that |state_cookie_| is not present only before first attach.
- base::Optional<std::string> state_cookie_;
+ // |session_state_cookie_| is nullptr before first attach.
+ blink::mojom::DevToolsSessionStatePtr session_state_cookie_;
base::WeakPtrFactory<DevToolsSession> weak_factory_;
};
diff --git a/chromium/content/browser/devtools/devtools_stream_file.cc b/chromium/content/browser/devtools/devtools_stream_file.cc
index c32261e092a..1e0aa6b6bd3 100644
--- a/chromium/content/browser/devtools/devtools_stream_file.cc
+++ b/chromium/content/browser/devtools/devtools_stream_file.cc
@@ -9,8 +9,8 @@
#include "base/files/file_util.h"
#include "base/sequenced_task_runner.h"
#include "base/strings/string_util.h"
-#include "base/task_scheduler/lazy_task_runner.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/lazy_task_runner.h"
+#include "base/task/post_task.h"
#include "base/third_party/icu/icu_utf.h"
#include "base/threading/thread_restrictions.h"
#include "content/public/browser/browser_thread.h"
@@ -19,8 +19,8 @@
namespace content {
scoped_refptr<base::SequencedTaskRunner> impl_task_runner() {
- constexpr base::TaskTraits kBlockingTraits = {base::MayBlock(),
- base::TaskPriority::BACKGROUND};
+ constexpr base::TaskTraits kBlockingTraits = {
+ base::MayBlock(), base::TaskPriority::BEST_EFFORT};
static base::LazySequencedTaskRunner s_sequenced_task_unner =
LAZY_SEQUENCED_TASK_RUNNER_INITIALIZER(kBlockingTraits);
return s_sequenced_task_unner.Get();
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 65329798837..d07eca5061f 100644
--- a/chromium/content/browser/devtools/devtools_url_interceptor_request_job.cc
+++ b/chromium/content/browser/devtools/devtools_url_interceptor_request_job.cc
@@ -566,7 +566,6 @@ DevToolsURLInterceptorRequestJob::DevToolsURLInterceptorRequestJob(
net::NetworkDelegate* original_network_delegate,
const base::UnguessableToken& devtools_token,
DevToolsNetworkInterceptor::RequestInterceptedCallback callback,
- bool is_redirect,
ResourceType resource_type,
InterceptionStage stage_to_intercept)
: net::URLRequestJob(original_request, original_network_delegate),
@@ -584,7 +583,6 @@ DevToolsURLInterceptorRequestJob::DevToolsURLInterceptorRequestJob(
owning_entry_id_(owning_entry_id),
devtools_token_(devtools_token),
callback_(callback),
- is_redirect_(is_redirect),
resource_type_(resource_type),
stage_to_intercept_(stage_to_intercept),
weak_ptr_factory_(this) {
@@ -635,26 +633,6 @@ void DevToolsURLInterceptorRequestJob::StartWithCookies(
return;
}
- if (is_redirect_) {
- if (stage_to_intercept_ == InterceptionStage::REQUEST) {
- // If we are a redirect and we do not plan on grabbing the response we are
- // done. If we are here this means we must have already sent an
- // intercepted event to front-end for this redirect and the front-end
- // allowed it. Since we have already allowed the redirect and we are only
- // intercepting the request, we only need to catch it again if it's
- // another redirect, which SubRequest will send the
- // OnSubRequestRedirectReceived event.
- sub_request_.reset(new SubRequest(request_details_, this, interceptor_));
- } else {
- // Otherwise we have already issued the request interception and had a
- // continue and now we must issue a response interception for the
- // redirect.
- sub_request_.reset(
- new InterceptedRequest(request_details_, this, interceptor_));
- }
- return;
- }
-
if (stage_to_intercept_ == InterceptionStage::RESPONSE) {
// We are only a response interception, we go right to dispatching the
// request.
@@ -821,8 +799,7 @@ void DevToolsURLInterceptorRequestJob::OnSubRequestRedirectReceived(
// If we're not intercepting results or are a response then cancel this
// redirect and tell the parent request it was redirected through |redirect_|.
- if (stage_to_intercept_ == InterceptionStage::DONT_INTERCEPT ||
- stage_to_intercept_ == InterceptionStage::RESPONSE) {
+ if (!(stage_to_intercept_ & InterceptionStage::RESPONSE)) {
*defer_redirect = false;
ProcessRedirect(redirectinfo.status_code, redirectinfo.new_url.spec());
redirect_.reset();
@@ -1045,7 +1022,6 @@ void DevToolsURLInterceptorRequestJob::ProcessRedirect(
base::MakeRefCounted<net::HttpResponseHeaders>(raw_headers), "", 0,
base::TimeTicks::Now()));
- interceptor_->ExpectRequestAfterRedirect(request(), interception_id_);
NotifyHeadersComplete();
}
@@ -1124,11 +1100,6 @@ void DevToolsURLInterceptorRequestJob::ProcessInterceptionResponse(
mock_response_details_.reset(new MockResponseDetails(
std::move(*modifications->raw_response), base::TimeTicks::Now()));
- std::string value;
- if (mock_response_details_->response_headers()->IsRedirect(&value)) {
- interceptor_->ExpectRequestAfterRedirect(request(), interception_id_);
- }
-
// Set cookies in the network stack.
net::CookieOptions options;
options.set_include_httponly();
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 e7531a1d79d..ac37f7204ff 100644
--- a/chromium/content/browser/devtools/devtools_url_interceptor_request_job.h
+++ b/chromium/content/browser/devtools/devtools_url_interceptor_request_job.h
@@ -37,7 +37,6 @@ class DevToolsURLInterceptorRequestJob : public net::URLRequestJob {
net::NetworkDelegate* original_network_delegate,
const base::UnguessableToken& devtools_token,
DevToolsNetworkInterceptor::RequestInterceptedCallback callback,
- bool is_redirect,
ResourceType resource_type,
DevToolsNetworkInterceptor::InterceptionStage stage_to_intercept);
@@ -157,7 +156,6 @@ class DevToolsURLInterceptorRequestJob : public net::URLRequestJob {
const intptr_t owning_entry_id_;
const base::UnguessableToken devtools_token_;
DevToolsNetworkInterceptor::RequestInterceptedCallback callback_;
- const bool is_redirect_;
const ResourceType resource_type_;
InterceptionStage stage_to_intercept_;
std::vector<std::unique_ptr<GetResponseBodyForInterceptionCallback>>
diff --git a/chromium/content/browser/devtools/devtools_url_loader_interceptor.cc b/chromium/content/browser/devtools/devtools_url_loader_interceptor.cc
index 6d4201baf6d..99e8fd164e5 100644
--- a/chromium/content/browser/devtools/devtools_url_loader_interceptor.cc
+++ b/chromium/content/browser/devtools/devtools_url_loader_interceptor.cc
@@ -252,8 +252,9 @@ class InterceptionJob : public network::mojom::URLLoaderClient,
void OnComplete(const network::URLLoaderCompletionStatus& status) override;
bool CanGetResponseBody(std::string* error_reason);
+ void UpdateIdAndRegister();
- const std::string id_;
+ const std::string id_prefix_;
const GlobalRequestId global_req_id_;
const base::UnguessableToken frame_token_;
const base::TimeTicks start_ticks_;
@@ -277,6 +278,7 @@ class InterceptionJob : public network::mojom::URLLoaderClient,
kNotStarted,
kRequestSent,
kRedirectReceived,
+ kFollowRedirect,
kAuthRequired,
kResponseReceived,
kResponseTaken,
@@ -284,6 +286,8 @@ class InterceptionJob : public network::mojom::URLLoaderClient,
State state_;
bool waiting_for_resolution_;
+ int redirect_count_;
+ std::string current_id_;
std::unique_ptr<BodyReader> body_reader_;
std::unique_ptr<ResponseMetadata> response_metadata_;
@@ -320,11 +324,11 @@ class DevToolsURLLoaderInterceptor::Impl
static int last_id = 0;
std::string id = base::StringPrintf("interception-job-%d", ++last_id);
- InterceptionJob* job = new InterceptionJob(
- this, id, frame_token, process_id, std::move(create_params),
- is_download, std::move(loader_request), std::move(client),
- std::move(target_factory));
- jobs_.emplace(std::move(id), job);
+ // This class will manage its own life time to match the loader client.
+ new InterceptionJob(this, std::move(id), frame_token, process_id,
+ std::move(create_params), is_download,
+ std::move(loader_request), std::move(client),
+ std::move(target_factory));
}
void SetPatterns(std::vector<DevToolsNetworkInterceptor::Pattern> patterns) {
@@ -392,6 +396,9 @@ class DevToolsURLLoaderInterceptor::Impl
}
void RemoveJob(const std::string& id) { jobs_.erase(id); }
+ void AddJob(const std::string& id, InterceptionJob* job) {
+ jobs_.emplace(id, job);
+ }
std::map<std::string, InterceptionJob*> jobs_;
RequestInterceptedCallback request_intercepted_callback_;
@@ -627,7 +634,7 @@ InterceptionJob::InterceptionJob(
network::mojom::URLLoaderRequest loader_request,
network::mojom::URLLoaderClientPtr client,
network::mojom::URLLoaderFactoryPtr target_factory)
- : id_(std::move(id)),
+ : id_prefix_(id),
global_req_id_(
std::make_tuple(process_id,
create_loader_params->request.render_frame_id,
@@ -644,7 +651,9 @@ InterceptionJob::InterceptionJob(
client_(std::move(client)),
target_factory_(std::move(target_factory)),
state_(kNotStarted),
- waiting_for_resolution_(false) {
+ waiting_for_resolution_(false),
+ redirect_count_(0) {
+ UpdateIdAndRegister();
const network::ResourceRequest& request = create_loader_params_->request;
stage_ = interceptor_->GetInterceptionStage(
request.url, static_cast<ResourceType>(request.resource_type));
@@ -665,6 +674,11 @@ InterceptionJob::InterceptionJob(
StartRequest();
}
+void InterceptionJob::UpdateIdAndRegister() {
+ current_id_ = id_prefix_ + base::StringPrintf(".%d", redirect_count_);
+ interceptor_->AddJob(current_id_, this);
+}
+
bool InterceptionJob::CanGetResponseBody(std::string* error_reason) {
if (!(stage_ & InterceptionStage::RESPONSE)) {
*error_reason =
@@ -786,6 +800,18 @@ Response InterceptionJob::InnerContinueRequest(
if (modifications->raw_response)
return ProcessResponseOverride(*modifications->raw_response);
+ if (state_ == State::kFollowRedirect) {
+ if (modifications->modified_url.isJust()) {
+ CancelRequest();
+ // Fall through to the generic logic of re-starting the request
+ // at the bottom of the method.
+ } else {
+ // TODO(caseq): report error if other modifications are present.
+ state_ = State::kRequestSent;
+ loader_->FollowRedirect(base::nullopt, base::nullopt);
+ return Response::OK();
+ }
+ }
if (state_ == State::kRedirectReceived) {
// TODO(caseq): report error if other modifications are present.
if (modifications->modified_url.isJust()) {
@@ -918,6 +944,7 @@ Response InterceptionJob::ProcessResponseOverride(const std::string& response) {
create_loader_params_->request.url, "",
net::ForceSniffFileUrlsForHtml::kDisabled,
&head->mime_type);
+ head->did_mime_sniff = true;
}
head->content_length = body_size;
head->encoded_data_length = header_size;
@@ -1037,7 +1064,7 @@ void InterceptionJob::CancelRequest() {
std::unique_ptr<InterceptedRequestInfo> InterceptionJob::BuildRequestInfo(
const network::ResourceResponseHead* head) {
auto result = std::make_unique<InterceptedRequestInfo>();
- result->interception_id = id_;
+ result->interception_id = current_id_;
result->network_request =
protocol::NetworkHandler::CreateRequestFromResourceRequest(
create_loader_params_->request);
@@ -1078,7 +1105,7 @@ void InterceptionJob::NotifyClient(
void InterceptionJob::Shutdown() {
if (interceptor_)
- interceptor_->RemoveJob(id_);
+ interceptor_->RemoveJob(current_id_);
delete this;
}
@@ -1100,9 +1127,24 @@ void InterceptionJob::FollowRedirect(
request->referrer_policy = info.new_referrer_policy;
request->referrer = GURL(info.new_referrer);
response_metadata_.reset();
+
if (interceptor_) {
+ // Pretend that each redirect hop is a new request -- this is for
+ // compatibilty with URLRequestJob-based interception implementation.
+ interceptor_->RemoveJob(current_id_);
+ redirect_count_++;
+ UpdateIdAndRegister();
+
stage_ = interceptor_->GetInterceptionStage(
request->url, static_cast<ResourceType>(request->resource_type));
+ if (stage_ & InterceptionStage::REQUEST) {
+ if (state_ == State::kRedirectReceived)
+ state_ = State::kFollowRedirect;
+ else
+ DCHECK_EQ(State::kNotStarted, state_);
+ NotifyClient(BuildRequestInfo(nullptr));
+ return;
+ }
}
if (state_ == State::kRedirectReceived) {
state_ = State::kRequestSent;
@@ -1168,7 +1210,7 @@ void InterceptionJob::OnReceiveRedirect(
response_metadata_->redirect_info =
std::make_unique<net::RedirectInfo>(redirect_info);
- if (!(stage_ & InterceptionStage::REQUEST)) {
+ if (!(stage_ & InterceptionStage::RESPONSE)) {
client_->OnReceiveRedirect(redirect_info, head);
return;
}
diff --git a/chromium/content/browser/devtools/devtools_url_request_interceptor.cc b/chromium/content/browser/devtools/devtools_url_request_interceptor.cc
index 0a02236d4dc..e6bf677b05b 100644
--- a/chromium/content/browser/devtools/devtools_url_request_interceptor.cc
+++ b/chromium/content/browser/devtools/devtools_url_request_interceptor.cc
@@ -141,8 +141,7 @@ net::URLRequestJob* DevToolsURLRequestInterceptor::InnerMaybeInterceptRequest(
return nullptr;
DCHECK(interception_stage != DONT_INTERCEPT);
- bool is_redirect;
- std::string interception_id = GetIdForRequest(request, &is_redirect);
+ std::string interception_id = base::StringPrintf("id-%zu", ++next_id_);
if (IsNavigationRequest(resource_type)) {
BrowserThread::PostTask(
@@ -155,8 +154,7 @@ net::URLRequestJob* DevToolsURLRequestInterceptor::InnerMaybeInterceptRequest(
DevToolsURLInterceptorRequestJob* job = new DevToolsURLInterceptorRequestJob(
this, interception_id, reinterpret_cast<intptr_t>(entry), request,
network_delegate, target_info->devtools_token, entry->callback,
- is_redirect, resource_request_info->GetResourceType(),
- interception_stage);
+ resource_request_info->GetResourceType(), interception_stage);
interception_id_to_job_map_[interception_id] = job;
return job;
}
@@ -261,28 +259,6 @@ void DevToolsURLRequestInterceptor::UnregisterSubRequest(
sub_requests_.erase(sub_request);
}
-void DevToolsURLRequestInterceptor::ExpectRequestAfterRedirect(
- const net::URLRequest* request,
- std::string id) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- expected_redirects_[request] = id;
-}
-
-std::string DevToolsURLRequestInterceptor::GetIdForRequest(
- const net::URLRequest* request,
- bool* is_redirect) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- auto find_it = expected_redirects_.find(request);
- if (find_it == expected_redirects_.end()) {
- *is_redirect = false;
- return base::StringPrintf("id-%zu", ++next_id_);
- }
- *is_redirect = true;
- std::string id = find_it->second;
- expected_redirects_.erase(find_it);
- return id;
-}
-
DevToolsURLInterceptorRequestJob* DevToolsURLRequestInterceptor::GetJob(
const std::string& interception_id) const {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
diff --git a/chromium/content/browser/devtools/devtools_url_request_interceptor.h b/chromium/content/browser/devtools/devtools_url_request_interceptor.h
index 96bb378be41..397dd660883 100644
--- a/chromium/content/browser/devtools/devtools_url_request_interceptor.h
+++ b/chromium/content/browser/devtools/devtools_url_request_interceptor.h
@@ -66,10 +66,6 @@ class DevToolsURLRequestInterceptor : public net::URLRequestInterceptor,
// Registers a |sub_request| that should not be intercepted.
void RegisterSubRequest(const net::URLRequest* sub_request);
void UnregisterSubRequest(const net::URLRequest* sub_request);
- // To make the user's life easier we make sure requests in a redirect chain
- // all have the same id.
- void ExpectRequestAfterRedirect(const net::URLRequest* request,
- std::string id);
void JobFinished(const std::string& interception_id, bool is_navigation);
private:
@@ -85,8 +81,6 @@ class DevToolsURLRequestInterceptor : public net::URLRequestInterceptor,
const DevToolsTargetRegistry::TargetInfo* TargetInfoForRequestInfo(
const ResourceRequestInfo* request_info) const;
- std::string GetIdForRequest(const net::URLRequest* request,
- bool* is_redirect);
// Returns a WeakPtr to the DevToolsURLInterceptorRequestJob corresponding
// to |interception_id|.
DevToolsURLInterceptorRequestJob* GetJob(
@@ -107,9 +101,6 @@ class DevToolsURLRequestInterceptor : public net::URLRequestInterceptor,
// requests.
base::flat_set<const net::URLRequest*> sub_requests_;
- // To simplify handling of redirect chains for the end user, we arrange for
- // all requests in the chain to have the same interception id.
- base::flat_map<const net::URLRequest*, std::string> expected_redirects_;
size_t next_id_;
base::WeakPtrFactory<DevToolsURLRequestInterceptor> weak_factory_;
diff --git a/chromium/content/browser/devtools/devtools_video_consumer.cc b/chromium/content/browser/devtools/devtools_video_consumer.cc
index 2b185d09f79..e6316a8681c 100644
--- a/chromium/content/browser/devtools/devtools_video_consumer.cc
+++ b/chromium/content/browser/devtools/devtools_video_consumer.cc
@@ -6,6 +6,7 @@
#include <utility>
+#include "base/memory/shared_memory_mapping.h"
#include "cc/paint/skia_paint_canvas.h"
#include "components/viz/host/host_frame_sink_manager.h"
#include "components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h"
@@ -129,31 +130,46 @@ bool DevToolsVideoConsumer::IsValidMinAndMaxFrameSize(
}
void DevToolsVideoConsumer::OnFrameCaptured(
- mojo::ScopedSharedBufferHandle buffer,
- uint32_t buffer_size,
+ base::ReadOnlySharedMemoryRegion data,
::media::mojom::VideoFrameInfoPtr info,
const gfx::Rect& update_rect,
const gfx::Rect& content_rect,
viz::mojom::FrameSinkVideoConsumerFrameCallbacksPtr callbacks) {
- if (!buffer.is_valid())
+ if (!data.IsValid())
return;
- mojo::ScopedSharedBufferMapping mapping = buffer->Map(buffer_size);
- if (!mapping) {
+ base::ReadOnlySharedMemoryMapping mapping = data.Map();
+ if (!mapping.IsValid()) {
DLOG(ERROR) << "Shared memory mapping failed.";
return;
}
+ if (mapping.size() <
+ media::VideoFrame::AllocationSize(info->pixel_format, info->coded_size)) {
+ DLOG(ERROR) << "Shared memory size was less than expected.";
+ return;
+ }
- scoped_refptr<media::VideoFrame> frame;
+ // Create a media::VideoFrame that wraps the read-only shared memory data.
+ // Unfortunately, a deep web of not-const-correct code exists in
+ // media::VideoFrame and media::PaintCanvasVideoRenderer (see
+ // GetSkBitmapFromFrame() above). So, the pointer's const attribute must be
+ // casted away. This is safe since the operating system will page fault if
+ // there is any attempt downstream to mutate the data.
+ //
// Setting |frame|'s visible rect equal to |content_rect| so that only the
- // portion of the frame that contain content are used.
- frame = media::VideoFrame::WrapExternalData(
+ // portion of the frame that contains content is used.
+ scoped_refptr<media::VideoFrame> frame = media::VideoFrame::WrapExternalData(
info->pixel_format, info->coded_size, content_rect, content_rect.size(),
- static_cast<uint8_t*>(mapping.get()), buffer_size, info->timestamp);
- if (!frame)
+ const_cast<uint8_t*>(static_cast<const uint8_t*>(mapping.memory())),
+ mapping.size(), info->timestamp);
+ if (!frame) {
+ DLOG(ERROR) << "Unable to create VideoFrame wrapper around the shmem.";
return;
+ }
frame->AddDestructionObserver(base::BindOnce(
- [](mojo::ScopedSharedBufferMapping mapping) {}, std::move(mapping)));
+ [](base::ReadOnlySharedMemoryMapping mapping,
+ viz::mojom::FrameSinkVideoConsumerFrameCallbacksPtr callbacks) {},
+ std::move(mapping), std::move(callbacks)));
frame->metadata()->MergeInternalValuesFrom(info->metadata);
callback_.Run(std::move(frame));
diff --git a/chromium/content/browser/devtools/devtools_video_consumer.h b/chromium/content/browser/devtools/devtools_video_consumer.h
index dd17f36abdd..2634849d6c2 100644
--- a/chromium/content/browser/devtools/devtools_video_consumer.h
+++ b/chromium/content/browser/devtools/devtools_video_consumer.h
@@ -10,7 +10,6 @@
#include "base/time/time.h"
#include "components/viz/host/client_frame_sink_video_capturer.h"
#include "content/common/content_export.h"
-#include "mojo/public/cpp/bindings/binding.h"
#include "ui/gfx/geometry/size.h"
class SkBitmap;
@@ -64,8 +63,7 @@ class CONTENT_EXPORT DevToolsVideoConsumer
// viz::mojom::FrameSinkVideoConsumer:
void OnFrameCaptured(
- mojo::ScopedSharedBufferHandle buffer,
- uint32_t buffer_size,
+ base::ReadOnlySharedMemoryRegion data,
::media::mojom::VideoFrameInfoPtr info,
const gfx::Rect& update_rect,
const gfx::Rect& content_rect,
diff --git a/chromium/content/browser/devtools/devtools_video_consumer_unittest.cc b/chromium/content/browser/devtools/devtools_video_consumer_unittest.cc
index 826ab906e49..6aefd60ca68 100644
--- a/chromium/content/browser/devtools/devtools_video_consumer_unittest.cc
+++ b/chromium/content/browser/devtools/devtools_video_consumer_unittest.cc
@@ -5,10 +5,13 @@
#include <utility>
#include <vector>
+#include "base/memory/read_only_shared_memory_region.h"
#include "base/message_loop/message_loop.h"
#include "content/browser/devtools/devtools_video_consumer.h"
#include "content/public/test/test_utils.h"
#include "media/base/limits.h"
+#include "mojo/public/cpp/base/shared_memory_utils.h"
+#include "mojo/public/cpp/bindings/binding.h"
#include "testing/gmock/include/gmock/gmock.h"
using testing::_;
@@ -91,6 +94,9 @@ class MockFrameSinkVideoCapturer : public viz::mojom::FrameSinkVideoCapturer {
}
MOCK_METHOD0(MockStop, void());
MOCK_METHOD0(RequestRefreshFrame, void());
+ MOCK_METHOD2(CreateOverlay,
+ void(int32_t stacking_index,
+ viz::mojom::FrameSinkVideoCaptureOverlayRequest request));
// Const accessors to get the cached variables.
base::TimeDelta min_capture_period() const { return min_capture_period_; }
@@ -169,8 +175,7 @@ class DevToolsVideoConsumerTest : public testing::Test {
consumer_->SetFrameSinkId(kInitialFrameSinkId);
}
- void SimulateFrameCapture(mojo::ScopedSharedBufferHandle buffer,
- uint32_t buffer_size) {
+ void SimulateFrameCapture(base::ReadOnlySharedMemoryRegion data) {
viz::mojom::FrameSinkVideoConsumerFrameCallbacksPtr callbacks_ptr;
callbacks.Bind(mojo::MakeRequest(&callbacks_ptr));
@@ -178,7 +183,7 @@ class DevToolsVideoConsumerTest : public testing::Test {
base::TimeDelta(), base::Value(base::Value::Type::DICTIONARY), kFormat,
kResolution, gfx::Rect(kResolution));
- consumer_->OnFrameCaptured(std::move(buffer), buffer_size, std::move(info),
+ consumer_->OnFrameCaptured(std::move(data), std::move(info),
gfx::Rect(kResolution), gfx::Rect(kResolution),
std::move(callbacks_ptr));
}
@@ -232,48 +237,40 @@ class DevToolsVideoConsumerTest : public testing::Test {
// Tests that the OnFrameFromVideoConsumer callbacks is called when
// OnFrameCaptured is passed a valid buffer with valid mapping.
TEST_F(DevToolsVideoConsumerTest, CallbacksAreCalledWhenBufferValid) {
- // Create a valid buffer.
- const size_t buffer_size =
- media::VideoFrame::AllocationSize(kFormat, kResolution);
- mojo::ScopedSharedBufferHandle buffer =
- mojo::SharedBufferHandle::Create(buffer_size);
-
// On valid buffer the |receiver_| gets a frame via OnFrameFromVideoConsumer.
EXPECT_CALL(receiver_, OnFrameFromVideoConsumerMock(_)).Times(1);
- SimulateFrameCapture(std::move(buffer), buffer_size);
+ auto region = mojo::CreateReadOnlySharedMemoryRegion(
+ media::VideoFrame::AllocationSize(kFormat, kResolution))
+ .region;
+ ASSERT_TRUE(region.IsValid());
+ SimulateFrameCapture(std::move(region));
base::RunLoop().RunUntilIdle();
}
// Tests that only the OnFrameFromVideoConsumer callback is not called when
// OnFrameCaptured is passed an invalid buffer.
-TEST_F(DevToolsVideoConsumerTest, OnFrameCapturedExitEarlyOnInvalidBuffer) {
- // Create an invalid buffer.
- const size_t buffer_size = 0;
- mojo::ScopedSharedBufferHandle buffer =
- mojo::SharedBufferHandle::Create(buffer_size);
-
+TEST_F(DevToolsVideoConsumerTest, CallbackIsNotCalledWhenBufferIsNotValid) {
// On invalid buffer, the |receiver_| doesn't get a frame.
EXPECT_CALL(receiver_, OnFrameFromVideoConsumerMock(_)).Times(0);
- SimulateFrameCapture(std::move(buffer), buffer_size);
+ SimulateFrameCapture(base::ReadOnlySharedMemoryRegion());
base::RunLoop().RunUntilIdle();
}
// Tests that the OnFrameFromVideoConsumer callback is not called when
-// OnFrameCaptured is passed a buffer with invalid mapping.
-TEST_F(DevToolsVideoConsumerTest, OnFrameCapturedExitsOnInvalidMapping) {
- // Create a valid buffer, but change buffer_size to simulate an invalid
- // mapping.
- size_t buffer_size = media::VideoFrame::AllocationSize(kFormat, kResolution);
- mojo::ScopedSharedBufferHandle buffer =
- mojo::SharedBufferHandle::Create(buffer_size);
- buffer_size = 0;
-
+// OnFrameCaptured is passed a buffer with less-than-expected size.
+TEST_F(DevToolsVideoConsumerTest, CallbackIsNotCalledWhenBufferIsTooSmall) {
// On invalid mapping, the |receiver_| doesn't get a frame.
EXPECT_CALL(receiver_, OnFrameFromVideoConsumerMock(_)).Times(0);
- SimulateFrameCapture(std::move(buffer), buffer_size);
+ constexpr size_t too_few_number_of_bytes = 4;
+ ASSERT_LT(too_few_number_of_bytes,
+ media::VideoFrame::AllocationSize(kFormat, kResolution));
+ auto region =
+ mojo::CreateReadOnlySharedMemoryRegion(too_few_number_of_bytes).region;
+ ASSERT_TRUE(region.IsValid());
+ SimulateFrameCapture(std::move(region));
base::RunLoop().RunUntilIdle();
}
diff --git a/chromium/content/browser/devtools/protocol/browser_handler.cc b/chromium/content/browser/devtools/protocol/browser_handler.cc
index 618ca845bad..2c57058886f 100644
--- a/chromium/content/browser/devtools/protocol/browser_handler.cc
+++ b/chromium/content/browser/devtools/protocol/browser_handler.cc
@@ -13,7 +13,11 @@
#include "base/metrics/statistics_recorder.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
+#include "content/browser/devtools/devtools_manager.h"
+#include "content/browser/permissions/permission_controller_impl.h"
+#include "content/public/browser/browser_context.h"
#include "content/public/browser/devtools_agent_host.h"
+#include "content/public/browser/permission_type.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/user_agent.h"
@@ -27,6 +31,24 @@ BrowserHandler::BrowserHandler()
BrowserHandler::~BrowserHandler() {}
+Response BrowserHandler::Disable() {
+ for (auto& browser_context_id : contexts_with_overridden_permissions_) {
+ content::BrowserContext* browser_context = nullptr;
+ std::string error;
+ Maybe<std::string> context_id =
+ browser_context_id == "" ? Maybe<std::string>()
+ : Maybe<std::string>(browser_context_id);
+ FindBrowserContext(context_id, &browser_context);
+ if (browser_context) {
+ PermissionControllerImpl* permission_controller =
+ PermissionControllerImpl::FromBrowserContext(browser_context);
+ permission_controller->ResetPermissionOverridesForDevTools();
+ }
+ }
+ contexts_with_overridden_permissions_.clear();
+ return Response::OK();
+}
+
void BrowserHandler::Wire(UberDispatcher* dispatcher) {
Browser::Dispatcher::wire(dispatcher, this);
}
@@ -81,6 +103,47 @@ std::unique_ptr<Browser::Histogram> Convert(base::HistogramBase& in_histogram,
.Build();
}
+Response FromProtocolPermissionType(
+ const protocol::Browser::PermissionType& type,
+ PermissionType* out_type) {
+ if (type == protocol::Browser::PermissionTypeEnum::Notifications) {
+ *out_type = PermissionType::NOTIFICATIONS;
+ } else if (type == protocol::Browser::PermissionTypeEnum::Geolocation) {
+ *out_type = PermissionType::GEOLOCATION;
+ } else if (type ==
+ protocol::Browser::PermissionTypeEnum::ProtectedMediaIdentifier) {
+ *out_type = PermissionType::PROTECTED_MEDIA_IDENTIFIER;
+ } else if (type == protocol::Browser::PermissionTypeEnum::Midi) {
+ *out_type = PermissionType::MIDI;
+ } else if (type == protocol::Browser::PermissionTypeEnum::MidiSysex) {
+ *out_type = PermissionType::MIDI_SYSEX;
+ } else if (type == protocol::Browser::PermissionTypeEnum::DurableStorage) {
+ *out_type = PermissionType::DURABLE_STORAGE;
+ } else if (type == protocol::Browser::PermissionTypeEnum::AudioCapture) {
+ *out_type = PermissionType::AUDIO_CAPTURE;
+ } else if (type == protocol::Browser::PermissionTypeEnum::VideoCapture) {
+ *out_type = PermissionType::VIDEO_CAPTURE;
+ } else if (type == protocol::Browser::PermissionTypeEnum::BackgroundSync) {
+ *out_type = PermissionType::BACKGROUND_SYNC;
+ } else if (type == protocol::Browser::PermissionTypeEnum::Flash) {
+ *out_type = PermissionType::FLASH;
+ } else if (type == protocol::Browser::PermissionTypeEnum::Sensors) {
+ *out_type = PermissionType::SENSORS;
+ } else if (type ==
+ protocol::Browser::PermissionTypeEnum::AccessibilityEvents) {
+ *out_type = PermissionType::ACCESSIBILITY_EVENTS;
+ } else if (type == protocol::Browser::PermissionTypeEnum::ClipboardRead) {
+ *out_type = PermissionType::CLIPBOARD_READ;
+ } else if (type == protocol::Browser::PermissionTypeEnum::ClipboardWrite) {
+ *out_type = PermissionType::CLIPBOARD_WRITE;
+ } else if (type == protocol::Browser::PermissionTypeEnum::PaymentHandler) {
+ *out_type = PermissionType::PAYMENT_HANDLER;
+ } else {
+ return Response::InvalidParams("Unknown permission type: " + type);
+ }
+ return Response::OK();
+}
+
} // namespace
Response BrowserHandler::GetHistograms(
@@ -101,6 +164,72 @@ Response BrowserHandler::GetHistograms(
return Response::OK();
}
+Response BrowserHandler::FindBrowserContext(
+ const Maybe<std::string>& browser_context_id,
+ BrowserContext** browser_context) {
+ DevToolsManagerDelegate* delegate =
+ DevToolsManager::GetInstance()->delegate();
+ if (!delegate)
+ return Response::Error("Browser context management is not supported.");
+ if (!browser_context_id.isJust()) {
+ *browser_context = delegate->GetDefaultBrowserContext();
+ if (*browser_context == nullptr)
+ return Response::Error("Browser context management is not supported.");
+ return Response::OK();
+ }
+
+ std::string context_id = browser_context_id.fromJust();
+ for (auto* context : delegate->GetBrowserContexts()) {
+ if (context->UniqueId() == context_id) {
+ *browser_context = context;
+ return Response::OK();
+ }
+ }
+ return Response::InvalidParams("Failed to find browser context for id " +
+ context_id);
+}
+
+Response BrowserHandler::GrantPermissions(
+ const std::string& origin,
+ std::unique_ptr<protocol::Array<protocol::Browser::PermissionType>>
+ permissions,
+ Maybe<std::string> browser_context_id) {
+ BrowserContext* browser_context = nullptr;
+ Response response = FindBrowserContext(browser_context_id, &browser_context);
+ if (!response.isSuccess())
+ return response;
+ PermissionControllerImpl::PermissionOverrides overrides;
+ for (size_t i = 0; i < permissions->length(); ++i) {
+ PermissionType type;
+ Response type_response =
+ FromProtocolPermissionType(permissions->get(i), &type);
+ if (!type_response.isSuccess())
+ return type_response;
+ overrides.insert(type);
+ }
+
+ PermissionControllerImpl* permission_controller =
+ PermissionControllerImpl::FromBrowserContext(browser_context);
+ GURL url = GURL(origin).GetOrigin();
+ permission_controller->SetPermissionOverridesForDevTools(url, overrides);
+ contexts_with_overridden_permissions_.insert(
+ browser_context_id.fromMaybe(""));
+ return Response::OK();
+}
+
+Response BrowserHandler::ResetPermissions(
+ Maybe<std::string> browser_context_id) {
+ BrowserContext* browser_context = nullptr;
+ Response response = FindBrowserContext(browser_context_id, &browser_context);
+ if (!response.isSuccess())
+ return response;
+ PermissionControllerImpl* permission_controller =
+ PermissionControllerImpl::FromBrowserContext(browser_context);
+ permission_controller->ResetPermissionOverridesForDevTools();
+ contexts_with_overridden_permissions_.erase(browser_context_id.fromMaybe(""));
+ return Response::OK();
+}
+
Response BrowserHandler::GetHistogram(
const std::string& in_name,
const Maybe<bool> in_delta,
@@ -119,8 +248,8 @@ Response BrowserHandler::GetHistogram(
}
Response BrowserHandler::GetBrowserCommandLine(
- std::unique_ptr<protocol::Array<String>>* arguments) {
- *arguments = protocol::Array<String>::create();
+ std::unique_ptr<protocol::Array<std::string>>* arguments) {
+ *arguments = protocol::Array<std::string>::create();
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
// The commandline is potentially sensitive, only return it if it
// contains kEnableAutomation.
diff --git a/chromium/content/browser/devtools/protocol/browser_handler.h b/chromium/content/browser/devtools/protocol/browser_handler.h
index 9ced0243186..5175b0ffb41 100644
--- a/chromium/content/browser/devtools/protocol/browser_handler.h
+++ b/chromium/content/browser/devtools/protocol/browser_handler.h
@@ -5,11 +5,15 @@
#ifndef CONTENT_BROWSER_DEVTOOLS_PROTOCOL_BROWSER_HANDLER_H_
#define CONTENT_BROWSER_DEVTOOLS_PROTOCOL_BROWSER_HANDLER_H_
+#include "base/containers/flat_set.h"
#include "base/macros.h"
#include "content/browser/devtools/protocol/browser.h"
#include "content/browser/devtools/protocol/devtools_domain_handler.h"
namespace content {
+
+class BrowserContext;
+
namespace protocol {
class BrowserHandler : public DevToolsDomainHandler, public Browser::Backend {
@@ -19,6 +23,8 @@ class BrowserHandler : public DevToolsDomainHandler, public Browser::Backend {
void Wire(UberDispatcher* dispatcher) override;
+ Response Disable() override;
+
// Protocol methods.
Response GetVersion(std::string* protocol_version,
std::string* product,
@@ -37,9 +43,22 @@ class BrowserHandler : public DevToolsDomainHandler, public Browser::Backend {
std::unique_ptr<Browser::Histogram>* out_histogram) override;
Response GetBrowserCommandLine(
- std::unique_ptr<protocol::Array<String>>* arguments) override;
+ std::unique_ptr<protocol::Array<std::string>>* arguments) override;
+
+ Response GrantPermissions(
+ const std::string& origin,
+ std::unique_ptr<protocol::Array<protocol::Browser::PermissionType>>
+ permissions,
+ Maybe<std::string> browser_context_id) override;
+
+ Response ResetPermissions(Maybe<std::string> browser_context_id) override;
private:
+ Response FindBrowserContext(const Maybe<std::string>& browser_context_id,
+ BrowserContext** browser_context);
+
+ base::flat_set<std::string> contexts_with_overridden_permissions_;
+
DISALLOW_COPY_AND_ASSIGN(BrowserHandler);
};
diff --git a/chromium/content/browser/devtools/protocol/devtools_download_manager_delegate.cc b/chromium/content/browser/devtools/protocol/devtools_download_manager_delegate.cc
index f71a5bf4ab3..bfaa525d37e 100644
--- a/chromium/content/browser/devtools/protocol/devtools_download_manager_delegate.cc
+++ b/chromium/content/browser/devtools/protocol/devtools_download_manager_delegate.cc
@@ -6,7 +6,7 @@
#include "base/bind.h"
#include "base/files/file_util.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_restrictions.h"
#include "content/browser/devtools/protocol/devtools_download_manager_helper.h"
#include "content/public/browser/browser_context.h"
diff --git a/chromium/content/browser/devtools/protocol/devtools_download_manager_helper.cc b/chromium/content/browser/devtools/protocol/devtools_download_manager_helper.cc
index d1b63f6f571..736caf3b557 100644
--- a/chromium/content/browser/devtools/protocol/devtools_download_manager_helper.cc
+++ b/chromium/content/browser/devtools/protocol/devtools_download_manager_helper.cc
@@ -6,9 +6,6 @@
#include "base/bind.h"
-DEFINE_WEB_CONTENTS_USER_DATA_KEY(
- content::protocol::DevToolsDownloadManagerHelper);
-
namespace content {
namespace protocol {
diff --git a/chromium/content/browser/devtools/protocol/devtools_protocol_browsertest.cc b/chromium/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
index aa29868d07d..c66b3c9454a 100644
--- a/chromium/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
+++ b/chromium/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
@@ -11,12 +11,8 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/command_line.h"
-#include "base/json/json_reader.h"
-#include "base/json/json_writer.h"
#include "base/logging.h"
-#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
#include "base/sys_info.h"
#include "base/values.h"
#include "build/build_config.h"
@@ -24,13 +20,13 @@
#include "components/download/public/common/download_file_impl.h"
#include "components/download/public/common/download_task_runner.h"
#include "content/browser/devtools/protocol/devtools_download_manager_delegate.h"
+#include "content/browser/devtools/protocol/devtools_protocol_test_support.h"
#include "content/browser/download/download_manager_impl.h"
#include "content/browser/frame_host/interstitial_page_impl.h"
#include "content/browser/frame_host/navigator.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/download_manager.h"
#include "content/public/browser/interstitial_page_delegate.h"
#include "content/public/browser/javascript_dialog_manager.h"
@@ -46,7 +42,6 @@
#include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h"
#include "content/public/test/browser_test_utils.h"
-#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/download_test_observer.h"
#include "content/public/test/slow_download_http_response.h"
@@ -55,10 +50,6 @@
#include "content/shell/browser/shell_browser_context.h"
#include "content/shell/browser/shell_content_browser_client.h"
#include "content/shell/browser/shell_download_manager_delegate.h"
-#include "content/test/content_browser_test_utils_internal.h"
-#include "net/dns/mock_host_resolver.h"
-#include "net/test/cert_test_util.h"
-#include "net/test/embedded_test_server/embedded_test_server.h"
#include "services/network/public/cpp/features.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "third_party/skia/include/core/SkBitmap.h"
@@ -84,10 +75,6 @@ namespace content {
namespace {
-const char kIdParam[] = "id";
-const char kMethodParam[] = "method";
-const char kParamsParam[] = "params";
-
// If |params| contains an explanation with a non-empty certificate list,
// returns true and points |certificate| to the certificate list of the first
// explanation that contains a nonempty certificate list. Otherwise returns
@@ -178,326 +165,6 @@ class TestJavaScriptDialogManager : public JavaScriptDialogManager,
} // namespace
-class DevToolsProtocolTest : public ContentBrowserTest,
- public DevToolsAgentHostClient,
- public WebContentsDelegate {
- public:
- typedef base::Callback<bool(base::DictionaryValue*)> NotificationMatcher;
-
- DevToolsProtocolTest()
- : last_sent_id_(0),
- waiting_for_command_result_id_(0),
- in_dispatch_(false),
- agent_host_can_close_(false) {}
-
- void SetUpOnMainThread() override {
- host_resolver()->AddRule("*", "127.0.0.1");
- }
-
- protected:
- // WebContentsDelegate methods:
- bool DidAddMessageToConsole(WebContents* source,
- int32_t level,
- const base::string16& message,
- int32_t line_no,
- const base::string16& source_id) override {
- console_messages_.push_back(base::UTF16ToUTF8(message));
- return true;
- }
-
- blink::WebSecurityStyle GetSecurityStyle(
- content::WebContents* web_contents,
- content::SecurityStyleExplanations* security_style_explanations)
- override {
- security_style_explanations->secure_explanations.push_back(
- SecurityStyleExplanation(
- "an explanation title", "an explanation summary",
- "an explanation description", cert_,
- blink::WebMixedContentContextType::kNotMixedContent));
- return blink::kWebSecurityStyleNeutral;
- }
-
- base::DictionaryValue* SendCommand(
- const std::string& method,
- std::unique_ptr<base::DictionaryValue> params) {
- return SendCommand(method, std::move(params), true);
- }
-
- base::DictionaryValue* SendCommand(
- const std::string& method,
- std::unique_ptr<base::DictionaryValue> params,
- bool wait) {
- in_dispatch_ = true;
- base::DictionaryValue command;
- command.SetInteger(kIdParam, ++last_sent_id_);
- command.SetString(kMethodParam, method);
- if (params)
- command.Set(kParamsParam, std::move(params));
-
- std::string json_command;
- base::JSONWriter::Write(command, &json_command);
- agent_host_->DispatchProtocolMessage(this, json_command);
- // Some messages are dispatched synchronously.
- // Only run loop if we are not finished yet.
- if (in_dispatch_ && wait) {
- WaitForResponse();
- in_dispatch_ = false;
- return result_.get();
- }
- in_dispatch_ = false;
- return result_.get();
- }
-
- void WaitForResponse() {
- waiting_for_command_result_id_ = last_sent_id_;
- base::RunLoop().Run();
- }
-
- bool HasValue(const std::string& path) {
- base::Value* value = nullptr;
- return result_->Get(path, &value);
- }
-
- bool HasListItem(const std::string& path_to_list,
- const std::string& name,
- const std::string& value) {
- base::ListValue* list;
- if (!result_->GetList(path_to_list, &list))
- return false;
-
- for (size_t i = 0; i != list->GetSize(); i++) {
- base::DictionaryValue* item;
- if (!list->GetDictionary(i, &item))
- return false;
- std::string id;
- if (!item->GetString(name, &id))
- return false;
- if (id == value)
- return true;
- }
- return false;
- }
-
- void Attach() {
- agent_host_ = DevToolsAgentHost::GetOrCreateFor(shell()->web_contents());
- agent_host_->AttachClient(this);
- shell()->web_contents()->SetDelegate(this);
- }
-
- void AttachToBrowserTarget() {
- // Tethering domain is not used in tests.
- agent_host_ = DevToolsAgentHost::CreateForBrowser(
- nullptr, DevToolsAgentHost::CreateServerSocketCallback());
- agent_host_->AttachClient(this);
- shell()->web_contents()->SetDelegate(this);
- }
-
- void Detach() {
- if (agent_host_) {
- agent_host_->DetachClient(this);
- agent_host_ = nullptr;
- }
- }
-
- void TearDownOnMainThread() override { Detach(); }
-
- std::unique_ptr<base::DictionaryValue> WaitForNotification(
- const std::string& notification) {
- return WaitForNotification(notification, false);
- }
-
- std::unique_ptr<base::DictionaryValue> WaitForNotification(
- const std::string& notification,
- bool allow_existing) {
- if (allow_existing) {
- for (size_t i = 0; i < notifications_.size(); i++) {
- if (notifications_[i] == notification) {
- std::unique_ptr<base::DictionaryValue> result =
- std::move(notification_params_[i]);
- notifications_.erase(notifications_.begin() + i);
- notification_params_.erase(notification_params_.begin() + i);
- return result;
- }
- }
- }
-
- waiting_for_notification_ = notification;
- RunMessageLoop();
- return std::move(waiting_for_notification_params_);
- }
-
- // Waits for a notification whose params, when passed to |matcher|, returns
- // true. Existing notifications are allowed.
- std::unique_ptr<base::DictionaryValue> WaitForMatchingNotification(
- const std::string& notification,
- const NotificationMatcher& matcher) {
- for (size_t i = 0; i < notifications_.size(); i++) {
- if (notifications_[i] == notification &&
- matcher.Run(notification_params_[i].get())) {
- std::unique_ptr<base::DictionaryValue> result =
- std::move(notification_params_[i]);
- notifications_.erase(notifications_.begin() + i);
- notification_params_.erase(notification_params_.begin() + i);
- return result;
- }
- }
-
- waiting_for_notification_ = notification;
- waiting_for_notification_matcher_ = matcher;
- RunMessageLoop();
- return std::move(waiting_for_notification_params_);
- }
-
- void ClearNotifications() {
- notifications_.clear();
- notification_params_.clear();
- }
-
- struct ExpectedNavigation {
- std::string url;
- bool is_redirect;
- bool abort;
- };
-
- std::string RemovePort(const GURL& url) {
- GURL::Replacements remove_port;
- remove_port.ClearPort();
- return url.ReplaceComponents(remove_port).spec();
- }
-
- // Waits for the expected navigations to occur in any order. If an expected
- // navigation occurs, Network.continueInterceptedRequest is called with the
- // specified navigation_response to either allow it to proceed or to cancel
- // it.
- void ProcessNavigationsAnyOrder(
- std::vector<ExpectedNavigation> expected_navigations) {
- std::unique_ptr<base::DictionaryValue> params;
- while (!expected_navigations.empty()) {
- std::unique_ptr<base::DictionaryValue> params =
- WaitForNotification("Network.requestIntercepted");
-
- std::string interception_id;
- ASSERT_TRUE(params->GetString("interceptionId", &interception_id));
- bool is_redirect = params->HasKey("redirectUrl");
- bool is_navigation;
- ASSERT_TRUE(params->GetBoolean("isNavigationRequest", &is_navigation));
- std::string resource_type;
- ASSERT_TRUE(params->GetString("resourceType", &resource_type));
- std::string url;
- ASSERT_TRUE(params->GetString("request.url", &url));
- if (is_redirect)
- ASSERT_TRUE(params->GetString("redirectUrl", &url));
- // The url will typically have a random port which we want to remove.
- url = RemovePort(GURL(url));
-
- if (!is_navigation) {
- params.reset(new base::DictionaryValue());
- params->SetString("interceptionId", interception_id);
- SendCommand("Network.continueInterceptedRequest", std::move(params),
- false);
- continue;
- }
-
- bool navigation_was_expected = false;
- for (auto it = expected_navigations.begin();
- it != expected_navigations.end(); it++) {
- if (url != it->url || is_redirect != it->is_redirect)
- continue;
-
- params.reset(new base::DictionaryValue());
- params->SetString("interceptionId", interception_id);
- if (it->abort)
- params->SetString("errorReason", "Aborted");
- SendCommand("Network.continueInterceptedRequest", std::move(params),
- false);
-
- navigation_was_expected = true;
- expected_navigations.erase(it);
- break;
- }
- EXPECT_TRUE(navigation_was_expected)
- << "url = " << url << "is_redirect = " << is_redirect;
- }
- }
-
- std::vector<std::string> GetAllFrameUrls() {
- std::vector<std::string> urls;
- for (RenderFrameHost* render_frame_host :
- shell()->web_contents()->GetAllFrames()) {
- urls.push_back(RemovePort(render_frame_host->GetLastCommittedURL()));
- }
- return urls;
- }
-
- void set_agent_host_can_close() { agent_host_can_close_ = true; }
-
- void SetSecurityExplanationCert(
- const scoped_refptr<net::X509Certificate>& cert) {
- cert_ = cert;
- }
-
- std::unique_ptr<base::DictionaryValue> result_;
- scoped_refptr<DevToolsAgentHost> agent_host_;
- int last_sent_id_;
- std::vector<int> result_ids_;
- std::vector<std::string> notifications_;
- std::vector<std::string> console_messages_;
- std::vector<std::unique_ptr<base::DictionaryValue>> notification_params_;
-
- private:
- void DispatchProtocolMessage(DevToolsAgentHost* agent_host,
- const std::string& message) override {
- std::unique_ptr<base::DictionaryValue> root(
- static_cast<base::DictionaryValue*>(
- base::JSONReader::Read(message).release()));
- int id;
- if (root->GetInteger("id", &id)) {
- result_ids_.push_back(id);
- base::DictionaryValue* result;
- ASSERT_TRUE(root->GetDictionary("result", &result));
- result_.reset(result->DeepCopy());
- in_dispatch_ = false;
- if (id && id == waiting_for_command_result_id_) {
- waiting_for_command_result_id_ = 0;
- base::RunLoop::QuitCurrentDeprecated();
- }
- } else {
- std::string notification;
- EXPECT_TRUE(root->GetString("method", &notification));
- notifications_.push_back(notification);
- base::DictionaryValue* params;
- if (root->GetDictionary("params", &params)) {
- notification_params_.push_back(params->CreateDeepCopy());
- } else {
- notification_params_.push_back(
- base::WrapUnique(new base::DictionaryValue()));
- }
- if (waiting_for_notification_ == notification &&
- (waiting_for_notification_matcher_.is_null() ||
- waiting_for_notification_matcher_.Run(
- notification_params_[notification_params_.size() - 1].get()))) {
- waiting_for_notification_ = std::string();
- waiting_for_notification_matcher_ = NotificationMatcher();
- waiting_for_notification_params_ = base::WrapUnique(
- notification_params_[notification_params_.size() - 1]->DeepCopy());
- base::RunLoop::QuitCurrentDeprecated();
- }
- }
- }
-
- void AgentHostClosed(DevToolsAgentHost* agent_host) override {
- if (!agent_host_can_close_)
- NOTREACHED();
- }
-
- std::string waiting_for_notification_;
- NotificationMatcher waiting_for_notification_matcher_;
- std::unique_ptr<base::DictionaryValue> waiting_for_notification_params_;
- int waiting_for_command_result_id_;
- bool in_dispatch_;
- bool agent_host_can_close_;
- scoped_refptr<net::X509Certificate> cert_;
-};
class TestInterstitialDelegate : public InterstitialPageDelegate {
private:
@@ -2438,7 +2105,7 @@ class DevToolsDownloadContentTest : public DevToolsProtocolTest {
std::string file_contents;
{
- base::ThreadRestrictions::ScopedAllowIO allow_io_during_test_verification;
+ base::ScopedAllowBlockingForTesting allow_blocking;
bool read = base::ReadFileToString(path, &file_contents);
EXPECT_TRUE(read) << "Failed reading file: " << path.value() << std::endl;
if (!read)
diff --git a/chromium/content/browser/devtools/protocol/devtools_protocol_test_support.cc b/chromium/content/browser/devtools/protocol/devtools_protocol_test_support.cc
new file mode 100644
index 00000000000..41ba4bc6448
--- /dev/null
+++ b/chromium/content/browser/devtools/protocol/devtools_protocol_test_support.cc
@@ -0,0 +1,285 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/devtools/protocol/devtools_protocol_test_support.h"
+#include "base/json/json_reader.h"
+#include "base/json/json_writer.h"
+#include "base/run_loop.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/public/browser/security_style_explanations.h"
+#include "content/public/test/test_utils.h"
+#include "content/shell/browser/shell.h"
+#include "net/dns/mock_host_resolver.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+
+namespace content {
+
+namespace {
+
+const char kIdParam[] = "id";
+const char kMethodParam[] = "method";
+const char kParamsParam[] = "params";
+
+} // namespace
+
+DevToolsProtocolTest::DevToolsProtocolTest()
+ : last_sent_id_(0),
+ waiting_for_command_result_id_(0),
+ in_dispatch_(false),
+ agent_host_can_close_(false) {}
+
+DevToolsProtocolTest::~DevToolsProtocolTest() = default;
+
+void DevToolsProtocolTest::SetUpOnMainThread() {
+ host_resolver()->AddRule("*", "127.0.0.1");
+}
+
+bool DevToolsProtocolTest::DidAddMessageToConsole(
+ WebContents* source,
+ int32_t level,
+ const base::string16& message,
+ int32_t line_no,
+ const base::string16& source_id) {
+ console_messages_.push_back(base::UTF16ToUTF8(message));
+ return true;
+}
+
+base::DictionaryValue* DevToolsProtocolTest::SendCommand(
+ const std::string& method,
+ std::unique_ptr<base::DictionaryValue> params,
+ bool wait) {
+ in_dispatch_ = true;
+ base::DictionaryValue command;
+ command.SetInteger(kIdParam, ++last_sent_id_);
+ command.SetString(kMethodParam, method);
+ if (params)
+ command.Set(kParamsParam, std::move(params));
+
+ std::string json_command;
+ base::JSONWriter::Write(command, &json_command);
+ agent_host_->DispatchProtocolMessage(this, json_command);
+ // Some messages are dispatched synchronously.
+ // Only run loop if we are not finished yet.
+ if (in_dispatch_ && wait) {
+ WaitForResponse();
+ in_dispatch_ = false;
+ return result_.get();
+ }
+ in_dispatch_ = false;
+ return result_.get();
+}
+
+void DevToolsProtocolTest::WaitForResponse() {
+ waiting_for_command_result_id_ = last_sent_id_;
+ RunLoopUpdatingQuitClosure();
+}
+
+bool DevToolsProtocolTest::HasValue(const std::string& path) {
+ base::Value* value = nullptr;
+ return result_->Get(path, &value);
+}
+
+bool DevToolsProtocolTest::HasListItem(const std::string& path_to_list,
+ const std::string& name,
+ const std::string& value) {
+ base::ListValue* list;
+ if (!result_->GetList(path_to_list, &list))
+ return false;
+
+ for (size_t i = 0; i != list->GetSize(); i++) {
+ base::DictionaryValue* item;
+ if (!list->GetDictionary(i, &item))
+ return false;
+ std::string id;
+ if (!item->GetString(name, &id))
+ return false;
+ if (id == value)
+ return true;
+ }
+ return false;
+}
+
+void DevToolsProtocolTest::Attach() {
+ agent_host_ = DevToolsAgentHost::GetOrCreateFor(shell()->web_contents());
+ agent_host_->AttachClient(this);
+ shell()->web_contents()->SetDelegate(this);
+}
+
+void DevToolsProtocolTest::AttachToBrowserTarget() {
+ // Tethering domain is not used in tests.
+ agent_host_ = DevToolsAgentHost::CreateForBrowser(
+ nullptr, DevToolsAgentHost::CreateServerSocketCallback());
+ agent_host_->AttachClient(this);
+ shell()->web_contents()->SetDelegate(this);
+}
+
+void DevToolsProtocolTest::TearDownOnMainThread() {
+ Detach();
+}
+
+std::unique_ptr<base::DictionaryValue>
+DevToolsProtocolTest::WaitForNotification(const std::string& notification,
+ bool allow_existing) {
+ if (allow_existing) {
+ for (size_t i = 0; i < notifications_.size(); i++) {
+ if (notifications_[i] == notification) {
+ std::unique_ptr<base::DictionaryValue> result =
+ std::move(notification_params_[i]);
+ notifications_.erase(notifications_.begin() + i);
+ notification_params_.erase(notification_params_.begin() + i);
+ return result;
+ }
+ }
+ }
+
+ waiting_for_notification_ = notification;
+ RunLoopUpdatingQuitClosure();
+ return std::move(waiting_for_notification_params_);
+}
+
+blink::WebSecurityStyle DevToolsProtocolTest::GetSecurityStyle(
+ content::WebContents* web_contents,
+ content::SecurityStyleExplanations* security_style_explanations) {
+ security_style_explanations->secure_explanations.push_back(
+ SecurityStyleExplanation(
+ "an explanation title", "an explanation summary",
+ "an explanation description", cert_,
+ blink::WebMixedContentContextType::kNotMixedContent));
+ return blink::kWebSecurityStyleNeutral;
+}
+
+std::unique_ptr<base::DictionaryValue>
+DevToolsProtocolTest::WaitForMatchingNotification(
+ const std::string& notification,
+ const NotificationMatcher& matcher) {
+ for (size_t i = 0; i < notifications_.size(); i++) {
+ if (notifications_[i] == notification &&
+ matcher.Run(notification_params_[i].get())) {
+ std::unique_ptr<base::DictionaryValue> result =
+ std::move(notification_params_[i]);
+ notifications_.erase(notifications_.begin() + i);
+ notification_params_.erase(notification_params_.begin() + i);
+ return result;
+ }
+ }
+
+ waiting_for_notification_ = notification;
+ waiting_for_notification_matcher_ = matcher;
+ RunLoopUpdatingQuitClosure();
+ return std::move(waiting_for_notification_params_);
+}
+
+void DevToolsProtocolTest::ProcessNavigationsAnyOrder(
+ std::vector<ExpectedNavigation> expected_navigations) {
+ std::unique_ptr<base::DictionaryValue> params;
+ while (!expected_navigations.empty()) {
+ std::unique_ptr<base::DictionaryValue> params =
+ WaitForNotification("Network.requestIntercepted");
+
+ std::string interception_id;
+ ASSERT_TRUE(params->GetString("interceptionId", &interception_id));
+ bool is_redirect = params->HasKey("redirectUrl");
+ bool is_navigation;
+ ASSERT_TRUE(params->GetBoolean("isNavigationRequest", &is_navigation));
+ std::string resource_type;
+ ASSERT_TRUE(params->GetString("resourceType", &resource_type));
+ std::string url;
+ ASSERT_TRUE(params->GetString("request.url", &url));
+ if (is_redirect)
+ ASSERT_TRUE(params->GetString("redirectUrl", &url));
+ // The url will typically have a random port which we want to remove.
+ url = RemovePort(GURL(url));
+
+ if (!is_navigation) {
+ params.reset(new base::DictionaryValue());
+ params->SetString("interceptionId", interception_id);
+ SendCommand("Network.continueInterceptedRequest", std::move(params),
+ false);
+ continue;
+ }
+
+ bool navigation_was_expected = false;
+ for (auto it = expected_navigations.begin();
+ it != expected_navigations.end(); it++) {
+ if (url != it->url || is_redirect != it->is_redirect)
+ continue;
+
+ params.reset(new base::DictionaryValue());
+ params->SetString("interceptionId", interception_id);
+ if (it->abort)
+ params->SetString("errorReason", "Aborted");
+ SendCommand("Network.continueInterceptedRequest", std::move(params),
+ false);
+
+ navigation_was_expected = true;
+ expected_navigations.erase(it);
+ break;
+ }
+ EXPECT_TRUE(navigation_was_expected)
+ << "url = " << url << "is_redirect = " << is_redirect;
+ }
+}
+
+void DevToolsProtocolTest::RunLoopUpdatingQuitClosure() {
+ base::RunLoop run_loop;
+ run_loop_quit_closure_ = run_loop.QuitClosure();
+ run_loop.Run();
+}
+
+void DevToolsProtocolTest::DispatchProtocolMessage(
+ DevToolsAgentHost* agent_host,
+ const std::string& message) {
+ std::unique_ptr<base::DictionaryValue> root(
+ static_cast<base::DictionaryValue*>(
+ base::JSONReader::Read(message).release()));
+ int id;
+ if (root->GetInteger("id", &id)) {
+ result_ids_.push_back(id);
+ base::DictionaryValue* result;
+ ASSERT_TRUE(root->GetDictionary("result", &result));
+ result_.reset(result->DeepCopy());
+ in_dispatch_ = false;
+ if (id && id == waiting_for_command_result_id_) {
+ waiting_for_command_result_id_ = 0;
+ std::move(run_loop_quit_closure_).Run();
+ }
+ } else {
+ std::string notification;
+ EXPECT_TRUE(root->GetString("method", &notification));
+ notifications_.push_back(notification);
+ base::DictionaryValue* params;
+ if (root->GetDictionary("params", &params)) {
+ notification_params_.push_back(params->CreateDeepCopy());
+ } else {
+ notification_params_.push_back(
+ base::WrapUnique(new base::DictionaryValue()));
+ }
+ if (waiting_for_notification_ == notification &&
+ (waiting_for_notification_matcher_.is_null() ||
+ waiting_for_notification_matcher_.Run(
+ notification_params_[notification_params_.size() - 1].get()))) {
+ waiting_for_notification_ = std::string();
+ waiting_for_notification_matcher_ = NotificationMatcher();
+ waiting_for_notification_params_ = base::WrapUnique(
+ notification_params_[notification_params_.size() - 1]->DeepCopy());
+ std::move(run_loop_quit_closure_).Run();
+ }
+ }
+}
+
+std::vector<std::string> DevToolsProtocolTest::GetAllFrameUrls() {
+ std::vector<std::string> urls;
+ for (RenderFrameHost* render_frame_host :
+ shell()->web_contents()->GetAllFrames()) {
+ urls.push_back(RemovePort(render_frame_host->GetLastCommittedURL()));
+ }
+ return urls;
+}
+
+void DevToolsProtocolTest::AgentHostClosed(DevToolsAgentHost* agent_host) {
+ if (!agent_host_can_close_)
+ NOTREACHED();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/devtools/protocol/devtools_protocol_test_support.h b/chromium/content/browser/devtools/protocol/devtools_protocol_test_support.h
new file mode 100644
index 00000000000..15e5d23afce
--- /dev/null
+++ b/chromium/content/browser/devtools/protocol/devtools_protocol_test_support.h
@@ -0,0 +1,150 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_DEVTOOLS_PROTOCOL_DEVTOOLS_PROTOCOL_TEST_SUPPORT_H_
+#define CONTENT_BROWSER_DEVTOOLS_PROTOCOL_DEVTOOLS_PROTOCOL_TEST_SUPPORT_H_
+
+#include <memory>
+#include <string>
+#include "base/callback.h"
+#include "base/values.h"
+#include "content/public/browser/devtools_agent_host.h"
+#include "content/public/browser/web_contents_delegate.h"
+#include "content/public/test/content_browser_test.h"
+#include "net/test/cert_test_util.h"
+
+namespace content {
+
+class DevToolsProtocolTest : public ContentBrowserTest,
+ public DevToolsAgentHostClient,
+ public WebContentsDelegate {
+ public:
+ typedef base::RepeatingCallback<bool(base::DictionaryValue*)>
+ NotificationMatcher;
+
+ DevToolsProtocolTest();
+ ~DevToolsProtocolTest() override;
+
+ void SetUpOnMainThread() override;
+
+ protected:
+ // WebContentsDelegate methods:
+ bool DidAddMessageToConsole(WebContents* source,
+ int32_t level,
+ const base::string16& message,
+ int32_t line_no,
+ const base::string16& source_id) override;
+
+ blink::WebSecurityStyle GetSecurityStyle(
+ content::WebContents* web_contents,
+ content::SecurityStyleExplanations* security_style_explanations) override;
+
+ base::DictionaryValue* SendCommand(
+ const std::string& method,
+ std::unique_ptr<base::DictionaryValue> params) {
+ return SendCommand(method, std::move(params), true);
+ }
+
+ base::DictionaryValue* SendCommand(
+ const std::string& method,
+ std::unique_ptr<base::DictionaryValue> params,
+ bool wait);
+
+ void WaitForResponse();
+
+ bool HasValue(const std::string& path);
+
+ bool HasListItem(const std::string& path_to_list,
+ const std::string& name,
+ const std::string& value);
+
+ void Attach();
+
+ void AttachToBrowserTarget();
+
+ void Detach() {
+ if (agent_host_) {
+ agent_host_->DetachClient(this);
+ agent_host_ = nullptr;
+ }
+ }
+
+ void TearDownOnMainThread() override;
+
+ std::unique_ptr<base::DictionaryValue> WaitForNotification(
+ const std::string& notification) {
+ return WaitForNotification(notification, false);
+ }
+
+ std::unique_ptr<base::DictionaryValue> WaitForNotification(
+ const std::string& notification,
+ bool allow_existing);
+
+ // Waits for a notification whose params, when passed to |matcher|, returns
+ // true. Existing notifications are allowed.
+ std::unique_ptr<base::DictionaryValue> WaitForMatchingNotification(
+ const std::string& notification,
+ const NotificationMatcher& matcher);
+
+ void ClearNotifications() {
+ notifications_.clear();
+ notification_params_.clear();
+ }
+
+ struct ExpectedNavigation {
+ std::string url;
+ bool is_redirect;
+ bool abort;
+ };
+
+ std::string RemovePort(const GURL& url) {
+ GURL::Replacements remove_port;
+ remove_port.ClearPort();
+ return url.ReplaceComponents(remove_port).spec();
+ }
+
+ // Waits for the expected navigations to occur in any order. If an expected
+ // navigation occurs, Network.continueInterceptedRequest is called with the
+ // specified navigation_response to either allow it to proceed or to cancel
+ // it.
+ void ProcessNavigationsAnyOrder(
+ std::vector<ExpectedNavigation> expected_navigations);
+
+ std::vector<std::string> GetAllFrameUrls();
+
+ void set_agent_host_can_close() { agent_host_can_close_ = true; }
+
+ void SetSecurityExplanationCert(
+ const scoped_refptr<net::X509Certificate>& cert) {
+ cert_ = cert;
+ }
+
+ std::unique_ptr<base::DictionaryValue> result_;
+ scoped_refptr<DevToolsAgentHost> agent_host_;
+ int last_sent_id_;
+ std::vector<int> result_ids_;
+ std::vector<std::string> notifications_;
+ std::vector<std::string> console_messages_;
+ std::vector<std::unique_ptr<base::DictionaryValue>> notification_params_;
+
+ private:
+ void RunLoopUpdatingQuitClosure();
+ void DispatchProtocolMessage(DevToolsAgentHost* agent_host,
+ const std::string& message) override;
+
+ void AgentHostClosed(DevToolsAgentHost* agent_host) override;
+
+ std::string waiting_for_notification_;
+ NotificationMatcher waiting_for_notification_matcher_;
+ std::unique_ptr<base::DictionaryValue> waiting_for_notification_params_;
+ int waiting_for_command_result_id_;
+ bool in_dispatch_;
+ bool agent_host_can_close_;
+ scoped_refptr<net::X509Certificate> cert_;
+ base::OnceClosure run_loop_quit_closure_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_DEVTOOLS_PROTOCOL_DEVTOOLS_PROTOCOL_TEST_SUPPORT_H_
diff --git a/chromium/content/browser/devtools/protocol/input_handler.cc b/chromium/content/browser/devtools/protocol/input_handler.cc
index e6b74e54193..d89856b04b3 100644
--- a/chromium/content/browser/devtools/protocol/input_handler.cc
+++ b/chromium/content/browser/devtools/protocol/input_handler.cc
@@ -19,11 +19,13 @@
#include "content/common/input/synthetic_pinch_gesture_params.h"
#include "content/common/input/synthetic_smooth_scroll_gesture_params.h"
#include "content/common/input/synthetic_tap_gesture_params.h"
+#include "content/public/browser/web_contents.h"
#include "ui/events/base_event_utils.h"
#include "ui/events/blink/web_input_event_traits.h"
#include "ui/events/gesture_detection/gesture_provider_config_helper.h"
#include "ui/events/keycodes/dom/keycode_converter.h"
#include "ui/gfx/geometry/point.h"
+#include "ui/gfx/range/range.h"
namespace content {
namespace protocol {
@@ -421,11 +423,18 @@ void InputHandler::SetRenderer(int process_host_id,
if (frame_host == host_)
return;
ClearInputState();
- if (host_ && ignore_input_events_)
- host_->GetRenderWidgetHost()->SetIgnoreInputEvents(false);
+
+ WebContents* old_web_contents = WebContents::FromRenderFrameHost(host_);
+ WebContents* new_web_contents = WebContents::FromRenderFrameHost(frame_host);
+
host_ = frame_host;
- if (host_ && ignore_input_events_)
- host_->GetRenderWidgetHost()->SetIgnoreInputEvents(true);
+
+ if (ignore_input_events_ && old_web_contents != new_web_contents) {
+ if (old_web_contents)
+ old_web_contents->SetIgnoreInputEvents(false);
+ if (new_web_contents)
+ new_web_contents->SetIgnoreInputEvents(true);
+ }
}
void InputHandler::Wire(UberDispatcher* dispatcher) {
@@ -438,8 +447,9 @@ void InputHandler::OnPageScaleFactorChanged(float page_scale_factor) {
Response InputHandler::Disable() {
ClearInputState();
- if (host_ && ignore_input_events_)
- host_->GetRenderWidgetHost()->SetIgnoreInputEvents(false);
+ WebContents* web_contents = WebContents::FromRenderFrameHost(host_);
+ if (web_contents && ignore_input_events_)
+ web_contents->SetIgnoreInputEvents(false);
ignore_input_events_ = false;
touch_points_.clear();
return Response::OK();
@@ -535,6 +545,31 @@ void InputHandler::DispatchKeyEvent(
EnsureInjector(widget_host)->InjectKeyboardEvent(event, std::move(callback));
}
+void InputHandler::InsertText(const std::string& text,
+ std::unique_ptr<InsertTextCallback> callback) {
+ base::string16 text16 = base::UTF8ToUTF16(text);
+ base::OnceClosure closure =
+ base::BindOnce(&InsertTextCallback::sendSuccess, std::move(callback));
+
+ if (!host_ || !host_->GetRenderWidgetHost()) {
+ callback->sendFailure(Response::InternalError());
+ return;
+ }
+
+ RenderWidgetHostImpl* widget_host = host_->GetRenderWidgetHost();
+ if (!host_->GetParent() && widget_host->delegate()) {
+ RenderWidgetHostImpl* target_host =
+ widget_host->delegate()->GetFocusedRenderWidgetHost(widget_host);
+ if (target_host)
+ widget_host = target_host;
+ }
+
+ widget_host->Focus();
+ widget_host->GetWidgetInputHandler()->ImeCommitText(
+ text16, std::vector<ui::ImeTextSpan>(), gfx::Range::InvalidRange(), 0,
+ std::move(closure));
+}
+
void InputHandler::DispatchMouseEvent(
const std::string& event_type,
double x,
@@ -832,8 +867,9 @@ Response InputHandler::EmulateTouchFromMouseEvent(const std::string& type,
Response InputHandler::SetIgnoreInputEvents(bool ignore) {
ignore_input_events_ = ignore;
- if (host_)
- host_->GetRenderWidgetHost()->SetIgnoreInputEvents(ignore);
+ WebContents* web_contents = WebContents::FromRenderFrameHost(host_);
+ if (web_contents)
+ web_contents->SetIgnoreInputEvents(ignore);
return Response::OK();
}
diff --git a/chromium/content/browser/devtools/protocol/input_handler.h b/chromium/content/browser/devtools/protocol/input_handler.h
index ae8fd55904c..293b7765a86 100644
--- a/chromium/content/browser/devtools/protocol/input_handler.h
+++ b/chromium/content/browser/devtools/protocol/input_handler.h
@@ -56,6 +56,9 @@ class InputHandler : public DevToolsDomainHandler, public Input::Backend {
Maybe<int> location,
std::unique_ptr<DispatchKeyEventCallback> callback) override;
+ void InsertText(const std::string& text,
+ std::unique_ptr<InsertTextCallback> callback) override;
+
void DispatchMouseEvent(
const std::string& type,
double x,
diff --git a/chromium/content/browser/devtools/protocol/memory_handler.cc b/chromium/content/browser/devtools/protocol/memory_handler.cc
index 06a5638dab3..328ecd8aeea 100644
--- a/chromium/content/browser/devtools/protocol/memory_handler.cc
+++ b/chromium/content/browser/devtools/protocol/memory_handler.cc
@@ -4,7 +4,10 @@
#include "content/browser/devtools/protocol/memory_handler.h"
+#include <cinttypes>
+
#include "base/memory/memory_pressure_listener.h"
+#include "base/sampling_heap_profiler/module_cache.h"
#include "base/sampling_heap_profiler/sampling_heap_profiler.h"
#include "base/strings/stringprintf.h"
#include "content/public/browser/render_process_host.h"
@@ -33,15 +36,19 @@ void MemoryHandler::SetRenderer(int process_host_id,
Response MemoryHandler::GetBrowserSamplingProfile(
std::unique_ptr<Memory::SamplingProfile>* out_profile) {
+ base::ModuleCache module_cache;
std::unique_ptr<Array<Memory::SamplingProfileNode>> samples =
Array<Memory::SamplingProfileNode>::create();
std::vector<base::SamplingHeapProfiler::Sample> raw_samples =
- base::SamplingHeapProfiler::GetInstance()->GetSamples(0);
+ base::SamplingHeapProfiler::Get()->GetSamples(0);
for (auto& sample : raw_samples) {
std::unique_ptr<Array<String>> stack = Array<String>::create();
- for (auto* frame : sample.stack)
- stack->addItem(base::StringPrintf("%p", frame));
+ for (const void* frame : sample.stack) {
+ uintptr_t address = reinterpret_cast<uintptr_t>(frame);
+ module_cache.GetModuleForAddress(address); // Populates module_cache.
+ stack->addItem(base::StringPrintf("0x%" PRIxPTR, address));
+ }
samples->addItem(Memory::SamplingProfileNode::Create()
.SetSize(sample.size)
.SetTotal(sample.total)
@@ -49,8 +56,23 @@ Response MemoryHandler::GetBrowserSamplingProfile(
.Build());
}
- *out_profile =
- Memory::SamplingProfile::Create().SetSamples(std::move(samples)).Build();
+ std::unique_ptr<Array<Memory::Module>> modules =
+ Array<Memory::Module>::create();
+ for (const auto* module : module_cache.GetModules()) {
+ modules->addItem(Memory::Module::Create()
+ .SetName(base::StringPrintf(
+ "%" PRIsFP, module->filename.value().c_str()))
+ .SetUuid(module->id)
+ .SetBaseAddress(base::StringPrintf(
+ "0x%" PRIxPTR, module->base_address))
+ .SetSize(static_cast<double>(module->size))
+ .Build());
+ }
+
+ *out_profile = Memory::SamplingProfile::Create()
+ .SetSamples(std::move(samples))
+ .SetModules(std::move(modules))
+ .Build();
return Response::OK();
}
diff --git a/chromium/content/browser/devtools/protocol/page_handler.cc b/chromium/content/browser/devtools/protocol/page_handler.cc
index a55920d878a..92d78224bbe 100644
--- a/chromium/content/browser/devtools/protocol/page_handler.cc
+++ b/chromium/content/browser/devtools/protocol/page_handler.cc
@@ -20,10 +20,9 @@
#include "base/strings/string16.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
-#include "components/viz/common/features.h"
#include "content/browser/devtools/devtools_session.h"
#include "content/browser/devtools/protocol/devtools_download_manager_delegate.h"
#include "content/browser/devtools/protocol/devtools_download_manager_helper.h"
@@ -47,7 +46,6 @@
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/common/browser_side_navigation_policy.h"
-#include "content/public/common/content_features.h"
#include "content/public/common/referrer.h"
#include "content/public/common/result_codes.h"
#include "content/public/common/use_zoom_for_dsf_policy.h"
@@ -61,6 +59,10 @@
#include "ui/gfx/skbitmap_operations.h"
#include "ui/snapshot/snapshot.h"
+#ifdef OS_ANDROID
+#include "content/browser/renderer_host/compositor_impl_android.h"
+#endif
+
namespace content {
namespace protocol {
@@ -118,16 +120,19 @@ std::unique_ptr<Page::ScreencastFrameMetadata> BuildScreencastFrameMetadata(
const gfx::SizeF content_size_dip =
gfx::ScaleSize(gfx::SizeF(surface_size), 1 / device_scale_factor);
float top_offset_dip = top_controls_height * top_controls_shown_ratio;
- if (IsUseZoomForDSFEnabled())
+ gfx::Vector2dF root_scroll_offset_dip = root_scroll_offset;
+ if (IsUseZoomForDSFEnabled()) {
top_offset_dip /= device_scale_factor;
+ root_scroll_offset_dip.Scale(1 / device_scale_factor);
+ }
std::unique_ptr<Page::ScreencastFrameMetadata> page_metadata =
Page::ScreencastFrameMetadata::Create()
.SetPageScaleFactor(page_scale_factor)
.SetOffsetTop(top_offset_dip)
.SetDeviceWidth(content_size_dip.width())
.SetDeviceHeight(content_size_dip.height())
- .SetScrollOffsetX(root_scroll_offset.x())
- .SetScrollOffsetY(root_scroll_offset.y())
+ .SetScrollOffsetX(root_scroll_offset_dip.x())
+ .SetScrollOffsetY(root_scroll_offset_dip.y())
.SetTimestamp(base::Time::Now().ToDoubleT())
.Build();
return page_metadata;
@@ -170,11 +175,16 @@ void GetMetadataFromFrame(const media::VideoFrame& frame,
media::VideoFrameMetadata::ROOT_SCROLL_OFFSET_X, &root_scroll_offset_x);
success &= frame.metadata()->GetDouble(
media::VideoFrameMetadata::ROOT_SCROLL_OFFSET_Y, &root_scroll_offset_y);
+#if defined(OS_ANDROID)
success &= frame.metadata()->GetDouble(
media::VideoFrameMetadata::TOP_CONTROLS_HEIGHT, top_controls_height);
success &= frame.metadata()->GetDouble(
media::VideoFrameMetadata::TOP_CONTROLS_SHOWN_RATIO,
top_controls_shown_ratio);
+#else
+ *top_controls_height = 0.;
+ *top_controls_shown_ratio = 0.;
+#endif // defined(OS_ANDROID)
DCHECK(success);
root_scroll_offset->set_x(root_scroll_offset_x);
@@ -202,9 +212,13 @@ PageHandler::PageHandler(EmulationHandler* emulation_handler)
emulation_handler_(emulation_handler),
observer_(this),
weak_factory_(this) {
- if (base::FeatureList::IsEnabled(features::kVizDisplayCompositor) ||
- base::FeatureList::IsEnabled(
- features::kUseVideoCaptureApiForDevToolsSnapshots)) {
+ bool create_video_consumer = true;
+#ifdef OS_ANDROID
+ // Video capture doesn't work on Android WebView. Use CopyFromSurface instead.
+ if (!CompositorImpl::IsInitialized())
+ create_video_consumer = false;
+#endif
+ if (create_video_consumer) {
video_consumer_ = std::make_unique<DevToolsVideoConsumer>(
base::BindRepeating(&PageHandler::OnFrameFromVideoConsumer,
weak_factory_.GetWeakPtr()));
@@ -264,18 +278,6 @@ void PageHandler::Wire(UberDispatcher* dispatcher) {
Page::Dispatcher::wire(dispatcher, this);
}
-void PageHandler::OnSwapCompositorFrame(
- viz::CompositorFrameMetadata frame_metadata) {
- if (video_consumer_)
- return;
-
- last_compositor_frame_metadata_ = std::move(frame_metadata);
- has_compositor_frame_metadata_ = true;
-
- if (screencast_enabled_)
- InnerSwapCompositorFrame();
-}
-
void PageHandler::OnSynchronousSwapCompositorFrame(
viz::CompositorFrameMetadata frame_metadata) {
if (has_compositor_frame_metadata_) {
@@ -406,24 +408,21 @@ Response PageHandler::Close() {
return Response::OK();
}
-Response PageHandler::Reload(Maybe<bool> bypassCache,
- Maybe<std::string> script_to_evaluate_on_load) {
+void PageHandler::Reload(Maybe<bool> bypassCache,
+ Maybe<std::string> script_to_evaluate_on_load,
+ std::unique_ptr<ReloadCallback> callback) {
WebContentsImpl* web_contents = GetWebContents();
- if (!web_contents)
- return Response::InternalError();
- if (web_contents->IsCrashed() ||
- web_contents->GetURL().scheme() == url::kDataScheme ||
- (web_contents->GetController().GetVisibleEntry() &&
- web_contents->GetController().GetVisibleEntry()->IsViewSourceMode())) {
- web_contents->GetController().Reload(bypassCache.fromMaybe(false)
- ? ReloadType::BYPASSING_CACHE
- : ReloadType::NORMAL,
- false);
- return Response::OK();
- } else {
- // Handle reload in renderer except for crashed and view source mode.
- return Response::FallThrough();
+ if (!web_contents) {
+ callback->sendFailure(Response::InternalError());
+ return;
}
+ // It is important to fallback before triggering reload, so that
+ // renderer could prepare beforehand.
+ callback->fallThrough();
+ web_contents->GetController().Reload(bypassCache.fromMaybe(false)
+ ? ReloadType::BYPASSING_CACHE
+ : ReloadType::NORMAL,
+ false);
}
void PageHandler::Navigate(const std::string& url,
@@ -946,13 +945,19 @@ void PageHandler::InnerSwapCompositorFrame() {
if (snapshot_size.IsEmpty())
return;
+ double top_controls_height = 0.;
+ double top_controls_shown_ratio = 0.;
+#if defined(OS_ANDROID)
+ top_controls_height = last_compositor_frame_metadata_.top_controls_height;
+ top_controls_shown_ratio =
+ last_compositor_frame_metadata_.top_controls_shown_ratio;
+#endif
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,
- last_compositor_frame_metadata_.top_controls_height,
- last_compositor_frame_metadata_.top_controls_shown_ratio);
+ 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 eb6a09acea3..ea8e3b17f31 100644
--- a/chromium/content/browser/devtools/protocol/page_handler.h
+++ b/chromium/content/browser/devtools/protocol/page_handler.h
@@ -68,7 +68,6 @@ class PageHandler : public DevToolsDomainHandler,
void Wire(UberDispatcher* dispatcher) override;
void SetRenderer(int process_host_id,
RenderFrameHostImpl* frame_host) override;
- void OnSwapCompositorFrame(viz::CompositorFrameMetadata frame_metadata);
void OnSynchronousSwapCompositorFrame(
viz::CompositorFrameMetadata frame_metadata);
void DidAttachInterstitialPage();
@@ -93,8 +92,9 @@ class PageHandler : public DevToolsDomainHandler,
Response Crash() override;
Response Close() override;
- Response Reload(Maybe<bool> bypassCache,
- Maybe<std::string> script_to_evaluate_on_load) override;
+ void Reload(Maybe<bool> bypassCache,
+ Maybe<std::string> script_to_evaluate_on_load,
+ std::unique_ptr<ReloadCallback> callback) override;
void Navigate(const std::string& url,
Maybe<std::string> referrer,
Maybe<std::string> transition_type,
diff --git a/chromium/content/browser/devtools/protocol/service_worker_handler.cc b/chromium/content/browser/devtools/protocol/service_worker_handler.cc
index 77d1cc9fda7..06c7cf436fd 100644
--- a/chromium/content/browser/devtools/protocol/service_worker_handler.cc
+++ b/chromium/content/browser/devtools/protocol/service_worker_handler.cc
@@ -27,7 +27,6 @@
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
-#include "content/public/common/push_event_payload.h"
#include "content/public/common/push_messaging_status.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"
@@ -309,11 +308,11 @@ Response ServiceWorkerHandler::DeliverPushMessage(
int64_t id = 0;
if (!base::StringToInt64(registration_id, &id))
return CreateInvalidVersionIdErrorResponse();
- PushEventPayload payload;
+ base::Optional<std::string> payload;
if (data.size() > 0)
- payload.setData(data);
+ payload = data;
BrowserContext::DeliverPushMessage(
- browser_context_, GURL(origin), id, payload,
+ browser_context_, GURL(origin), id, std::move(payload),
base::BindRepeating([](mojom::PushDeliveryStatus status) {}));
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 c6673d3451c..c0c84ef83f8 100644
--- a/chromium/content/browser/devtools/protocol/system_info_handler.cc
+++ b/chromium/content/browser/devtools/protocol/system_info_handler.cc
@@ -33,7 +33,8 @@ using GetInfoCallback = SystemInfo::Backend::GetInfoCallback;
// Give the GPU process a few seconds to provide GPU info.
// Linux Debug builds need more time -- see Issue 796437.
-#if defined(OS_LINUX) && !defined(NDEBUG)
+// Windows builds need more time -- see Issue 873112.
+#if (defined(OS_LINUX) && !defined(NDEBUG)) || defined(OS_WIN)
const int kGPUInfoWatchdogTimeoutMs = 20000;
#else
const int kGPUInfoWatchdogTimeoutMs = 5000;
diff --git a/chromium/content/browser/devtools/protocol/target_handler.cc b/chromium/content/browser/devtools/protocol/target_handler.cc
index 1d467539ccc..f24ac4f28e2 100644
--- a/chromium/content/browser/devtools/protocol/target_handler.cc
+++ b/chromium/content/browser/devtools/protocol/target_handler.cc
@@ -27,8 +27,6 @@ namespace protocol {
namespace {
-static const char kMethod[] = "method";
-static const char kResumeMethod[] = "Runtime.runIfWaitingForDebugger";
static const char kInitializerScript[] = R"(
(function() {
const bindingName = "%s";
@@ -241,8 +239,10 @@ class TargetHandler::Session : public DevToolsAgentHostClient {
DevToolsAgentHostImpl* agent_host_impl =
static_cast<DevToolsAgentHostImpl*>(agent_host);
if (flatten_protocol) {
- handler->target_registry_->AttachSubtargetSession(id, agent_host_impl,
- session);
+ handler->target_registry_->AttachSubtargetSession(
+ id, agent_host_impl, session,
+ base::BindOnce(&Session::ResumeIfThrottled,
+ base::Unretained(session)));
} else {
agent_host_impl->AttachClient(session);
}
@@ -275,17 +275,16 @@ class TargetHandler::Session : public DevToolsAgentHostClient {
void SetThrottle(Throttle* throttle) { throttle_ = throttle; }
+ void ResumeIfThrottled() {
+ if (throttle_)
+ throttle_->Clear();
+ }
+
void SendMessageToAgentHost(const std::string& message) {
if (throttle_) {
- bool resuming = false;
std::unique_ptr<base::Value> value = base::JSONReader::Read(message);
- if (value && value->is_dict()) {
- base::Value* method = value->FindKey(kMethod);
- resuming = method && method->is_string() &&
- method->GetString() == kResumeMethod;
- }
- if (resuming)
- throttle_->Clear();
+ if (TargetRegistry::IsRuntimeResumeCommand(value.get()))
+ ResumeIfThrottled();
}
agent_host_->DispatchProtocolMessage(this, message);
@@ -426,7 +425,7 @@ void TargetHandler::SetRenderer(int process_host_id,
}
Response TargetHandler::Disable() {
- SetAutoAttach(false, false);
+ SetAutoAttach(false, false, false);
SetDiscoverTargets(false);
auto_attached_sessions_.clear();
attached_sessions_.clear();
@@ -455,7 +454,7 @@ void TargetHandler::ClearThrottles() {
void TargetHandler::AutoAttach(DevToolsAgentHost* host,
bool waiting_for_debugger) {
std::string session_id =
- Session::Attach(this, host, waiting_for_debugger, false);
+ Session::Attach(this, host, waiting_for_debugger, flatten_auto_attach_);
auto_attached_sessions_[host] = attached_sessions_[session_id].get();
}
@@ -517,8 +516,10 @@ Response TargetHandler::SetDiscoverTargets(bool discover) {
return Response::OK();
}
-Response TargetHandler::SetAutoAttach(
- bool auto_attach, bool wait_for_debugger_on_start) {
+Response TargetHandler::SetAutoAttach(bool auto_attach,
+ bool wait_for_debugger_on_start,
+ Maybe<bool> flatten) {
+ flatten_auto_attach_ = flatten.fromMaybe(false);
auto_attacher_.SetAutoAttach(auto_attach, wait_for_debugger_on_start);
if (!auto_attacher_.ShouldThrottleFramesNavigation())
ClearThrottles();
@@ -643,19 +644,6 @@ Response TargetHandler::ExposeDevToolsProtocol(
return Response::OK();
}
-Response TargetHandler::CreateBrowserContext(std::string* out_context_id) {
- return Response::Error("Not supported");
-}
-
-Response TargetHandler::DisposeBrowserContext(const std::string& context_id) {
- return Response::Error("Not supported");
-}
-
-Response TargetHandler::GetBrowserContexts(
- std::unique_ptr<protocol::Array<String>>* browser_context_ids) {
- return Response::Error("Not supported");
-}
-
Response TargetHandler::CreateTarget(const std::string& url,
Maybe<int> width,
Maybe<int> height,
@@ -732,5 +720,67 @@ void TargetHandler::DevToolsAgentHostCrashed(DevToolsAgentHost* host,
: 0);
}
+protocol::Response TargetHandler::CreateBrowserContext(
+ std::string* out_context_id) {
+ DevToolsManagerDelegate* delegate =
+ DevToolsManager::GetInstance()->delegate();
+ if (!delegate)
+ return Response::Error("Browser context management is not supported.");
+ BrowserContext* context = delegate->CreateBrowserContext();
+ if (!context)
+ return Response::Error("Failed to create browser context.");
+ *out_context_id = context->UniqueId();
+ return protocol::Response::OK();
+}
+
+protocol::Response TargetHandler::GetBrowserContexts(
+ std::unique_ptr<protocol::Array<protocol::String>>* browser_context_ids) {
+ DevToolsManagerDelegate* delegate =
+ DevToolsManager::GetInstance()->delegate();
+ if (!delegate)
+ return Response::Error("Browser context management is not supported.");
+ std::vector<content::BrowserContext*> contexts =
+ delegate->GetBrowserContexts();
+ *browser_context_ids = std::make_unique<protocol::Array<protocol::String>>();
+ for (auto* context : contexts)
+ (*browser_context_ids)->addItem(context->UniqueId());
+ return protocol::Response::OK();
+}
+
+void TargetHandler::DisposeBrowserContext(
+ const std::string& context_id,
+ std::unique_ptr<DisposeBrowserContextCallback> callback) {
+ DevToolsManagerDelegate* delegate =
+ DevToolsManager::GetInstance()->delegate();
+ if (!delegate) {
+ callback->sendFailure(protocol::Response::Error(
+ "Browser context management is not supported."));
+ return;
+ }
+ std::vector<content::BrowserContext*> contexts =
+ delegate->GetBrowserContexts();
+ auto context_it =
+ std::find_if(contexts.begin(), contexts.end(),
+ [&context_id](content::BrowserContext* context) {
+ return context->UniqueId() == context_id;
+ });
+ if (context_it == contexts.end()) {
+ callback->sendFailure(protocol::Response::Error(
+ "Failed to find context with id " + context_id));
+ return;
+ }
+ delegate->DisposeBrowserContext(
+ *context_it,
+ base::BindOnce(
+ [](std::unique_ptr<DisposeBrowserContextCallback> callback,
+ bool success, const std::string& error) {
+ if (success)
+ callback->sendSuccess();
+ else
+ callback->sendFailure(protocol::Response::Error(error));
+ },
+ std::move(callback)));
+}
+
} // namespace protocol
} // namespace content
diff --git a/chromium/content/browser/devtools/protocol/target_handler.h b/chromium/content/browser/devtools/protocol/target_handler.h
index ba5702adbd0..06a9bbb9ca5 100644
--- a/chromium/content/browser/devtools/protocol/target_handler.h
+++ b/chromium/content/browser/devtools/protocol/target_handler.h
@@ -49,7 +49,8 @@ class TargetHandler : public DevToolsDomainHandler,
// Domain implementation.
Response SetDiscoverTargets(bool discover) override;
Response SetAutoAttach(bool auto_attach,
- bool wait_for_debugger_on_start) override;
+ bool wait_for_debugger_on_start,
+ Maybe<bool> flatten) override;
Response SetRemoteLocations(
std::unique_ptr<protocol::Array<Target::RemoteLocation>>) override;
Response AttachToTarget(const std::string& target_id,
@@ -70,7 +71,9 @@ class TargetHandler : public DevToolsDomainHandler,
Response ExposeDevToolsProtocol(const std::string& target_id,
Maybe<std::string> binding_name) override;
Response CreateBrowserContext(std::string* out_context_id) override;
- Response DisposeBrowserContext(const std::string& context_id) override;
+ void DisposeBrowserContext(
+ const std::string& context_id,
+ std::unique_ptr<DisposeBrowserContextCallback> callback) override;
Response GetBrowserContexts(
std::unique_ptr<protocol::Array<String>>* browser_context_ids) override;
Response CreateTarget(const std::string& url,
@@ -107,6 +110,7 @@ class TargetHandler : public DevToolsDomainHandler,
std::unique_ptr<Target::Frontend> frontend_;
TargetAutoAttacher auto_attacher_;
+ bool flatten_auto_attach_ = false;
bool discover_;
std::map<std::string, std::unique_ptr<Session>> attached_sessions_;
std::map<DevToolsAgentHost*, Session*> auto_attached_sessions_;
diff --git a/chromium/content/browser/devtools/protocol/tethering_handler.cc b/chromium/content/browser/devtools/protocol/tethering_handler.cc
index ce6738651b2..4640abe9ff0 100644
--- a/chromium/content/browser/devtools/protocol/tethering_handler.cc
+++ b/chromium/content/browser/devtools/protocol/tethering_handler.cc
@@ -108,8 +108,8 @@ class SocketPump {
new net::IOBuffer(kSocketPumpBufferSize);
int result =
from->Read(buffer.get(), kSocketPumpBufferSize,
- base::Bind(&SocketPump::OnRead, base::Unretained(this), from,
- to, buffer));
+ base::BindOnce(&SocketPump::OnRead, base::Unretained(this),
+ from, to, buffer));
if (result != net::ERR_IO_PENDING)
OnRead(from, to, buffer, result);
}
@@ -125,13 +125,14 @@ class SocketPump {
int total = result;
scoped_refptr<net::DrainableIOBuffer> drainable =
- new net::DrainableIOBuffer(buffer.get(), total);
+ base::MakeRefCounted<net::DrainableIOBuffer>(std::move(buffer), total);
++pending_writes_;
- result = to->Write(drainable.get(), total,
- base::Bind(&SocketPump::OnWritten,
- base::Unretained(this), drainable, from, to),
- kTrafficAnnotation);
+ result =
+ to->Write(drainable.get(), total,
+ base::BindOnce(&SocketPump::OnWritten, base::Unretained(this),
+ drainable, from, to),
+ kTrafficAnnotation);
if (result != net::ERR_IO_PENDING)
OnWritten(drainable, from, to, result);
}
@@ -151,8 +152,8 @@ class SocketPump {
++pending_writes_;
result =
to->Write(drainable.get(), drainable->BytesRemaining(),
- base::Bind(&SocketPump::OnWritten, base::Unretained(this),
- drainable, from, to),
+ base::BindOnce(&SocketPump::OnWritten,
+ base::Unretained(this), drainable, from, to),
kTrafficAnnotation);
if (result != net::ERR_IO_PENDING)
OnWritten(drainable, from, to, result);
diff --git a/chromium/content/browser/devtools/protocol/tracing_handler.cc b/chromium/content/browser/devtools/protocol/tracing_handler.cc
index 9546e5dd5a3..a93a43faa7c 100644
--- a/chromium/content/browser/devtools/protocol/tracing_handler.cc
+++ b/chromium/content/browser/devtools/protocol/tracing_handler.cc
@@ -24,7 +24,6 @@
#include "base/trace_event/trace_event_impl.h"
#include "base/trace_event/tracing_agent.h"
#include "components/tracing/common/trace_startup_config.h"
-#include "components/viz/common/features.h"
#include "content/browser/devtools/devtools_frame_trace_recorder.h"
#include "content/browser/devtools/devtools_io_context.h"
#include "content/browser/devtools/devtools_session.h"
@@ -35,10 +34,10 @@
#include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/frame_host/navigation_handle_impl.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/browser/gpu/gpu_process_host.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/tracing/tracing_controller_impl.h"
#include "content/public/browser/browser_thread.h"
-#include "content/public/common/content_features.h"
#include "services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h"
#include "services/tracing/public/mojom/constants.mojom.h"
@@ -218,10 +217,7 @@ TracingHandler::TracingHandler(FrameTreeNode* frame_tree_node_,
return_as_stream_(false),
gzip_compression_(false),
weak_factory_(this) {
- bool use_video_capture_api =
- base::FeatureList::IsEnabled(features::kVizDisplayCompositor) ||
- base::FeatureList::IsEnabled(
- features::kUseVideoCaptureApiForDevToolsSnapshots);
+ bool use_video_capture_api = true;
#ifdef OS_ANDROID
// Video capture API cannot be used on Android WebView.
if (!CompositorImpl::IsInitialized())
@@ -409,12 +405,30 @@ void TracingHandler::Start(Maybe<std::string> categories,
options.fromMaybe(""));
}
- // If inspected target is a render process Tracing.start will be handled by
- // tracing agent in the renderer.
- if (frame_tree_node_)
- callback->fallThrough();
+ // GPU process id can only be retrieved on IO thread. Do some thread hopping.
+ BrowserThread::PostTaskAndReplyWithResult(
+ BrowserThread::IO, FROM_HERE, base::BindOnce([]() {
+ GpuProcessHost* gpu_process_host =
+ GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
+ /* force_create */ false);
+ return gpu_process_host ? gpu_process_host->process_id()
+ : base::kNullProcessId;
+ }),
+ base::BindOnce(&TracingHandler::StartTracingWithGpuPid,
+ weak_factory_.GetWeakPtr(), std::move(callback)));
+}
+
+void TracingHandler::StartTracingWithGpuPid(
+ std::unique_ptr<StartCallback> callback,
+ base::ProcessId gpu_pid) {
+ // Check if tracing was stopped in mid-air.
+ if (!did_initiate_recording_) {
+ callback->sendFailure(Response::Error(
+ "Tracing was stopped before start has been completed."));
+ return;
+ }
- SetupProcessFilter(nullptr);
+ SetupProcessFilter(gpu_pid, nullptr);
TracingController::GetInstance()->StartTracing(
trace_config_, base::BindRepeating(&TracingHandler::OnRecordingEnabled,
@@ -423,14 +437,20 @@ void TracingHandler::Start(Maybe<std::string> categories,
}
void TracingHandler::SetupProcessFilter(
+ base::ProcessId gpu_pid,
RenderFrameHost* new_render_frame_host) {
if (!frame_tree_node_)
return;
base::ProcessId browser_pid = base::Process::Current().Pid();
std::unordered_set<base::ProcessId> included_process_ids({browser_pid});
+
+ if (gpu_pid != base::kNullProcessId)
+ included_process_ids.insert(gpu_pid);
+
if (new_render_frame_host)
AppendProcessId(new_render_frame_host, &included_process_ids);
+
for (FrameTreeNode* node :
frame_tree_node_->frame_tree()->SubtreeNodes(frame_tree_node_)) {
RenderFrameHost* frame_host = node->current_frame_host();
@@ -467,14 +487,12 @@ void TracingHandler::OnProcessReady(RenderProcessHost* process_host) {
trace_config_, base::RepeatingCallback<void()>());
}
-void TracingHandler::End(std::unique_ptr<EndCallback> callback) {
+Response TracingHandler::End() {
// Startup tracing triggered by --trace-config-file is a special case, where
// tracing is started automatically upon browser startup and can be stopped
// via DevTools.
- if (!did_initiate_recording_ && !IsStartupTracingActive()) {
- callback->sendFailure(Response::Error("Tracing is not started"));
- return;
- }
+ if (!did_initiate_recording_ && !IsStartupTracingActive())
+ return Response::Error("Tracing is not started");
scoped_refptr<TracingController::TraceDataEndpoint> endpoint;
if (return_as_stream_) {
@@ -493,12 +511,8 @@ void TracingHandler::End(std::unique_ptr<EndCallback> callback) {
endpoint = new DevToolsTraceEndpointProxy(weak_factory_.GetWeakPtr());
StopTracing(endpoint, tracing::mojom::kChromeTraceEventLabel);
}
- // If inspected target is a render process Tracing.end will be handled by
- // tracing agent in the renderer.
- if (frame_tree_node_)
- callback->fallThrough();
- else
- callback->sendSuccess();
+
+ return Response::OK();
}
void TracingHandler::GetCategories(
@@ -511,10 +525,14 @@ void TracingHandler::GetCategories(
void TracingHandler::OnRecordingEnabled(
std::unique_ptr<StartCallback> callback) {
- EmitFrameTree();
+ if (!did_initiate_recording_) {
+ callback->sendFailure(Response::Error(
+ "Tracing was stopped before start has been completed."));
+ return;
+ }
- if (!frame_tree_node_)
- callback->sendSuccess();
+ EmitFrameTree();
+ callback->sendSuccess();
bool screenshot_enabled;
TRACE_EVENT_CATEGORY_GROUP_ENABLED(
@@ -663,7 +681,8 @@ void TracingHandler::ReadyToCommitNavigation(
"FrameCommittedInBrowser", TRACE_EVENT_SCOPE_THREAD,
"data", std::move(data));
- SetupProcessFilter(navigation_handle->GetRenderFrameHost());
+ SetupProcessFilter(base::kNullProcessId,
+ navigation_handle->GetRenderFrameHost());
TracingController::GetInstance()->StartTracing(
trace_config_, base::RepeatingCallback<void()>());
}
diff --git a/chromium/content/browser/devtools/protocol/tracing_handler.h b/chromium/content/browser/devtools/protocol/tracing_handler.h
index 82f11ef2a25..97ba2286280 100644
--- a/chromium/content/browser/devtools/protocol/tracing_handler.h
+++ b/chromium/content/browser/devtools/protocol/tracing_handler.h
@@ -69,7 +69,7 @@ class TracingHandler : public DevToolsDomainHandler, public Tracing::Backend {
Maybe<std::string> transfer_compression,
Maybe<Tracing::TraceConfig> config,
std::unique_ptr<StartCallback> callback) override;
- void End(std::unique_ptr<EndCallback> callback) override;
+ Response End() override;
void GetCategories(std::unique_ptr<GetCategoriesCallback> callback) override;
void RequestMemoryDump(
std::unique_ptr<RequestMemoryDumpCallback> callback) override;
@@ -116,7 +116,9 @@ class TracingHandler : public DevToolsDomainHandler, public Tracing::Backend {
CONTENT_EXPORT static base::trace_event::TraceConfig
GetTraceConfigFromDevToolsConfig(
const base::DictionaryValue& devtools_config);
- void SetupProcessFilter(RenderFrameHost*);
+ void SetupProcessFilter(base::ProcessId gpu_pid, RenderFrameHost*);
+ void StartTracingWithGpuPid(std::unique_ptr<StartCallback>,
+ base::ProcessId gpu_pid);
void AppendProcessId(RenderFrameHost*,
std::unordered_set<base::ProcessId>* process_set);
void OnProcessReady(RenderProcessHost*);
diff --git a/chromium/content/browser/devtools/protocol_config.json b/chromium/content/browser/devtools/protocol_config.json
index 0919b220303..1c779296c95 100644
--- a/chromium/content/browser/devtools/protocol_config.json
+++ b/chromium/content/browser/devtools/protocol_config.json
@@ -11,7 +11,7 @@
"options": [
{
"domain": "Browser",
- "include": ["getVersion", "getHistograms", "getHistogram", "getBrowserCommandLine"]
+ "include": ["getVersion", "getHistograms", "getHistogram", "getBrowserCommandLine", "grantPermissions", "resetPermissions"]
},
{
"domain": "DOM",
@@ -24,7 +24,7 @@
},
{
"domain": "Input",
- "async": ["dispatchKeyEvent", "dispatchMouseEvent", "dispatchTouchEvent", "synthesizePinchGesture", "synthesizeScrollGesture", "synthesizeTapGesture"]
+ "async": ["dispatchKeyEvent", "insertText", "dispatchMouseEvent", "dispatchTouchEvent", "synthesizePinchGesture", "synthesizeScrollGesture", "synthesizeTapGesture"]
},
{
"domain": "Inspector"
@@ -51,7 +51,7 @@
"startScreencast", "stopScreencast", "screencastFrameAck", "handleJavaScriptDialog", "setColorPickerEnabled", "requestAppBanner",
"printToPDF", "bringToFront", "setDownloadBehavior", "getAppManifest", "crash", "close", "setWebLifecycleState"],
"include_events": ["colorPicked", "interstitialShown", "interstitialHidden", "javascriptDialogOpening", "javascriptDialogClosed", "screencastVisibilityChanged", "screencastFrame"],
- "async": ["captureScreenshot", "printToPDF", "navigate", "getAppManifest"]
+ "async": ["captureScreenshot", "printToPDF", "navigate", "getAppManifest", "reload"]
},
{
"domain": "Runtime",
@@ -77,7 +77,8 @@
"async": ["getInfo"]
},
{
- "domain": "Target"
+ "domain": "Target",
+ "async": ["disposeBrowserContext"]
},
{
"domain": "Tethering",
@@ -85,7 +86,7 @@
},
{
"domain": "Tracing",
- "async": ["start", "end", "getCategories", "requestMemoryDump"]
+ "async": ["start", "getCategories", "requestMemoryDump"]
}
]
},
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 9493103481a..f80fb077ae0 100644
--- a/chromium/content/browser/devtools/render_frame_devtools_agent_host.cc
+++ b/chromium/content/browser/devtools/render_frame_devtools_agent_host.cc
@@ -12,7 +12,6 @@
#include "base/memory/ptr_util.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
-#include "components/viz/common/features.h"
#include "content/browser/bad_message.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/devtools/devtools_frame_trace_recorder.h"
@@ -51,7 +50,6 @@
#include "content/public/browser/render_widget_host_iterator.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/common/browser_side_navigation_policy.h"
-#include "content/public/common/content_features.h"
#include "mojo/public/cpp/bindings/associated_binding.h"
#include "net/base/load_flags.h"
#include "net/http/http_request_headers.h"
@@ -429,14 +427,7 @@ WebContents* RenderFrameDevToolsAgentHost::GetWebContents() {
bool RenderFrameDevToolsAgentHost::AttachSession(DevToolsSession* session,
TargetRegistry* registry) {
- DevToolsManager* manager = DevToolsManager::GetInstance();
- if (manager->delegate() && web_contents()) {
- if (!manager->delegate()->AllowInspectingWebContents(web_contents()))
- return false;
- }
- const bool is_webui =
- frame_host_ && (frame_host_->web_ui() || frame_host_->pending_web_ui());
- if (!session->client()->MayAttachToRenderer(frame_host_, is_webui))
+ if (!ShouldAllowSession(session, frame_host_))
return false;
session->SetRenderer(frame_host_ ? frame_host_->GetProcess()->GetID()
@@ -477,10 +468,7 @@ bool RenderFrameDevToolsAgentHost::AttachSession(DevToolsSession* session,
session->AttachToAgent(agent_ptr_);
if (sessions().size() == 1) {
- bool use_video_capture_api =
- base::FeatureList::IsEnabled(features::kVizDisplayCompositor) ||
- base::FeatureList::IsEnabled(
- features::kUseVideoCaptureApiForDevToolsSnapshots);
+ bool use_video_capture_api = true;
#ifdef OS_ANDROID
// Video capture API cannot be used on Android WebView.
if (!CompositorImpl::IsInitialized())
@@ -604,14 +592,10 @@ void RenderFrameDevToolsAgentHost::UpdateFrameHost(
agent_ptr_.reset();
std::vector<DevToolsSession*> restricted_sessions;
- const bool is_webui =
- frame_host && (frame_host->web_ui() || frame_host->pending_web_ui());
-
for (DevToolsSession* session : sessions()) {
- if (!session->client()->MayAttachToRenderer(frame_host, is_webui))
+ if (!ShouldAllowSession(session, frame_host))
restricted_sessions.push_back(session);
}
-
if (!restricted_sessions.empty())
ForceDetachRestrictedSessions(restricted_sessions);
@@ -786,23 +770,6 @@ void RenderFrameDevToolsAgentHost::OnVisibilityChanged(
#endif
}
-void RenderFrameDevToolsAgentHost::DidReceiveCompositorFrame() {
- const viz::CompositorFrameMetadata& metadata =
- RenderWidgetHostImpl::From(
- web_contents()->GetRenderViewHost()->GetWidget())
- ->last_frame_metadata();
- for (auto* page : protocol::PageHandler::ForAgentHost(this))
- page->OnSwapCompositorFrame(metadata.Clone());
-
- if (!frame_trace_recorder_)
- return;
- bool did_initiate_recording = false;
- for (auto* tracing : protocol::TracingHandler::ForAgentHost(this))
- did_initiate_recording |= tracing->did_initiate_recording();
- if (did_initiate_recording)
- frame_trace_recorder_->OnSwapCompositorFrame(frame_host_, metadata);
-}
-
void RenderFrameDevToolsAgentHost::OnPageScaleFactorChanged(
float page_scale_factor) {
for (auto* input : protocol::InputHandler::ForAgentHost(this))
@@ -981,4 +948,19 @@ bool RenderFrameDevToolsAgentHost::IsChildFrame() {
return frame_tree_node_ && frame_tree_node_->parent();
}
+bool RenderFrameDevToolsAgentHost::ShouldAllowSession(
+ DevToolsSession* session,
+ RenderFrameHostImpl* frame_host) {
+ DevToolsManager* manager = DevToolsManager::GetInstance();
+ if (manager->delegate() && frame_host) {
+ if (!manager->delegate()->AllowInspectingRenderFrameHost(frame_host))
+ return false;
+ }
+ const bool is_webui =
+ frame_host && (frame_host->web_ui() || frame_host->pending_web_ui());
+ if (!session->client()->MayAttachToRenderer(frame_host, is_webui))
+ return false;
+ return true;
+}
+
} // namespace content
diff --git a/chromium/content/browser/devtools/render_frame_devtools_agent_host.h b/chromium/content/browser/devtools/render_frame_devtools_agent_host.h
index b4184bb250d..37f0c8d1e77 100644
--- a/chromium/content/browser/devtools/render_frame_devtools_agent_host.h
+++ b/chromium/content/browser/devtools/render_frame_devtools_agent_host.h
@@ -178,7 +178,6 @@ class CONTENT_EXPORT RenderFrameDevToolsAgentHost
void DidAttachInterstitialPage() override;
void DidDetachInterstitialPage() override;
void OnVisibilityChanged(content::Visibility visibility) override;
- void DidReceiveCompositorFrame() override;
void OnPageScaleFactorChanged(float page_scale_factor) override;
bool IsChildFrame();
@@ -191,6 +190,9 @@ class CONTENT_EXPORT RenderFrameDevToolsAgentHost
void RevokePolicy();
void SetFrameTreeNode(FrameTreeNode* frame_tree_node);
+ bool ShouldAllowSession(DevToolsSession* session,
+ RenderFrameHostImpl* frame_host);
+
#if defined(OS_ANDROID)
device::mojom::WakeLock* GetWakeLock();
#endif
diff --git a/chromium/content/browser/devtools/service_worker_devtools_manager.h b/chromium/content/browser/devtools/service_worker_devtools_manager.h
index 1018d40705a..0153f487adb 100644
--- a/chromium/content/browser/devtools/service_worker_devtools_manager.h
+++ b/chromium/content/browser/devtools/service_worker_devtools_manager.h
@@ -109,7 +109,7 @@ class CONTENT_EXPORT ServiceWorkerDevToolsManager {
ServiceWorkerDevToolsManager();
~ServiceWorkerDevToolsManager();
- base::ObserverList<Observer> observer_list_;
+ base::ObserverList<Observer>::Unchecked observer_list_;
bool debug_service_worker_on_start_;
// We retatin agent hosts as long as the service worker is alive.
diff --git a/chromium/content/browser/devtools/target_registry.cc b/chromium/content/browser/devtools/target_registry.cc
index 07d168aa79b..6250b22c8e5 100644
--- a/chromium/content/browser/devtools/target_registry.cc
+++ b/chromium/content/browser/devtools/target_registry.cc
@@ -9,35 +9,76 @@
namespace content {
+namespace {
+static const char kMethod[] = "method";
+static const char kResumeMethod[] = "Runtime.runIfWaitingForDebugger";
+} // namespace
+
+// static
+bool TargetRegistry::IsRuntimeResumeCommand(base::Value* value) {
+ if (value && value->is_dict()) {
+ base::Value* method = value->FindKey(kMethod);
+ return method && method->is_string() &&
+ method->GetString() == kResumeMethod;
+ }
+ return false;
+}
+
+struct TargetRegistry::SessionInfo {
+ SessionInfo(scoped_refptr<DevToolsAgentHostImpl> agent_host,
+ DevToolsAgentHostClient* client,
+ base::OnceClosure resume_if_throttled)
+ : agent_host(agent_host),
+ client(client),
+ resume_if_throttled(std::move(resume_if_throttled)) {}
+ scoped_refptr<DevToolsAgentHostImpl> agent_host;
+ DevToolsAgentHostClient* client;
+ base::OnceClosure resume_if_throttled;
+};
+
TargetRegistry::TargetRegistry(DevToolsSession* root_session)
: root_session_(root_session) {}
TargetRegistry::~TargetRegistry() {}
-void TargetRegistry::AttachSubtargetSession(const std::string& session_id,
- DevToolsAgentHostImpl* agent_host,
- DevToolsAgentHostClient* client) {
- sessions_[session_id] = std::make_pair(agent_host, client);
+void TargetRegistry::AttachSubtargetSession(
+ const std::string& session_id,
+ DevToolsAgentHostImpl* agent_host,
+ DevToolsAgentHostClient* client,
+ base::OnceClosure resume_if_throttled) {
+ sessions_[session_id] = std::make_unique<SessionInfo>(
+ agent_host, client, std::move(resume_if_throttled));
agent_host->AttachSubtargetClient(client, this);
}
void TargetRegistry::DetachSubtargetSession(const std::string& session_id) {
sessions_.erase(session_id);
}
-bool TargetRegistry::DispatchMessageOnAgentHost(
- const std::string& message,
+bool TargetRegistry::CanDispatchMessageOnAgentHost(
base::DictionaryValue* parsed_message) {
+ return parsed_message->FindKeyOfType("sessionId",
+ base::DictionaryValue::Type::STRING);
+}
+
+void TargetRegistry::DispatchMessageOnAgentHost(
+ const std::string& message,
+ std::unique_ptr<base::DictionaryValue> parsed_message) {
std::string session_id;
- if (!parsed_message->GetString("sessionId", &session_id))
- return false;
+ bool result = parsed_message->GetString("sessionId", &session_id);
+ DCHECK(result);
auto it = sessions_.find(session_id);
if (it == sessions_.end()) {
LOG(ERROR) << "Unknown session " << session_id;
- return true;
+ return;
+ }
+ scoped_refptr<DevToolsAgentHostImpl> agent_host = it->second->agent_host;
+ DevToolsAgentHostClient* client = it->second->client;
+ if (!it->second->resume_if_throttled.is_null() &&
+ IsRuntimeResumeCommand(parsed_message.get())) {
+ std::move(it->second->resume_if_throttled).Run();
}
- scoped_refptr<DevToolsAgentHostImpl> agent_host = it->second.first;
- DevToolsAgentHostClient* client = it->second.second;
- return agent_host->DispatchProtocolMessage(client, message, parsed_message);
+ agent_host->DispatchProtocolMessage(client, message,
+ std::move(parsed_message));
}
void TargetRegistry::SendMessageToClient(const std::string& session_id,
diff --git a/chromium/content/browser/devtools/target_registry.h b/chromium/content/browser/devtools/target_registry.h
index d915e1f1368..9892da5507e 100644
--- a/chromium/content/browser/devtools/target_registry.h
+++ b/chromium/content/browser/devtools/target_registry.h
@@ -7,6 +7,7 @@
#include <string>
+#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/containers/flat_map.h"
#include "base/values.h"
@@ -18,24 +19,27 @@ class DevToolsSession;
class TargetRegistry {
public:
+ static bool IsRuntimeResumeCommand(base::Value* value);
+
explicit TargetRegistry(DevToolsSession* root_session);
~TargetRegistry();
void AttachSubtargetSession(const std::string& session_id,
DevToolsAgentHostImpl* agent_host,
- DevToolsAgentHostClient* client);
+ DevToolsAgentHostClient* client,
+ base::OnceClosure resume_if_throttled);
void DetachSubtargetSession(const std::string& session_id);
- bool DispatchMessageOnAgentHost(const std::string& message,
- base::DictionaryValue* parsed_message);
+ bool CanDispatchMessageOnAgentHost(base::DictionaryValue* parsed_message);
+ void DispatchMessageOnAgentHost(
+ const std::string& message,
+ std::unique_ptr<base::DictionaryValue> parsed_message);
void SendMessageToClient(const std::string& session_id,
const std::string& message);
private:
DevToolsSession* root_session_;
- base::flat_map<
- std::string,
- std::pair<scoped_refptr<DevToolsAgentHostImpl>, DevToolsAgentHostClient*>>
- sessions_;
+ struct SessionInfo;
+ base::flat_map<std::string, std::unique_ptr<SessionInfo>> sessions_;
DISALLOW_COPY_AND_ASSIGN(TargetRegistry);
};
diff --git a/chromium/content/browser/display_cutout/display_cutout_host_impl.cc b/chromium/content/browser/display_cutout/display_cutout_host_impl.cc
index 4785df22f40..5d61832fc4e 100644
--- a/chromium/content/browser/display_cutout/display_cutout_host_impl.cc
+++ b/chromium/content/browser/display_cutout/display_cutout_host_impl.cc
@@ -12,12 +12,8 @@
namespace content {
-DisplayCutoutHostImpl::DisplayCutoutHostImpl(
- WebContentsImpl* web_contents,
- ViewportFitChangedCallback callback)
- : WebContentsObserver(web_contents),
- viewport_fit_changed_callback_(callback),
- bindings_(web_contents, this) {}
+DisplayCutoutHostImpl::DisplayCutoutHostImpl(WebContentsImpl* web_contents)
+ : bindings_(web_contents, this), web_contents_impl_(web_contents) {}
DisplayCutoutHostImpl::~DisplayCutoutHostImpl() = default;
@@ -37,7 +33,7 @@ void DisplayCutoutHostImpl::ViewportFitChangedForFrame(
// If we are the current |RenderFrameHost| frame then notify
// WebContentsObservers about the new value.
if (current_rfh_ == rfh)
- viewport_fit_changed_callback_.Run(value);
+ web_contents_impl_->NotifyViewportFitChanged(value);
MaybeQueueUKMEvent(rfh);
}
@@ -46,11 +42,8 @@ void DisplayCutoutHostImpl::DidAcquireFullscreen(RenderFrameHost* rfh) {
SetCurrentRenderFrameHost(rfh);
}
-void DisplayCutoutHostImpl::DidToggleFullscreenModeForTab(
- bool entered_fullscreen,
- bool will_cause_resize) {
- if (!entered_fullscreen)
- SetCurrentRenderFrameHost(nullptr);
+void DisplayCutoutHostImpl::DidExitFullscreen() {
+ SetCurrentRenderFrameHost(nullptr);
}
void DisplayCutoutHostImpl::DidStartNavigation(
@@ -78,11 +71,10 @@ void DisplayCutoutHostImpl::DidFinishNavigation(
// fullscreen then we should make the main frame the current
// |RenderFrameHost|.
RenderWidgetHostImpl* rwh =
- web_contents_impl()->GetRenderViewHost()->GetWidget();
- blink::WebDisplayMode mode = web_contents_impl()->GetDisplayMode(rwh);
- if (mode == blink::WebDisplayMode::kWebDisplayModeFullscreen) {
- SetCurrentRenderFrameHost(web_contents_impl()->GetMainFrame());
- }
+ web_contents_impl_->GetRenderViewHost()->GetWidget();
+ blink::WebDisplayMode mode = web_contents_impl_->GetDisplayMode(rwh);
+ if (mode == blink::WebDisplayMode::kWebDisplayModeFullscreen)
+ SetCurrentRenderFrameHost(web_contents_impl_->GetMainFrame());
}
void DisplayCutoutHostImpl::RenderFrameDeleted(RenderFrameHost* rfh) {
@@ -132,7 +124,8 @@ void DisplayCutoutHostImpl::SetCurrentRenderFrameHost(RenderFrameHost* rfh) {
// If the new RenderFrameHost is nullptr we should stop here and notify
// observers that the new viewport fit is kAuto (the default).
if (!rfh) {
- viewport_fit_changed_callback_.Run(blink::mojom::ViewportFit::kAuto);
+ web_contents_impl_->NotifyViewportFitChanged(
+ blink::mojom::ViewportFit::kAuto);
return;
}
@@ -143,7 +136,7 @@ void DisplayCutoutHostImpl::SetCurrentRenderFrameHost(RenderFrameHost* rfh) {
SendSafeAreaToFrame(rfh, insets_);
// Notify the WebContentsObservers that the viewport fit value has changed.
- viewport_fit_changed_callback_.Run(GetValueOrDefault(rfh));
+ web_contents_impl_->NotifyViewportFitChanged(GetValueOrDefault(rfh));
}
void DisplayCutoutHostImpl::SendSafeAreaToFrame(RenderFrameHost* rfh,
@@ -167,10 +160,6 @@ blink::mojom::ViewportFit DisplayCutoutHostImpl::GetValueOrDefault(
return blink::mojom::ViewportFit::kAuto;
}
-WebContentsImpl* DisplayCutoutHostImpl::web_contents_impl() {
- return static_cast<WebContentsImpl*>(web_contents());
-}
-
void DisplayCutoutHostImpl::MaybeQueueUKMEvent(RenderFrameHost* frame) {
if (!frame)
return;
@@ -206,7 +195,7 @@ void DisplayCutoutHostImpl::MaybeQueueUKMEvent(RenderFrameHost* frame) {
void DisplayCutoutHostImpl::RecordPendingUKMEvents() {
for (const auto& event : pending_ukm_events_) {
ukm::builders::Layout_DisplayCutout_StateChanged builder(
- web_contents_impl()->GetUkmSourceIdForLastCommittedSource());
+ web_contents_impl_->GetUkmSourceIdForLastCommittedSource());
builder.SetIsMainFrame(event.is_main_frame);
builder.SetViewportFit_Applied(static_cast<int>(event.applied_value));
builder.SetViewportFit_Supplied(static_cast<int>(event.supplied_value));
diff --git a/chromium/content/browser/display_cutout/display_cutout_host_impl.h b/chromium/content/browser/display_cutout/display_cutout_host_impl.h
index eba70e23dac..3c24e135971 100644
--- a/chromium/content/browser/display_cutout/display_cutout_host_impl.h
+++ b/chromium/content/browser/display_cutout/display_cutout_host_impl.h
@@ -11,14 +11,9 @@
namespace content {
-class DisplayCutoutHostImpl : public blink::mojom::DisplayCutoutHost,
- public WebContentsObserver {
+class DisplayCutoutHostImpl : public blink::mojom::DisplayCutoutHost {
public:
- // Called when the effective viewport fit value has changed.
- using ViewportFitChangedCallback =
- base::RepeatingCallback<void(blink::mojom::ViewportFit)>;
-
- DisplayCutoutHostImpl(WebContentsImpl*, ViewportFitChangedCallback);
+ explicit DisplayCutoutHostImpl(WebContentsImpl*);
~DisplayCutoutHostImpl() override;
// blink::mojom::DisplayCutoutHost
@@ -29,15 +24,14 @@ class DisplayCutoutHostImpl : public blink::mojom::DisplayCutoutHost,
void ViewportFitChangedForFrame(RenderFrameHost* rfh,
blink::mojom::ViewportFit value);
- // WebContentsObserver override.
- void DidAcquireFullscreen(RenderFrameHost* rfh) override;
- void DidToggleFullscreenModeForTab(bool entered_fullscreen,
- bool will_cause_resize) override;
- void DidStartNavigation(NavigationHandle* navigation_handle) override;
- void DidFinishNavigation(NavigationHandle* navigation_handle) override;
- void RenderFrameDeleted(RenderFrameHost* rfh) override;
- void RenderFrameCreated(RenderFrameHost* rfh) override;
- void WebContentsDestroyed() override;
+ // Called by WebContents when various events occur.
+ void DidAcquireFullscreen(RenderFrameHost* rfh);
+ void DidExitFullscreen();
+ void DidStartNavigation(NavigationHandle* navigation_handle);
+ void DidFinishNavigation(NavigationHandle* navigation_handle);
+ void RenderFrameDeleted(RenderFrameHost* rfh);
+ void RenderFrameCreated(RenderFrameHost* rfh);
+ void WebContentsDestroyed();
// Updates the safe area insets on the current frame.
void SetDisplayCutoutSafeArea(gfx::Insets insets);
@@ -63,8 +57,6 @@ class DisplayCutoutHostImpl : public blink::mojom::DisplayCutoutHost,
// stored value.
blink::mojom::ViewportFit GetValueOrDefault(RenderFrameHost* rfh) const;
- WebContentsImpl* web_contents_impl();
-
// Builds and records a Layout.DisplayCutout.StateChanged UKM event for the
// provided |frame|. The event will be added to the list of pending events.
void MaybeQueueUKMEvent(RenderFrameHost* frame);
@@ -88,11 +80,13 @@ class DisplayCutoutHostImpl : public blink::mojom::DisplayCutoutHost,
// Stores a map of RenderFrameHosts and their current viewport fit values.
std::map<RenderFrameHost*, blink::mojom::ViewportFit> values_;
- // Stores the callback for when the effective viewport fit value has changed.
- ViewportFitChangedCallback viewport_fit_changed_callback_;
-
// Holds WebContents associated mojo bindings.
WebContentsFrameBindingSet<blink::mojom::DisplayCutoutHost> bindings_;
+
+ // Weak pointer to the owning |WebContentsImpl| instance.
+ WebContentsImpl* web_contents_impl_;
+
+ DISALLOW_COPY_AND_ASSIGN(DisplayCutoutHostImpl);
};
} // namespace content
diff --git a/chromium/content/browser/do_not_track_browsertest.cc b/chromium/content/browser/do_not_track_browsertest.cc
index 83c39160e4c..1aa00dc5b57 100644
--- a/chromium/content/browser/do_not_track_browsertest.cc
+++ b/chromium/content/browser/do_not_track_browsertest.cc
@@ -267,6 +267,103 @@ IN_PROC_BROWSER_TEST_F(DoNotTrackTest, FetchFromServiceWorker) {
ExpectPageTextEq("1");
}
+// Checks that the DNT header is preserved when fetching from a page controlled
+// by a service worker which doesn't have a fetch handler and falls back to the
+// network.
+IN_PROC_BROWSER_TEST_F(DoNotTrackTest,
+ FetchFromServiceWorkerControlledPage_NoFetchHandler) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+ if (!EnableDoNotTrack())
+ return;
+
+ {
+ // Register a service worker which controls /service_worker.
+ const GURL url = embedded_test_server()->GetURL(
+ "/service_worker/create_service_worker.html?"
+ "worker_url=/service_worker/empty.js");
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+ const base::string16 title = base::ASCIIToUTF16("DONE");
+ TitleWatcher watcher(shell()->web_contents(), title);
+ EXPECT_EQ(title, watcher.WaitAndGetTitle());
+ }
+
+ {
+ // Issue a request from a controlled page.
+ const GURL url = embedded_test_server()->GetURL(
+ "/service_worker/fetch_from_page.html?url=/echoheader?DNT");
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+ const base::string16 title = base::ASCIIToUTF16("DONE");
+ TitleWatcher watcher(shell()->web_contents(), title);
+ EXPECT_EQ(title, watcher.WaitAndGetTitle());
+ }
+
+ ExpectPageTextEq("1");
+}
+
+// Checks that the DNT header is preserved when fetching from a page controlled
+// by a service worker which has a fetch handler but falls back to the network.
+IN_PROC_BROWSER_TEST_F(DoNotTrackTest,
+ FetchFromServiceWorkerControlledPage_PassThrough) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+ if (!EnableDoNotTrack())
+ return;
+
+ {
+ // Register a service worker which controls /service_worker.
+ const GURL url = embedded_test_server()->GetURL(
+ "/service_worker/create_service_worker.html?"
+ "worker_url=/service_worker/fetch_event_pass_through.js");
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+ const base::string16 title = base::ASCIIToUTF16("DONE");
+ TitleWatcher watcher(shell()->web_contents(), title);
+ EXPECT_EQ(title, watcher.WaitAndGetTitle());
+ }
+
+ {
+ // Issue a request from a controlled page.
+ const GURL url = embedded_test_server()->GetURL(
+ "/service_worker/fetch_from_page.html?url=/echoheader?DNT");
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+ const base::string16 title = base::ASCIIToUTF16("DONE");
+ TitleWatcher watcher(shell()->web_contents(), title);
+ EXPECT_EQ(title, watcher.WaitAndGetTitle());
+ }
+
+ ExpectPageTextEq("1");
+}
+
+// Checks that the DNT header is preserved when fetching from a page controlled
+// by a service worker which has a fetch handler and responds with fetch().
+IN_PROC_BROWSER_TEST_F(DoNotTrackTest,
+ FetchFromServiceWorkerControlledPage_RespondWithFetch) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+ if (!EnableDoNotTrack())
+ return;
+
+ {
+ // Register a service worker which controls /service_worker.
+ const GURL url = embedded_test_server()->GetURL(
+ "/service_worker/create_service_worker.html?"
+ "worker_url=/service_worker/fetch_event_respond_with_fetch.js");
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+ const base::string16 title = base::ASCIIToUTF16("DONE");
+ TitleWatcher watcher(shell()->web_contents(), title);
+ EXPECT_EQ(title, watcher.WaitAndGetTitle());
+ }
+
+ {
+ // Issue a request from a controlled page.
+ const GURL url = embedded_test_server()->GetURL(
+ "/service_worker/fetch_from_page.html?url=/echoheader?DNT");
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+ const base::string16 title = base::ASCIIToUTF16("DONE");
+ TitleWatcher watcher(shell()->web_contents(), title);
+ EXPECT_EQ(title, watcher.WaitAndGetTitle());
+ }
+
+ ExpectPageTextEq("1");
+}
+
} // namespace
} // namespace content
diff --git a/chromium/content/browser/dom_storage/OWNERS b/chromium/content/browser/dom_storage/OWNERS
index 19d6324eaf3..60343af7f2a 100644
--- a/chromium/content/browser/dom_storage/OWNERS
+++ b/chromium/content/browser/dom_storage/OWNERS
@@ -1,5 +1,9 @@
+# Primary
dmurph@chromium.org
mek@chromium.org
+# Secondary
+pwnall@chromium.org
+
# TEAM: storage-dev@chromium.org
# COMPONENT: Blink>Storage>DOMStorage
diff --git a/chromium/content/browser/dom_storage/README.md b/chromium/content/browser/dom_storage/README.md
new file mode 100644
index 00000000000..803f4757cf9
--- /dev/null
+++ b/chromium/content/browser/dom_storage/README.md
@@ -0,0 +1,105 @@
+# DOM Storage
+
+*Under Contruction*
+
+# Session Storage (Mojo)
+
+*Under Contruction*
+
+The browser manages the lifetime of session storage namespaces with
+[SessionStorageNamespaceImpl](
+https://cs.chromium.org/chromium/src/content/browser/dom_storage/session_storage_namespace_impl.h).
+
+The object calls [`SessionStorageContextMojo::CreateSessionNamespace`](
+https://cs.chromium.org/chromium/src/content/browser/dom_storage/session_storage_context_mojo.h?dr=CSs&l=50)
+when it is created, and [`SessionStorageContextMojo::DeleteSessionNamespace`](
+https://cs.chromium.org/chromium/src/content/browser/dom_storage/session_storage_context_mojo.h?dr=CSs&l=53)
+when it's destructed.
+
+
+This object is primarily held by both the [`NavigationControllerImpl`](
+https://cs.chromium.org/chromium/src/content/browser/frame_host/navigation_controller_impl.h?dr=CSs&l=426)
+and in the [`ContentPlatformSpecificTabData`](
+https://cs.chromium.org/chromium/src/components/sessions/content/content_platform_specific_tab_data.h?dr=C&l=35)
+which is used to restore tabs. The services stores recent tab
+closures for possible browser restore [here](
+https://cs.chromium.org/chromium/src/components/sessions/core/tab_restore_service_helper.h?dr=C&l=186).
+
+In the future when it's fully mojo-ified, the lifetime will be managed by the
+mojo [`SessionStorageNamespace`](
+https://cs.chromium.org/chromium/src/content/common/storage_partition_service.mojom)
+which can be passed to the renderer and the session restore service. There will
+always need to be an ID though as we save this ID to disk in the session
+restore service.
+
+## High Level Access And Lifetime Flow
+
+ 1. Before a renderer tab is opened, a `SessionStorageNamespaceImpl` object is
+ created, which in turn calls
+ `SessionStorageContextMojo::CreateSessionNamespace`.
+ * This can happen by either navigation or session restore.
+ 1. The following can happen in any order:
+ * Renderer creation, usage, and destruction
+ * The `session_namespace_id` is sent to the renderer, which uses
+ `StorageParitionService` to access storage.
+ * The renderer is destroyed, calling
+ `SessionStorageContextMojo::DeleteSessionNamespace`.
+ * If `SetShouldPersist(true)` was not called (or called with false),
+ then the data is deleted from disk.
+ * `SetShouldPersist(true)` is called from the session restores service,
+ which means the data should NOT be deleted on disk when the namespace is
+ destroyed. This is called for all tabs that the session restore services
+ wants to persist to disk.
+ * The session restore service calls
+ `DomStorageContext::StartScavengingUnusedSessionStorage` to clean up any
+ namespaces that are on disk but were not used by any recreated tab. This
+ is an 'after startup task', and usually happens before `SetShouldPesist`
+ is called.
+
+## Possible Edge Case: Persisted Data vs Stale Disk Data
+
+Namespace is created, persisted, destroyed, and then we scavange unused session
+storage.
+
+Flow:
+ 1. `SessionStorageContextMojo::CreateSessionNamespace`
+ 1. `SetShouldPersist(true)`
+ 1. `SessionStorageContextMojo::DeleteSessionNamespace`
+ 1. `DomStorageContext::StartScavengingUnusedSessionStorage`
+ 1. The data should still reside on disk after scavenging.
+
+The namespace could accidentally be considered a 'leftover' namespace by the
+scavenging algorithm and deleted from disk.
+
+## Navigation Details
+
+When navigating from a previous frame, the previous frame will allocate a new
+session storage id for the new frame, as well as issue the 'clone' call [here](https://cs.chromium.org/chromium/src/content/renderer/render_view_impl.cc?q=RenderViewImpl::RenderViewImpl&l=1273).
+
+The `session_namespace_id` for a frame's session storage is stored in the
+`CreateNewWindowParams` object in [frame.mojom](https://cs.chromium.org/chromium/src/content/common/frame.mojom).
+
+If the frame wasn't created from a previous frame, the SessionStorage namespace
+object is created [here](https://cs.chromium.org/chromium/src/content/browser/frame_host/navigation_controller_impl.cc?type=cs&l=1904)
+and the id is accessed [here](https://cs.chromium.org/chromium/src/content/browser/renderer_host/render_view_host_impl.cc?type=cs&l=321).
+
+## Renderer Connection to Session Storage
+
+Renderers use the `session_namespace_id` from the `CreateNewWindowParams`. They
+access session storage by using [`StoragePartitionService::OpenSessionStorage`](
+https://cs.chromium.org/chromium/src/content/common/storage_partition_service.mojom),
+and then `SessionStorageNamespace::OpenArea` with the `session_namespace_id`.
+
+They can then bind to a `LevelDBWrapper` on a per-origin basis.
+
+## Session Restore Service Interaction
+
+A reference to the session is stored in the [`ContentPlatformSpecificTabData`](
+https://cs.chromium.org/chromium/src/components/sessions/content/content_platform_specific_tab_data.h?dr=C&l=35)
+which is used to restore recently closed tabs. The services stores recent tab
+closures for possible browser restore [here](
+https://cs.chromium.org/chromium/src/components/sessions/core/tab_restore_service_helper.h?dr=C&l=186).
+
+When tabs are inserted, the session storage service saves the id to disk [here](https://cs.chromium.org/chromium/src/chrome/browser/sessions/session_service.cc?type=cs&l=313)
+using the `commands` (which are saved to disk). The session id is also accessed
+here for saving in `commands` in `TabClosing` and `BuildCommandsForTab`.
diff --git a/chromium/content/browser/dom_storage/dom_storage_context_impl.h b/chromium/content/browser/dom_storage/dom_storage_context_impl.h
index c2177798926..2c1e6c8b229 100644
--- a/chromium/content/browser/dom_storage/dom_storage_context_impl.h
+++ b/chromium/content/browser/dom_storage/dom_storage_context_impl.h
@@ -217,7 +217,7 @@ class CONTENT_EXPORT DOMStorageContextImpl
scoped_refptr<DOMStorageTaskRunner> task_runner_;
// List of objects observing local storage events.
- base::ObserverList<EventObserver> event_observers_;
+ base::ObserverList<EventObserver>::Unchecked event_observers_;
// For diagnostic purposes.
base::circular_deque<std::string> recently_deleted_session_ids_;
diff --git a/chromium/content/browser/dom_storage/dom_storage_context_wrapper.cc b/chromium/content/browser/dom_storage/dom_storage_context_wrapper.cc
index 3d71c01f1ec..1f5335f00de 100644
--- a/chromium/content/browser/dom_storage/dom_storage_context_wrapper.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_context_wrapper.cc
@@ -19,7 +19,7 @@
#include "base/sequenced_task_runner.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "content/browser/dom_storage/dom_storage_area.h"
@@ -35,7 +35,7 @@
#include "content/public/common/content_client.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
-#include "sql/connection.h"
+#include "sql/database.h"
namespace content {
namespace {
@@ -128,7 +128,7 @@ DOMStorageContextWrapper::DOMStorageContextWrapper(
base::TaskShutdownBehavior::BLOCK_SHUTDOWN});
scoped_refptr<base::SequencedTaskRunner> commit_sequence =
base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BACKGROUND,
+ {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::BLOCK_SHUTDOWN});
legacy_localstorage_path_ =
@@ -173,7 +173,8 @@ DOMStorageContextWrapper::DOMStorageContextWrapper(
base::MemoryCoordinatorClientRegistry::GetInstance()->Register(this);
} else {
memory_pressure_listener_.reset(new base::MemoryPressureListener(
- base::Bind(&DOMStorageContextWrapper::OnMemoryPressure, this)));
+ base::BindRepeating(&DOMStorageContextWrapper::OnMemoryPressure,
+ base::Unretained(this))));
}
}
@@ -243,7 +244,7 @@ void DOMStorageContextWrapper::DeleteLocalStorage(const GURL& origin,
if (!legacy_localstorage_path_.empty()) {
context_->task_runner()->PostShutdownBlockingTask(
FROM_HERE, DOMStorageTaskRunner::PRIMARY_SEQUENCE,
- base::BindOnce(base::IgnoreResult(&sql::Connection::Delete),
+ base::BindOnce(base::IgnoreResult(&sql::Database::Delete),
legacy_localstorage_path_.Append(
DOMStorageArea::DatabaseFileNameFromOrigin(
url::Origin::Create(origin)))));
@@ -395,6 +396,7 @@ void DOMStorageContextWrapper::OpenLocalStorage(
void DOMStorageContextWrapper::OpenSessionStorage(
int process_id,
const std::string& namespace_id,
+ mojo::ReportBadMessageCallback bad_message_callback,
blink::mojom::SessionStorageNamespaceRequest request) {
if (!mojo_session_state_)
return;
@@ -403,9 +405,11 @@ void DOMStorageContextWrapper::OpenSessionStorage(
// as soon as that task is posted, mojo_state_ is set to null, preventing
// further tasks from being queued.
mojo_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&SessionStorageContextMojo::OpenSessionStorage,
- base::Unretained(mojo_session_state_),
- process_id, namespace_id, std::move(request)));
+ FROM_HERE,
+ base::BindOnce(&SessionStorageContextMojo::OpenSessionStorage,
+ base::Unretained(mojo_session_state_), process_id,
+ namespace_id, std::move(bad_message_callback),
+ std::move(request)));
}
void DOMStorageContextWrapper::SetLocalStorageDatabaseForTesting(
diff --git a/chromium/content/browser/dom_storage/dom_storage_context_wrapper.h b/chromium/content/browser/dom_storage/dom_storage_context_wrapper.h
index 9ab2eed323a..ac7e069f4c7 100644
--- a/chromium/content/browser/dom_storage/dom_storage_context_wrapper.h
+++ b/chromium/content/browser/dom_storage/dom_storage_context_wrapper.h
@@ -18,6 +18,7 @@
#include "content/browser/dom_storage/dom_storage_context_impl.h"
#include "content/common/content_export.h"
#include "content/public/browser/dom_storage_context.h"
+#include "mojo/public/cpp/bindings/message.h"
#include "third_party/blink/public/mojom/dom_storage/session_storage_namespace.mojom.h"
#include "third_party/blink/public/mojom/dom_storage/storage_area.mojom.h"
#include "url/origin.h"
@@ -83,6 +84,7 @@ class CONTENT_EXPORT DOMStorageContextWrapper
blink::mojom::StorageAreaRequest request);
void OpenSessionStorage(int process_id,
const std::string& namespace_id,
+ mojo::ReportBadMessageCallback bad_message_callback,
blink::mojom::SessionStorageNamespaceRequest request);
void SetLocalStorageDatabaseForTesting(
diff --git a/chromium/content/browser/dom_storage/dom_storage_database.cc b/chromium/content/browser/dom_storage/dom_storage_database.cc
index b260d7f3e46..2609b896ee6 100644
--- a/chromium/content/browser/dom_storage/dom_storage_database.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_database.cc
@@ -35,7 +35,7 @@ DOMStorageDatabase::~DOMStorageDatabase() {
if (known_to_be_empty_ && !file_path_.empty()) {
// Delete the db and any lingering journal file from disk.
Close();
- sql::Connection::Delete(file_path_);
+ sql::Database::Delete(file_path_);
}
}
@@ -148,7 +148,7 @@ bool DOMStorageDatabase::LazyOpen(bool create_if_needed) {
return false;
}
- db_.reset(new sql::Connection());
+ db_.reset(new sql::Database());
db_->set_histogram_tag("DOMStorageDatabase");
// This db does not use [meta] table, store mmap status data elsewhere.
@@ -173,7 +173,7 @@ bool DOMStorageDatabase::LazyOpen(bool create_if_needed) {
}
}
- // sql::Connection uses UTF-8 encoding, but WebCore style databases use
+ // sql::Database uses UTF-8 encoding, but WebCore style databases use
// UTF-16, so ensure we match.
ignore_result(db_->Execute("PRAGMA encoding=\"UTF-16\""));
@@ -186,12 +186,8 @@ bool DOMStorageDatabase::LazyOpen(bool create_if_needed) {
// and whether it's usable (i.e. not corrupted).
SchemaVersion current_version = DetectSchemaVersion();
- if (current_version == V2) {
+ if (current_version == V2)
return true;
- } else if (current_version == V1) {
- if (UpgradeVersion1To2())
- return true;
- }
}
// This is the exceptional case - to try and recover we'll attempt
@@ -206,7 +202,7 @@ DOMStorageDatabase::SchemaVersion DOMStorageDatabase::DetectSchemaVersion() {
// Connection::Open() may succeed even if the file we try and open is not a
// database, however in the case that the database is corrupted to the point
// that SQLite doesn't actually think it's a database,
- // sql::Connection::GetCachedStatement will DCHECK when we later try and
+ // sql::Database::GetCachedStatement will DCHECK when we later try and
// run statements. So we run a query here that will not DCHECK but fail
// on an invalid database to verify that what we've opened is usable.
if (db_->ExecuteAndReturnErrorCode("PRAGMA auto_vacuum") != SQLITE_OK)
@@ -218,20 +214,7 @@ DOMStorageDatabase::SchemaVersion DOMStorageDatabase::DetectSchemaVersion() {
!db_->DoesColumnExist("ItemTable", "value"))
return INVALID;
- // We must use a unique statement here as we aren't going to step it.
- sql::Statement statement(
- db_->GetUniqueStatement("SELECT key,value from ItemTable LIMIT 1"));
- if (statement.DeclaredColumnType(0) != sql::COLUMN_TYPE_TEXT)
- return INVALID;
-
- switch (statement.DeclaredColumnType(1)) {
- case sql::COLUMN_TYPE_BLOB:
- return V2;
- case sql::COLUMN_TYPE_TEXT:
- return V1;
- default:
- return INVALID;
- }
+ return V2;
}
bool DOMStorageDatabase::CreateTableV2() {
@@ -254,8 +237,7 @@ bool DOMStorageDatabase::DeleteFileAndRecreate() {
tried_to_recreate_ = true;
// If it's not a directory and we can delete the file, try and open it again.
- if (!base::DirectoryExists(file_path_) &&
- sql::Connection::Delete(file_path_)) {
+ if (!base::DirectoryExists(file_path_) && sql::Database::Delete(file_path_)) {
return LazyOpen(true);
}
@@ -263,32 +245,6 @@ bool DOMStorageDatabase::DeleteFileAndRecreate() {
return false;
}
-bool DOMStorageDatabase::UpgradeVersion1To2() {
- DCHECK(IsOpen());
- DCHECK(DetectSchemaVersion() == V1);
-
- sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE,
- "SELECT * FROM ItemTable"));
- DCHECK(statement.is_valid());
-
- // Need to migrate from TEXT value column to BLOB.
- // Store the current database content so we can re-insert
- // the data into the new V2 table.
- DOMStorageValuesMap values;
- while (statement.Step()) {
- base::string16 key = statement.ColumnString16(0);
- base::NullableString16 value(statement.ColumnString16(1), false);
- values[key] = value;
- }
-
- sql::Transaction migration(db_.get());
- return migration.Begin() &&
- db_->Execute("DROP TABLE ItemTable") &&
- CreateTableV2() &&
- CommitChanges(false, values) &&
- migration.Commit();
-}
-
void DOMStorageDatabase::Close() {
db_.reset(nullptr);
}
diff --git a/chromium/content/browser/dom_storage/dom_storage_database.h b/chromium/content/browser/dom_storage/dom_storage_database.h
index 5ea7d79329b..77bed12178c 100644
--- a/chromium/content/browser/dom_storage/dom_storage_database.h
+++ b/chromium/content/browser/dom_storage/dom_storage_database.h
@@ -15,7 +15,7 @@
#include "base/strings/string16.h"
#include "content/common/content_export.h"
#include "content/common/dom_storage/dom_storage_types.h"
-#include "sql/connection.h"
+#include "sql/database.h"
namespace base {
namespace trace_event {
@@ -80,8 +80,11 @@ class CONTENT_EXPORT DOMStorageDatabase {
enum SchemaVersion {
INVALID,
- V1,
- V2
+
+ // V1 is deprecated.
+
+ // 2011-07-15 - https://bugs.webkit.org/show_bug.cgi?id=58762
+ V2,
};
// Open the database at file_path_ if it exists already and creates it if
@@ -105,12 +108,6 @@ class CONTENT_EXPORT DOMStorageDatabase {
// scratch.
bool DeleteFileAndRecreate();
- // Version 1 -> 2 migrates the value column in the ItemTable from a TEXT
- // to a BLOB. Exisitng data is preserved on success. Returns false if the
- // upgrade failed. If true is returned, the database is guaranteed to be at
- // version 2.
- bool UpgradeVersion1To2();
-
void Close();
bool IsOpen() const { return db_.get() ? db_->is_open() : false; }
@@ -119,7 +116,7 @@ class CONTENT_EXPORT DOMStorageDatabase {
// Path to the database on disk.
const base::FilePath file_path_;
- std::unique_ptr<sql::Connection> db_;
+ std::unique_ptr<sql::Database> db_;
bool failed_to_open_;
bool tried_to_recreate_;
bool known_to_be_empty_;
diff --git a/chromium/content/browser/dom_storage/dom_storage_database_unittest.cc b/chromium/content/browser/dom_storage/dom_storage_database_unittest.cc
index d3b199a0e86..7c83def70b8 100644
--- a/chromium/content/browser/dom_storage/dom_storage_database_unittest.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_database_unittest.cc
@@ -18,16 +18,7 @@ using base::ASCIIToUTF16;
namespace content {
-void CreateV1Table(sql::Connection* db) {
- ASSERT_TRUE(db->is_open());
- ASSERT_TRUE(db->Execute("DROP TABLE IF EXISTS ItemTable"));
- ASSERT_TRUE(db->Execute(
- "CREATE TABLE ItemTable ("
- "key TEXT UNIQUE ON CONFLICT REPLACE, "
- "value TEXT NOT NULL ON CONFLICT FAIL)"));
-}
-
-void CreateV2Table(sql::Connection* db) {
+void CreateV2Table(sql::Database* db) {
ASSERT_TRUE(db->is_open());
ASSERT_TRUE(db->Execute("DROP TABLE IF EXISTS ItemTable"));
ASSERT_TRUE(db->Execute(
@@ -36,37 +27,15 @@ void CreateV2Table(sql::Connection* db) {
"value BLOB NOT NULL ON CONFLICT FAIL)"));
}
-void CreateInvalidKeyColumnTable(sql::Connection* db) {
- // Create a table with the key type as FLOAT - this is "invalid"
+void CreateInvalidTable(sql::Database* db) {
+ // Create a table with out a key column - this is "invalid"
// as far as the DOM Storage db is concerned.
ASSERT_TRUE(db->is_open());
ASSERT_TRUE(db->Execute("DROP TABLE IF EXISTS ItemTable"));
ASSERT_TRUE(db->Execute(
"CREATE TABLE IF NOT EXISTS ItemTable ("
- "key FLOAT UNIQUE ON CONFLICT REPLACE, "
"value BLOB NOT NULL ON CONFLICT FAIL)"));
}
-void CreateInvalidValueColumnTable(sql::Connection* db) {
- // Create a table with the value type as FLOAT - this is "invalid"
- // as far as the DOM Storage db is concerned.
- ASSERT_TRUE(db->is_open());
- ASSERT_TRUE(db->Execute("DROP TABLE IF EXISTS ItemTable"));
- ASSERT_TRUE(db->Execute(
- "CREATE TABLE IF NOT EXISTS ItemTable ("
- "key TEXT UNIQUE ON CONFLICT REPLACE, "
- "value FLOAT NOT NULL ON CONFLICT FAIL)"));
-}
-
-void InsertDataV1(sql::Connection* db,
- const base::string16& key,
- const base::string16& value) {
- sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE,
- "INSERT INTO ItemTable VALUES (?,?)"));
- statement.BindString16(0, key);
- statement.BindString16(1, value);
- ASSERT_TRUE(statement.is_valid());
- statement.Run();
-}
void CheckValuesMatch(DOMStorageDatabase* db,
const DOMStorageValuesMap& expected) {
@@ -198,42 +167,16 @@ TEST(DOMStorageDatabaseTest, TestLazyOpenIsLazy) {
TEST(DOMStorageDatabaseTest, TestDetectSchemaVersion) {
DOMStorageDatabase db;
- db.db_.reset(new sql::Connection());
+ db.db_.reset(new sql::Database());
ASSERT_TRUE(db.db_->OpenInMemory());
- CreateInvalidValueColumnTable(db.db_.get());
+ CreateInvalidTable(db.db_.get());
EXPECT_EQ(DOMStorageDatabase::INVALID, db.DetectSchemaVersion());
- CreateInvalidKeyColumnTable(db.db_.get());
- EXPECT_EQ(DOMStorageDatabase::INVALID, db.DetectSchemaVersion());
-
- CreateV1Table(db.db_.get());
- EXPECT_EQ(DOMStorageDatabase::V1, db.DetectSchemaVersion());
-
CreateV2Table(db.db_.get());
EXPECT_EQ(DOMStorageDatabase::V2, db.DetectSchemaVersion());
}
-TEST(DOMStorageDatabaseTest, TestLazyOpenUpgradesDatabase) {
- // This test needs to operate with a file on disk so that we
- // can create a table at version 1 and then close it again
- // so that LazyOpen sees there is work to do (LazyOpen will return
- // early if the database is already open).
- base::ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
- base::FilePath file_name =
- temp_dir.GetPath().AppendASCII("TestDOMStorageDatabase.db");
-
- DOMStorageDatabase db(file_name);
- db.db_.reset(new sql::Connection());
- ASSERT_TRUE(db.db_->Open(file_name));
- CreateV1Table(db.db_.get());
- db.Close();
-
- EXPECT_TRUE(db.LazyOpen(true));
- EXPECT_EQ(DOMStorageDatabase::V2, db.DetectSchemaVersion());
-}
-
TEST(DOMStorageDatabaseTest, SimpleWriteAndReadBack) {
DOMStorageDatabase db;
@@ -266,25 +209,6 @@ TEST(DOMStorageDatabaseTest, WriteWithClear) {
CheckValuesMatch(&db, storage);
}
-TEST(DOMStorageDatabaseTest, UpgradeFromV1ToV2WithData) {
- const base::string16 kCannedKey = ASCIIToUTF16("foo");
- const base::NullableString16 kCannedValue(ASCIIToUTF16("bar"), false);
- DOMStorageValuesMap expected;
- expected[kCannedKey] = kCannedValue;
-
- DOMStorageDatabase db;
- db.db_.reset(new sql::Connection());
- ASSERT_TRUE(db.db_->OpenInMemory());
- CreateV1Table(db.db_.get());
- InsertDataV1(db.db_.get(), kCannedKey, kCannedValue.string());
-
- ASSERT_TRUE(db.UpgradeVersion1To2());
-
- EXPECT_EQ(DOMStorageDatabase::V2, db.DetectSchemaVersion());
-
- CheckValuesMatch(&db, expected);
-}
-
TEST(DOMStorageDatabaseTest, TestSimpleRemoveOneValue) {
DOMStorageDatabase db;
diff --git a/chromium/content/browser/dom_storage/local_storage_context_mojo.cc b/chromium/content/browser/dom_storage/local_storage_context_mojo.cc
index 3d90057ed86..2ace7b3ef8b 100644
--- a/chromium/content/browser/dom_storage/local_storage_context_mojo.cc
+++ b/chromium/content/browser/dom_storage/local_storage_context_mojo.cc
@@ -32,7 +32,7 @@
#include "content/public/browser/local_storage_usage_info.h"
#include "services/file/public/mojom/constants.mojom.h"
#include "services/service_manager/public/cpp/connector.h"
-#include "sql/connection.h"
+#include "sql/database.h"
#include "storage/browser/quota/special_storage_policy.h"
#include "third_party/leveldatabase/env_chromium.h"
#include "third_party/leveldatabase/leveldb_chrome.h"
@@ -264,7 +264,7 @@ class LocalStorageContextMojo::StorageAreaHolder final
deleted_old_data_ = true;
context_->task_runner_->PostShutdownBlockingTask(
FROM_HERE, DOMStorageTaskRunner::PRIMARY_SEQUENCE,
- base::BindOnce(base::IgnoreResult(&sql::Connection::Delete),
+ base::BindOnce(base::IgnoreResult(&sql::Database::Delete),
sql_db_path()));
}
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 a01c79873af..1a9716341c2 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
@@ -1081,7 +1081,6 @@ TEST_F(LocalStorageContextMojoTestWithService, RecreateOnCommitFailure) {
area1->Put(key, value, base::nullopt, "source",
base::BindLambdaForTesting([&](bool success) {
EXPECT_TRUE(success);
- put_loop.Quit();
}));
put_loop.RunUntilIdle();
values_written++;
@@ -1093,6 +1092,7 @@ TEST_F(LocalStorageContextMojoTestWithService, RecreateOnCommitFailure) {
// Make sure all messages to the DB have been processed (Flush above merely
// schedules a commit, but there is no guarantee about those having been
// processed yet).
+ mock_leveldb_service.FlushBindingsForTesting();
if (mock_db)
mock_db->FlushForTesting();
// At this point enough commit failures should have happened to cause the
diff --git a/chromium/content/browser/dom_storage/session_storage_area_impl_unittest.cc b/chromium/content/browser/dom_storage/session_storage_area_impl_unittest.cc
index 7fdc77561d6..30a580275b7 100644
--- a/chromium/content/browser/dom_storage/session_storage_area_impl_unittest.cc
+++ b/chromium/content/browser/dom_storage/session_storage_area_impl_unittest.cc
@@ -12,7 +12,7 @@
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "base/sequenced_task_runner.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "base/test/bind_test_util.h"
#include "base/test/scoped_task_environment.h"
#include "base/threading/thread.h"
diff --git a/chromium/content/browser/dom_storage/session_storage_context_mojo.cc b/chromium/content/browser/dom_storage/session_storage_context_mojo.cc
index a3998a49115..f64bab5bd63 100644
--- a/chromium/content/browser/dom_storage/session_storage_context_mojo.cc
+++ b/chromium/content/browser/dom_storage/session_storage_context_mojo.cc
@@ -121,25 +121,25 @@ SessionStorageContextMojo::~SessionStorageContextMojo() {
void SessionStorageContextMojo::OpenSessionStorage(
int process_id,
const std::string& namespace_id,
+ mojo::ReportBadMessageCallback bad_message_callback,
blink::mojom::SessionStorageNamespaceRequest request) {
if (connection_state_ != CONNECTION_FINISHED) {
RunWhenConnected(
base::BindOnce(&SessionStorageContextMojo::OpenSessionStorage,
weak_ptr_factory_.GetWeakPtr(), process_id, namespace_id,
- std::move(request)));
+ std::move(bad_message_callback), std::move(request)));
return;
}
auto found = namespaces_.find(namespace_id);
if (found == namespaces_.end()) {
- mojo::ReportBadMessage("Namespace not found: " + namespace_id);
+ std::move(bad_message_callback).Run("Namespace not found: " + namespace_id);
return;
}
if (!found->second->IsPopulated() &&
!found->second->waiting_on_clone_population()) {
found->second->PopulateFromMetadata(
- database_.get(), metadata_.GetOrCreateNamespaceEntry(namespace_id),
- data_maps_);
+ database_.get(), metadata_.GetOrCreateNamespaceEntry(namespace_id));
}
PurgeUnusedAreasIfNeeded();
@@ -439,6 +439,39 @@ bool SessionStorageContextMojo::OnMemoryDump(
return true;
}
+void SessionStorageContextMojo::SetDatabaseForTesting(
+ leveldb::mojom::LevelDBDatabaseAssociatedPtr database) {
+ DCHECK_EQ(connection_state_, NO_CONNECTION);
+ connection_state_ = CONNECTION_IN_PROGRESS;
+ database_ = std::move(database);
+ OnDatabaseOpened(true, leveldb::mojom::DatabaseError::OK);
+}
+
+void SessionStorageContextMojo::FlushAreaForTesting(
+ const std::string& namespace_id,
+ const url::Origin& origin) {
+ if (connection_state_ != CONNECTION_FINISHED)
+ return;
+ const auto& it = namespaces_.find(namespace_id);
+ if (it == namespaces_.end())
+ return;
+ it->second->FlushOriginForTesting(origin);
+}
+
+scoped_refptr<SessionStorageMetadata::MapData>
+SessionStorageContextMojo::RegisterNewAreaMap(
+ SessionStorageMetadata::NamespaceEntry namespace_entry,
+ const url::Origin& origin) {
+ std::vector<leveldb::mojom::BatchedOperationPtr> save_operations;
+ scoped_refptr<SessionStorageMetadata::MapData> map_entry =
+ metadata_.RegisterNewMap(namespace_entry, origin, &save_operations);
+
+ database_->Write(std::move(save_operations),
+ base::BindOnce(&SessionStorageContextMojo::OnCommitResult,
+ base::Unretained(this)));
+ return map_entry;
+}
+
void SessionStorageContextMojo::OnDataMapCreation(
const std::vector<uint8_t>& map_prefix,
SessionStorageDataMap* map) {
@@ -481,37 +514,13 @@ void SessionStorageContextMojo::OnCommitResult(
}
}
-void SessionStorageContextMojo::SetDatabaseForTesting(
- leveldb::mojom::LevelDBDatabaseAssociatedPtr database) {
- DCHECK_EQ(connection_state_, NO_CONNECTION);
- connection_state_ = CONNECTION_IN_PROGRESS;
- database_ = std::move(database);
- OnDatabaseOpened(true, leveldb::mojom::DatabaseError::OK);
-}
-
-void SessionStorageContextMojo::FlushAreaForTesting(
- const std::string& namespace_id,
- const url::Origin& origin) {
- if (connection_state_ != CONNECTION_FINISHED)
- return;
- const auto& it = namespaces_.find(namespace_id);
- if (it == namespaces_.end())
- return;
- it->second->FlushOriginForTesting(origin);
-}
-
-scoped_refptr<SessionStorageMetadata::MapData>
-SessionStorageContextMojo::RegisterNewAreaMap(
- SessionStorageMetadata::NamespaceEntry namespace_entry,
- const url::Origin& origin) {
- std::vector<leveldb::mojom::BatchedOperationPtr> save_operations;
- scoped_refptr<SessionStorageMetadata::MapData> map_entry =
- metadata_.RegisterNewMap(namespace_entry, origin, &save_operations);
-
- database_->Write(std::move(save_operations),
- base::BindOnce(&SessionStorageContextMojo::OnCommitResult,
- base::Unretained(this)));
- return map_entry;
+scoped_refptr<SessionStorageDataMap>
+SessionStorageContextMojo::MaybeGetExistingDataMapForId(
+ const std::vector<uint8_t>& map_number_as_bytes) {
+ auto it = data_maps_.find(map_number_as_bytes);
+ if (it == data_maps_.end())
+ return nullptr;
+ return base::WrapRefCounted(it->second);
}
void SessionStorageContextMojo::RegisterShallowClonedNamespace(
@@ -525,6 +534,7 @@ void SessionStorageContextMojo::RegisterShallowClonedNamespace(
if (it != namespaces_.end()) {
found = true;
if (it->second->IsPopulated()) {
+ // Assumes this method is called on a stack handling a mojo message.
mojo::ReportBadMessage("Cannot clone to already populated namespace");
return;
}
@@ -555,17 +565,12 @@ void SessionStorageContextMojo::RegisterShallowClonedNamespace(
std::unique_ptr<SessionStorageNamespaceImplMojo>
SessionStorageContextMojo::CreateSessionStorageNamespaceImplMojo(
std::string namespace_id) {
- SessionStorageNamespaceImplMojo::RegisterShallowClonedNamespace
- add_namespace_callback = base::BindRepeating(
- &SessionStorageContextMojo::RegisterShallowClonedNamespace,
- base::Unretained(this));
SessionStorageAreaImpl::RegisterNewAreaMap map_id_callback =
base::BindRepeating(&SessionStorageContextMojo::RegisterNewAreaMap,
base::Unretained(this));
return std::make_unique<SessionStorageNamespaceImplMojo>(
- std::move(namespace_id), this, std::move(add_namespace_callback),
- std::move(map_id_callback));
+ std::move(namespace_id), this, std::move(map_id_callback), this);
}
void SessionStorageContextMojo::DoDatabaseDelete(
diff --git a/chromium/content/browser/dom_storage/session_storage_context_mojo.h b/chromium/content/browser/dom_storage/session_storage_context_mojo.h
index 9a4c3aa3d20..3cf456dc89a 100644
--- a/chromium/content/browser/dom_storage/session_storage_context_mojo.h
+++ b/chromium/content/browser/dom_storage/session_storage_context_mojo.h
@@ -23,6 +23,7 @@
#include "content/browser/dom_storage/session_storage_namespace_impl_mojo.h"
#include "content/common/content_export.h"
#include "content/public/browser/session_storage_usage_info.h"
+#include "mojo/public/cpp/bindings/message.h"
#include "services/file/public/mojom/file_system.mojom.h"
#include "third_party/blink/public/mojom/dom_storage/session_storage_namespace.mojom.h"
#include "url/origin.h"
@@ -45,7 +46,8 @@ struct SessionStorageUsageInfo;
// ShutdownAndDelete (on the correct task runner).
class CONTENT_EXPORT SessionStorageContextMojo
: public base::trace_event::MemoryDumpProvider,
- public SessionStorageDataMap::Listener {
+ public SessionStorageDataMap::Listener,
+ public SessionStorageNamespaceImplMojo::Delegate {
public:
using GetStorageUsageCallback =
base::OnceCallback<void(std::vector<SessionStorageUsageInfo>)>;
@@ -82,6 +84,7 @@ class CONTENT_EXPORT SessionStorageContextMojo
void OpenSessionStorage(int process_id,
const std::string& namespace_id,
+ mojo::ReportBadMessageCallback bad_message_callback,
blink::mojom::SessionStorageNamespaceRequest request);
void CreateSessionNamespace(const std::string& namespace_id);
@@ -123,12 +126,6 @@ class CONTENT_EXPORT SessionStorageContextMojo
bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
base::trace_event::ProcessMemoryDump* pmd) override;
- // SessionStorageAreaImpl::Listener implementation:
- void OnDataMapCreation(const std::vector<uint8_t>& map_prefix,
- SessionStorageDataMap* map) override;
- void OnDataMapDestruction(const std::vector<uint8_t>& map_prefix) override;
- void OnCommitResult(leveldb::mojom::DatabaseError error) override;
-
// Sets the database for testing.
void SetDatabaseForTesting(
leveldb::mojom::LevelDBDatabaseAssociatedPtr database);
@@ -152,10 +149,20 @@ class CONTENT_EXPORT SessionStorageContextMojo
SessionStorageMetadata::NamespaceEntry namespace_entry,
const url::Origin& origin);
+ // SessionStorageAreaImpl::Listener implementation:
+ void OnDataMapCreation(const std::vector<uint8_t>& map_prefix,
+ SessionStorageDataMap* map) override;
+ void OnDataMapDestruction(const std::vector<uint8_t>& map_prefix) override;
+ void OnCommitResult(leveldb::mojom::DatabaseError error) override;
+
+ // SessionStorageNamespaceImplMojo::Delegate implementation:
+ scoped_refptr<SessionStorageDataMap> MaybeGetExistingDataMapForId(
+ const std::vector<uint8_t>& map_number_as_bytes) override;
void RegisterShallowClonedNamespace(
SessionStorageMetadata::NamespaceEntry source_namespace_entry,
const std::string& new_namespace_id,
- const SessionStorageNamespaceImplMojo::OriginAreas& clone_from_areas);
+ const SessionStorageNamespaceImplMojo::OriginAreas& clone_from_areas)
+ override;
std::unique_ptr<SessionStorageNamespaceImplMojo>
CreateSessionStorageNamespaceImplMojo(std::string namespace_id);
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 f09686f30e9..d7584324c3c 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
@@ -72,6 +72,11 @@ class SessionStorageContextMojoTest : public test::MojoTestWithFileService {
mojo::core::ProcessErrorCallback());
}
+ mojo::ReportBadMessageCallback GetBadMessageCallback() {
+ return base::BindOnce(&SessionStorageContextMojoTest::OnBadMessage,
+ base::Unretained(this));
+ }
+
void OnBadMessage(const std::string& reason) { bad_message_called_ = true; }
void SetBackingMode(SessionStorageContextMojo::BackingMode backing_mode) {
@@ -111,6 +116,7 @@ class SessionStorageContextMojoTest : public test::MojoTestWithFileService {
context()->CreateSessionNamespace(namespace_id);
blink::mojom::SessionStorageNamespacePtr ss_namespace;
context()->OpenSessionStorage(kTestProcessId, namespace_id,
+ GetBadMessageCallback(),
mojo::MakeRequest(&ss_namespace));
blink::mojom::StorageAreaAssociatedPtr leveldb;
ss_namespace->OpenArea(origin, mojo::MakeRequest(&leveldb));
@@ -127,6 +133,7 @@ class SessionStorageContextMojoTest : public test::MojoTestWithFileService {
context()->CreateSessionNamespace(namespace_id);
blink::mojom::SessionStorageNamespacePtr ss_namespace;
context()->OpenSessionStorage(kTestProcessId, namespace_id,
+ GetBadMessageCallback(),
mojo::MakeRequest(&ss_namespace));
blink::mojom::StorageAreaAssociatedPtr leveldb;
ss_namespace->OpenArea(origin, mojo::MakeRequest(&leveldb));
@@ -188,9 +195,11 @@ TEST_F(SessionStorageContextMojoTest, MigrationV0ToV1) {
blink::mojom::SessionStorageNamespacePtr ss_namespace1;
context()->OpenSessionStorage(kTestProcessId, namespace_id1,
+ GetBadMessageCallback(),
mojo::MakeRequest(&ss_namespace1));
blink::mojom::SessionStorageNamespacePtr ss_namespace2;
context()->OpenSessionStorage(kTestProcessId, namespace_id2,
+ GetBadMessageCallback(),
mojo::MakeRequest(&ss_namespace2));
blink::mojom::StorageAreaAssociatedPtr leveldb_n2_o1;
@@ -220,6 +229,7 @@ TEST_F(SessionStorageContextMojoTest, StartupShutdownSave) {
blink::mojom::SessionStorageNamespacePtr ss_namespace1;
context()->OpenSessionStorage(kTestProcessId, namespace_id1,
+ GetBadMessageCallback(),
mojo::MakeRequest(&ss_namespace1));
blink::mojom::StorageAreaAssociatedPtr leveldb_n1_o1;
@@ -247,6 +257,7 @@ TEST_F(SessionStorageContextMojoTest, StartupShutdownSave) {
// This will re-open the context, and load the persisted namespace.
context()->CreateSessionNamespace(namespace_id1);
context()->OpenSessionStorage(kTestProcessId, namespace_id1,
+ GetBadMessageCallback(),
mojo::MakeRequest(&ss_namespace1));
ss_namespace1->OpenArea(origin1, mojo::MakeRequest(&leveldb_n1_o1));
@@ -261,6 +272,7 @@ TEST_F(SessionStorageContextMojoTest, StartupShutdownSave) {
// This will re-open the context, and the namespace should be empty.
context()->CreateSessionNamespace(namespace_id1);
context()->OpenSessionStorage(kTestProcessId, namespace_id1,
+ GetBadMessageCallback(),
mojo::MakeRequest(&ss_namespace1));
ss_namespace1->OpenArea(origin1, mojo::MakeRequest(&leveldb_n1_o1));
@@ -276,6 +288,7 @@ TEST_F(SessionStorageContextMojoTest, CloneBeforeBrowserClone) {
context()->CreateSessionNamespace(namespace_id1);
blink::mojom::SessionStorageNamespacePtr ss_namespace1;
context()->OpenSessionStorage(kTestProcessId, namespace_id1,
+ GetBadMessageCallback(),
mojo::MakeRequest(&ss_namespace1));
blink::mojom::StorageAreaAssociatedPtr leveldb_n1_o1;
ss_namespace1->OpenArea(origin1, mojo::MakeRequest(&leveldb_n1_o1));
@@ -296,6 +309,7 @@ TEST_F(SessionStorageContextMojoTest, CloneBeforeBrowserClone) {
// Open the second namespace.
blink::mojom::SessionStorageNamespacePtr ss_namespace2;
context()->OpenSessionStorage(kTestProcessId, namespace_id2,
+ GetBadMessageCallback(),
mojo::MakeRequest(&ss_namespace2));
blink::mojom::StorageAreaAssociatedPtr leveldb_n2_o1;
ss_namespace2->OpenArea(origin1, mojo::MakeRequest(&leveldb_n2_o1));
@@ -313,6 +327,7 @@ TEST_F(SessionStorageContextMojoTest, Cloning) {
context()->CreateSessionNamespace(namespace_id1);
blink::mojom::SessionStorageNamespacePtr ss_namespace1;
context()->OpenSessionStorage(kTestProcessId, namespace_id1,
+ GetBadMessageCallback(),
mojo::MakeRequest(&ss_namespace1));
blink::mojom::StorageAreaAssociatedPtr leveldb_n1_o1;
ss_namespace1->OpenArea(origin1, mojo::MakeRequest(&leveldb_n1_o1));
@@ -334,6 +349,7 @@ TEST_F(SessionStorageContextMojoTest, Cloning) {
// Open the second namespace.
blink::mojom::SessionStorageNamespacePtr ss_namespace2;
context()->OpenSessionStorage(kTestProcessId, namespace_id2,
+ GetBadMessageCallback(),
mojo::MakeRequest(&ss_namespace2));
blink::mojom::StorageAreaAssociatedPtr leveldb_n2_o1;
ss_namespace2->OpenArea(origin1, mojo::MakeRequest(&leveldb_n2_o1));
@@ -358,6 +374,7 @@ TEST_F(SessionStorageContextMojoTest, Cloning) {
// Re-open namespace 1, check that we don't have the extra data.
context()->CreateSessionNamespace(namespace_id1);
context()->OpenSessionStorage(kTestProcessId, namespace_id1,
+ GetBadMessageCallback(),
mojo::MakeRequest(&ss_namespace1));
ss_namespace1->OpenArea(origin1, mojo::MakeRequest(&leveldb_n1_o1));
@@ -374,6 +391,7 @@ TEST_F(SessionStorageContextMojoTest, ImmediateCloning) {
context()->CreateSessionNamespace(namespace_id1);
blink::mojom::SessionStorageNamespacePtr ss_namespace1;
context()->OpenSessionStorage(kTestProcessId, namespace_id1,
+ GetBadMessageCallback(),
mojo::MakeRequest(&ss_namespace1));
blink::mojom::StorageAreaAssociatedPtr leveldb_n1_o1;
ss_namespace1->OpenArea(origin1, mojo::MakeRequest(&leveldb_n1_o1));
@@ -387,6 +405,7 @@ TEST_F(SessionStorageContextMojoTest, ImmediateCloning) {
{
blink::mojom::SessionStorageNamespacePtr ss_namespace2;
context()->OpenSessionStorage(kTestProcessId, namespace_id2,
+ GetBadMessageCallback(),
mojo::MakeRequest(&ss_namespace2));
blink::mojom::StorageAreaAssociatedPtr leveldb_n2_o1;
ss_namespace2->OpenArea(origin1, mojo::MakeRequest(&leveldb_n2_o1));
@@ -411,6 +430,7 @@ TEST_F(SessionStorageContextMojoTest, ImmediateCloning) {
{
blink::mojom::SessionStorageNamespacePtr ss_namespace2;
context()->OpenSessionStorage(kTestProcessId, namespace_id2,
+ GetBadMessageCallback(),
mojo::MakeRequest(&ss_namespace2));
blink::mojom::StorageAreaAssociatedPtr leveldb_n2_o1;
ss_namespace2->OpenArea(origin1, mojo::MakeRequest(&leveldb_n2_o1));
@@ -457,6 +477,7 @@ TEST_F(SessionStorageContextMojoTest, Scavenging) {
blink::mojom::SessionStorageNamespacePtr ss_namespace1;
context()->OpenSessionStorage(kTestProcessId, namespace_id1,
+ GetBadMessageCallback(),
mojo::MakeRequest(&ss_namespace1));
blink::mojom::StorageAreaAssociatedPtr leveldb_n1_o1;
ss_namespace1->OpenArea(origin1, mojo::MakeRequest(&leveldb_n1_o1));
@@ -490,6 +511,7 @@ TEST_F(SessionStorageContextMojoTest, Scavenging) {
// data.
context()->CreateSessionNamespace(namespace_id1);
context()->OpenSessionStorage(kTestProcessId, namespace_id1,
+ GetBadMessageCallback(),
mojo::MakeRequest(&ss_namespace1));
ss_namespace1->OpenArea(origin1, mojo::MakeRequest(&leveldb_n1_o1));
std::vector<blink::mojom::KeyValuePtr> data;
@@ -509,6 +531,7 @@ TEST_F(SessionStorageContextMojoTest, Scavenging) {
}
context()->CreateSessionNamespace(namespace_id1);
context()->OpenSessionStorage(kTestProcessId, namespace_id1,
+ GetBadMessageCallback(),
mojo::MakeRequest(&ss_namespace1));
ss_namespace1->OpenArea(origin1, mojo::MakeRequest(&leveldb_n1_o1));
EXPECT_TRUE(test::GetAllSync(leveldb_n1_o1.get(), &data));
@@ -616,6 +639,7 @@ TEST_F(SessionStorageContextMojoTest, RecreateOnCommitFailure) {
base::RunLoop loop;
fake_leveldb_service.SetOnOpenCallback(loop.QuitClosure());
context()->OpenSessionStorage(kTestProcessId, namespace_id,
+ GetBadMessageCallback(),
mojo::MakeRequest(&ss_namespace));
ss_namespace->OpenArea(origin1, mojo::MakeRequest(&area1));
ss_namespace->OpenArea(origin2, mojo::MakeRequest(&area2));
@@ -663,7 +687,6 @@ TEST_F(SessionStorageContextMojoTest, RecreateOnCommitFailure) {
area1->Put(leveldb::StringPieceToUint8Vector("key"), value, base::nullopt,
"source", base::BindLambdaForTesting([&](bool success) {
EXPECT_TRUE(success);
- put_loop.Quit();
}));
area1.FlushForTesting();
put_loop.RunUntilIdle();
@@ -674,6 +697,7 @@ TEST_F(SessionStorageContextMojoTest, RecreateOnCommitFailure) {
// Make sure all messages to the DB have been processed (Flush above merely
// schedules a commit, but there is no guarantee about those having been
// processed yet).
+ fake_leveldb_service.FlushBindingsForTesting();
if (mock_db)
mock_db->FlushForTesting();
// At this point enough commit failures should have happened to cause the
@@ -689,6 +713,7 @@ TEST_F(SessionStorageContextMojoTest, RecreateOnCommitFailure) {
// Reconnect area1 to the database, and try to read a value.
context()->OpenSessionStorage(kTestProcessId, namespace_id,
+ GetBadMessageCallback(),
mojo::MakeRequest(&ss_namespace));
ss_namespace->OpenArea(origin1, mojo::MakeRequest(&area1));
@@ -751,6 +776,7 @@ TEST_F(SessionStorageContextMojoTest, DontRecreateOnRepeatedCommitFailure) {
base::RunLoop loop;
fake_leveldb_service.SetOnOpenCallback(loop.QuitClosure());
context()->OpenSessionStorage(kTestProcessId, namespace_id,
+ GetBadMessageCallback(),
mojo::MakeRequest(&ss_namespace));
ss_namespace->OpenArea(origin1, mojo::MakeRequest(&area));
loop.Run();
@@ -822,6 +848,7 @@ TEST_F(SessionStorageContextMojoTest, DontRecreateOnRepeatedCommitFailure) {
// This time all should just keep getting written, and commit errors are
// getting ignored.
context()->OpenSessionStorage(kTestProcessId, namespace_id,
+ GetBadMessageCallback(),
mojo::MakeRequest(&ss_namespace));
ss_namespace->OpenArea(origin1, mojo::MakeRequest(&area));
old_value = base::nullopt;
@@ -861,10 +888,10 @@ TEST_F(SessionStorageContextMojoTest, GetUsage) {
context()->CreateSessionNamespace(namespace_id1);
blink::mojom::SessionStorageNamespacePtr ss_namespace1;
context()->OpenSessionStorage(kTestProcessId, namespace_id1,
+ GetBadMessageCallback(),
mojo::MakeRequest(&ss_namespace1));
blink::mojom::StorageAreaAssociatedPtr leveldb_n1_o1;
ss_namespace1->OpenArea(origin1, mojo::MakeRequest(&leveldb_n1_o1));
-
// Put some data.
EXPECT_TRUE(test::PutSync(
leveldb_n1_o1.get(), leveldb::StringPieceToUint8Vector("key1"),
@@ -889,6 +916,7 @@ TEST_F(SessionStorageContextMojoTest, DeleteStorage) {
context()->CreateSessionNamespace(namespace_id1);
blink::mojom::SessionStorageNamespacePtr ss_namespace1;
context()->OpenSessionStorage(kTestProcessId, namespace_id1,
+ GetBadMessageCallback(),
mojo::MakeRequest(&ss_namespace1));
blink::mojom::StorageAreaAssociatedPtr leveldb_n1_o1;
ss_namespace1->OpenArea(origin1, mojo::MakeRequest(&leveldb_n1_o1));
@@ -919,6 +947,7 @@ TEST_F(SessionStorageContextMojoTest, DeleteStorage) {
context()->CreateSessionNamespace(namespace_id1);
context()->OpenSessionStorage(kTestProcessId, namespace_id1,
+ GetBadMessageCallback(),
mojo::MakeRequest(&ss_namespace1));
ss_namespace1->OpenArea(origin1, mojo::MakeRequest(&leveldb_n1_o1));
data.clear();
@@ -934,6 +963,7 @@ TEST_F(SessionStorageContextMojoTest, PurgeInactiveWrappers) {
context()->CreateSessionNamespace(namespace_id1);
blink::mojom::SessionStorageNamespacePtr ss_namespace1;
context()->OpenSessionStorage(kTestProcessId, namespace_id1,
+ GetBadMessageCallback(),
mojo::MakeRequest(&ss_namespace1));
blink::mojom::StorageAreaAssociatedPtr leveldb;
ss_namespace1->OpenArea(origin1, mojo::MakeRequest(&leveldb));
@@ -961,6 +991,7 @@ TEST_F(SessionStorageContextMojoTest, PurgeInactiveWrappers) {
for (int i = 1; i <= 100; ++i) {
blink::mojom::SessionStorageNamespacePtr ss_namespace1;
context()->OpenSessionStorage(kTestProcessId, namespace_id1,
+ GetBadMessageCallback(),
mojo::MakeRequest(&ss_namespace1));
blink::mojom::StorageAreaAssociatedPtr leveldb;
ss_namespace1->OpenArea(url::Origin::Create(GURL(base::StringPrintf(
@@ -973,6 +1004,7 @@ TEST_F(SessionStorageContextMojoTest, PurgeInactiveWrappers) {
// And make sure caches were actually cleared.
context()->OpenSessionStorage(kTestProcessId, namespace_id1,
+ GetBadMessageCallback(),
mojo::MakeRequest(&ss_namespace1));
ss_namespace1->OpenArea(origin1, mojo::MakeRequest(&leveldb));
std::vector<blink::mojom::KeyValuePtr> data;
@@ -988,6 +1020,7 @@ TEST_F(SessionStorageContextMojoTest, ClearDiskState) {
blink::mojom::SessionStorageNamespacePtr ss_namespace1;
context()->OpenSessionStorage(kTestProcessId, namespace_id1,
+ GetBadMessageCallback(),
mojo::MakeRequest(&ss_namespace1));
blink::mojom::StorageAreaAssociatedPtr leveldb_n1_o1;
@@ -1012,6 +1045,7 @@ TEST_F(SessionStorageContextMojoTest, ClearDiskState) {
// should have been deleted due to our backing mode.
context()->CreateSessionNamespace(namespace_id1);
context()->OpenSessionStorage(kTestProcessId, namespace_id1,
+ GetBadMessageCallback(),
mojo::MakeRequest(&ss_namespace1));
ss_namespace1->OpenArea(origin1, mojo::MakeRequest(&leveldb_n1_o1));
@@ -1031,6 +1065,7 @@ TEST_F(SessionStorageContextMojoTest, PurgeMemoryDoesNotCrashOrHang) {
context()->CreateSessionNamespace(namespace_id1);
blink::mojom::SessionStorageNamespacePtr ss_namespace1;
context()->OpenSessionStorage(kTestProcessId, namespace_id1,
+ GetBadMessageCallback(),
mojo::MakeRequest(&ss_namespace1));
blink::mojom::StorageAreaAssociatedPtr leveldb_n1_o1;
ss_namespace1->OpenArea(origin1, mojo::MakeRequest(&leveldb_n1_o1));
@@ -1038,6 +1073,7 @@ TEST_F(SessionStorageContextMojoTest, PurgeMemoryDoesNotCrashOrHang) {
context()->CreateSessionNamespace(namespace_id2);
blink::mojom::SessionStorageNamespacePtr ss_namespace2;
context()->OpenSessionStorage(kTestProcessId, namespace_id2,
+ GetBadMessageCallback(),
mojo::MakeRequest(&ss_namespace2));
blink::mojom::StorageAreaAssociatedPtr leveldb_n2_o1;
ss_namespace2->OpenArea(origin1, mojo::MakeRequest(&leveldb_n2_o1));
diff --git a/chromium/content/browser/dom_storage/session_storage_database.cc b/chromium/content/browser/dom_storage/session_storage_database.cc
index cc9e839424a..2a8d889e3a4 100644
--- a/chromium/content/browser/dom_storage/session_storage_database.cc
+++ b/chromium/content/browser/dom_storage/session_storage_database.cc
@@ -7,6 +7,7 @@
#include <inttypes.h>
#include <stddef.h>
+#include <utility>
#include <vector>
#include "base/files/file_util.h"
@@ -430,7 +431,11 @@ bool SessionStorageDatabase::LazyOpen(bool create_if_needed) {
<< ", error: " << s.ToString();
// Clear the directory and try again.
- base::DeleteFile(file_path_, true);
+ s = leveldb_chrome::DeleteDB(file_path_, leveldb_env::Options());
+ if (!s.ok()) {
+ LOG(WARNING) << "Failed to delete leveldb in " << file_path_.value()
+ << ", error: " << s.ToString();
+ }
s = TryToOpen(&db_);
if (!s.ok()) {
LOG(WARNING) << "Failed to open leveldb in " << file_path_.value()
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 6bc8e13b918..136cf48e5b4 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
@@ -16,12 +16,12 @@ namespace content {
SessionStorageNamespaceImplMojo::SessionStorageNamespaceImplMojo(
std::string namespace_id,
SessionStorageDataMap::Listener* data_map_listener,
- RegisterShallowClonedNamespace add_namespace_callback,
- SessionStorageAreaImpl::RegisterNewAreaMap register_new_map_callback)
+ SessionStorageAreaImpl::RegisterNewAreaMap register_new_map_callback,
+ Delegate* delegate)
: namespace_id_(std::move(namespace_id)),
data_map_listener_(data_map_listener),
- add_namespace_callback_(std::move(add_namespace_callback)),
- register_new_map_callback_(std::move(register_new_map_callback)) {}
+ register_new_map_callback_(std::move(register_new_map_callback)),
+ delegate_(delegate) {}
SessionStorageNamespaceImplMojo::~SessionStorageNamespaceImplMojo() = default;
@@ -32,22 +32,19 @@ bool SessionStorageNamespaceImplMojo::HasAreaForOrigin(
void SessionStorageNamespaceImplMojo::PopulateFromMetadata(
leveldb::mojom::LevelDBDatabase* database,
- SessionStorageMetadata::NamespaceEntry namespace_metadata,
- const std::map<std::vector<uint8_t>, SessionStorageDataMap*>&
- current_data_maps) {
+ SessionStorageMetadata::NamespaceEntry namespace_metadata) {
DCHECK(!IsPopulated());
DCHECK(!waiting_on_clone_population());
database_ = database;
populated_ = true;
namespace_entry_ = namespace_metadata;
for (const auto& pair : namespace_entry_->second) {
- scoped_refptr<SessionStorageDataMap> data_map;
- auto map_it = current_data_maps.find(pair.second->MapNumberAsBytes());
- if (map_it == current_data_maps.end()) {
+ scoped_refptr<SessionStorageDataMap> data_map =
+ delegate_->MaybeGetExistingDataMapForId(
+ pair.second->MapNumberAsBytes());
+ if (!data_map) {
data_map = SessionStorageDataMap::Create(data_map_listener_, pair.second,
database_);
- } else {
- data_map = base::WrapRefCounted(map_it->second);
}
origin_areas_[pair.first] = std::make_unique<SessionStorageAreaImpl>(
namespace_entry_, pair.first, std::move(data_map),
@@ -145,23 +142,29 @@ void SessionStorageNamespaceImplMojo::OpenArea(
}
auto it = origin_areas_.find(origin);
if (it == origin_areas_.end()) {
- scoped_refptr<SessionStorageMetadata::MapData> map_data;
// The area may have been purged due to lack of bindings, so check the
// metadata for the map.
- auto map_it = namespace_entry_->second.find(origin);
- if (map_it != namespace_entry_->second.end()) {
- map_data = map_it->second;
+ scoped_refptr<SessionStorageDataMap> data_map;
+ auto map_data_it = namespace_entry_->second.find(origin);
+ if (map_data_it != namespace_entry_->second.end()) {
+ scoped_refptr<SessionStorageMetadata::MapData> map_data =
+ map_data_it->second;
+ data_map =
+ delegate_->MaybeGetExistingDataMapForId(map_data->MapNumberAsBytes());
+ if (!data_map) {
+ data_map = SessionStorageDataMap::Create(data_map_listener_, map_data,
+ database_);
+ }
} else {
- map_data = register_new_map_callback_.Run(namespace_entry_, origin);
+ data_map = SessionStorageDataMap::Create(
+ data_map_listener_,
+ register_new_map_callback_.Run(namespace_entry_, origin), database_);
}
it = origin_areas_
.emplace(std::make_pair(
- origin,
- std::make_unique<SessionStorageAreaImpl>(
- namespace_entry_, origin,
- SessionStorageDataMap::Create(
- data_map_listener_, std::move(map_data), database_),
- register_new_map_callback_)))
+ origin, std::make_unique<SessionStorageAreaImpl>(
+ namespace_entry_, origin, std::move(data_map),
+ register_new_map_callback_)))
.first;
}
it->second->Bind(std::move(database));
@@ -169,8 +172,8 @@ void SessionStorageNamespaceImplMojo::OpenArea(
void SessionStorageNamespaceImplMojo::Clone(
const std::string& clone_to_namespace) {
- add_namespace_callback_.Run(namespace_entry_, clone_to_namespace,
- origin_areas_);
+ delegate_->RegisterShallowClonedNamespace(namespace_entry_,
+ clone_to_namespace, origin_areas_);
}
void SessionStorageNamespaceImplMojo::FlushOriginForTesting(
diff --git a/chromium/content/browser/dom_storage/session_storage_namespace_impl_mojo.h b/chromium/content/browser/dom_storage/session_storage_namespace_impl_mojo.h
index eb70ad8dde2..0951c9b74d1 100644
--- a/chromium/content/browser/dom_storage/session_storage_namespace_impl_mojo.h
+++ b/chromium/content/browser/dom_storage/session_storage_namespace_impl_mojo.h
@@ -4,6 +4,7 @@
#ifndef CONTENT_BROWSER_DOM_STORAGE_SESSION_STORAGE_NAMESPACE_IMPL_MOJO_H_
#define CONTENT_BROWSER_DOM_STORAGE_SESSION_STORAGE_NAMESPACE_IMPL_MOJO_H_
+#include <map>
#include <memory>
#include "base/callback.h"
@@ -49,23 +50,38 @@ class CONTENT_EXPORT SessionStorageNamespaceImplMojo final
public:
using OriginAreas =
std::map<url::Origin, std::unique_ptr<SessionStorageAreaImpl>>;
- using RegisterShallowClonedNamespace = base::RepeatingCallback<void(
- SessionStorageMetadata::NamespaceEntry source_namespace,
- const std::string& destination_namespace,
- const OriginAreas& areas_to_clone)>;
+
+ class Delegate {
+ public:
+ virtual ~Delegate() = default;
+
+ // This is called when the |Clone()| method is called by mojo.
+ virtual void RegisterShallowClonedNamespace(
+ SessionStorageMetadata::NamespaceEntry source_namespace,
+ const std::string& destination_namespace,
+ const OriginAreas& areas_to_clone) = 0;
+
+ // This is called when |OpenArea()| is called. The map could have been
+ // purged in a call to |PurgeUnboundAreas| but the map could still be alive
+ // as a clone, used by another namespace.
+ // Returns nullptr if a data map was not found.
+ virtual scoped_refptr<SessionStorageDataMap> MaybeGetExistingDataMapForId(
+ const std::vector<uint8_t>& map_number_as_bytes) = 0;
+ };
// Constructs a namespace with the given |namespace_id|, expecting to be
// populated and bound later (see class comment). The |database| and
// |data_map_listener| are given to any data maps constructed for this
- // namespace. The |add_namespace_callback| is called when the |Clone| method
- // is called by mojo. The |register_new_map_callback| is given to the the
- // SessionStorageAreaImpl's, used per-origin, that are bound to in
- // OpenArea.
+ // namespace. The |delegate| is called when the |Clone| method
+ // is called by mojo, as well as when the |OpenArea| method is called and the
+ // map id for that origin is found in our metadata. The
+ // |register_new_map_callback| is given to the the SessionStorageAreaImpl's,
+ // used per-origin, that are bound to in OpenArea.
SessionStorageNamespaceImplMojo(
std::string namespace_id,
SessionStorageDataMap::Listener* data_map_listener,
- RegisterShallowClonedNamespace add_namespace_callback,
- SessionStorageAreaImpl::RegisterNewAreaMap register_new_map_callback);
+ SessionStorageAreaImpl::RegisterNewAreaMap register_new_map_callback,
+ Delegate* delegate);
~SessionStorageNamespaceImplMojo() override;
@@ -80,9 +96,7 @@ class CONTENT_EXPORT SessionStorageNamespaceImplMojo final
// disk. Should be called before |Bind|.
void PopulateFromMetadata(
leveldb::mojom::LevelDBDatabase* database,
- SessionStorageMetadata::NamespaceEntry namespace_metadata,
- const std::map<std::vector<uint8_t>, SessionStorageDataMap*>&
- current_data_maps);
+ SessionStorageMetadata::NamespaceEntry namespace_metadata);
// Can either be called before |Bind|, or if the source namespace isn't
// available yet, |SetWaitingForClonePopulation| can be called. Then |Bind|
@@ -137,14 +151,16 @@ class CONTENT_EXPORT SessionStorageNamespaceImplMojo final
private:
FRIEND_TEST_ALL_PREFIXES(SessionStorageContextMojoTest,
PurgeMemoryDoesNotCrashOrHang);
+ FRIEND_TEST_ALL_PREFIXES(SessionStorageNamespaceImplMojoTest,
+ ReopenClonedAreaAfterPurge);
const std::string namespace_id_;
SessionStorageMetadata::NamespaceEntry namespace_entry_;
- leveldb::mojom::LevelDBDatabase* database_;
+ leveldb::mojom::LevelDBDatabase* database_ = nullptr;
SessionStorageDataMap::Listener* data_map_listener_;
- RegisterShallowClonedNamespace add_namespace_callback_;
SessionStorageAreaImpl::RegisterNewAreaMap register_new_map_callback_;
+ Delegate* delegate_;
bool waiting_on_clone_population_ = false;
bool bind_waiting_on_clone_population_ = false;
diff --git a/chromium/content/browser/dom_storage/session_storage_namespace_impl_mojo_unittest.cc b/chromium/content/browser/dom_storage/session_storage_namespace_impl_mojo_unittest.cc
index b813634fcf5..5080467a908 100644
--- a/chromium/content/browser/dom_storage/session_storage_namespace_impl_mojo_unittest.cc
+++ b/chromium/content/browser/dom_storage/session_storage_namespace_impl_mojo_unittest.cc
@@ -42,7 +42,9 @@ class MockListener : public SessionStorageDataMap::Listener {
MOCK_METHOD1(OnCommitResult, void(leveldb::mojom::DatabaseError error));
};
-class SessionStorageNamespaceImplMojoTest : public testing::Test {
+class SessionStorageNamespaceImplMojoTest
+ : public testing::Test,
+ public SessionStorageNamespaceImplMojo::Delegate {
public:
SessionStorageNamespaceImplMojoTest()
: test_namespace_id1_(base::GenerateGUID()),
@@ -100,19 +102,13 @@ class SessionStorageNamespaceImplMojoTest : public testing::Test {
SessionStorageNamespaceImplMojo* CreateSessionStorageNamespaceImplMojo(
const std::string& namespace_id) {
DCHECK(namespaces_.find(namespace_id) == namespaces_.end());
- SessionStorageNamespaceImplMojo::RegisterShallowClonedNamespace
- add_namespace_callback =
- base::BindRepeating(&SessionStorageNamespaceImplMojoTest::
- RegisterShallowClonedNamespace,
- base::Unretained(this));
SessionStorageAreaImpl::RegisterNewAreaMap map_id_callback =
base::BindRepeating(
&SessionStorageNamespaceImplMojoTest::RegisterNewAreaMap,
base::Unretained(this));
auto namespace_impl = std::make_unique<SessionStorageNamespaceImplMojo>(
- namespace_id, &listener_, std::move(add_namespace_callback),
- std::move(map_id_callback));
+ namespace_id, &listener_, std::move(map_id_callback), this);
auto* namespace_impl_ptr = namespace_impl.get();
namespaces_[namespace_id] = std::move(namespace_impl);
return namespace_impl_ptr;
@@ -131,7 +127,8 @@ class SessionStorageNamespaceImplMojoTest : public testing::Test {
void RegisterShallowClonedNamespace(
NamespaceEntry source_namespace,
const std::string& destination_namespace,
- const SessionStorageNamespaceImplMojo::OriginAreas& areas_to_clone) {
+ const SessionStorageNamespaceImplMojo::OriginAreas& areas_to_clone)
+ override {
std::vector<leveldb::mojom::BatchedOperationPtr> save_operations;
NamespaceEntry namespace_entry =
metadata_.GetOrCreateNamespaceEntry(destination_namespace);
@@ -150,6 +147,14 @@ class SessionStorageNamespaceImplMojoTest : public testing::Test {
it->second->PopulateAsClone(&database_, namespace_entry, areas_to_clone);
}
+ scoped_refptr<SessionStorageDataMap> MaybeGetExistingDataMapForId(
+ const std::vector<uint8_t>& map_number_as_bytes) override {
+ auto it = data_maps_.find(map_number_as_bytes);
+ if (it == data_maps_.end())
+ return nullptr;
+ return it->second;
+ }
+
protected:
TestBrowserThreadBundle test_browser_thread_bundle_;
const std::string test_namespace_id1_;
@@ -162,6 +167,8 @@ class SessionStorageNamespaceImplMojoTest : public testing::Test {
std::map<std::string, std::unique_ptr<SessionStorageNamespaceImplMojo>>
namespaces_;
+ std::map<std::vector<uint8_t>, scoped_refptr<SessionStorageDataMap>>
+ data_maps_;
testing::StrictMock<MockListener> listener_;
std::map<std::vector<uint8_t>, std::vector<uint8_t>> mock_data_;
@@ -178,8 +185,7 @@ TEST_F(SessionStorageNamespaceImplMojoTest, MetadataLoad) {
.Times(1);
namespace_impl->PopulateFromMetadata(
- &database_, metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_),
- std::map<std::vector<uint8_t>, SessionStorageDataMap*>());
+ &database_, metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_));
blink::mojom::SessionStorageNamespacePtr ss_namespace;
namespace_impl->Bind(mojo::MakeRequest(&ss_namespace), kTestProcessIdOrigin1);
@@ -210,8 +216,7 @@ TEST_F(SessionStorageNamespaceImplMojoTest, MetadataLoadWithMapOperations) {
.Times(1);
namespace_impl->PopulateFromMetadata(
- &database_, metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_),
- std::map<std::vector<uint8_t>, SessionStorageDataMap*>());
+ &database_, metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_));
blink::mojom::SessionStorageNamespacePtr ss_namespace;
namespace_impl->Bind(mojo::MakeRequest(&ss_namespace), kTestProcessIdOrigin1);
@@ -250,8 +255,7 @@ TEST_F(SessionStorageNamespaceImplMojoTest, CloneBeforeBind) {
.Times(1);
namespace_impl1->PopulateFromMetadata(
- &database_, metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_),
- std::map<std::vector<uint8_t>, SessionStorageDataMap*>());
+ &database_, metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_));
blink::mojom::SessionStorageNamespacePtr ss_namespace1;
namespace_impl1->Bind(mojo::MakeRequest(&ss_namespace1),
@@ -306,8 +310,7 @@ TEST_F(SessionStorageNamespaceImplMojoTest, CloneAfterBind) {
.Times(1);
namespace_impl1->PopulateFromMetadata(
- &database_, metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_),
- std::map<std::vector<uint8_t>, SessionStorageDataMap*>());
+ &database_, metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_));
blink::mojom::SessionStorageNamespacePtr ss_namespace1;
namespace_impl1->Bind(mojo::MakeRequest(&ss_namespace1),
@@ -369,8 +372,7 @@ TEST_F(SessionStorageNamespaceImplMojoTest, RemoveOriginData) {
.Times(1);
namespace_impl->PopulateFromMetadata(
- &database_, metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_),
- std::map<std::vector<uint8_t>, SessionStorageDataMap*>());
+ &database_, metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_));
blink::mojom::SessionStorageNamespacePtr ss_namespace;
namespace_impl->Bind(mojo::MakeRequest(&ss_namespace), kTestProcessIdOrigin1);
@@ -416,8 +418,7 @@ TEST_F(SessionStorageNamespaceImplMojoTest, RemoveOriginDataWithoutBinding) {
.Times(1);
namespace_impl->PopulateFromMetadata(
- &database_, metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_),
- std::map<std::vector<uint8_t>, SessionStorageDataMap*>());
+ &database_, metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_));
base::RunLoop loop;
EXPECT_CALL(listener_, OnCommitResult(DatabaseError::OK))
@@ -441,8 +442,7 @@ TEST_F(SessionStorageNamespaceImplMojoTest, ProcessLockedToOtherOrigin) {
.Times(1);
namespace_impl->PopulateFromMetadata(
- &database_, metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_),
- std::map<std::vector<uint8_t>, SessionStorageDataMap*>());
+ &database_, metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_));
blink::mojom::SessionStorageNamespacePtr ss_namespace;
namespace_impl->Bind(mojo::MakeRequest(&ss_namespace), kTestProcessIdOrigin1);
@@ -467,8 +467,7 @@ TEST_F(SessionStorageNamespaceImplMojoTest, PurgeUnused) {
.Times(1);
namespace_impl->PopulateFromMetadata(
- &database_, metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_),
- std::map<std::vector<uint8_t>, SessionStorageDataMap*>());
+ &database_, metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_));
blink::mojom::SessionStorageNamespacePtr ss_namespace;
namespace_impl->Bind(mojo::MakeRequest(&ss_namespace), kTestProcessIdOrigin1);
@@ -499,8 +498,7 @@ TEST_F(SessionStorageNamespaceImplMojoTest, NamespaceBindingPerOrigin) {
.Times(1);
namespace_impl->PopulateFromMetadata(
- &database_, metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_),
- std::map<std::vector<uint8_t>, SessionStorageDataMap*>());
+ &database_, metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_));
blink::mojom::SessionStorageNamespacePtr ss_namespace_o1;
namespace_impl->Bind(mojo::MakeRequest(&ss_namespace_o1),
@@ -528,6 +526,45 @@ TEST_F(SessionStorageNamespaceImplMojoTest, NamespaceBindingPerOrigin) {
.Times(1);
namespaces_.clear();
}
-
} // namespace
+
+TEST_F(SessionStorageNamespaceImplMojoTest, ReopenClonedAreaAfterPurge) {
+ // Verifies that areas are kept alive after the area is unbound, and they
+ // are removed when PurgeUnboundWrappers() is called.
+ SessionStorageNamespaceImplMojo* namespace_impl =
+ CreateSessionStorageNamespaceImplMojo(test_namespace_id1_);
+
+ SessionStorageDataMap* data_map;
+ EXPECT_CALL(listener_,
+ OnDataMapCreation(StdStringToUint8Vector("0"), testing::_))
+ .WillOnce(testing::SaveArg<1>(&data_map));
+
+ namespace_impl->PopulateFromMetadata(
+ &database_, metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_));
+
+ blink::mojom::SessionStorageNamespacePtr ss_namespace;
+ namespace_impl->Bind(mojo::MakeRequest(&ss_namespace), kTestProcessIdOrigin1);
+
+ blink::mojom::StorageAreaAssociatedPtr leveldb_1;
+ ss_namespace->OpenArea(test_origin1_, mojo::MakeRequest(&leveldb_1));
+
+ // Save the data map, as if we did a clone:
+ data_maps_[data_map->map_data()->MapNumberAsBytes()] = data_map;
+
+ leveldb_1.reset();
+ namespace_impl->PurgeUnboundAreas();
+ EXPECT_FALSE(namespace_impl->HasAreaForOrigin(test_origin1_));
+
+ ss_namespace->OpenArea(test_origin1_, mojo::MakeRequest(&leveldb_1));
+ ss_namespace.FlushForTesting();
+
+ EXPECT_EQ(namespace_impl->origin_areas_[test_origin1_]->data_map(), data_map);
+
+ data_maps_.clear();
+
+ EXPECT_CALL(listener_, OnDataMapDestruction(StdStringToUint8Vector("0")))
+ .Times(1);
+
+ namespaces_.clear();
+}
} // namespace content
diff --git a/chromium/content/browser/dom_storage/storage_area_impl_unittest.cc b/chromium/content/browser/dom_storage/storage_area_impl_unittest.cc
index 4b0d1190af7..b858637ce97 100644
--- a/chromium/content/browser/dom_storage/storage_area_impl_unittest.cc
+++ b/chromium/content/browser/dom_storage/storage_area_impl_unittest.cc
@@ -9,14 +9,15 @@
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
+#include "base/task/post_task.h"
#include "base/task_runner_util.h"
-#include "base/task_scheduler/post_task.h"
#include "base/test/test_simple_task_runner.h"
#include "base/threading/thread.h"
#include "components/services/leveldb/public/cpp/util.h"
#include "components/services/leveldb/public/interfaces/leveldb.mojom.h"
#include "content/browser/dom_storage/test/storage_area_test_util.h"
#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/test/barrier_builder.h"
#include "content/test/fake_leveldb_database.h"
#include "mojo/public/cpp/bindings/associated_binding.h"
#include "mojo/public/cpp/bindings/strong_associated_binding.h"
@@ -26,9 +27,9 @@
namespace content {
namespace {
-using test::MakeSuccessCallback;
-using test::MakeGetAllCallback;
using test::GetAllCallback;
+using test::MakeGetAllCallback;
+using test::MakeSuccessCallback;
using CacheMode = StorageAreaImpl::CacheMode;
using DatabaseError = leveldb::mojom::DatabaseError;
@@ -43,53 +44,6 @@ std::vector<uint8_t> ToBytes(const std::string& input) {
return leveldb::StdStringToUint8Vector(input);
}
-class InternalIncrementalBarrier {
- public:
- InternalIncrementalBarrier(base::OnceClosure done_closure)
- : num_callbacks_left_(1), done_closure_(std::move(done_closure)) {}
-
- void Dec() {
- // This is the same as in BarrierClosure.
- DCHECK(!num_callbacks_left_.IsZero());
- if (!num_callbacks_left_.Decrement()) {
- base::OnceClosure done = std::move(done_closure_);
- delete this;
- std::move(done).Run();
- }
- }
-
- base::OnceClosure Inc() {
- num_callbacks_left_.Increment();
- return base::BindOnce(&InternalIncrementalBarrier::Dec,
- base::Unretained(this));
- }
-
- private:
- base::AtomicRefCount num_callbacks_left_;
- base::OnceClosure done_closure_;
-
- DISALLOW_COPY_AND_ASSIGN(InternalIncrementalBarrier);
-};
-
-// The callbacks returned by Get might get called after destruction of this
-// class (and thus the done_closure), so there needs to be an internal class
-// to hold the final callback & manage the refcount.
-class IncrementalBarrier {
- public:
- explicit IncrementalBarrier(base::OnceClosure done_closure)
- : internal_barrier_(
- new InternalIncrementalBarrier(std::move(done_closure))) {}
-
- ~IncrementalBarrier() { internal_barrier_->Dec(); }
-
- base::OnceClosure Get() { return internal_barrier_->Inc(); }
-
- private:
- InternalIncrementalBarrier* internal_barrier_; // self-deleting
-
- DISALLOW_COPY_AND_ASSIGN(IncrementalBarrier);
-};
-
class MockDelegate : public StorageAreaImpl::Delegate {
public:
MockDelegate() {}
@@ -278,6 +232,8 @@ class StorageAreaImplTest : public testing::Test,
area->ScheduleImmediateCommit();
loop.Run();
}
+
+ db_.FlushBindingsForTesting();
}
const std::vector<Observation>& observations() { return observations_; }
@@ -380,11 +336,12 @@ TEST_F(StorageAreaImplTest, GetFromPutOverwrite) {
std::vector<uint8_t> result;
bool get_success = false;
{
- IncrementalBarrier barrier(loop.QuitClosure());
- storage_area()->Put(key, value, test_value2_bytes_, test_source_,
- MakeSuccessCallback(barrier.Get(), &put_success));
- storage_area()->Get(key,
- MakeGetCallback(barrier.Get(), &get_success, &result));
+ BarrierBuilder barrier(loop.QuitClosure());
+ storage_area()->Put(
+ key, value, test_value2_bytes_, test_source_,
+ MakeSuccessCallback(barrier.AddClosure(), &put_success));
+ storage_area()->Get(
+ key, MakeGetCallback(barrier.AddClosure(), &get_success, &result));
}
loop.Run();
@@ -452,17 +409,17 @@ TEST_P(StorageAreaImplParamTest, CommitPutToDB) {
bool put_success2 = false;
bool put_success3 = false;
{
- IncrementalBarrier barrier(loop.QuitClosure());
-
- storage_area()->Put(ToBytes(key1), ToBytes(value1), test_value2_bytes_,
- test_source_,
- MakeSuccessCallback(barrier.Get(), &put_success1));
- storage_area()->Put(ToBytes(key2), ToBytes("old value"), base::nullopt,
- test_source_,
- MakeSuccessCallback(barrier.Get(), &put_success2));
- storage_area()->Put(ToBytes(key2), ToBytes(value2), ToBytes("old value"),
- test_source_,
- MakeSuccessCallback(barrier.Get(), &put_success3));
+ BarrierBuilder barrier(loop.QuitClosure());
+
+ storage_area()->Put(
+ ToBytes(key1), ToBytes(value1), test_value2_bytes_, test_source_,
+ MakeSuccessCallback(barrier.AddClosure(), &put_success1));
+ storage_area()->Put(
+ ToBytes(key2), ToBytes("old value"), base::nullopt, test_source_,
+ MakeSuccessCallback(barrier.AddClosure(), &put_success2));
+ storage_area()->Put(
+ ToBytes(key2), ToBytes(value2), ToBytes("old value"), test_source_,
+ MakeSuccessCallback(barrier.AddClosure(), &put_success3));
}
loop.Run();
@@ -875,16 +832,18 @@ TEST_F(StorageAreaImplTest, GetAllWhenCacheOnlyKeys) {
bool put_result1 = false;
bool put_result2 = false;
{
- IncrementalBarrier barrier(loop.QuitClosure());
+ BarrierBuilder barrier(loop.QuitClosure());
- storage_area()->Put(key, value, value2, test_source_,
- MakeSuccessCallback(barrier.Get(), &put_result1));
+ storage_area()->Put(
+ key, value, value2, test_source_,
+ MakeSuccessCallback(barrier.AddClosure(), &put_result1));
storage_area()->GetAll(
- GetAllCallback::CreateAndBind(&result, barrier.Get()),
+ GetAllCallback::CreateAndBind(&result, barrier.AddClosure()),
MakeGetAllCallback(&get_all_success, &data));
- storage_area()->Put(key, value2, value, test_source_,
- MakeSuccessCallback(barrier.Get(), &put_result2));
+ storage_area()->Put(
+ key, value2, value, test_source_,
+ MakeSuccessCallback(barrier.AddClosure(), &put_result2));
FlushAreaBinding();
}
@@ -944,10 +903,11 @@ TEST_F(StorageAreaImplTest, GetAllAfterSetCacheMode) {
bool get_all_callback_success = false;
bool delete_success = false;
{
- IncrementalBarrier barrier(loop.QuitClosure());
+ BarrierBuilder barrier(loop.QuitClosure());
- storage_area()->Put(key, value, value2, test_source_,
- MakeSuccessCallback(barrier.Get(), &put_success));
+ storage_area()->Put(
+ key, value, value2, test_source_,
+ MakeSuccessCallback(barrier.AddClosure(), &put_success));
// Put task triggers database upgrade, so there are no more changes
// to commit.
@@ -956,12 +916,13 @@ TEST_F(StorageAreaImplTest, GetAllAfterSetCacheMode) {
EXPECT_TRUE(storage_area_impl()->has_pending_load_tasks());
storage_area()->GetAll(
- GetAllCallback::CreateAndBind(&get_all_success, barrier.Get()),
+ GetAllCallback::CreateAndBind(&get_all_success, barrier.AddClosure()),
MakeGetAllCallback(&get_all_callback_success, &data));
// This Delete() should not affect the value returned by GetAll().
- storage_area()->Delete(key, value, test_source_,
- MakeSuccessCallback(barrier.Get(), &delete_success));
+ storage_area()->Delete(
+ key, value, test_source_,
+ MakeSuccessCallback(barrier.AddClosure(), &delete_success));
}
loop.Run();
@@ -1091,7 +1052,7 @@ TEST_P(StorageAreaImplParamTest, PrefixForking) {
bool put_success3 = false;
base::RunLoop loop;
{
- IncrementalBarrier barrier(loop.QuitClosure());
+ BarrierBuilder barrier(loop.QuitClosure());
// Create fork 1.
fork1 = storage_area_impl()->ForkToNewPrefix(test_copy_prefix1_,
@@ -1101,16 +1062,17 @@ TEST_P(StorageAreaImplParamTest, PrefixForking) {
// Note - these are 'skipping' the mojo layer, which is why the fork isn't
// scheduled.
fork1->Put(test_key2_bytes_, ToBytes(value4), test_value2_bytes_,
- test_source_, MakeSuccessCallback(barrier.Get(), &put_success1));
+ test_source_,
+ MakeSuccessCallback(barrier.AddClosure(), &put_success1));
fork2 =
fork1->ForkToNewPrefix(test_copy_prefix2_, &fork2_delegate, options);
fork1->Put(test_key2_bytes_, ToBytes(value5), ToBytes(value4), test_source_,
- MakeSuccessCallback(barrier.Get(), &put_success2));
+ MakeSuccessCallback(barrier.AddClosure(), &put_success2));
// Do a put on original and create fork 3, which is key-only.
- storage_area_impl()->Put(test_key1_bytes_, ToBytes(value3),
- test_value1_bytes_, test_source_,
- MakeSuccessCallback(barrier.Get(), &put_success3));
+ storage_area_impl()->Put(
+ test_key1_bytes_, ToBytes(value3), test_value1_bytes_, test_source_,
+ MakeSuccessCallback(barrier.AddClosure(), &put_success3));
fork3 = storage_area_impl()->ForkToNewPrefix(
test_copy_prefix3_, &fork3_delegate,
GetDefaultTestingOptions(CacheMode::KEYS_ONLY_WHEN_POSSIBLE));
@@ -1201,7 +1163,7 @@ TEST_F(StorageAreaImplTest, PrefixForkingPsuedoFuzzer) {
base::RunLoop loop;
{
- IncrementalBarrier barrier(loop.QuitClosure());
+ BarrierBuilder barrier(loop.QuitClosure());
for (int64_t i = 0; i < kTotalAreas; i++) {
FuzzState& state = states[i];
if (!areas[i]) {
@@ -1221,26 +1183,27 @@ TEST_F(StorageAreaImplTest, PrefixForkingPsuedoFuzzer) {
FuzzState old_state = state;
state.val1 = base::nullopt;
successes.push_back(false);
- areas[i]->Delete(kKey1Vec, old_state.val1, test_source_,
- MakeSuccessCallback(barrier.Get(), &successes.back()));
+ areas[i]->Delete(
+ kKey1Vec, old_state.val1, test_source_,
+ MakeSuccessCallback(barrier.AddClosure(), &successes.back()));
}
if (i % 4 == 0) {
FuzzState old_state = state;
state.val2 = base::make_optional<std::vector<uint8_t>>(
{static_cast<uint8_t>(i)});
successes.push_back(false);
- areas[i]->Put(kKey2Vec, state.val2.value(), old_state.val2,
- test_source_,
- MakeSuccessCallback(barrier.Get(), &successes.back()));
+ areas[i]->Put(
+ kKey2Vec, state.val2.value(), old_state.val2, test_source_,
+ MakeSuccessCallback(barrier.AddClosure(), &successes.back()));
}
if (i % 3 == 0) {
FuzzState old_state = state;
state.val1 = base::make_optional<std::vector<uint8_t>>(
{static_cast<uint8_t>(i + 5)});
successes.push_back(false);
- areas[i]->Put(kKey1Vec, state.val1.value(), old_state.val1,
- test_source_,
- MakeSuccessCallback(barrier.Get(), &successes.back()));
+ areas[i]->Put(
+ kKey1Vec, state.val1.value(), old_state.val1, test_source_,
+ MakeSuccessCallback(barrier.AddClosure(), &successes.back()));
}
if (i % 11 == 0) {
state.val1 = base::nullopt;
@@ -1248,7 +1211,7 @@ TEST_F(StorageAreaImplTest, PrefixForkingPsuedoFuzzer) {
successes.push_back(false);
areas[i]->DeleteAll(
test_source_,
- MakeSuccessCallback(barrier.Get(), &successes.back()));
+ MakeSuccessCallback(barrier.AddClosure(), &successes.back()));
}
if (i % 2 == 0 && forks + 1 < kTotalAreas) {
CacheMode mode = i % 3 == 0 ? CacheMode::KEYS_AND_VALUES
@@ -1264,9 +1227,9 @@ TEST_F(StorageAreaImplTest, PrefixForkingPsuedoFuzzer) {
state.val1 = base::make_optional<std::vector<uint8_t>>(
{static_cast<uint8_t>(i + 9)});
successes.push_back(false);
- areas[i]->Put(kKey1Vec, state.val1.value(), old_state.val1,
- test_source_,
- MakeSuccessCallback(barrier.Get(), &successes.back()));
+ areas[i]->Put(
+ kKey1Vec, state.val1.value(), old_state.val1, test_source_,
+ MakeSuccessCallback(barrier.AddClosure(), &successes.back()));
}
}
}
diff --git a/chromium/content/browser/download/download_browsertest.cc b/chromium/content/browser/download/download_browsertest.cc
index 58882960352..3ae60d75623 100644
--- a/chromium/content/browser/download/download_browsertest.cc
+++ b/chromium/content/browser/download/download_browsertest.cc
@@ -869,7 +869,7 @@ class DownloadContentTest : public ContentBrowserTest {
std::string file_contents;
{
- base::ThreadRestrictions::ScopedAllowIO allow_io_during_test_verification;
+ base::ScopedAllowBlockingForTesting allow_blocking;
bool read = base::ReadFileToString(path, &file_contents);
EXPECT_TRUE(read) << "Failed reading file: " << path.value() << std::endl;
if (!read)
@@ -906,14 +906,14 @@ class DownloadContentTest : public ContentBrowserTest {
}
static bool PathExists(const base::FilePath& path) {
- base::ThreadRestrictions::ScopedAllowIO allow_io_during_test_verification;
+ base::ScopedAllowBlockingForTesting allow_blocking;
return base::PathExists(path);
}
static void ReadAndVerifyFileContents(int seed,
int64_t expected_size,
const base::FilePath& path) {
- base::ThreadRestrictions::ScopedAllowIO allow_io_during_test_verification;
+ base::ScopedAllowBlockingForTesting allow_blocking;
base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_READ);
ASSERT_TRUE(file.IsValid());
int64_t file_length = file.GetLength();
@@ -1812,7 +1812,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, RestartIfNoPartialFile) {
// Delete the intermediate file.
{
- base::ThreadRestrictions::ScopedAllowIO allow_io_for_testing;
+ base::ScopedAllowBlockingForTesting allow_blocking;
ASSERT_TRUE(PathExists(download->GetFullPath()));
ASSERT_TRUE(base::DeleteFile(download->GetFullPath(), false));
}
@@ -2360,7 +2360,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeRestoredDownload_NoHash) {
std::string output = TestDownloadHttpResponse::GetPatternBytes(
parameters.pattern_generator_seed, 0, kIntermediateSize);
{
- base::ThreadRestrictions::ScopedAllowIO allow_io_for_test_setup;
+ base::ScopedAllowBlockingForTesting allow_blocking;
ASSERT_EQ(kIntermediateSize, base::WriteFile(intermediate_file_path,
output.data(), output.size()));
}
@@ -2413,7 +2413,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest,
std::string output = TestDownloadHttpResponse::GetPatternBytes(
parameters.pattern_generator_seed + 1, 0, kIntermediateSize);
{
- base::ThreadRestrictions::ScopedAllowIO allow_io_for_test_setup;
+ base::ScopedAllowBlockingForTesting allow_blocking;
ASSERT_EQ(kIntermediateSize, base::WriteFile(intermediate_file_path,
output.data(), output.size()));
}
@@ -2467,7 +2467,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest,
std::string output = TestDownloadHttpResponse::GetPatternBytes(
parameters.pattern_generator_seed, 0, kIntermediateSize);
{
- base::ThreadRestrictions::ScopedAllowIO allow_io_for_test_setup;
+ base::ScopedAllowBlockingForTesting allow_blocking;
ASSERT_EQ(kIntermediateSize, base::WriteFile(intermediate_file_path,
output.data(), output.size()));
}
@@ -2532,7 +2532,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeRestoredDownload_WrongHash) {
const int kIntermediateSize = 1331;
std::vector<char> buffer(kIntermediateSize);
{
- base::ThreadRestrictions::ScopedAllowIO allow_io_for_test_setup;
+ base::ScopedAllowBlockingForTesting allow_blocking;
ASSERT_EQ(kIntermediateSize, base::WriteFile(intermediate_file_path,
buffer.data(), buffer.size()));
}
@@ -2614,7 +2614,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeRestoredDownload_ShortFile) {
std::string output = TestDownloadHttpResponse::GetPatternBytes(
parameters.pattern_generator_seed, 0, kIntermediateSize - 100);
{
- base::ThreadRestrictions::ScopedAllowIO allow_io_for_test_setup;
+ base::ScopedAllowBlockingForTesting allow_blocking;
ASSERT_EQ(
kIntermediateSize - 100,
base::WriteFile(intermediate_file_path, output.data(), output.size()));
@@ -2687,7 +2687,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeRestoredDownload_LongFile) {
std::string output = TestDownloadHttpResponse::GetPatternBytes(
parameters.pattern_generator_seed, 0, kIntermediateSize + 100);
{
- base::ThreadRestrictions::ScopedAllowIO allow_io_for_test_setup;
+ base::ScopedAllowBlockingForTesting allow_blocking;
ASSERT_EQ(
kIntermediateSize + 100,
base::WriteFile(intermediate_file_path, output.data(), output.size()));
@@ -3189,7 +3189,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTestWithMojoBlobURLs,
}
IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadAttributeSameSiteCookie) {
- base::ThreadRestrictions::ScopedAllowIO allow_io_during_test;
+ base::ScopedAllowBlockingForTesting allow_blocking;
net::EmbeddedTestServer test_server;
ASSERT_TRUE(test_server.InitializeAndListen());
diff --git a/chromium/content/browser/download/download_manager_impl.cc b/chromium/content/browser/download/download_manager_impl.cc
index f8c137fe6d7..37cabf2c9ff 100644
--- a/chromium/content/browser/download/download_manager_impl.cc
+++ b/chromium/content/browser/download/download_manager_impl.cc
@@ -23,8 +23,8 @@
#include "build/build_config.h"
#include "components/download/database/in_progress/download_entry.h"
#include "components/download/database/in_progress/in_progress_cache_impl.h"
-#include "components/download/database/switches.h"
#include "components/download/public/common/download_create_info.h"
+#include "components/download/public/common/download_features.h"
#include "components/download/public/common/download_file.h"
#include "components/download/public/common/download_interrupt_reasons.h"
#include "components/download/public/common/download_item_factory.h"
@@ -33,6 +33,7 @@
#include "components/download/public/common/download_stats.h"
#include "components/download/public/common/download_task_runner.h"
#include "components/download/public/common/download_url_loader_factory_getter.h"
+#include "components/download/public/common/download_url_loader_factory_getter_impl.h"
#include "components/download/public/common/download_url_parameters.h"
#include "components/download/public/common/download_utils.h"
#include "components/download/public/common/url_download_handler_factory.h"
@@ -41,9 +42,9 @@
#include "content/browser/devtools/render_frame_devtools_agent_host.h"
#include "content/browser/download/byte_stream_input_stream.h"
#include "content/browser/download/download_resource_handler.h"
-#include "content/browser/download/download_url_loader_factory_getter_impl.h"
#include "content/browser/download/download_utils.h"
#include "content/browser/download/file_download_url_loader_factory_getter.h"
+#include "content/browser/download/file_system_download_url_loader_factory_getter.h"
#include "content/browser/download/network_download_url_loader_factory_getter.h"
#include "content/browser/download/url_downloader.h"
#include "content/browser/download/url_downloader_factory.h"
@@ -296,15 +297,29 @@ DownloadManagerImpl::DownloadManagerImpl(BrowserContext* browser_context)
in_progress_cache_initialized_(false),
browser_context_(browser_context),
delegate_(nullptr),
+ in_progress_manager_(
+ browser_context_->RetriveInProgressDownloadManager()),
+ next_download_id_(download::DownloadItem::kInvalidId),
+ is_history_download_id_retrieved_(false),
weak_factory_(this) {
DCHECK(browser_context);
download::SetIOTaskRunner(
BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
if (!base::FeatureList::IsEnabled(network::features::kNetworkService))
download::UrlDownloadHandlerFactory::Install(new UrlDownloaderFactory());
- in_progress_manager_ = std::make_unique<download::InProgressDownloadManager>(
- this, IsOffTheRecord() ? base::FilePath() : browser_context_->GetPath(),
- base::BindRepeating(&IsOriginSecure));
+
+ if (!in_progress_manager_) {
+ in_progress_manager_ =
+ std::make_unique<download::InProgressDownloadManager>(
+ this,
+ IsOffTheRecord() ? base::FilePath() : browser_context_->GetPath(),
+ base::BindRepeating(&IsOriginSecure));
+ } else {
+ in_progress_manager_->set_delegate(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()));
@@ -331,14 +346,43 @@ download::DownloadItemImpl* DownloadManagerImpl::CreateActiveItem(
return download;
}
-void DownloadManagerImpl::GetNextId(const DownloadIdCallback& callback) {
+void DownloadManagerImpl::GetNextId(GetNextIdCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- if (delegate_) {
- delegate_->GetNextId(callback);
+ if (IsNextIdInitialized()) {
+ std::move(callback).Run(next_download_id_++);
return;
}
- static uint32_t next_id = download::DownloadItem::kInvalidId + 1;
- callback.Run(next_id++);
+
+ id_callbacks_.emplace_back(
+ std::make_unique<GetNextIdCallback>(std::move(callback)));
+ // If we are first time here, call the delegate to get the next ID from
+ // history db.
+ if (!is_history_download_id_retrieved_ && id_callbacks_.size() == 1u) {
+ if (delegate_) {
+ delegate_->GetNextId(
+ base::BindRepeating(&DownloadManagerImpl::OnHistoryNextIdRetrived,
+ weak_factory_.GetWeakPtr()));
+ } else {
+ OnHistoryNextIdRetrived(download::DownloadItem::kInvalidId + 1);
+ }
+ }
+}
+
+void DownloadManagerImpl::SetNextId(uint32_t next_id) {
+ if (next_id > next_download_id_)
+ next_download_id_ = next_id;
+ if (!IsNextIdInitialized())
+ return;
+
+ for (auto& callback : id_callbacks_)
+ std::move(*callback).Run(next_download_id_++);
+ id_callbacks_.clear();
+}
+
+void DownloadManagerImpl::OnHistoryNextIdRetrived(uint32_t next_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ is_history_download_id_retrieved_ = true;
+ SetNextId(next_id);
}
void DownloadManagerImpl::DetermineDownloadTarget(
@@ -494,6 +538,7 @@ base::FilePath DownloadManagerImpl::GetDefaultDownloadDirectory() {
void DownloadManagerImpl::OnInProgressDownloadManagerInitialized() {
std::vector<std::unique_ptr<download::DownloadItemImpl>>
in_progress_downloads = in_progress_manager_->TakeInProgressDownloads();
+ uint32_t max_id = download::DownloadItem::kInvalidId;
for (auto& download : in_progress_downloads) {
DCHECK(!base::ContainsKey(downloads_by_guid_, download->GetGuid()));
DCHECK(!base::ContainsKey(downloads_, download->GetId()));
@@ -501,12 +546,16 @@ void DownloadManagerImpl::OnInProgressDownloadManagerInitialized() {
download::DownloadItemImpl* item = download.get();
item->SetDelegate(this);
downloads_by_guid_[download->GetGuid()] = item;
- downloads_[download->GetId()] = std::move(download);
+ uint32_t id = download->GetId();
+ downloads_[id] = std::move(download);
+ if (id > max_id)
+ max_id = id;
for (auto& observer : observers_)
observer.OnDownloadCreated(this, item);
DVLOG(20) << __func__ << "() download = " << item->DebugString(true);
}
PostInitialization(DOWNLOAD_INITIALIZATION_DEPENDENCY_IN_PROGRESS_CACHE);
+ SetNextId(max_id + 1);
}
void DownloadManagerImpl::StartDownloadItem(
@@ -522,10 +571,9 @@ void DownloadManagerImpl::StartDownloadItem(
std::move(callback).Run(std::move(info), download);
OnDownloadStarted(download, on_started);
} else {
- GetNextId(
- base::BindRepeating(&DownloadManagerImpl::CreateNewDownloadItemToStart,
- weak_factory_.GetWeakPtr(), base::Passed(&info),
- on_started, base::Passed(&callback)));
+ GetNextId(base::BindOnce(&DownloadManagerImpl::CreateNewDownloadItemToStart,
+ weak_factory_.GetWeakPtr(), std::move(info),
+ on_started, std::move(callback)));
}
}
@@ -578,8 +626,8 @@ void DownloadManagerImpl::CheckForHistoryFilesRemoval() {
void DownloadManagerImpl::OnHistoryQueryComplete(
base::OnceClosure load_history_downloads_cb) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- download::switches::kEnableDownloadDB) &&
+ if (base::FeatureList::IsEnabled(
+ download::features::kDownloadDBForNewDownloads) &&
!in_progress_cache_initialized_) {
load_history_downloads_cb_ = std::move(load_history_downloads_cb);
} else {
@@ -628,10 +676,10 @@ void DownloadManagerImpl::CreateSavePackageDownloadItem(
const DownloadItemImplCreated& item_created) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
GetNextId(
- base::Bind(&DownloadManagerImpl::CreateSavePackageDownloadItemWithId,
- weak_factory_.GetWeakPtr(), main_file_path, page_url,
- mime_type, render_process_id, render_frame_id,
- base::Passed(std::move(request_handle)), item_created));
+ base::BindOnce(&DownloadManagerImpl::CreateSavePackageDownloadItemWithId,
+ weak_factory_.GetWeakPtr(), main_file_path, page_url,
+ mime_type, render_process_id, render_frame_id,
+ std::move(request_handle), item_created));
}
void DownloadManagerImpl::CreateSavePackageDownloadItemWithId(
@@ -1118,7 +1166,7 @@ void DownloadManagerImpl::BeginResourceDownloadOnChecksComplete(
if (blob_url_loader_factory) {
DCHECK(params->url().SchemeIsBlob());
url_loader_factory_getter =
- base::MakeRefCounted<DownloadURLLoaderFactoryGetterImpl>(
+ base::MakeRefCounted<download::DownloadURLLoaderFactoryGetterImpl>(
blob_url_loader_factory->Clone());
} else if (params->url().SchemeIsFile()) {
url_loader_factory_getter =
@@ -1128,6 +1176,24 @@ void DownloadManagerImpl::BeginResourceDownloadOnChecksComplete(
url_loader_factory_getter =
base::MakeRefCounted<WebUIDownloadURLLoaderFactoryGetter>(
rfh, params->url());
+ } else if (rfh && params->url().SchemeIsFileSystem()) {
+ StoragePartitionImpl* storage_partition =
+ static_cast<StoragePartitionImpl*>(
+ BrowserContext::GetStoragePartitionForSite(browser_context_,
+ site_url));
+ std::string storage_domain;
+ auto* site_instance = rfh->GetSiteInstance();
+ if (site_instance) {
+ std::string partition_name;
+ bool in_memory;
+ GetContentClient()->browser()->GetStoragePartitionConfigForSite(
+ browser_context_, site_url, true, &storage_domain, &partition_name,
+ &in_memory);
+ }
+ url_loader_factory_getter =
+ base::MakeRefCounted<FileSystemDownloadURLLoaderFactoryGetter>(
+ params->url(), rfh, /*is_navigation=*/false,
+ storage_partition->GetFileSystemContext(), storage_domain);
} else {
StoragePartitionImpl* storage_partition =
static_cast<StoragePartitionImpl*>(
@@ -1198,7 +1264,11 @@ void DownloadManagerImpl::BeginDownloadInternal(
std::move(blob_data_handle),
browser_context_->GetResourceContext(), is_new_download,
weak_factory_.GetWeakPtr()));
- }
+ }
+}
+
+bool DownloadManagerImpl::IsNextIdInitialized() const {
+ return is_history_download_id_retrieved_ && in_progress_cache_initialized_;
}
} // namespace content
diff --git a/chromium/content/browser/download/download_manager_impl.h b/chromium/content/browser/download/download_manager_impl.h
index 4f07f57f252..5f53beb1236 100644
--- a/chromium/content/browser/download/download_manager_impl.h
+++ b/chromium/content/browser/download/download_manager_impl.h
@@ -214,9 +214,18 @@ class CONTENT_EXPORT DownloadManagerImpl
download::InProgressDownloadManager::StartDownloadItemCallback callback,
uint32_t id);
+ using GetNextIdCallback = base::OnceCallback<void(uint32_t)>;
// Called to get an ID for a new download. |callback| may be called
// synchronously.
- void GetNextId(const DownloadIdCallback& callback);
+ void GetNextId(GetNextIdCallback callback);
+
+ // Sets the |next_download_id_| if the |next_id| is larger. Runs all the
+ // |id_callbacks_| if both the ID from both history db and in-progress db
+ // are retrieved.
+ void SetNextId(uint32_t next_id);
+
+ // Called when the next ID from history db is retrieved.
+ void OnHistoryNextIdRetrived(uint32_t next_id);
// Create a new active item based on the info. Separate from
// StartDownload() for testing.
@@ -279,6 +288,9 @@ class CONTENT_EXPORT DownloadManagerImpl
const GURL& site_url,
bool is_download_allowed);
+ // Whether |next_download_id_| is initialized.
+ bool IsNextIdInitialized() const;
+
// Factory for creation of downloads items.
std::unique_ptr<download::DownloadItemFactory> item_factory_;
@@ -308,7 +320,7 @@ class CONTENT_EXPORT DownloadManagerImpl
bool in_progress_cache_initialized_;
// Observers that want to be notified of changes to the set of downloads.
- base::ObserverList<Observer> observers_;
+ base::ObserverList<Observer>::Unchecked observers_;
// Stores information about in-progress download items.
std::unique_ptr<download::DownloadItem::Observer>
@@ -329,6 +341,18 @@ class CONTENT_EXPORT DownloadManagerImpl
// Callback to run to load all history downloads.
base::OnceClosure load_history_downloads_cb_;
+ // The next download id to issue to new downloads. The |next_download_id_| can
+ // only be used when both history and in-progress db have provided their
+ // values.
+ uint32_t next_download_id_;
+
+ // Whether next download ID from history DB is being retrieved.
+ bool is_history_download_id_retrieved_;
+
+ // Callbacks to run once download ID is determined.
+ using IdCallbackVector = std::vector<std::unique_ptr<GetNextIdCallback>>;
+ IdCallbackVector id_callbacks_;
+
base::WeakPtrFactory<DownloadManagerImpl> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(DownloadManagerImpl);
diff --git a/chromium/content/browser/download/download_manager_impl_unittest.cc b/chromium/content/browser/download/download_manager_impl_unittest.cc
index c4e5f80b78f..7df5b5b6539 100644
--- a/chromium/content/browser/download/download_manager_impl_unittest.cc
+++ b/chromium/content/browser/download/download_manager_impl_unittest.cc
@@ -522,6 +522,7 @@ TEST_F(DownloadManagerTest, StartDownload) {
std::unique_ptr<ByteStreamReader> stream(new MockByteStreamReader);
uint32_t local_id(5); // Random value
base::FilePath download_path(FILE_PATH_LITERAL("download/path"));
+ OnInProgressDownloadManagerInitialized();
EXPECT_FALSE(download_manager_->GetDownload(local_id));
diff --git a/chromium/content/browser/download/download_request_core.cc b/chromium/content/browser/download/download_request_core.cc
index fb6a33bcd83..a4cdc54c64b 100644
--- a/chromium/content/browser/download/download_request_core.cc
+++ b/chromium/content/browser/download/download_request_core.cc
@@ -245,7 +245,6 @@ bool DownloadRequestCore::OnResponseStarted(
const std::string& override_mime_type) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DVLOG(20) << __func__ << "() " << DebugString();
- download_start_time_ = base::TimeTicks::Now();
download::DownloadInterruptReason result =
request()->response_headers() ? download::HandleSuccessfulServerResponse(
@@ -361,7 +360,6 @@ bool DownloadRequestCore::OnReadCompleted(int bytes_read, bool* defer) {
if (!stream_writer_->Write(read_buffer_, bytes_read)) {
PauseRequest();
*defer = was_deferred_ = true;
- last_stream_pause_time_ = base::TimeTicks::Now();
}
read_buffer_ = nullptr; // Drop our reference.
@@ -411,10 +409,6 @@ void DownloadRequestCore::OnResponseCompleted(
request()->response_headers()->EnumerateHeader(nullptr, "Accept-Ranges",
&accept_ranges);
}
- download::RecordAcceptsRanges(accept_ranges, bytes_read_,
- has_strong_validators);
- download::RecordNetworkBlockage(base::TimeTicks::Now() - download_start_time_,
- total_pause_time_);
// Send the info down the stream. Conditional is in case we get
// OnResponseCompleted without OnResponseStarted.
@@ -462,10 +456,6 @@ void DownloadRequestCore::ResumeRequest() {
return;
was_deferred_ = false;
- if (!last_stream_pause_time_.is_null()) {
- total_pause_time_ += (base::TimeTicks::Now() - last_stream_pause_time_);
- last_stream_pause_time_ = base::TimeTicks();
- }
delegate_->OnReadyToRead();
}
diff --git a/chromium/content/browser/download/download_request_core.h b/chromium/content/browser/download/download_request_core.h
index 0fdd19edd45..0a4a2db6000 100644
--- a/chromium/content/browser/download/download_request_core.h
+++ b/chromium/content/browser/download/download_request_core.h
@@ -145,11 +145,6 @@ class CONTENT_EXPORT DownloadRequestCore
// URLRequest to fail and the associated download will be interrupted.
device::mojom::WakeLockPtr wake_lock_;
- // The following are used to collect stats.
- base::TimeTicks download_start_time_;
- base::TimeTicks last_stream_pause_time_;
- base::TimeDelta total_pause_time_;
-
int64_t bytes_read_;
int pause_count_;
diff --git a/chromium/content/browser/download/download_url_loader_factory_getter_impl.cc b/chromium/content/browser/download/download_url_loader_factory_getter_impl.cc
deleted file mode 100644
index e26386c8bb6..00000000000
--- a/chromium/content/browser/download/download_url_loader_factory_getter_impl.cc
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/download/download_url_loader_factory_getter_impl.h"
-
-namespace content {
-
-DownloadURLLoaderFactoryGetterImpl::DownloadURLLoaderFactoryGetterImpl(
- std::unique_ptr<network::SharedURLLoaderFactoryInfo> url_loader_factory)
- : url_loader_factory_info_(std::move(url_loader_factory)) {}
-
-DownloadURLLoaderFactoryGetterImpl::~DownloadURLLoaderFactoryGetterImpl() =
- default;
-
-scoped_refptr<network::SharedURLLoaderFactory>
-DownloadURLLoaderFactoryGetterImpl::GetURLLoaderFactory() {
- if (!url_loader_factory_) {
- url_loader_factory_ = network::SharedURLLoaderFactory::Create(
- std::move(url_loader_factory_info_));
- }
- return url_loader_factory_;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/download/download_url_loader_factory_getter_impl.h b/chromium/content/browser/download/download_url_loader_factory_getter_impl.h
deleted file mode 100644
index d002dbb1e14..00000000000
--- a/chromium/content/browser/download/download_url_loader_factory_getter_impl.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_DOWNLOAD_DOWNLOAD_URL_LOADER_FACTORY_GETTER_IMPL_H_
-#define CONTENT_BROWSER_DOWNLOAD_DOWNLOAD_URL_LOADER_FACTORY_GETTER_IMPL_H_
-
-#include "components/download/public/common/download_url_loader_factory_getter.h"
-#include "services/network/public/cpp/shared_url_loader_factory.h"
-
-namespace content {
-
-// Class for retrieving a fixed SharedURLLoaderFactory.
-class DownloadURLLoaderFactoryGetterImpl
- : public download::DownloadURLLoaderFactoryGetter {
- public:
- explicit DownloadURLLoaderFactoryGetterImpl(
- std::unique_ptr<network::SharedURLLoaderFactoryInfo> url_loader_factory);
-
- // download::DownloadURLLoaderFactoryGetter implementation.
- scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() override;
-
- protected:
- ~DownloadURLLoaderFactoryGetterImpl() override;
-
- private:
- // Only one of the following two members is ever set. Initially that would be
- // |url_loader_factory_info_|, but after GetURLLoaderFactory is called for the
- // first time instead |url_loader_factory_| will be set. This is safe because
- // GetURLLoaderFactory is always called from the same thread.
- std::unique_ptr<network::SharedURLLoaderFactoryInfo> url_loader_factory_info_;
- scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(DownloadURLLoaderFactoryGetterImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_DOWNLOAD_DOWNLOAD_URL_LOADER_FACTORY_GETTER_IMPL_H_
diff --git a/chromium/content/browser/download/download_utils.cc b/chromium/content/browser/download/download_utils.cc
index fec2b6a861c..0fd9009103d 100644
--- a/chromium/content/browser/download/download_utils.cc
+++ b/chromium/content/browser/download/download_utils.cc
@@ -8,7 +8,7 @@
#include "base/process/process_handle.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/stringprintf.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "components/download/database/in_progress/download_entry.h"
#include "components/download/database/in_progress/in_progress_cache.h"
#include "components/download/public/common/download_create_info.h"
diff --git a/chromium/content/browser/download/file_download_url_loader_factory_getter.cc b/chromium/content/browser/download/file_download_url_loader_factory_getter.cc
index 973baed881d..86dfd9a6aee 100644
--- a/chromium/content/browser/download/file_download_url_loader_factory_getter.cc
+++ b/chromium/content/browser/download/file_download_url_loader_factory_getter.cc
@@ -4,8 +4,8 @@
#include "content/browser/download/file_download_url_loader_factory_getter.h"
-#include "base/task_scheduler/post_task.h"
-#include "base/task_scheduler/task_traits.h"
+#include "base/task/post_task.h"
+#include "base/task/task_traits.h"
#include "components/download/public/common/download_task_runner.h"
#include "content/browser/file_url_loader_factory.h"
#include "content/browser/url_loader_factory_getter.h"
@@ -33,7 +33,7 @@ FileDownloadURLLoaderFactoryGetter::GetURLLoaderFactory() {
mojo::MakeStrongBinding(
std::make_unique<FileURLLoaderFactory>(
profile_path_, base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BACKGROUND,
+ {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})),
MakeRequest(&url_loader_factory_ptr_info));
diff --git a/chromium/content/browser/download/file_system_download_url_loader_factory_getter.cc b/chromium/content/browser/download/file_system_download_url_loader_factory_getter.cc
new file mode 100644
index 00000000000..3c4780ec159
--- /dev/null
+++ b/chromium/content/browser/download/file_system_download_url_loader_factory_getter.cc
@@ -0,0 +1,52 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/download/file_system_download_url_loader_factory_getter.h"
+
+#include "base/task/post_task.h"
+#include "base/task/task_traits.h"
+#include "components/download/public/common/download_task_runner.h"
+#include "content/browser/fileapi/file_system_url_loader_factory.h"
+#include "content/browser/url_loader_factory_getter.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
+#include "services/network/public/mojom/url_loader_factory.mojom.h"
+
+namespace content {
+
+FileSystemDownloadURLLoaderFactoryGetter::
+ FileSystemDownloadURLLoaderFactoryGetter(
+ const GURL& url,
+ RenderFrameHost* rfh,
+ bool is_navigation,
+ scoped_refptr<storage::FileSystemContext> file_system_context,
+ const std::string& storage_domain)
+ : rfh_(rfh),
+ is_navigation_(is_navigation),
+ file_system_context_(file_system_context),
+ storage_domain_(storage_domain) {
+ DCHECK(url.SchemeIs(url::kFileSystemScheme));
+ DCHECK(rfh);
+}
+
+FileSystemDownloadURLLoaderFactoryGetter::
+ ~FileSystemDownloadURLLoaderFactoryGetter() = default;
+
+scoped_refptr<network::SharedURLLoaderFactory>
+FileSystemDownloadURLLoaderFactoryGetter::GetURLLoaderFactory() {
+ DCHECK(download::GetIOTaskRunner()->BelongsToCurrentThread());
+
+ std::unique_ptr<network::mojom::URLLoaderFactory> factory =
+ CreateFileSystemURLLoaderFactory(rfh_, is_navigation_,
+ file_system_context_, storage_domain_);
+
+ network::mojom::URLLoaderFactoryPtrInfo url_loader_factory_ptr_info;
+ mojo::MakeStrongBinding(std::move(factory),
+ MakeRequest(&url_loader_factory_ptr_info));
+
+ return base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
+ std::move(url_loader_factory_ptr_info));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/download/file_system_download_url_loader_factory_getter.h b/chromium/content/browser/download/file_system_download_url_loader_factory_getter.h
new file mode 100644
index 00000000000..422a6e9ab2b
--- /dev/null
+++ b/chromium/content/browser/download/file_system_download_url_loader_factory_getter.h
@@ -0,0 +1,50 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_DOWNLOAD_FILE_SYSTEM_DOWNLOAD_URL_LOADER_FACTORY_GETTER_H_
+#define CONTENT_BROWSER_DOWNLOAD_FILE_SYSTEM_DOWNLOAD_URL_LOADER_FACTORY_GETTER_H_
+
+#include <string>
+
+#include "base/memory/scoped_refptr.h"
+#include "components/download/public/common/download_url_loader_factory_getter.h"
+#include "url/gurl.h"
+
+namespace storage {
+class FileSystemContext;
+}
+
+namespace content {
+
+class RenderFrameHost;
+
+// Class for retrieving the URLLoaderFactory for a file URL.
+class FileSystemDownloadURLLoaderFactoryGetter
+ : public download::DownloadURLLoaderFactoryGetter {
+ public:
+ FileSystemDownloadURLLoaderFactoryGetter(
+ const GURL& url,
+ RenderFrameHost* rfh,
+ bool is_navigation,
+ scoped_refptr<storage::FileSystemContext> file_system_context,
+ const std::string& storage_domain);
+
+ // download::DownloadURLLoaderFactoryGetter implementation.
+ scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() override;
+
+ protected:
+ ~FileSystemDownloadURLLoaderFactoryGetter() override;
+
+ private:
+ RenderFrameHost* rfh_;
+ const bool is_navigation_;
+ scoped_refptr<storage::FileSystemContext> file_system_context_;
+ const std::string storage_domain_;
+
+ DISALLOW_COPY_AND_ASSIGN(FileSystemDownloadURLLoaderFactoryGetter);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_DOWNLOAD_FILE_SYSTEM_DOWNLOAD_URL_LOADER_FACTORY_GETTER_H_
diff --git a/chromium/content/browser/download/mhtml_generation_browsertest.cc b/chromium/content/browser/download/mhtml_generation_browsertest.cc
index 379cc3ac485..5d8e517f459 100644
--- a/chromium/content/browser/download/mhtml_generation_browsertest.cc
+++ b/chromium/content/browser/download/mhtml_generation_browsertest.cc
@@ -57,6 +57,7 @@ class FindTrackingDelegate : public WebContentsDelegate {
web_contents->SetDelegate(this);
blink::WebFindOptions options;
+ options.run_synchronously_for_testing = true;
options.match_case = false;
web_contents->Find(global_request_id++, base::UTF8ToUTF16(search_),
@@ -149,7 +150,7 @@ class MHTMLGenerationTest : public ContentBrowserTest {
}
int64_t ReadFileSizeFromDisk(base::FilePath path) {
- base::ThreadRestrictions::ScopedAllowIO allow_io_to_test_file_size;
+ base::ScopedAllowBlockingForTesting allow_blocking;
int64_t file_size;
if (!base::GetFileSize(path, &file_size)) return -1;
return file_size;
@@ -249,7 +250,7 @@ IN_PROC_BROWSER_TEST_F(MHTMLGenerationTest, GenerateMHTML) {
EXPECT_GT(ReadFileSizeFromDisk(path), 100); // Verify the actual file size.
{
- base::ThreadRestrictions::ScopedAllowIO allow_io_for_content_verification;
+ base::ScopedAllowBlockingForTesting allow_blocking;
std::string mhtml;
ASSERT_TRUE(base::ReadFileToString(path, &mhtml));
EXPECT_THAT(mhtml,
@@ -411,7 +412,7 @@ IN_PROC_BROWSER_TEST_F(MHTMLGenerationTest, GenerateNonBinaryMHTMLWithImage) {
EXPECT_GT(ReadFileSizeFromDisk(path), 100); // Verify the actual file size.
{
- base::ThreadRestrictions::ScopedAllowIO allow_io_for_content_verification;
+ base::ScopedAllowBlockingForTesting allow_blocking;
std::string mhtml;
ASSERT_TRUE(base::ReadFileToString(path, &mhtml));
EXPECT_THAT(mhtml, HasSubstr("Content-Transfer-Encoding: base64"));
@@ -438,7 +439,7 @@ IN_PROC_BROWSER_TEST_F(MHTMLGenerationTest, GenerateBinaryMHTMLWithImage) {
EXPECT_GT(ReadFileSizeFromDisk(path), 100); // Verify the actual file size.
{
- base::ThreadRestrictions::ScopedAllowIO allow_io_for_content_verification;
+ base::ScopedAllowBlockingForTesting allow_blocking;
std::string mhtml;
ASSERT_TRUE(base::ReadFileToString(path, &mhtml));
EXPECT_THAT(mhtml, HasSubstr("Content-Transfer-Encoding: binary"));
@@ -460,7 +461,7 @@ IN_PROC_BROWSER_TEST_F(MHTMLGenerationTest, GenerateMHTMLIgnoreNoStore) {
std::string mhtml;
{
- base::ThreadRestrictions::ScopedAllowIO allow_io_for_content_verification;
+ base::ScopedAllowBlockingForTesting allow_blocking;
ASSERT_TRUE(base::ReadFileToString(path, &mhtml));
}
@@ -488,7 +489,7 @@ IN_PROC_BROWSER_TEST_F(MHTMLGenerationTest, GenerateMHTMLObeyNoStoreMainFrame) {
std::string mhtml;
{
- base::ThreadRestrictions::ScopedAllowIO allow_io_for_content_verification;
+ base::ScopedAllowBlockingForTesting allow_blocking;
ASSERT_TRUE(base::ReadFileToString(path, &mhtml));
}
@@ -519,7 +520,7 @@ IN_PROC_BROWSER_TEST_F(MHTMLGenerationTest,
std::string mhtml;
{
- base::ThreadRestrictions::ScopedAllowIO allow_io_for_content_verification;
+ base::ScopedAllowBlockingForTesting allow_blocking;
ASSERT_TRUE(base::ReadFileToString(path, &mhtml));
}
@@ -546,7 +547,7 @@ IN_PROC_BROWSER_TEST_F(MHTMLGenerationTest, GenerateMHTMLObeyNoStoreSubFrame) {
std::string mhtml;
{
- base::ThreadRestrictions::ScopedAllowIO allow_io_for_content_verification;
+ base::ScopedAllowBlockingForTesting allow_blocking;
ASSERT_TRUE(base::ReadFileToString(path, &mhtml));
}
@@ -589,7 +590,7 @@ IN_PROC_BROWSER_TEST_F(
std::string mhtml;
{
- base::ThreadRestrictions::ScopedAllowIO allow_io_for_content_verification;
+ base::ScopedAllowBlockingForTesting allow_blocking;
ASSERT_TRUE(base::ReadFileToString(params.file_path, &mhtml));
}
}
@@ -616,7 +617,7 @@ IN_PROC_BROWSER_TEST_F(MHTMLGenerationTest,
std::string mhtml;
{
- base::ThreadRestrictions::ScopedAllowIO allow_io_for_content_verification;
+ base::ScopedAllowBlockingForTesting allow_blocking;
ASSERT_TRUE(base::ReadFileToString(params.file_path, &mhtml));
}
}
@@ -657,7 +658,7 @@ IN_PROC_BROWSER_TEST_F(MHTMLGenerationSitePerProcessTest, GenerateMHTML) {
std::string mhtml;
{
- base::ThreadRestrictions::ScopedAllowIO allow_io_for_content_verification;
+ base::ScopedAllowBlockingForTesting allow_blocking;
ASSERT_TRUE(base::ReadFileToString(path, &mhtml));
}
@@ -686,7 +687,7 @@ IN_PROC_BROWSER_TEST_F(MHTMLGenerationTest, RemovePopupOverlay) {
std::string mhtml;
{
- base::ThreadRestrictions::ScopedAllowIO allow_io_for_content_verification;
+ base::ScopedAllowBlockingForTesting allow_blocking;
ASSERT_TRUE(base::ReadFileToString(path, &mhtml));
}
@@ -727,7 +728,7 @@ IN_PROC_BROWSER_TEST_F(MHTMLGenerationTest, GenerateMHTMLWithExtraData) {
std::string mhtml;
{
- base::ThreadRestrictions::ScopedAllowIO allow_io_for_content_verification;
+ base::ScopedAllowBlockingForTesting allow_blocking;
ASSERT_TRUE(base::ReadFileToString(path, &mhtml));
}
diff --git a/chromium/content/browser/download/save_package.cc b/chromium/content/browser/download/save_package.cc
index 0310f540c34..187d62297d0 100644
--- a/chromium/content/browser/download/save_package.cc
+++ b/chromium/content/browser/download/save_package.cc
@@ -263,7 +263,11 @@ void SavePackage::InternalInit() {
ukm_download_id_ = download::GetUniqueDownloadId();
download::DownloadUkmHelper::RecordDownloadStarted(
ukm_download_id_, ukm_source_id_, download::DownloadContent::TEXT,
- download::DownloadSource::UNKNOWN);
+ download::DownloadSource::UNKNOWN,
+ download::CheckDownloadConnectionSecurity(
+ web_contents()->GetLastCommittedURL(),
+ std::vector<GURL>{web_contents()->GetLastCommittedURL()}),
+ true /* is_same_host_download */);
}
bool SavePackage::Init(
diff --git a/chromium/content/browser/file_url_loader_factory.cc b/chromium/content/browser/file_url_loader_factory.cc
index 44eb522466d..ea4d8eee977 100644
--- a/chromium/content/browser/file_url_loader_factory.cc
+++ b/chromium/content/browser/file_url_loader_factory.cc
@@ -19,7 +19,7 @@
#include "base/strings/string_util.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "content/public/browser/content_browser_client.h"
@@ -86,6 +86,13 @@ enum class LinkFollowingPolicy {
kDoNotFollow,
};
+GURL AppendUrlSeparator(const GURL& url) {
+ std::string new_path = url.path() + '/';
+ GURL::Replacements replacements;
+ replacements.SetPathStr(new_path);
+ return url.ReplaceComponents(replacements);
+}
+
class FileURLDirectoryLoader
: public network::mojom::URLLoader,
public net::DirectoryLister::DirectoryListerDelegate {
@@ -321,7 +328,26 @@ class FileURLLoader : public network::mojom::URLLoader {
void FollowRedirect(const base::Optional<std::vector<std::string>>&
to_be_removed_request_headers,
const base::Optional<net::HttpRequestHeaders>&
- modified_request_headers) override {}
+ modified_request_headers) override {
+ std::unique_ptr<RedirectData> redirect_data = std::move(redirect_data_);
+ if (redirect_data->is_directory) {
+ FileURLDirectoryLoader::CreateAndStart(
+ redirect_data->profile_path, redirect_data->request,
+ binding_.Unbind(), client_.PassInterface(),
+ std::move(redirect_data->observer),
+ std::move(redirect_data->extra_response_headers));
+ } else {
+ FileURLLoader::CreateAndStart(
+ redirect_data->profile_path, redirect_data->request,
+ binding_.Unbind(), client_.PassInterface(),
+ redirect_data->directory_loading_policy,
+ redirect_data->file_access_policy,
+ redirect_data->link_following_policy,
+ std::move(redirect_data->observer),
+ std::move(redirect_data->extra_response_headers));
+ }
+ MaybeDeleteSelf();
+ }
void ProceedWithResponse() override {}
void SetPriority(net::RequestPriority priority,
int32_t intra_priority_value) override {}
@@ -329,6 +355,23 @@ class FileURLLoader : public network::mojom::URLLoader {
void ResumeReadingBodyFromNet() override {}
private:
+ // Used to save outstanding redirect data while waiting for FollowRedirect
+ // to be called. Values default to their most restrictive in case they are
+ // not set.
+ struct RedirectData {
+ bool is_directory = false;
+ base::FilePath profile_path;
+ network::ResourceRequest request;
+ network::mojom::URLLoaderRequest loader;
+ DirectoryLoadingPolicy directory_loading_policy =
+ DirectoryLoadingPolicy::kFail;
+ FileAccessPolicy file_access_policy = FileAccessPolicy::kRestricted;
+ LinkFollowingPolicy link_following_policy =
+ LinkFollowingPolicy::kDoNotFollow;
+ std::unique_ptr<FileURLLoaderObserver> observer;
+ scoped_refptr<net::HttpResponseHeaders> extra_response_headers;
+ };
+
FileURLLoader() : binding_(this) {}
~FileURLLoader() override = default;
@@ -349,62 +392,50 @@ class FileURLLoader : public network::mojom::URLLoader {
binding_.set_connection_error_handler(base::BindOnce(
&FileURLLoader::OnConnectionError, base::Unretained(this)));
- network::mojom::URLLoaderClientPtr client;
- client.Bind(std::move(client_info));
+ client_.Bind(std::move(client_info));
base::FilePath path;
if (!net::FileURLToFilePath(request.url, &path)) {
- client->OnComplete(network::URLLoaderCompletionStatus(net::ERR_FAILED));
- if (observer)
- observer->OnDoneReading();
+ OnClientComplete(net::ERR_FAILED, std::move(observer));
return;
}
base::File::Info info;
if (!base::GetFileInfo(path, &info)) {
- client->OnComplete(
- network::URLLoaderCompletionStatus(net::ERR_FILE_NOT_FOUND));
- if (observer)
- observer->OnDoneReading();
+ OnClientComplete(net::ERR_FILE_NOT_FOUND, std::move(observer));
return;
}
if (info.is_directory) {
if (directory_loading_policy == DirectoryLoadingPolicy::kFail) {
- client->OnComplete(
- network::URLLoaderCompletionStatus(net::ERR_FILE_NOT_FOUND));
- if (observer)
- observer->OnDoneReading();
+ OnClientComplete(net::ERR_FILE_NOT_FOUND, std::move(observer));
return;
}
DCHECK_EQ(directory_loading_policy,
DirectoryLoadingPolicy::kRespondWithListing);
- GURL directory_url = request.url;
- if (!path.EndsWithSeparator()) {
- // If the named path is a directory with no trailing slash, redirect to
- // the same path, but with a trailing slash.
- std::string new_path = directory_url.path() + '/';
- GURL::Replacements replacements;
- replacements.SetPathStr(new_path);
- directory_url = directory_url.ReplaceComponents(replacements);
-
- net::RedirectInfo redirect_info;
- redirect_info.new_method = "GET";
- redirect_info.status_code = 301;
- redirect_info.new_url = directory_url;
- head.encoded_data_length = 0;
- client->OnReceiveRedirect(redirect_info, head);
- }
+ net::RedirectInfo redirect_info;
+ redirect_info.new_method = "GET";
+ redirect_info.status_code = 301;
+ redirect_info.new_url = path.EndsWithSeparator()
+ ? request.url
+ : AppendUrlSeparator(request.url);
+ head.encoded_data_length = 0;
- // Restart the request with a directory loader.
- network::ResourceRequest new_request = request;
- new_request.url = directory_url;
- FileURLDirectoryLoader::CreateAndStart(
- profile_path, new_request, binding_.Unbind(), client.PassInterface(),
- std::move(observer), std::move(extra_response_headers));
- MaybeDeleteSelf();
+ redirect_data_ = std::make_unique<RedirectData>();
+ redirect_data_->is_directory = true;
+ redirect_data_->profile_path = std::move(profile_path);
+ redirect_data_->request = request;
+ redirect_data_->directory_loading_policy = directory_loading_policy;
+ redirect_data_->file_access_policy = file_access_policy;
+ redirect_data_->link_following_policy = link_following_policy;
+ redirect_data_->request.url = redirect_info.new_url;
+ redirect_data_->observer = std::move(observer);
+ redirect_data_->extra_response_headers =
+ std::move(extra_response_headers);
+
+ client_->OnReceiveRedirect(redirect_info, head);
return;
}
@@ -414,40 +445,48 @@ class FileURLLoader : public network::mojom::URLLoader {
base::LowerCaseEqualsASCII(path.Extension(), ".lnk") &&
base::win::ResolveShortcut(path, &shortcut_target, nullptr)) {
// Follow Windows shortcuts
+ redirect_data_ = std::make_unique<RedirectData>();
+ if (!base::GetFileInfo(shortcut_target, &info)) {
+ OnClientComplete(net::ERR_FILE_NOT_FOUND, std::move(observer));
+ return;
+ }
+
GURL new_url = net::FilePathToFileURL(shortcut_target);
+ if (info.is_directory && !path.EndsWithSeparator())
+ new_url = AppendUrlSeparator(new_url);
net::RedirectInfo redirect_info;
redirect_info.new_method = "GET";
redirect_info.status_code = 301;
redirect_info.new_url = new_url;
head.encoded_data_length = 0;
- client->OnReceiveRedirect(redirect_info, head);
-
- // Restart the request with the new URL.
- network::ResourceRequest new_request = request;
- new_request.url = redirect_info.new_url;
- return Start(profile_path, request, binding_.Unbind(),
- client.PassInterface(), directory_loading_policy,
- file_access_policy, link_following_policy,
- std::move(observer), std::move(extra_response_headers));
+
+ redirect_data_->is_directory = info.is_directory;
+ redirect_data_->profile_path = std::move(profile_path);
+ redirect_data_->request = request;
+ redirect_data_->directory_loading_policy = directory_loading_policy;
+ redirect_data_->file_access_policy = file_access_policy;
+ redirect_data_->link_following_policy = link_following_policy;
+ redirect_data_->request.url = redirect_info.new_url;
+ redirect_data_->observer = std::move(observer);
+ redirect_data_->extra_response_headers =
+ std::move(extra_response_headers);
+
+ client_->OnReceiveRedirect(redirect_info, head);
+ return;
}
#endif // defined(OS_WIN)
if (file_access_policy == FileAccessPolicy::kRestricted &&
!GetContentClient()->browser()->IsFileAccessAllowed(
path, base::MakeAbsoluteFilePath(path), profile_path)) {
- client->OnComplete(
- network::URLLoaderCompletionStatus(net::ERR_ACCESS_DENIED));
- if (observer)
- observer->OnDoneReading();
+ OnClientComplete(net::ERR_ACCESS_DENIED, std::move(observer));
return;
}
mojo::DataPipe pipe(kDefaultFileUrlPipeSize);
if (!pipe.consumer_handle.is_valid()) {
- client->OnComplete(network::URLLoaderCompletionStatus(net::ERR_FAILED));
- if (observer)
- observer->OnDoneReading();
+ OnClientComplete(net::ERR_FAILED, std::move(observer));
return;
}
@@ -466,7 +505,8 @@ class FileURLLoader : public network::mojom::URLLoader {
observer->OnDoneReading();
}
net::Error net_error = net::FileErrorToNetError(file.error_details());
- client->OnComplete(network::URLLoaderCompletionStatus(net_error));
+ client_->OnComplete(network::URLLoaderCompletionStatus(net_error));
+ client_.reset();
MaybeDeleteSelf();
return;
}
@@ -484,7 +524,9 @@ class FileURLLoader : public network::mojom::URLLoader {
observer->OnDoneReading();
}
net::Error net_error = net::FileErrorToNetError(read_error);
- client->OnComplete(network::URLLoaderCompletionStatus(net_error));
+ client_->OnComplete(network::URLLoaderCompletionStatus(net_error));
+ client_.reset();
+ MaybeDeleteSelf();
return;
} else if (observer) {
observer->OnBytesRead(initial_read_buffer, initial_read_result,
@@ -509,16 +551,17 @@ class FileURLLoader : public network::mojom::URLLoader {
}
if (fail) {
- client->OnComplete(network::URLLoaderCompletionStatus(
- net::ERR_REQUEST_RANGE_NOT_SATISFIABLE));
- if (observer)
- observer->OnDoneReading();
+ OnClientComplete(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE,
+ std::move(observer));
return;
}
}
size_t first_byte_to_send = 0;
size_t total_bytes_to_send = static_cast<size_t>(info.size);
+
+ total_bytes_written_ = static_cast<size_t>(info.size);
+
if (byte_range.IsValid()) {
first_byte_to_send =
static_cast<size_t>(byte_range.first_byte_position());
@@ -557,15 +600,15 @@ class FileURLLoader : public network::mojom::URLLoader {
? net::ForceSniffFileUrlsForHtml::kEnabled
: net::ForceSniffFileUrlsForHtml::kDisabled,
&head.mime_type);
+ head.did_mime_sniff = true;
}
if (head.headers) {
head.headers->AddHeader(
base::StringPrintf("%s: %s", net::HttpRequestHeaders::kContentType,
head.mime_type.c_str()));
}
- client->OnReceiveResponse(head);
- client->OnStartLoadingResponseBody(std::move(pipe.consumer_handle));
- client_ = std::move(client);
+ client_->OnReceiveResponse(head);
+ client_->OnStartLoadingResponseBody(std::move(pipe.consumer_handle));
if (total_bytes_to_send == 0) {
// There's definitely no more data, so we're already done.
@@ -594,6 +637,15 @@ class FileURLLoader : public network::mojom::URLLoader {
MaybeDeleteSelf();
}
+ void OnClientComplete(net::Error net_error,
+ std::unique_ptr<FileURLLoaderObserver> observer) {
+ client_->OnComplete(network::URLLoaderCompletionStatus(net_error));
+ client_.reset();
+ if (observer)
+ observer->OnDoneReading();
+ MaybeDeleteSelf();
+ }
+
void MaybeDeleteSelf() {
if (!binding_.is_bound() && !client_.is_bound())
delete this;
@@ -607,10 +659,15 @@ class FileURLLoader : public network::mojom::URLLoader {
if (observer)
observer->OnDoneReading();
- if (result == MOJO_RESULT_OK)
- client_->OnComplete(network::URLLoaderCompletionStatus(net::OK));
- else
+ if (result == MOJO_RESULT_OK) {
+ network::URLLoaderCompletionStatus status(net::OK);
+ status.encoded_data_length = total_bytes_written_;
+ status.encoded_body_length = total_bytes_written_;
+ status.decoded_body_length = total_bytes_written_;
+ client_->OnComplete(status);
+ } else {
client_->OnComplete(network::URLLoaderCompletionStatus(net::ERR_FAILED));
+ }
client_.reset();
MaybeDeleteSelf();
}
@@ -618,6 +675,12 @@ class FileURLLoader : public network::mojom::URLLoader {
std::unique_ptr<mojo::FileDataPipeProducer> data_producer_;
mojo::Binding<network::mojom::URLLoader> binding_;
network::mojom::URLLoaderClientPtr client_;
+ std::unique_ptr<RedirectData> redirect_data_;
+
+ // In case of successful loads, this holds the total of bytes written.
+ // It is used to set some of the URLLoaderCompletionStatus data passed back
+ // to the URLLoaderClients (eg SimpleURLLoader).
+ size_t total_bytes_written_ = 0;
DISALLOW_COPY_AND_ASSIGN(FileURLLoader);
};
@@ -640,8 +703,12 @@ void FileURLLoaderFactory::CreateLoaderAndStart(
network::mojom::URLLoaderClientPtr client,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
base::FilePath file_path;
- const bool is_file = net::FileURLToFilePath(request.url, &file_path);
- if (is_file && file_path.EndsWithSeparator() && file_path.IsAbsolute()) {
+ if (!net::FileURLToFilePath(request.url, &file_path)) {
+ client->OnComplete(
+ network::URLLoaderCompletionStatus(net::ERR_INVALID_URL));
+ return;
+ }
+ if (file_path.EndsWithSeparator() && file_path.IsAbsolute()) {
task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&FileURLDirectoryLoader::CreateAndStart, profile_path_,
@@ -672,7 +739,7 @@ void CreateFileURLLoader(
std::unique_ptr<FileURLLoaderObserver> observer,
scoped_refptr<net::HttpResponseHeaders> extra_response_headers) {
auto task_runner = base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BACKGROUND,
+ {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
task_runner->PostTask(
FROM_HERE,
@@ -684,4 +751,12 @@ void CreateFileURLLoader(
std::move(extra_response_headers)));
}
+std::unique_ptr<network::mojom::URLLoaderFactory> CreateFileURLLoaderFactory(
+ const base::FilePath& profile_path) {
+ return std::make_unique<content::FileURLLoaderFactory>(
+ profile_path, base::CreateSequencedTaskRunnerWithTraits(
+ {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+ base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}));
+}
+
} // namespace content
diff --git a/chromium/content/browser/fileapi/browser_file_system_helper.cc b/chromium/content/browser/fileapi/browser_file_system_helper.cc
index acf067a117b..7227c691e73 100644
--- a/chromium/content/browser/fileapi/browser_file_system_helper.cc
+++ b/chromium/content/browser/fileapi/browser_file_system_helper.cc
@@ -14,7 +14,7 @@
#include "base/files/file_path.h"
#include "base/sequenced_task_runner.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/task_scheduler/lazy_task_runner.h"
+#include "base/task/lazy_task_runner.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
diff --git a/chromium/content/browser/fileapi/file_system_chooser.cc b/chromium/content/browser/fileapi/file_system_chooser.cc
new file mode 100644
index 00000000000..0c8ae67d894
--- /dev/null
+++ b/chromium/content/browser/fileapi/file_system_chooser.cc
@@ -0,0 +1,105 @@
+// 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/fileapi/file_system_chooser.h"
+
+#include "base/bind.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/child_process_security_policy.h"
+#include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/common/content_client.h"
+#include "storage/browser/fileapi/isolated_context.h"
+#include "ui/shell_dialogs/select_file_policy.h"
+
+namespace content {
+
+// static
+void FileSystemChooser::CreateAndShow(
+ int render_process_id,
+ int frame_id,
+ ResultCallback callback,
+ scoped_refptr<base::TaskRunner> callback_runner) {
+ 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, std::move(callback),
+ std::move(callback_runner));
+ listener->dialog_ = ui::SelectFileDialog::Create(
+ listener,
+ GetContentClient()->browser()->CreateSelectFilePolicy(web_contents));
+ // TODO(https://crbug.com/878581): Better/more specific options to pass to
+ // SelectFile.
+ listener->dialog_->SelectFile(
+ ui::SelectFileDialog::SELECT_OPEN_FILE, /*title=*/base::string16(),
+ /*default_path=*/base::FilePath(), /*file_types=*/nullptr,
+ /*file_type_index=*/0,
+ /*default_extension=*/base::FilePath::StringType(),
+ web_contents ? web_contents->GetTopLevelNativeWindow() : nullptr,
+ /*params=*/nullptr);
+}
+
+FileSystemChooser::FileSystemChooser(
+ int render_process_id,
+ ResultCallback callback,
+ scoped_refptr<base::TaskRunner> callback_runner)
+ : render_process_id_(render_process_id),
+ callback_(std::move(callback)),
+ callback_runner_(std::move(callback_runner)) {}
+
+FileSystemChooser::~FileSystemChooser() {
+ if (dialog_)
+ dialog_->ListenerDestroyed();
+}
+
+void FileSystemChooser::FileSelected(const base::FilePath& path,
+ int index,
+ void* params) {
+ MultiFilesSelected({path}, params);
+}
+
+void FileSystemChooser::MultiFilesSelected(
+ const std::vector<base::FilePath>& files,
+ void* params) {
+ 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::kFileSystemTypeNativeForPlatformApp, std::string(), path,
+ &entry->base_name);
+
+ // TODO(https://crbug.com/878585): Determine if we always want to grant
+ // write permission.
+ security_policy->GrantReadFileSystem(render_process_id_,
+ entry->file_system_id);
+ 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));
+ }
+
+ callback_runner_->PostTask(
+ FROM_HERE, base::BindOnce(std::move(callback_), base::File::FILE_OK,
+ std::move(result)));
+ 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>()));
+ delete this;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/fileapi/file_system_chooser.h b/chromium/content/browser/fileapi/file_system_chooser.h
new file mode 100644
index 00000000000..2283a6725e3
--- /dev/null
+++ b/chromium/content/browser/fileapi/file_system_chooser.h
@@ -0,0 +1,55 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_FILEAPI_FILE_SYSTEM_CHOOSER_H_
+#define CONTENT_BROWSER_FILEAPI_FILE_SYSTEM_CHOOSER_H_
+
+#include "base/files/file.h"
+#include "base/task_runner.h"
+#include "third_party/blink/public/mojom/filesystem/file_system.mojom.h"
+#include "ui/shell_dialogs/select_file_dialog.h"
+
+namespace content {
+
+// This is a ui::SelectFileDialog::Listener implementation that grants access to
+// the selected files to a specific renderer process on success, and then calls
+// a callback on a specific task runner. Furthermore the listener will delete
+// itself when any of its listener methods are called.
+// All of this class has to be called on the UI thread.
+class FileSystemChooser : public ui::SelectFileDialog::Listener {
+ public:
+ using ResultCallback =
+ base::OnceCallback<void(base::File::Error,
+ std::vector<blink::mojom::FileSystemEntryPtr>)>;
+
+ static void CreateAndShow(int render_process_id,
+ int frame_id,
+ ResultCallback callback,
+ scoped_refptr<base::TaskRunner> callback_runner);
+
+ FileSystemChooser(int render_process_id,
+ ResultCallback callback,
+ scoped_refptr<base::TaskRunner> callback_runner);
+
+ private:
+ ~FileSystemChooser() override;
+
+ // ui::SelectFileDialog::Listener:
+ void FileSelected(const base::FilePath& path,
+ int index,
+ void* params) override;
+ void MultiFilesSelected(const std::vector<base::FilePath>& files,
+ void* params) override;
+ void FileSelectionCanceled(void* params) override;
+
+ int render_process_id_;
+ ResultCallback callback_;
+ scoped_refptr<base::TaskRunner> callback_runner_;
+
+ scoped_refptr<ui::SelectFileDialog> dialog_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_FILEAPI_FILE_SYSTEM_CHOOSER_H_
diff --git a/chromium/content/browser/fileapi/file_system_manager_impl.cc b/chromium/content/browser/fileapi/file_system_manager_impl.cc
new file mode 100644
index 00000000000..e8b7272c921
--- /dev/null
+++ b/chromium/content/browser/fileapi/file_system_manager_impl.cc
@@ -0,0 +1,872 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/fileapi/file_system_manager_impl.h"
+
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/metrics/user_metrics.h"
+#include "base/sequenced_task_runner.h"
+#include "base/strings/string_util.h"
+#include "base/threading/thread.h"
+#include "base/time/time.h"
+#include "build/build_config.h"
+#include "components/services/filesystem/public/interfaces/types.mojom.h"
+#include "content/browser/bad_message.h"
+#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_thread.h"
+#include "ipc/ipc_platform_file.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "net/base/mime_util.h"
+#include "storage/browser/blob/blob_data_builder.h"
+#include "storage/browser/blob/blob_storage_context.h"
+#include "storage/browser/blob/shareable_file_reference.h"
+#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"
+#include "storage/common/fileapi/file_system_types.h"
+#include "storage/common/fileapi/file_system_util.h"
+#include "third_party/blink/public/common/features.h"
+#include "url/gurl.h"
+
+using storage::FileSystemFileUtil;
+using storage::FileSystemBackend;
+using storage::FileSystemOperation;
+using storage::FileSystemURL;
+using storage::BlobDataBuilder;
+using storage::BlobStorageContext;
+
+namespace content {
+
+namespace {
+
+void RevokeFilePermission(int child_id, const base::FilePath& path) {
+ ChildProcessSecurityPolicyImpl::GetInstance()->RevokeAllPermissionsForFile(
+ child_id, path);
+}
+
+} // namespace
+
+class FileSystemManagerImpl::FileSystemCancellableOperationImpl
+ : public blink::mojom::FileSystemCancellableOperation {
+ using OperationID = storage::FileSystemOperationRunner::OperationID;
+
+ public:
+ FileSystemCancellableOperationImpl(
+ OperationID id,
+ FileSystemManagerImpl* file_system_manager_impl)
+ : id_(id), file_system_manager_impl_(file_system_manager_impl) {}
+ ~FileSystemCancellableOperationImpl() override = default;
+
+ private:
+ void Cancel(CancelCallback callback) override {
+ file_system_manager_impl_->Cancel(id_, std::move(callback));
+ }
+
+ const OperationID id_;
+ // |file_system_manager_impl| owns |this| through a StrongBindingSet.
+ FileSystemManagerImpl* const file_system_manager_impl_;
+};
+
+class FileSystemManagerImpl::ReceivedSnapshotListenerImpl
+ : public blink::mojom::ReceivedSnapshotListener {
+ public:
+ ReceivedSnapshotListenerImpl(int snapshot_id,
+ FileSystemManagerImpl* file_system_manager_impl)
+ : snapshot_id_(snapshot_id),
+ file_system_manager_impl_(file_system_manager_impl) {}
+ ~ReceivedSnapshotListenerImpl() override = default;
+
+ private:
+ void DidReceiveSnapshotFile() override {
+ file_system_manager_impl_->DidReceiveSnapshotFile(snapshot_id_);
+ }
+
+ const int snapshot_id_;
+ // |file_system_manager_impl| owns |this| through a StrongBindingSet.
+ FileSystemManagerImpl* const file_system_manager_impl_;
+};
+
+struct FileSystemManagerImpl::WriteSyncCallbackEntry {
+ WriteSyncCallback callback;
+ int64_t bytes;
+
+ explicit WriteSyncCallbackEntry(WriteSyncCallback cb)
+ : callback(std::move(cb)), bytes(0) {}
+};
+
+struct FileSystemManagerImpl::ReadDirectorySyncCallbackEntry {
+ ReadDirectorySyncCallback callback;
+ std::vector<filesystem::mojom::DirectoryEntryPtr> entries;
+
+ explicit ReadDirectorySyncCallbackEntry(ReadDirectorySyncCallback cb)
+ : callback(std::move(cb)) {}
+};
+
+FileSystemManagerImpl::FileSystemManagerImpl(
+ int process_id,
+ storage::FileSystemContext* file_system_context,
+ scoped_refptr<ChromeBlobStorageContext> blob_storage_context)
+ : process_id_(process_id),
+ context_(file_system_context),
+ security_policy_(ChildProcessSecurityPolicyImpl::GetInstance()),
+ blob_storage_context_(blob_storage_context),
+ weak_factory_(this) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(context_);
+ DCHECK(blob_storage_context);
+ bindings_.set_connection_error_handler(base::BindRepeating(
+ &FileSystemManagerImpl::OnConnectionError, base::Unretained(this)));
+}
+
+FileSystemManagerImpl::~FileSystemManagerImpl() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+}
+
+base::WeakPtr<FileSystemManagerImpl> FileSystemManagerImpl::GetWeakPtr() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ return weak_factory_.GetWeakPtr();
+}
+
+void FileSystemManagerImpl::BindRequest(
+ blink::mojom::FileSystemManagerRequest request) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (!operation_runner_)
+ operation_runner_ = context_->CreateFileSystemOperationRunner();
+ bindings_.AddBinding(this, std::move(request));
+}
+
+void FileSystemManagerImpl::Open(const GURL& origin_url,
+ blink::mojom::FileSystemType file_system_type,
+ OpenCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (file_system_type == blink::mojom::FileSystemType::kTemporary) {
+ RecordAction(base::UserMetricsAction("OpenFileSystemTemporary"));
+ } else if (file_system_type == blink::mojom::FileSystemType::kPersistent) {
+ RecordAction(base::UserMetricsAction("OpenFileSystemPersistent"));
+ }
+ context_->OpenFileSystem(
+ origin_url, mojo::ConvertTo<storage::FileSystemType>(file_system_type),
+ storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
+ base::BindOnce(&FileSystemManagerImpl::DidOpenFileSystem, GetWeakPtr(),
+ std::move(callback)));
+};
+
+void FileSystemManagerImpl::ResolveURL(const GURL& filesystem_url,
+ ResolveURLCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ FileSystemURL url(context_->CrackURL(filesystem_url));
+ base::Optional<base::File::Error> opt_error = ValidateFileSystemURL(url);
+ if (opt_error) {
+ std::move(callback).Run(blink::mojom::FileSystemInfo::New(),
+ base::FilePath(), false, opt_error.value());
+ return;
+ }
+
+ if (!security_policy_->CanReadFileSystemFile(process_id_, url)) {
+ std::move(callback).Run(blink::mojom::FileSystemInfo::New(),
+ base::FilePath(), false,
+ base::File::FILE_ERROR_SECURITY);
+ return;
+ }
+
+ context_->ResolveURL(
+ url, base::BindOnce(&FileSystemManagerImpl::DidResolveURL, GetWeakPtr(),
+ std::move(callback)));
+}
+
+void FileSystemManagerImpl::Move(const GURL& src_path,
+ const GURL& dest_path,
+ MoveCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ FileSystemURL src_url(context_->CrackURL(src_path));
+ FileSystemURL dest_url(context_->CrackURL(dest_path));
+ base::Optional<base::File::Error> opt_error = ValidateFileSystemURL(src_url);
+ if (!opt_error)
+ opt_error = ValidateFileSystemURL(dest_url);
+ if (opt_error) {
+ std::move(callback).Run(opt_error.value());
+ return;
+ }
+ if (!security_policy_->CanReadFileSystemFile(process_id_, src_url) ||
+ !security_policy_->CanDeleteFileSystemFile(process_id_, src_url) ||
+ !security_policy_->CanCreateFileSystemFile(process_id_, dest_url)) {
+ std::move(callback).Run(base::File::FILE_ERROR_SECURITY);
+ return;
+ }
+
+ operation_runner()->Move(
+ src_url, dest_url, storage::FileSystemOperation::OPTION_NONE,
+ base::BindRepeating(&FileSystemManagerImpl::DidFinish, GetWeakPtr(),
+ base::Passed(&callback)));
+}
+
+void FileSystemManagerImpl::Copy(const GURL& src_path,
+ const GURL& dest_path,
+ CopyCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ FileSystemURL src_url(context_->CrackURL(src_path));
+ FileSystemURL dest_url(context_->CrackURL(dest_path));
+ base::Optional<base::File::Error> opt_error = ValidateFileSystemURL(src_url);
+ if (!opt_error)
+ opt_error = ValidateFileSystemURL(dest_url);
+ if (opt_error) {
+ std::move(callback).Run(opt_error.value());
+ return;
+ }
+ if (!security_policy_->CanReadFileSystemFile(process_id_, src_url) ||
+ !security_policy_->CanCopyIntoFileSystemFile(process_id_, dest_url)) {
+ std::move(callback).Run(base::File::FILE_ERROR_SECURITY);
+ return;
+ }
+
+ operation_runner()->Copy(
+ src_url, dest_url, storage::FileSystemOperation::OPTION_NONE,
+ FileSystemOperation::ERROR_BEHAVIOR_ABORT,
+ storage::FileSystemOperationRunner::CopyProgressCallback(),
+ base::BindRepeating(&FileSystemManagerImpl::DidFinish, GetWeakPtr(),
+ base::Passed(&callback)));
+}
+
+void FileSystemManagerImpl::Remove(const GURL& path,
+ bool recursive,
+ RemoveCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ FileSystemURL url(context_->CrackURL(path));
+ base::Optional<base::File::Error> opt_error = ValidateFileSystemURL(url);
+ if (opt_error) {
+ std::move(callback).Run(opt_error.value());
+ return;
+ }
+ if (!security_policy_->CanDeleteFileSystemFile(process_id_, url)) {
+ std::move(callback).Run(base::File::FILE_ERROR_SECURITY);
+ return;
+ }
+
+ operation_runner()->Remove(
+ url, recursive,
+ base::BindRepeating(&FileSystemManagerImpl::DidFinish, GetWeakPtr(),
+ base::Passed(&callback)));
+}
+
+void FileSystemManagerImpl::ReadMetadata(const GURL& path,
+ ReadMetadataCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ FileSystemURL url(context_->CrackURL(path));
+ base::Optional<base::File::Error> opt_error = ValidateFileSystemURL(url);
+ if (opt_error) {
+ std::move(callback).Run(base::File::Info(), opt_error.value());
+ return;
+ }
+ if (!security_policy_->CanReadFileSystemFile(process_id_, url)) {
+ std::move(callback).Run(base::File::Info(),
+ base::File::FILE_ERROR_SECURITY);
+ return;
+ }
+
+ operation_runner()->GetMetadata(
+ url,
+ FileSystemOperation::GET_METADATA_FIELD_IS_DIRECTORY |
+ FileSystemOperation::GET_METADATA_FIELD_SIZE |
+ FileSystemOperation::GET_METADATA_FIELD_LAST_MODIFIED,
+ base::BindRepeating(&FileSystemManagerImpl::DidGetMetadata, GetWeakPtr(),
+ base::Passed(&callback)));
+}
+
+void FileSystemManagerImpl::Create(const GURL& path,
+ bool exclusive,
+ bool is_directory,
+ bool recursive,
+ CreateCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ FileSystemURL url(context_->CrackURL(path));
+ base::Optional<base::File::Error> opt_error = ValidateFileSystemURL(url);
+ if (opt_error) {
+ std::move(callback).Run(opt_error.value());
+ return;
+ }
+ if (!security_policy_->CanCreateFileSystemFile(process_id_, url)) {
+ std::move(callback).Run(base::File::FILE_ERROR_SECURITY);
+ return;
+ }
+
+ if (is_directory) {
+ operation_runner()->CreateDirectory(
+ url, exclusive, recursive,
+ base::BindRepeating(&FileSystemManagerImpl::DidFinish, GetWeakPtr(),
+ base::Passed(&callback)));
+ } else {
+ operation_runner()->CreateFile(
+ url, exclusive,
+ base::BindRepeating(&FileSystemManagerImpl::DidFinish, GetWeakPtr(),
+ base::Passed(&callback)));
+ }
+}
+
+void FileSystemManagerImpl::Exists(const GURL& path,
+ bool is_directory,
+ ExistsCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ FileSystemURL url(context_->CrackURL(path));
+ base::Optional<base::File::Error> opt_error = ValidateFileSystemURL(url);
+ if (opt_error) {
+ std::move(callback).Run(opt_error.value());
+ return;
+ }
+ if (!security_policy_->CanReadFileSystemFile(process_id_, url)) {
+ std::move(callback).Run(base::File::FILE_ERROR_SECURITY);
+ return;
+ }
+
+ if (is_directory) {
+ operation_runner()->DirectoryExists(
+ url, base::BindRepeating(&FileSystemManagerImpl::DidFinish,
+ GetWeakPtr(), base::Passed(&callback)));
+ } else {
+ operation_runner()->FileExists(
+ url, base::BindRepeating(&FileSystemManagerImpl::DidFinish,
+ GetWeakPtr(), base::Passed(&callback)));
+ }
+}
+
+void FileSystemManagerImpl::ReadDirectory(
+ const GURL& path,
+ blink::mojom::FileSystemOperationListenerPtr listener) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ FileSystemURL url(context_->CrackURL(path));
+ base::Optional<base::File::Error> opt_error = ValidateFileSystemURL(url);
+ if (opt_error) {
+ listener->ErrorOccurred(opt_error.value());
+ return;
+ }
+ if (!security_policy_->CanReadFileSystemFile(process_id_, url)) {
+ listener->ErrorOccurred(base::File::FILE_ERROR_SECURITY);
+ return;
+ }
+
+ OperationListenerID listener_id = AddOpListener(std::move(listener));
+ operation_runner()->ReadDirectory(
+ url, base::BindRepeating(&FileSystemManagerImpl::DidReadDirectory,
+ GetWeakPtr(), listener_id));
+}
+
+void FileSystemManagerImpl::ReadDirectorySync(
+ const GURL& path,
+ ReadDirectorySyncCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ FileSystemURL url(context_->CrackURL(path));
+ base::Optional<base::File::Error> opt_error = ValidateFileSystemURL(url);
+ if (opt_error) {
+ std::move(callback).Run(std::vector<filesystem::mojom::DirectoryEntryPtr>(),
+ opt_error.value());
+ return;
+ }
+ if (!security_policy_->CanReadFileSystemFile(process_id_, url)) {
+ std::move(callback).Run(std::vector<filesystem::mojom::DirectoryEntryPtr>(),
+ base::File::FILE_ERROR_SECURITY);
+ return;
+ }
+
+ operation_runner()->ReadDirectory(
+ url, base::BindRepeating(
+ &FileSystemManagerImpl::DidReadDirectorySync, GetWeakPtr(),
+ base::Owned(
+ new ReadDirectorySyncCallbackEntry(std::move(callback)))));
+}
+
+void FileSystemManagerImpl::Write(
+ const GURL& file_path,
+ const std::string& blob_uuid,
+ int64_t position,
+ blink::mojom::FileSystemCancellableOperationRequest op_request,
+ blink::mojom::FileSystemOperationListenerPtr listener) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ FileSystemURL url(context_->CrackURL(file_path));
+ base::Optional<base::File::Error> opt_error = ValidateFileSystemURL(url);
+ if (opt_error) {
+ listener->ErrorOccurred(opt_error.value());
+ return;
+ }
+ if (!security_policy_->CanWriteFileSystemFile(process_id_, url)) {
+ listener->ErrorOccurred(base::File::FILE_ERROR_SECURITY);
+ return;
+ }
+ std::unique_ptr<storage::BlobDataHandle> blob =
+ blob_storage_context_->context()->GetBlobDataFromUUID(blob_uuid);
+
+ OperationListenerID listener_id = AddOpListener(std::move(listener));
+
+ OperationID op_id = operation_runner()->Write(
+ url, std::move(blob), position,
+ base::BindRepeating(&FileSystemManagerImpl::DidWrite, GetWeakPtr(),
+ listener_id));
+ cancellable_operations_.AddBinding(
+ std::make_unique<FileSystemCancellableOperationImpl>(op_id, this),
+ std::move(op_request));
+}
+
+void FileSystemManagerImpl::WriteSync(const GURL& file_path,
+ const std::string& blob_uuid,
+ int64_t position,
+ WriteSyncCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ FileSystemURL url(context_->CrackURL(file_path));
+ base::Optional<base::File::Error> opt_error = ValidateFileSystemURL(url);
+ if (opt_error) {
+ std::move(callback).Run(0, opt_error.value());
+ return;
+ }
+ if (!security_policy_->CanWriteFileSystemFile(process_id_, url)) {
+ std::move(callback).Run(0, base::File::FILE_ERROR_SECURITY);
+ return;
+ }
+ std::unique_ptr<storage::BlobDataHandle> blob =
+ blob_storage_context_->context()->GetBlobDataFromUUID(blob_uuid);
+
+ operation_runner()->Write(
+ url, std::move(blob), position,
+ base::BindRepeating(
+ &FileSystemManagerImpl::DidWriteSync, GetWeakPtr(),
+ base::Owned(new WriteSyncCallbackEntry(std::move(callback)))));
+}
+
+void FileSystemManagerImpl::Truncate(
+ const GURL& file_path,
+ int64_t length,
+ blink::mojom::FileSystemCancellableOperationRequest op_request,
+ TruncateCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ 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());
+ return;
+ }
+ if (!security_policy_->CanWriteFileSystemFile(process_id_, url)) {
+ std::move(callback).Run(base::File::FILE_ERROR_SECURITY);
+ return;
+ }
+
+ OperationID op_id = operation_runner()->Truncate(
+ url, length,
+ base::BindRepeating(&FileSystemManagerImpl::DidFinish, GetWeakPtr(),
+ base::Passed(&callback)));
+ cancellable_operations_.AddBinding(
+ std::make_unique<FileSystemCancellableOperationImpl>(op_id, this),
+ std::move(op_request));
+}
+
+void FileSystemManagerImpl::TruncateSync(const GURL& file_path,
+ int64_t length,
+ TruncateSyncCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ 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());
+ return;
+ }
+ if (!security_policy_->CanWriteFileSystemFile(process_id_, url)) {
+ std::move(callback).Run(base::File::FILE_ERROR_SECURITY);
+ return;
+ }
+
+ operation_runner()->Truncate(
+ url, length,
+ base::BindRepeating(&FileSystemManagerImpl::DidFinish, GetWeakPtr(),
+ base::Passed(&callback)));
+}
+
+void FileSystemManagerImpl::TouchFile(const GURL& path,
+ base::Time last_access_time,
+ base::Time last_modified_time,
+ TouchFileCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ FileSystemURL url(context_->CrackURL(path));
+ base::Optional<base::File::Error> opt_error = ValidateFileSystemURL(url);
+ if (opt_error) {
+ std::move(callback).Run(opt_error.value());
+ return;
+ }
+ if (!security_policy_->CanCreateFileSystemFile(process_id_, url)) {
+ std::move(callback).Run(base::File::FILE_ERROR_SECURITY);
+ return;
+ }
+
+ operation_runner()->TouchFile(
+ url, last_access_time, last_modified_time,
+ base::BindRepeating(&FileSystemManagerImpl::DidFinish, GetWeakPtr(),
+ base::Passed(&callback)));
+}
+
+void FileSystemManagerImpl::CreateSnapshotFile(
+ const GURL& file_path,
+ CreateSnapshotFileCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ FileSystemURL url(context_->CrackURL(file_path));
+
+ // Make sure if this file can be read by the renderer as this is
+ // called when the renderer is about to create a new File object
+ // (for reading the file).
+ base::Optional<base::File::Error> opt_error = ValidateFileSystemURL(url);
+ if (opt_error) {
+ std::move(callback).Run(base::File::Info(), base::FilePath(),
+ opt_error.value(), nullptr);
+ return;
+ }
+ if (!security_policy_->CanReadFileSystemFile(process_id_, url)) {
+ std::move(callback).Run(base::File::Info(), base::FilePath(),
+ base::File::FILE_ERROR_SECURITY, nullptr);
+ return;
+ }
+
+ FileSystemBackend* backend = context_->GetFileSystemBackend(url.type());
+ if (backend->SupportsStreaming(url)) {
+ operation_runner()->GetMetadata(
+ url,
+ FileSystemOperation::GET_METADATA_FIELD_IS_DIRECTORY |
+ FileSystemOperation::GET_METADATA_FIELD_SIZE |
+ FileSystemOperation::GET_METADATA_FIELD_LAST_MODIFIED,
+ base::BindRepeating(&FileSystemManagerImpl::DidGetMetadataForStreaming,
+ GetWeakPtr(), base::Passed(&callback)));
+ } else {
+ operation_runner()->CreateSnapshotFile(
+ url, base::BindRepeating(&FileSystemManagerImpl::DidCreateSnapshot,
+ GetWeakPtr(), base::Passed(&callback), url));
+ }
+}
+
+void FileSystemManagerImpl::GetPlatformPath(const GURL& path,
+ GetPlatformPathCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ base::FilePath platform_path;
+ context_->default_file_task_runner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&FileSystemManagerImpl::GetPlatformPathOnFileThread, path,
+ process_id_, base::Unretained(context_), GetWeakPtr(),
+ std::move(callback)));
+}
+
+void FileSystemManagerImpl::CreateWriter(const GURL& file_path,
+ CreateWriterCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ 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(int32_t render_frame_id,
+ ChooseEntryCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (!base::FeatureList::IsEnabled(blink::features::kWritableFilesAPI)) {
+ bindings_.ReportBadMessage("FSMI_WRITABLE_FILES_DISABLED");
+ return;
+ }
+
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&FileSystemChooser::CreateAndShow, process_id_,
+ render_frame_id, std::move(callback),
+ BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)));
+}
+
+void FileSystemManagerImpl::Cancel(
+ OperationID op_id,
+ FileSystemCancellableOperationImpl::CancelCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ operation_runner()->Cancel(
+ op_id, base::BindRepeating(&FileSystemManagerImpl::DidFinish,
+ GetWeakPtr(), base::Passed(&callback)));
+}
+
+void FileSystemManagerImpl::DidReceiveSnapshotFile(int snapshot_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ in_transit_snapshot_files_.Remove(snapshot_id);
+}
+
+void FileSystemManagerImpl::OnConnectionError() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (bindings_.empty()) {
+ in_transit_snapshot_files_.Clear();
+ operation_runner_.reset();
+ }
+}
+
+void FileSystemManagerImpl::DidFinish(
+ base::OnceCallback<void(base::File::Error)> callback,
+ base::File::Error error_code) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ std::move(callback).Run(error_code);
+}
+
+void FileSystemManagerImpl::DidGetMetadata(ReadMetadataCallback callback,
+ base::File::Error result,
+ const base::File::Info& info) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ std::move(callback).Run(info, result);
+}
+
+void FileSystemManagerImpl::DidGetMetadataForStreaming(
+ CreateSnapshotFileCallback callback,
+ base::File::Error result,
+ const base::File::Info& info) {
+ // For now, streaming Blobs are implemented as a successful snapshot file
+ // creation with an empty path.
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ std::move(callback).Run(info, base::FilePath(), result, nullptr);
+}
+
+void FileSystemManagerImpl::DidReadDirectory(
+ OperationListenerID listener_id,
+ base::File::Error result,
+ std::vector<filesystem::mojom::DirectoryEntry> entries,
+ bool has_more) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ blink::mojom::FileSystemOperationListener* listener =
+ GetOpListener(listener_id);
+ if (!listener)
+ return;
+ if (result != base::File::FILE_OK) {
+ DCHECK(!has_more);
+ listener->ErrorOccurred(result);
+ RemoveOpListener(listener_id);
+ return;
+ }
+ std::vector<filesystem::mojom::DirectoryEntryPtr> entry_struct_ptrs;
+ for (const auto& entry : entries) {
+ entry_struct_ptrs.emplace_back(
+ filesystem::mojom::DirectoryEntry::New(entry));
+ }
+ listener->ResultsRetrieved(std::move(entry_struct_ptrs), has_more);
+ if (!has_more)
+ RemoveOpListener(listener_id);
+}
+
+void FileSystemManagerImpl::DidReadDirectorySync(
+ ReadDirectorySyncCallbackEntry* callback_entry,
+ base::File::Error result,
+ std::vector<filesystem::mojom::DirectoryEntry> entries,
+ bool has_more) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ for (const auto& entry : entries) {
+ callback_entry->entries.emplace_back(
+ filesystem::mojom::DirectoryEntry::New(std::move(entry)));
+ }
+ if (result != base::File::FILE_OK || !has_more) {
+ std::move(callback_entry->callback)
+ .Run(std::move(callback_entry->entries), result);
+ }
+}
+
+void FileSystemManagerImpl::DidWrite(OperationListenerID listener_id,
+ base::File::Error result,
+ int64_t bytes,
+ bool complete) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ blink::mojom::FileSystemOperationListener* listener =
+ GetOpListener(listener_id);
+ if (!listener)
+ return;
+ if (result == base::File::FILE_OK) {
+ listener->DidWrite(bytes, complete);
+ if (complete)
+ RemoveOpListener(listener_id);
+ } else {
+ listener->ErrorOccurred(result);
+ RemoveOpListener(listener_id);
+ }
+}
+
+void FileSystemManagerImpl::DidWriteSync(WriteSyncCallbackEntry* entry,
+ base::File::Error result,
+ int64_t bytes,
+ bool complete) {
+ entry->bytes += bytes;
+ if (complete || result != base::File::FILE_OK)
+ std::move(entry->callback).Run(entry->bytes, result);
+}
+
+void FileSystemManagerImpl::DidOpenFileSystem(
+ OpenCallback callback,
+ const GURL& root,
+ const std::string& filesystem_name,
+ base::File::Error result) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(root.is_valid() || result != base::File::FILE_OK);
+ std::move(callback).Run(filesystem_name, root, result);
+ // For OpenFileSystem we do not create a new operation, so no unregister here.
+}
+
+void FileSystemManagerImpl::DidResolveURL(
+ ResolveURLCallback callback,
+ base::File::Error result,
+ const storage::FileSystemInfo& info,
+ const base::FilePath& file_path,
+ storage::FileSystemContext::ResolvedEntryType type) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (result == base::File::FILE_OK &&
+ type == storage::FileSystemContext::RESOLVED_ENTRY_NOT_FOUND)
+ result = base::File::FILE_ERROR_NOT_FOUND;
+
+ std::move(callback).Run(
+ mojo::ConvertTo<blink::mojom::FileSystemInfoPtr>(info), file_path,
+ type == storage::FileSystemContext::RESOLVED_ENTRY_DIRECTORY, result);
+ // For ResolveURL we do not create a new operation, so no unregister here.
+}
+
+void FileSystemManagerImpl::DidCreateSnapshot(
+ CreateSnapshotFileCallback callback,
+ const storage::FileSystemURL& url,
+ base::File::Error result,
+ const base::File::Info& info,
+ const base::FilePath& platform_path,
+ scoped_refptr<storage::ShareableFileReference> /* unused */) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (result != base::File::FILE_OK) {
+ std::move(callback).Run(base::File::Info(), base::FilePath(), result,
+ nullptr);
+ return;
+ }
+
+ scoped_refptr<storage::ShareableFileReference> file_ref =
+ storage::ShareableFileReference::Get(platform_path);
+ if (!security_policy_->CanReadFile(process_id_, platform_path)) {
+ // Give per-file read permission to the snapshot file if it hasn't it yet.
+ // In order for the renderer to be able to read the file via File object,
+ // it must be granted per-file read permission for the file's platform
+ // path. By now, it has already been verified that the renderer has
+ // sufficient permissions to read the file, so giving per-file permission
+ // here must be safe.
+ security_policy_->GrantReadFile(process_id_, platform_path);
+
+ // Revoke all permissions for the file when the last ref of the file
+ // is dropped.
+ if (!file_ref.get()) {
+ // Create a reference for temporary permission handling.
+ file_ref = storage::ShareableFileReference::GetOrCreate(
+ platform_path,
+ storage::ShareableFileReference::DONT_DELETE_ON_FINAL_RELEASE,
+ context_->default_file_task_runner());
+ }
+ file_ref->AddFinalReleaseCallback(
+ base::BindOnce(&RevokeFilePermission, process_id_));
+ }
+
+ if (file_ref.get()) {
+ // This ref is held until DidReceiveSnapshotFile is called.
+ int request_id = in_transit_snapshot_files_.Add(file_ref);
+ blink::mojom::ReceivedSnapshotListenerPtr listener_ptr;
+ snapshot_listeners_.AddBinding(
+ std::make_unique<ReceivedSnapshotListenerImpl>(request_id, this),
+ mojo::MakeRequest<blink::mojom::ReceivedSnapshotListener>(
+ &listener_ptr));
+ // Return the file info and platform_path.
+ std::move(callback).Run(info, platform_path, result,
+ std::move(listener_ptr));
+ return;
+ }
+
+ // Return the file info and platform_path.
+ std::move(callback).Run(info, platform_path, result, nullptr);
+}
+
+void FileSystemManagerImpl::DidGetPlatformPath(GetPlatformPathCallback callback,
+ base::FilePath platform_path) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ std::move(callback).Run(platform_path);
+}
+
+// static
+void FileSystemManagerImpl::GetPlatformPathOnFileThread(
+ const GURL& path,
+ int process_id,
+ storage::FileSystemContext* context,
+ base::WeakPtr<FileSystemManagerImpl> file_system_manager,
+ GetPlatformPathCallback callback) {
+ base::FilePath platform_path;
+ SyncGetPlatformPath(context, process_id, path, &platform_path);
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&FileSystemManagerImpl::DidGetPlatformPath,
+ file_system_manager, std::move(callback), platform_path));
+}
+
+base::Optional<base::File::Error> FileSystemManagerImpl::ValidateFileSystemURL(
+ const storage::FileSystemURL& url) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (!FileSystemURLIsValid(context_, url))
+ return base::File::FILE_ERROR_INVALID_URL;
+
+ // Deny access to files in PluginPrivate FileSystem from JavaScript.
+ // TODO(nhiroki): Move this filter somewhere else since this is not for
+ // validation.
+ if (url.type() == storage::kFileSystemTypePluginPrivate)
+ return base::File::FILE_ERROR_SECURITY;
+
+ return base::nullopt;
+}
+
+FileSystemManagerImpl::OperationListenerID FileSystemManagerImpl::AddOpListener(
+ blink::mojom::FileSystemOperationListenerPtr listener) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ int op_id = next_operation_listener_id_++;
+ listener.set_connection_error_handler(
+ base::BindOnce(&FileSystemManagerImpl::OnConnectionErrorForOpListeners,
+ base::Unretained(this), op_id));
+ op_listeners_[op_id] = std::move(listener);
+ return op_id;
+}
+
+void FileSystemManagerImpl::RemoveOpListener(OperationListenerID listener_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(op_listeners_.find(listener_id) != op_listeners_.end());
+ op_listeners_.erase(listener_id);
+}
+
+blink::mojom::FileSystemOperationListener* FileSystemManagerImpl::GetOpListener(
+ OperationListenerID listener_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (op_listeners_.find(listener_id) == op_listeners_.end())
+ return nullptr;
+ return &*op_listeners_[listener_id];
+}
+
+void FileSystemManagerImpl::OnConnectionErrorForOpListeners(
+ OperationListenerID listener_id) {
+ RemoveOpListener(listener_id);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/fileapi/file_system_manager_impl.h b/chromium/content/browser/fileapi/file_system_manager_impl.h
new file mode 100644
index 00000000000..f5e4cbf7f4c
--- /dev/null
+++ b/chromium/content/browser/fileapi/file_system_manager_impl.h
@@ -0,0 +1,237 @@
+// Copyright (c) 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_FILEAPI_FILE_SYSTEM_MANAGER_IMPL_H_
+#define CONTENT_BROWSER_FILEAPI_FILE_SYSTEM_MANAGER_IMPL_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <map>
+#include <memory>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/containers/hash_tables.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/shared_memory.h"
+#include "components/services/filesystem/public/interfaces/types.mojom.h"
+#include "content/browser/streams/stream.h"
+#include "content/browser/streams/stream_context.h"
+#include "content/common/content_export.h"
+#include "content/public/browser/browser_message_filter.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
+#include "mojo/public/cpp/bindings/interface_ptr_set.h"
+#include "mojo/public/cpp/bindings/strong_binding_set.h"
+#include "storage/browser/fileapi/file_system_context.h"
+#include "storage/browser/fileapi/file_system_operation_runner.h"
+#include "storage/common/fileapi/file_system_types.h"
+#include "third_party/blink/public/mojom/filesystem/file_system.mojom.h"
+
+class GURL;
+
+namespace base {
+class FilePath;
+class Time;
+} // namespace base
+
+namespace storage {
+class FileSystemURL;
+class FileSystemOperationRunner;
+struct FileSystemInfo;
+class ShareableFileReference;
+} // namespace storage
+
+namespace content {
+class ChildProcessSecurityPolicyImpl;
+class ChromeBlobStorageContext;
+
+// All methods for this class are expected to be called on the IO thread,
+// except for the constructor. The destructor must also be called on the IO
+// thread as weak refs are created on that thread. A single instance of this
+// class is owned by RenderProcessHostImpl.
+class CONTENT_EXPORT FileSystemManagerImpl
+ : public blink::mojom::FileSystemManager {
+ public:
+ // Used by the renderer process host on the UI thread.
+ FileSystemManagerImpl(
+ int process_id,
+ storage::FileSystemContext* file_system_context,
+ scoped_refptr<ChromeBlobStorageContext> blob_storage_context);
+ ~FileSystemManagerImpl() override;
+ base::WeakPtr<FileSystemManagerImpl> GetWeakPtr();
+
+ void BindRequest(blink::mojom::FileSystemManagerRequest request);
+
+ // blink::mojom::FileSystem
+ void Open(const GURL& origin_url,
+ blink::mojom::FileSystemType file_system_type,
+ OpenCallback callback) override;
+ void ResolveURL(const GURL& filesystem_url,
+ ResolveURLCallback callback) override;
+ void Move(const GURL& src_path,
+ const GURL& dest_path,
+ MoveCallback callback) override;
+ void Copy(const GURL& src_path,
+ const GURL& dest_path,
+ CopyCallback callback) override;
+ void Remove(const GURL& path,
+ bool recursive,
+ RemoveCallback callback) override;
+ void ReadMetadata(const GURL& path, ReadMetadataCallback callback) override;
+ void Create(const GURL& path,
+ bool exclusive,
+ bool is_directory,
+ bool recursive,
+ CreateCallback callback) override;
+ void Exists(const GURL& path,
+ bool is_directory,
+ ExistsCallback callback) override;
+ void ReadDirectory(
+ const GURL& path,
+ blink::mojom::FileSystemOperationListenerPtr listener) override;
+ void ReadDirectorySync(const GURL& path,
+ ReadDirectorySyncCallback callback) override;
+ void Write(const GURL& file_path,
+ const std::string& blob_uuid,
+ int64_t position,
+ blink::mojom::FileSystemCancellableOperationRequest op_request,
+ blink::mojom::FileSystemOperationListenerPtr listener) override;
+ void WriteSync(const GURL& file_path,
+ const std::string& blob_uuid,
+ int64_t position,
+ WriteSyncCallback callback) override;
+ void Truncate(const GURL& file_path,
+ int64_t length,
+ blink::mojom::FileSystemCancellableOperationRequest op_request,
+ TruncateCallback callback) override;
+ void TruncateSync(const GURL& file_path,
+ int64_t length,
+ TruncateSyncCallback callback) override;
+ void TouchFile(const GURL& path,
+ base::Time last_access_time,
+ base::Time last_modified_time,
+ TouchFileCallback callback) override;
+ void CreateSnapshotFile(const GURL& file_path,
+ CreateSnapshotFileCallback callback) override;
+ void GetPlatformPath(const GURL& file_path,
+ GetPlatformPathCallback callback) override;
+ void CreateWriter(const GURL& file_path,
+ CreateWriterCallback callback) override;
+ void ChooseEntry(int32_t render_frame_id,
+ ChooseEntryCallback callback) override;
+
+ private:
+ class FileSystemCancellableOperationImpl;
+ class ReceivedSnapshotListenerImpl;
+ using OperationID = storage::FileSystemOperationRunner::OperationID;
+ using OperationListenerID = int;
+ struct WriteSyncCallbackEntry;
+ struct ReadDirectorySyncCallbackEntry;
+
+ void Cancel(
+ OperationID op_id,
+ blink::mojom::FileSystemCancellableOperation::CancelCallback callback);
+ void DidReceiveSnapshotFile(int snapshot_id);
+ void OnConnectionError();
+
+ // Callback functions to be used when each file operation is finished.
+ void DidFinish(base::OnceCallback<void(base::File::Error)> callback,
+ base::File::Error error_code);
+ void DidGetMetadata(ReadMetadataCallback callback,
+ base::File::Error result,
+ const base::File::Info& info);
+ void DidGetMetadataForStreaming(CreateSnapshotFileCallback callback,
+ base::File::Error result,
+ const base::File::Info& info);
+ void DidReadDirectory(OperationListenerID listener_id,
+ base::File::Error result,
+ std::vector<filesystem::mojom::DirectoryEntry> entries,
+ bool has_more);
+ void DidReadDirectorySync(
+ ReadDirectorySyncCallbackEntry* callback_entry,
+ base::File::Error result,
+ std::vector<filesystem::mojom::DirectoryEntry> entries,
+ bool has_more);
+ void DidWrite(OperationListenerID listener_id,
+ base::File::Error result,
+ int64_t bytes,
+ bool complete);
+ void DidWriteSync(WriteSyncCallbackEntry* entry,
+ base::File::Error result,
+ int64_t bytes,
+ bool complete);
+ void DidOpenFileSystem(OpenCallback callback,
+ const GURL& root,
+ const std::string& filesystem_name,
+ base::File::Error result);
+ void DidResolveURL(ResolveURLCallback callback,
+ base::File::Error result,
+ const storage::FileSystemInfo& info,
+ const base::FilePath& file_path,
+ storage::FileSystemContext::ResolvedEntryType type);
+ void DidCreateSnapshot(
+ CreateSnapshotFileCallback callback,
+ const storage::FileSystemURL& url,
+ base::File::Error result,
+ const base::File::Info& info,
+ const base::FilePath& platform_path,
+ scoped_refptr<storage::ShareableFileReference> file_ref);
+ void DidGetPlatformPath(GetPlatformPathCallback callback,
+ base::FilePath platform_path);
+
+ static void GetPlatformPathOnFileThread(
+ const GURL& path,
+ int process_id,
+ storage::FileSystemContext* context,
+ base::WeakPtr<FileSystemManagerImpl> file_system_manager,
+ GetPlatformPathCallback callback);
+ // Returns an error if |url| is invalid.
+ base::Optional<base::File::Error> ValidateFileSystemURL(
+ const storage::FileSystemURL& url);
+
+ storage::FileSystemOperationRunner* operation_runner() {
+ return operation_runner_.get();
+ }
+
+ OperationListenerID AddOpListener(
+ blink::mojom::FileSystemOperationListenerPtr listener);
+ void RemoveOpListener(OperationListenerID listener_id);
+ blink::mojom::FileSystemOperationListener* GetOpListener(
+ OperationListenerID listener_id);
+ void OnConnectionErrorForOpListeners(OperationListenerID listener_id);
+
+ const int process_id_;
+ storage::FileSystemContext* const context_;
+ ChildProcessSecurityPolicyImpl* const security_policy_;
+ const scoped_refptr<ChromeBlobStorageContext> blob_storage_context_;
+ std::unique_ptr<storage::FileSystemOperationRunner> operation_runner_;
+
+ mojo::BindingSet<blink::mojom::FileSystemManager> bindings_;
+ mojo::StrongBindingSet<blink::mojom::FileSystemCancellableOperation>
+ cancellable_operations_;
+ mojo::StrongBindingSet<blink::mojom::ReceivedSnapshotListener>
+ snapshot_listeners_;
+
+ std::unordered_map<OperationListenerID,
+ blink::mojom::FileSystemOperationListenerPtr>
+ op_listeners_;
+ OperationListenerID next_operation_listener_id_ = 1;
+
+ // Used to keep snapshot files alive while a DidCreateSnapshot
+ // is being sent to the renderer.
+ base::IDMap<scoped_refptr<storage::ShareableFileReference>>
+ in_transit_snapshot_files_;
+
+ base::WeakPtrFactory<FileSystemManagerImpl> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(FileSystemManagerImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_FILEAPI_FILE_SYSTEM_MANAGER_IMPL_H_
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 68bc445357a..8b520d24936 100644
--- a/chromium/content/browser/fileapi/file_system_operation_runner_unittest.cc
+++ b/chromium/content/browser/fileapi/file_system_operation_runner_unittest.cc
@@ -8,9 +8,9 @@
#include "base/files/scoped_temp_dir.h"
#include "base/macros.h"
#include "base/run_loop.h"
-#include "base/task_scheduler/post_task.h"
-#include "base/task_scheduler/task_scheduler.h"
-#include "base/task_scheduler/task_traits.h"
+#include "base/task/post_task.h"
+#include "base/task/task_scheduler/task_scheduler.h"
+#include "base/task/task_traits.h"
#include "base/test/scoped_task_environment.h"
#include "base/threading/thread_restrictions.h"
#include "base/threading/thread_task_runner_handle.h"
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 7ef37b18b9f..3e55c0fa785 100644
--- a/chromium/content/browser/fileapi/file_system_url_loader_factory.cc
+++ b/chromium/content/browser/fileapi/file_system_url_loader_factory.cc
@@ -15,8 +15,8 @@
#include "base/memory/weak_ptr.h"
#include "base/sequenced_task_runner.h"
#include "base/strings/stringprintf.h"
-#include "base/task_scheduler/post_task.h"
-#include "base/task_scheduler/task_traits.h"
+#include "base/task/post_task.h"
+#include "base/task/task_traits.h"
#include "build/build_config.h"
#include "components/services/filesystem/public/interfaces/types.mojom.h"
#include "content/browser/child_process_security_policy_impl.h"
@@ -446,14 +446,6 @@ class FileSystemFileURLLoader : public FileSystemEntryURLLoader {
original_request_.url.ReplaceComponents(replacements);
head_.encoded_data_length = 0;
client_->OnReceiveRedirect(redirect_info, head_);
-
- // Restart the request with a directory loader.
- network::ResourceRequest new_request = original_request_;
- new_request.url = redirect_info.new_url;
- FileSystemDirectoryURLLoader::CreateAndStart(
- new_request, binding_.Unbind(), client_.PassInterface(),
- std::move(params_), io_task_runner_);
- MaybeDeleteSelf();
return;
}
@@ -522,6 +514,7 @@ class FileSystemFileURLLoader : public FileSystemEntryURLLoader {
SniffMimeType(file_data_->data(), result, url_.ToGURL(), type_hint,
net::ForceSniffFileUrlsForHtml::kDisabled,
&head_.mime_type);
+ head_.did_mime_sniff = true;
}
client_->OnReceiveResponse(head_);
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 82cfc2765d2..980fddbef0f 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
@@ -739,6 +739,7 @@ IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, FileGetMimeType) {
EXPECT_TRUE(client->has_received_completion());
EXPECT_EQ(mime_type_direct, client->response_head().mime_type);
+ EXPECT_TRUE(client->response_head().did_mime_sniff);
}
IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, FileIncognito) {
diff --git a/chromium/content/browser/fileapi/fileapi_message_filter.cc b/chromium/content/browser/fileapi/fileapi_message_filter.cc
deleted file mode 100644
index 1e427681d69..00000000000
--- a/chromium/content/browser/fileapi/fileapi_message_filter.cc
+++ /dev/null
@@ -1,642 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/fileapi/fileapi_message_filter.h"
-
-#include <memory>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/files/file_path.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/metrics/user_metrics.h"
-#include "base/sequenced_task_runner.h"
-#include "base/strings/string_util.h"
-#include "base/threading/thread.h"
-#include "base/time/time.h"
-#include "build/build_config.h"
-#include "components/services/filesystem/public/interfaces/types.mojom.h"
-#include "content/browser/bad_message.h"
-#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/common/fileapi/file_system_messages.h"
-#include "content/common/fileapi/webblob_messages.h"
-#include "content/public/browser/browser_thread.h"
-#include "ipc/ipc_platform_file.h"
-#include "net/base/mime_util.h"
-#include "net/url_request/url_request_context.h"
-#include "net/url_request/url_request_context_getter.h"
-#include "storage/browser/blob/blob_data_builder.h"
-#include "storage/browser/blob/blob_storage_context.h"
-#include "storage/browser/blob/shareable_file_reference.h"
-#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/isolated_context.h"
-#include "storage/common/fileapi/file_system_info.h"
-#include "storage/common/fileapi/file_system_types.h"
-#include "storage/common/fileapi/file_system_util.h"
-#include "url/gurl.h"
-
-using storage::FileSystemFileUtil;
-using storage::FileSystemBackend;
-using storage::FileSystemOperation;
-using storage::FileSystemURL;
-using storage::BlobDataBuilder;
-using storage::BlobStorageContext;
-
-namespace content {
-
-namespace {
-
-const uint32_t kFileApiFilteredMessageClasses[] = {FileSystemMsgStart,
- BlobMsgStart};
-
-void RevokeFilePermission(int child_id, const base::FilePath& path) {
- ChildProcessSecurityPolicyImpl::GetInstance()->RevokeAllPermissionsForFile(
- child_id, path);
-}
-
-} // namespace
-
-FileAPIMessageFilter::FileAPIMessageFilter(
- int process_id,
- net::URLRequestContextGetter* request_context_getter,
- storage::FileSystemContext* file_system_context,
- ChromeBlobStorageContext* blob_storage_context)
- : BrowserMessageFilter(kFileApiFilteredMessageClasses,
- arraysize(kFileApiFilteredMessageClasses)),
- process_id_(process_id),
- context_(file_system_context),
- security_policy_(ChildProcessSecurityPolicyImpl::GetInstance()),
- request_context_getter_(request_context_getter),
- request_context_(nullptr),
- blob_storage_context_(blob_storage_context) {
- DCHECK(context_);
- DCHECK(request_context_getter_.get());
- DCHECK(blob_storage_context);
-}
-
-FileAPIMessageFilter::FileAPIMessageFilter(
- int process_id,
- net::URLRequestContext* request_context,
- storage::FileSystemContext* file_system_context,
- ChromeBlobStorageContext* blob_storage_context)
- : BrowserMessageFilter(kFileApiFilteredMessageClasses,
- arraysize(kFileApiFilteredMessageClasses)),
- process_id_(process_id),
- context_(file_system_context),
- security_policy_(ChildProcessSecurityPolicyImpl::GetInstance()),
- request_context_(request_context),
- blob_storage_context_(blob_storage_context) {
- DCHECK(context_);
- DCHECK(request_context_);
- DCHECK(blob_storage_context);
-}
-
-void FileAPIMessageFilter::OnChannelConnected(int32_t peer_pid) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- if (request_context_getter_.get()) {
- DCHECK(!request_context_);
- request_context_ = request_context_getter_->GetURLRequestContext();
- request_context_getter_ = nullptr;
- DCHECK(request_context_);
- }
-
- operation_runner_ = context_->CreateFileSystemOperationRunner();
-}
-
-void FileAPIMessageFilter::OnChannelClosing() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- in_transit_snapshot_files_.clear();
-
- operation_runner_.reset();
- operations_.clear();
-}
-
-base::TaskRunner* FileAPIMessageFilter::OverrideTaskRunnerForMessage(
- const IPC::Message& message) {
- if (message.type() == FileSystemHostMsg_SyncGetPlatformPath::ID)
- return context_->default_file_task_runner();
- return nullptr;
-}
-
-bool FileAPIMessageFilter::OnMessageReceived(const IPC::Message& message) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(FileAPIMessageFilter, message)
- IPC_MESSAGE_HANDLER(FileSystemHostMsg_OpenFileSystem, OnOpenFileSystem)
- IPC_MESSAGE_HANDLER(FileSystemHostMsg_ResolveURL, OnResolveURL)
- IPC_MESSAGE_HANDLER(FileSystemHostMsg_Move, OnMove)
- IPC_MESSAGE_HANDLER(FileSystemHostMsg_Copy, OnCopy)
- IPC_MESSAGE_HANDLER(FileSystemHostMsg_Remove, OnRemove)
- IPC_MESSAGE_HANDLER(FileSystemHostMsg_ReadMetadata, OnReadMetadata)
- IPC_MESSAGE_HANDLER(FileSystemHostMsg_Create, OnCreate)
- IPC_MESSAGE_HANDLER(FileSystemHostMsg_Exists, OnExists)
- IPC_MESSAGE_HANDLER(FileSystemHostMsg_ReadDirectory, OnReadDirectory)
- IPC_MESSAGE_HANDLER(FileSystemHostMsg_Write, OnWrite)
- IPC_MESSAGE_HANDLER(FileSystemHostMsg_Truncate, OnTruncate)
- IPC_MESSAGE_HANDLER(FileSystemHostMsg_TouchFile, OnTouchFile)
- IPC_MESSAGE_HANDLER(FileSystemHostMsg_CancelWrite, OnCancel)
- IPC_MESSAGE_HANDLER(FileSystemHostMsg_CreateSnapshotFile,
- OnCreateSnapshotFile)
- IPC_MESSAGE_HANDLER(FileSystemHostMsg_DidReceiveSnapshotFile,
- OnDidReceiveSnapshotFile)
- IPC_MESSAGE_HANDLER(FileSystemHostMsg_SyncGetPlatformPath,
- OnSyncGetPlatformPath)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-FileAPIMessageFilter::~FileAPIMessageFilter() {}
-
-void FileAPIMessageFilter::OnOpenFileSystem(int request_id,
- const GURL& origin_url,
- storage::FileSystemType type) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (type == storage::kFileSystemTypeTemporary) {
- RecordAction(base::UserMetricsAction("OpenFileSystemTemporary"));
- } else if (type == storage::kFileSystemTypePersistent) {
- RecordAction(base::UserMetricsAction("OpenFileSystemPersistent"));
- }
- storage::OpenFileSystemMode mode =
- storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT;
- context_->OpenFileSystem(
- origin_url, type, mode,
- base::BindOnce(&FileAPIMessageFilter::DidOpenFileSystem, this,
- request_id));
-}
-
-void FileAPIMessageFilter::OnResolveURL(
- int request_id,
- const GURL& filesystem_url) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- FileSystemURL url(context_->CrackURL(filesystem_url));
- if (!ValidateFileSystemURL(request_id, url))
- return;
- if (!security_policy_->CanReadFileSystemFile(process_id_, url)) {
- Send(new FileSystemMsg_DidFail(request_id,
- base::File::FILE_ERROR_SECURITY));
- return;
- }
-
- context_->ResolveURL(url, base::BindOnce(&FileAPIMessageFilter::DidResolveURL,
- this, request_id));
-}
-
-void FileAPIMessageFilter::OnMove(
- int request_id, const GURL& src_path, const GURL& dest_path) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- FileSystemURL src_url(context_->CrackURL(src_path));
- FileSystemURL dest_url(context_->CrackURL(dest_path));
- if (!ValidateFileSystemURL(request_id, src_url) ||
- !ValidateFileSystemURL(request_id, dest_url)) {
- return;
- }
- if (!security_policy_->CanReadFileSystemFile(process_id_, src_url) ||
- !security_policy_->CanDeleteFileSystemFile(process_id_, src_url) ||
- !security_policy_->CanCreateFileSystemFile(process_id_, dest_url)) {
- Send(new FileSystemMsg_DidFail(request_id,
- base::File::FILE_ERROR_SECURITY));
- return;
- }
-
- operations_[request_id] = operation_runner()->Move(
- src_url,
- dest_url,
- storage::FileSystemOperation::OPTION_NONE,
- base::Bind(&FileAPIMessageFilter::DidFinish, this, request_id));
-}
-
-void FileAPIMessageFilter::OnCopy(
- int request_id, const GURL& src_path, const GURL& dest_path) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- FileSystemURL src_url(context_->CrackURL(src_path));
- FileSystemURL dest_url(context_->CrackURL(dest_path));
- if (!ValidateFileSystemURL(request_id, src_url) ||
- !ValidateFileSystemURL(request_id, dest_url)) {
- return;
- }
- if (!security_policy_->CanReadFileSystemFile(process_id_, src_url) ||
- !security_policy_->CanCopyIntoFileSystemFile(process_id_, dest_url)) {
- Send(new FileSystemMsg_DidFail(request_id,
- base::File::FILE_ERROR_SECURITY));
- return;
- }
-
- operations_[request_id] = operation_runner()->Copy(
- src_url, dest_url, storage::FileSystemOperation::OPTION_NONE,
- FileSystemOperation::ERROR_BEHAVIOR_ABORT,
- storage::FileSystemOperationRunner::CopyProgressCallback(),
- base::Bind(&FileAPIMessageFilter::DidFinish, this, request_id));
-}
-
-void FileAPIMessageFilter::OnRemove(
- int request_id, const GURL& path, bool recursive) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- FileSystemURL url(context_->CrackURL(path));
- if (!ValidateFileSystemURL(request_id, url))
- return;
- if (!security_policy_->CanDeleteFileSystemFile(process_id_, url)) {
- Send(new FileSystemMsg_DidFail(request_id,
- base::File::FILE_ERROR_SECURITY));
- return;
- }
-
- operations_[request_id] = operation_runner()->Remove(
- url, recursive,
- base::Bind(&FileAPIMessageFilter::DidFinish, this, request_id));
-}
-
-void FileAPIMessageFilter::OnReadMetadata(
- int request_id, const GURL& path) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- FileSystemURL url(context_->CrackURL(path));
- if (!ValidateFileSystemURL(request_id, url))
- return;
- if (!security_policy_->CanReadFileSystemFile(process_id_, url)) {
- Send(new FileSystemMsg_DidFail(request_id,
- base::File::FILE_ERROR_SECURITY));
- return;
- }
-
- operations_[request_id] = operation_runner()->GetMetadata(
- url, FileSystemOperation::GET_METADATA_FIELD_IS_DIRECTORY |
- FileSystemOperation::GET_METADATA_FIELD_SIZE |
- FileSystemOperation::GET_METADATA_FIELD_LAST_MODIFIED,
- base::Bind(&FileAPIMessageFilter::DidGetMetadata, this, request_id));
-}
-
-void FileAPIMessageFilter::OnCreate(
- int request_id, const GURL& path, bool exclusive,
- bool is_directory, bool recursive) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- FileSystemURL url(context_->CrackURL(path));
- if (!ValidateFileSystemURL(request_id, url))
- return;
- if (!security_policy_->CanCreateFileSystemFile(process_id_, url)) {
- Send(new FileSystemMsg_DidFail(request_id,
- base::File::FILE_ERROR_SECURITY));
- return;
- }
-
- if (is_directory) {
- operations_[request_id] = operation_runner()->CreateDirectory(
- url, exclusive, recursive,
- base::Bind(&FileAPIMessageFilter::DidFinish, this, request_id));
- } else {
- operations_[request_id] = operation_runner()->CreateFile(
- url, exclusive,
- base::Bind(&FileAPIMessageFilter::DidFinish, this, request_id));
- }
-}
-
-void FileAPIMessageFilter::OnExists(
- int request_id, const GURL& path, bool is_directory) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- FileSystemURL url(context_->CrackURL(path));
- if (!ValidateFileSystemURL(request_id, url))
- return;
- if (!security_policy_->CanReadFileSystemFile(process_id_, url)) {
- Send(new FileSystemMsg_DidFail(request_id,
- base::File::FILE_ERROR_SECURITY));
- return;
- }
-
- if (is_directory) {
- operations_[request_id] = operation_runner()->DirectoryExists(
- url,
- base::Bind(&FileAPIMessageFilter::DidFinish, this, request_id));
- } else {
- operations_[request_id] = operation_runner()->FileExists(
- url,
- base::Bind(&FileAPIMessageFilter::DidFinish, this, request_id));
- }
-}
-
-void FileAPIMessageFilter::OnReadDirectory(
- int request_id, const GURL& path) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- FileSystemURL url(context_->CrackURL(path));
- if (!ValidateFileSystemURL(request_id, url))
- return;
- if (!security_policy_->CanReadFileSystemFile(process_id_, url)) {
- Send(new FileSystemMsg_DidFail(request_id,
- base::File::FILE_ERROR_SECURITY));
- return;
- }
-
- operations_[request_id] = operation_runner()->ReadDirectory(
- url, base::BindRepeating(&FileAPIMessageFilter::DidReadDirectory, this,
- request_id));
-}
-
-void FileAPIMessageFilter::OnWrite(int request_id,
- const GURL& path,
- const std::string& blob_uuid,
- int64_t offset) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (!request_context_) {
- // We can't write w/o a request context, trying to do so will crash.
- NOTREACHED();
- return;
- }
-
- FileSystemURL url(context_->CrackURL(path));
- if (!ValidateFileSystemURL(request_id, url))
- return;
- if (!security_policy_->CanWriteFileSystemFile(process_id_, url)) {
- Send(new FileSystemMsg_DidFail(request_id,
- base::File::FILE_ERROR_SECURITY));
- return;
- }
-
- std::unique_ptr<storage::BlobDataHandle> blob =
- blob_storage_context_->context()->GetBlobDataFromUUID(blob_uuid);
-
- operations_[request_id] = operation_runner()->Write(
- request_context_, url, std::move(blob), offset,
- base::Bind(&FileAPIMessageFilter::DidWrite, this, request_id));
-}
-
-void FileAPIMessageFilter::OnTruncate(int request_id,
- const GURL& path,
- int64_t length) {
- FileSystemURL url(context_->CrackURL(path));
- if (!ValidateFileSystemURL(request_id, url))
- return;
- if (!security_policy_->CanWriteFileSystemFile(process_id_, url)) {
- Send(new FileSystemMsg_DidFail(request_id,
- base::File::FILE_ERROR_SECURITY));
- return;
- }
-
- operations_[request_id] = operation_runner()->Truncate(
- url, length,
- base::Bind(&FileAPIMessageFilter::DidFinish, this, request_id));
-}
-
-void FileAPIMessageFilter::OnTouchFile(
- int request_id,
- const GURL& path,
- const base::Time& last_access_time,
- const base::Time& last_modified_time) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- FileSystemURL url(context_->CrackURL(path));
- if (!ValidateFileSystemURL(request_id, url))
- return;
- if (!security_policy_->CanCreateFileSystemFile(process_id_, url)) {
- Send(new FileSystemMsg_DidFail(request_id,
- base::File::FILE_ERROR_SECURITY));
- return;
- }
-
- operations_[request_id] = operation_runner()->TouchFile(
- url, last_access_time, last_modified_time,
- base::Bind(&FileAPIMessageFilter::DidFinish, this, request_id));
-}
-
-void FileAPIMessageFilter::OnCancel(
- int request_id,
- int request_id_to_cancel) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- OperationsMap::iterator found = operations_.find(request_id_to_cancel);
- if (found != operations_.end()) {
- // The cancel will eventually send both the write failure and the cancel
- // success.
- operation_runner()->Cancel(
- found->second,
- base::Bind(&FileAPIMessageFilter::DidFinish, this, request_id));
- } else {
- // The write already finished; report that we failed to stop it.
- Send(new FileSystemMsg_DidFail(
- request_id, base::File::FILE_ERROR_INVALID_OPERATION));
- }
-}
-
-void FileAPIMessageFilter::OnSyncGetPlatformPath(
- const GURL& path, base::FilePath* platform_path) {
- SyncGetPlatformPath(context_, process_id_, path, platform_path);
-}
-
-void FileAPIMessageFilter::OnCreateSnapshotFile(
- int request_id, const GURL& path) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- FileSystemURL url(context_->CrackURL(path));
-
- // Make sure if this file can be read by the renderer as this is
- // called when the renderer is about to create a new File object
- // (for reading the file).
- if (!ValidateFileSystemURL(request_id, url))
- return;
- if (!security_policy_->CanReadFileSystemFile(process_id_, url)) {
- Send(new FileSystemMsg_DidFail(request_id,
- base::File::FILE_ERROR_SECURITY));
- return;
- }
-
- FileSystemBackend* backend = context_->GetFileSystemBackend(url.type());
- if (backend->SupportsStreaming(url)) {
- operations_[request_id] = operation_runner()->GetMetadata(
- url, FileSystemOperation::GET_METADATA_FIELD_IS_DIRECTORY |
- FileSystemOperation::GET_METADATA_FIELD_SIZE |
- FileSystemOperation::GET_METADATA_FIELD_LAST_MODIFIED,
- base::Bind(&FileAPIMessageFilter::DidGetMetadataForStreaming, this,
- request_id));
- } else {
- operations_[request_id] = operation_runner()->CreateSnapshotFile(
- url,
- base::Bind(&FileAPIMessageFilter::DidCreateSnapshot,
- this, request_id, url));
- }
-}
-
-void FileAPIMessageFilter::OnDidReceiveSnapshotFile(int request_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- in_transit_snapshot_files_.erase(request_id);
-}
-
-void FileAPIMessageFilter::DidFinish(int request_id,
- base::File::Error result) {
- if (result == base::File::FILE_OK)
- Send(new FileSystemMsg_DidSucceed(request_id));
- else
- Send(new FileSystemMsg_DidFail(request_id, result));
- operations_.erase(request_id);
-}
-
-void FileAPIMessageFilter::DidGetMetadata(
- int request_id,
- base::File::Error result,
- const base::File::Info& info) {
- if (result == base::File::FILE_OK)
- Send(new FileSystemMsg_DidReadMetadata(request_id, info));
- else
- Send(new FileSystemMsg_DidFail(request_id, result));
- operations_.erase(request_id);
-}
-
-void FileAPIMessageFilter::DidGetMetadataForStreaming(
- int request_id,
- base::File::Error result,
- const base::File::Info& info) {
- if (result == base::File::FILE_OK) {
- // For now, streaming Blobs are implemented as a successful snapshot file
- // creation with an empty path.
- Send(new FileSystemMsg_DidCreateSnapshotFile(request_id, info,
- base::FilePath()));
- } else {
- Send(new FileSystemMsg_DidFail(request_id, result));
- }
- operations_.erase(request_id);
-}
-
-void FileAPIMessageFilter::DidReadDirectory(
- int request_id,
- base::File::Error result,
- std::vector<filesystem::mojom::DirectoryEntry> entries,
- bool has_more) {
- if (result == base::File::FILE_OK) {
- if (!entries.empty() || !has_more)
- Send(new FileSystemMsg_DidReadDirectory(request_id, std::move(entries),
- has_more));
- } else {
- DCHECK(!has_more);
- Send(new FileSystemMsg_DidFail(request_id, result));
- }
- if (!has_more)
- operations_.erase(request_id);
-}
-
-void FileAPIMessageFilter::DidWrite(int request_id,
- base::File::Error result,
- int64_t bytes,
- bool complete) {
- if (result == base::File::FILE_OK) {
- Send(new FileSystemMsg_DidWrite(request_id, bytes, complete));
- if (complete)
- operations_.erase(request_id);
- } else {
- Send(new FileSystemMsg_DidFail(request_id, result));
- operations_.erase(request_id);
- }
-}
-
-void FileAPIMessageFilter::DidOpenFileSystem(int request_id,
- const GURL& root,
- const std::string& filesystem_name,
- base::File::Error result) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (result == base::File::FILE_OK) {
- DCHECK(root.is_valid());
- Send(new FileSystemMsg_DidOpenFileSystem(
- request_id, filesystem_name, root));
- } else {
- Send(new FileSystemMsg_DidFail(request_id, result));
- }
- // For OpenFileSystem we do not create a new operation, so no unregister here.
-}
-
-void FileAPIMessageFilter::DidResolveURL(
- int request_id,
- base::File::Error result,
- const storage::FileSystemInfo& info,
- const base::FilePath& file_path,
- storage::FileSystemContext::ResolvedEntryType type) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (result == base::File::FILE_OK &&
- type == storage::FileSystemContext::RESOLVED_ENTRY_NOT_FOUND)
- result = base::File::FILE_ERROR_NOT_FOUND;
-
- if (result == base::File::FILE_OK) {
- DCHECK(info.root_url.is_valid());
- Send(new FileSystemMsg_DidResolveURL(
- request_id,
- info,
- file_path,
- type == storage::FileSystemContext::RESOLVED_ENTRY_DIRECTORY));
- } else {
- Send(new FileSystemMsg_DidFail(request_id, result));
- }
- // For ResolveURL we do not create a new operation, so no unregister here.
-}
-
-void FileAPIMessageFilter::DidCreateSnapshot(
- int request_id,
- const storage::FileSystemURL& url,
- base::File::Error result,
- const base::File::Info& info,
- const base::FilePath& platform_path,
- scoped_refptr<storage::ShareableFileReference> /* unused */) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- operations_.erase(request_id);
-
- if (result != base::File::FILE_OK) {
- Send(new FileSystemMsg_DidFail(request_id, result));
- return;
- }
-
- scoped_refptr<storage::ShareableFileReference> file_ref =
- storage::ShareableFileReference::Get(platform_path);
- if (!security_policy_->CanReadFile(process_id_, platform_path)) {
- // Give per-file read permission to the snapshot file if it hasn't it yet.
- // In order for the renderer to be able to read the file via File object,
- // it must be granted per-file read permission for the file's platform
- // path. By now, it has already been verified that the renderer has
- // sufficient permissions to read the file, so giving per-file permission
- // here must be safe.
- security_policy_->GrantReadFile(process_id_, platform_path);
-
- // Revoke all permissions for the file when the last ref of the file
- // is dropped.
- if (!file_ref.get()) {
- // Create a reference for temporary permission handling.
- file_ref = storage::ShareableFileReference::GetOrCreate(
- platform_path,
- storage::ShareableFileReference::DONT_DELETE_ON_FINAL_RELEASE,
- context_->default_file_task_runner());
- }
- file_ref->AddFinalReleaseCallback(
- base::BindOnce(&RevokeFilePermission, process_id_));
- }
-
- if (file_ref.get()) {
- // This ref is held until OnDidReceiveSnapshotFile is called.
- in_transit_snapshot_files_[request_id] = file_ref;
- }
-
- // Return the file info and platform_path.
- Send(new FileSystemMsg_DidCreateSnapshotFile(
- request_id, info, platform_path));
-}
-
-bool FileAPIMessageFilter::ValidateFileSystemURL(
- int request_id,
- const storage::FileSystemURL& url) {
- if (!FileSystemURLIsValid(context_, url)) {
- Send(new FileSystemMsg_DidFail(request_id,
- base::File::FILE_ERROR_INVALID_URL));
- return false;
- }
-
- // Deny access to files in PluginPrivate FileSystem from JavaScript.
- // TODO(nhiroki): Move this filter somewhere else since this is not for
- // validation.
- if (url.type() == storage::kFileSystemTypePluginPrivate) {
- Send(new FileSystemMsg_DidFail(request_id,
- base::File::FILE_ERROR_SECURITY));
- return false;
- }
-
- return true;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/fileapi/fileapi_message_filter.h b/chromium/content/browser/fileapi/fileapi_message_filter.h
deleted file mode 100644
index 7188c686f4d..00000000000
--- a/chromium/content/browser/fileapi/fileapi_message_filter.h
+++ /dev/null
@@ -1,194 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_FILEAPI_FILEAPI_MESSAGE_FILTER_H_
-#define CONTENT_BROWSER_FILEAPI_FILEAPI_MESSAGE_FILTER_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <map>
-#include <memory>
-#include <set>
-#include <string>
-#include <vector>
-
-#include "base/callback.h"
-#include "base/containers/hash_tables.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/shared_memory.h"
-#include "components/services/filesystem/public/interfaces/types.mojom.h"
-#include "content/browser/streams/stream.h"
-#include "content/browser/streams/stream_context.h"
-#include "content/common/content_export.h"
-#include "content/public/browser/browser_message_filter.h"
-#include "storage/browser/fileapi/file_system_context.h"
-#include "storage/browser/fileapi/file_system_operation_runner.h"
-#include "storage/common/fileapi/file_system_types.h"
-
-class GURL;
-
-namespace base {
-class FilePath;
-class Time;
-}
-
-namespace storage {
-class FileSystemURL;
-class FileSystemOperationRunner;
-struct FileSystemInfo;
-}
-
-namespace net {
-class URLRequestContext;
-class URLRequestContextGetter;
-} // namespace net
-
-namespace storage {
-class ShareableFileReference;
-}
-
-namespace content {
-class ChildProcessSecurityPolicyImpl;
-class ChromeBlobStorageContext;
-
-// TODO(tyoshino): Factor out code except for IPC gluing from
-// FileAPIMessageFilter into separate classes. See crbug.com/263741.
-class CONTENT_EXPORT FileAPIMessageFilter : public BrowserMessageFilter {
- public:
- // Used by the renderer process host on the UI thread.
- FileAPIMessageFilter(int process_id,
- net::URLRequestContextGetter* request_context_getter,
- storage::FileSystemContext* file_system_context,
- ChromeBlobStorageContext* blob_storage_context);
- // Used by the worker process host on the IO thread.
- FileAPIMessageFilter(int process_id,
- net::URLRequestContext* request_context,
- storage::FileSystemContext* file_system_context,
- ChromeBlobStorageContext* blob_storage_context);
-
- // BrowserMessageFilter implementation.
- void OnChannelConnected(int32_t peer_pid) override;
- void OnChannelClosing() override;
- base::TaskRunner* OverrideTaskRunnerForMessage(
- const IPC::Message& message) override;
- bool OnMessageReceived(const IPC::Message& message) override;
-
- protected:
- ~FileAPIMessageFilter() override;
-
- private:
- typedef storage::FileSystemOperationRunner::OperationID OperationID;
-
- void OnOpenFileSystem(int request_id,
- const GURL& origin_url,
- storage::FileSystemType type);
- void OnResolveURL(int request_id,
- const GURL& filesystem_url);
- void OnMove(int request_id,
- const GURL& src_path,
- const GURL& dest_path);
- void OnCopy(int request_id,
- const GURL& src_path,
- const GURL& dest_path);
- void OnRemove(int request_id, const GURL& path, bool recursive);
- void OnReadMetadata(int request_id, const GURL& path);
- void OnCreate(int request_id,
- const GURL& path,
- bool exclusive,
- bool is_directory,
- bool recursive);
- void OnExists(int request_id, const GURL& path, bool is_directory);
- void OnReadDirectory(int request_id, const GURL& path);
- void OnWrite(int request_id,
- const GURL& path,
- const std::string& blob_uuid,
- int64_t offset);
- void OnTruncate(int request_id, const GURL& path, int64_t length);
- void OnTouchFile(int request_id,
- const GURL& path,
- const base::Time& last_access_time,
- const base::Time& last_modified_time);
- void OnCancel(int request_id, int request_to_cancel);
- void OnSyncGetPlatformPath(const GURL& path,
- base::FilePath* platform_path);
- void OnCreateSnapshotFile(int request_id,
- const GURL& path);
- void OnDidReceiveSnapshotFile(int request_id);
-
- // Callback functions to be used when each file operation is finished.
- void DidFinish(int request_id, base::File::Error result);
- void DidGetMetadata(int request_id,
- base::File::Error result,
- const base::File::Info& info);
- void DidGetMetadataForStreaming(int request_id,
- base::File::Error result,
- const base::File::Info& info);
- void DidReadDirectory(int request_id,
- base::File::Error result,
- std::vector<filesystem::mojom::DirectoryEntry> entries,
- bool has_more);
- void DidWrite(int request_id,
- base::File::Error result,
- int64_t bytes,
- bool complete);
- void DidOpenFileSystem(int request_id,
- const GURL& root,
- const std::string& filesystem_name,
- base::File::Error result);
- void DidResolveURL(int request_id,
- base::File::Error result,
- const storage::FileSystemInfo& info,
- const base::FilePath& file_path,
- storage::FileSystemContext::ResolvedEntryType type);
- void DidCreateSnapshot(
- int request_id,
- const storage::FileSystemURL& url,
- base::File::Error result,
- const base::File::Info& info,
- const base::FilePath& platform_path,
- scoped_refptr<storage::ShareableFileReference> file_ref);
-
- // Sends a FileSystemMsg_DidFail and returns false if |url| is invalid.
- bool ValidateFileSystemURL(int request_id, const storage::FileSystemURL& url);
-
- storage::FileSystemOperationRunner* operation_runner() {
- return operation_runner_.get();
- }
-
- int process_id_;
-
- storage::FileSystemContext* context_;
- ChildProcessSecurityPolicyImpl* security_policy_;
-
- // Keeps map from request_id to OperationID for ongoing operations.
- // (Primarily for Cancel operation)
- typedef std::map<int, OperationID> OperationsMap;
- OperationsMap operations_;
-
- // The getter holds the context until OnChannelConnected() can be called from
- // the IO thread, which will extract the net::URLRequestContext from it.
- scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
- net::URLRequestContext* request_context_;
-
- scoped_refptr<ChromeBlobStorageContext> blob_storage_context_;
-
- std::unique_ptr<storage::FileSystemOperationRunner> operation_runner_;
-
- // Keep track of stream URLs registered in this process. Need to unregister
- // all of them when the renderer process dies.
- base::hash_set<std::string> stream_urls_;
-
- // Used to keep snapshot files alive while a DidCreateSnapshot
- // is being sent to the renderer.
- std::map<int, scoped_refptr<storage::ShareableFileReference> >
- in_transit_snapshot_files_;
-
- DISALLOW_COPY_AND_ASSIGN(FileAPIMessageFilter);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_FILEAPI_FILEAPI_MESSAGE_FILTER_H_
diff --git a/chromium/content/browser/fileapi/fileapi_message_filter_unittest.cc b/chromium/content/browser/fileapi/fileapi_message_filter_unittest.cc
deleted file mode 100644
index c996e7c34e2..00000000000
--- a/chromium/content/browser/fileapi/fileapi_message_filter_unittest.cc
+++ /dev/null
@@ -1,129 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/fileapi/fileapi_message_filter.h"
-
-#include <stddef.h>
-
-#include <string>
-#include <vector>
-
-#include "base/memory/ref_counted.h"
-#include "base/memory/shared_memory.h"
-#include "base/process/process_handle.h"
-#include "base/run_loop.h"
-#include "content/browser/blob_storage/chrome_blob_storage_context.h"
-#include "content/browser/child_process_security_policy_impl.h"
-#include "content/common/fileapi/file_system_messages.h"
-#include "content/common/fileapi/webblob_messages.h"
-#include "content/public/browser/browser_context.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/storage_partition.h"
-#include "content/public/common/common_param_traits.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.h"
-#include "content/public/test/test_browser_thread_bundle.h"
-#include "net/base/io_buffer.h"
-#include "storage/browser/blob/blob_storage_context.h"
-#include "storage/browser/fileapi/file_system_context.h"
-#include "storage/browser/test/test_file_system_context.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-
-class FileAPIMessageFilterTest : public testing::Test {
- public:
- FileAPIMessageFilterTest()
- : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {
- }
-
- protected:
- void SetUp() override {
- file_system_context_ =
- CreateFileSystemContextForTesting(nullptr, base::FilePath());
-
- for (const storage::FileSystemType& type :
- file_system_context_->GetFileSystemTypes()) {
- ChildProcessSecurityPolicyImpl::GetInstance()
- ->RegisterFileSystemPermissionPolicy(
- type, storage::FileSystemContext::GetPermissionPolicy(type));
- }
-
- blob_storage_context_ = ChromeBlobStorageContext::GetFor(&browser_context_);
-
- filter_ = new FileAPIMessageFilter(
- 0 /* process_id */,
- BrowserContext::GetDefaultStoragePartition(&browser_context_)
- ->GetURLRequestContext(),
- file_system_context_.get(), blob_storage_context_);
-
- // Complete initialization.
- base::RunLoop().RunUntilIdle();
- }
-
- TestBrowserThreadBundle browser_thread_bundle_;
- TestBrowserContext browser_context_;
- scoped_refptr<storage::FileSystemContext> file_system_context_;
- ChromeBlobStorageContext* blob_storage_context_;
-
- scoped_refptr<FileAPIMessageFilter> filter_;
-};
-
-TEST_F(FileAPIMessageFilterTest, CloseChannelWithInflightRequest) {
- scoped_refptr<FileAPIMessageFilter> filter(new FileAPIMessageFilter(
- 0 /* process_id */,
- BrowserContext::GetDefaultStoragePartition(&browser_context_)
- ->GetURLRequestContext(),
- file_system_context_.get(),
- ChromeBlobStorageContext::GetFor(&browser_context_)));
- filter->OnChannelConnected(0);
-
- // Complete initialization.
- base::RunLoop().RunUntilIdle();
-
- int request_id = 0;
- const GURL kUrl("filesystem:http://example.com/temporary/foo");
- FileSystemHostMsg_ReadMetadata read_metadata(request_id++, kUrl);
- EXPECT_TRUE(filter->OnMessageReceived(read_metadata));
-
- // Close the filter while it has inflight request.
- filter->OnChannelClosing();
-
- // This shouldn't cause DCHECK failure.
- base::RunLoop().RunUntilIdle();
-}
-
-TEST_F(FileAPIMessageFilterTest, MultipleFilters) {
- scoped_refptr<FileAPIMessageFilter> filter1(new FileAPIMessageFilter(
- 0 /* process_id */,
- BrowserContext::GetDefaultStoragePartition(&browser_context_)
- ->GetURLRequestContext(),
- file_system_context_.get(),
- ChromeBlobStorageContext::GetFor(&browser_context_)));
- scoped_refptr<FileAPIMessageFilter> filter2(new FileAPIMessageFilter(
- 1 /* process_id */,
- BrowserContext::GetDefaultStoragePartition(&browser_context_)
- ->GetURLRequestContext(),
- file_system_context_.get(),
- ChromeBlobStorageContext::GetFor(&browser_context_)));
- filter1->OnChannelConnected(0);
- filter2->OnChannelConnected(1);
-
- // Complete initialization.
- base::RunLoop().RunUntilIdle();
-
- int request_id = 0;
- const GURL kUrl("filesystem:http://example.com/temporary/foo");
- FileSystemHostMsg_ReadMetadata read_metadata(request_id++, kUrl);
- EXPECT_TRUE(filter1->OnMessageReceived(read_metadata));
-
- // Close the other filter before the request for filter1 is processed.
- filter2->OnChannelClosing();
-
- // This shouldn't cause DCHECK failure.
- base::RunLoop().RunUntilIdle();
-}
-
-} // namespace content
diff --git a/chromium/content/browser/find_in_page_client.cc b/chromium/content/browser/find_in_page_client.cc
new file mode 100644
index 00000000000..7812fe0c923
--- /dev/null
+++ b/chromium/content/browser/find_in_page_client.cc
@@ -0,0 +1,67 @@
+// 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/find_in_page_client.h"
+
+#include "content/browser/find_request_manager.h"
+#include "content/browser/frame_host/render_frame_host_impl.h"
+
+namespace content {
+
+FindInPageClient::FindInPageClient(FindRequestManager* find_request_manager,
+ RenderFrameHostImpl* rfh)
+ : frame_(rfh), find_request_manager_(find_request_manager), binding_(this) {
+ blink::mojom::FindInPageClientPtr client;
+ binding_.Bind(MakeRequest(&client));
+ frame_->GetFindInPage()->SetClient(std::move(client));
+}
+
+FindInPageClient::~FindInPageClient() {}
+
+void FindInPageClient::SetNumberOfMatches(
+ int request_id,
+ unsigned int number_of_matches,
+ blink::mojom::FindMatchUpdateType update_type) {
+ if (find_request_manager_->ShouldIgnoreReply(frame_, request_id))
+ return;
+ const int old_matches = number_of_matches_;
+ number_of_matches_ = number_of_matches;
+ find_request_manager_->UpdatedFrameNumberOfMatches(frame_, old_matches,
+ number_of_matches);
+ HandleUpdateType(request_id, update_type);
+}
+
+void FindInPageClient::SetActiveMatch(
+ int request_id,
+ const gfx::Rect& active_match_rect,
+ int active_match_ordinal,
+ blink::mojom::FindMatchUpdateType update_type) {
+ if (find_request_manager_->ShouldIgnoreReply(frame_, request_id))
+ return;
+ find_request_manager_->SetActiveMatchRect(active_match_rect);
+ find_request_manager_->SetActiveMatchOrdinal(frame_, request_id,
+ active_match_ordinal);
+ HandleUpdateType(request_id, update_type);
+}
+
+void FindInPageClient::ActivateNearestFindResult(int request_id,
+ const gfx::PointF& point) {
+ frame_->GetFindInPage()->ActivateNearestFindResult(request_id, point);
+}
+
+void FindInPageClient::HandleUpdateType(
+ int request_id,
+ blink::mojom::FindMatchUpdateType update_type) {
+ // If this is the final update for this frame, it might be the final update
+ // for the find request out of all the frames, so we need to handle it.
+ // Otherwise just notify directly while saying this is not the final update
+ // for the request.
+ if (update_type == blink::mojom::FindMatchUpdateType::kFinalUpdate)
+ find_request_manager_->HandleFinalUpdateForFrame(frame_, request_id);
+ else
+ find_request_manager_->NotifyFindReply(request_id,
+ false /* final_update */);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/find_in_page_client.h b/chromium/content/browser/find_in_page_client.h
new file mode 100644
index 00000000000..083e457cf6a
--- /dev/null
+++ b/chromium/content/browser/find_in_page_client.h
@@ -0,0 +1,54 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_FIND_IN_PAGE_CLIENT_H_
+#define CONTENT_BROWSER_FIND_IN_PAGE_CLIENT_H_
+
+#include "mojo/public/cpp/bindings/binding.h"
+#include "third_party/blink/public/mojom/frame/find_in_page.mojom.h"
+
+namespace content {
+
+class RenderFrameHostImpl;
+class FindRequestManager;
+
+// Per-frame client of FindInPage, owned by FindRequestManager.
+// Keeps track of the current match count for the frame.
+class FindInPageClient final : public blink::mojom::FindInPageClient {
+ public:
+ FindInPageClient(FindRequestManager* find_request_manager,
+ RenderFrameHostImpl* rfh);
+
+ ~FindInPageClient() override;
+
+ void ActivateNearestFindResult(int request_id, const gfx::PointF& point);
+
+ // Current number of matches for this frame.
+ int number_of_matches() { return number_of_matches_; }
+
+ // blink::mojom::FindInPageClient overrides
+
+ void SetNumberOfMatches(int request_id,
+ unsigned int current_number_of_matches,
+ blink::mojom::FindMatchUpdateType update_type) final;
+
+ void SetActiveMatch(int request_id,
+ const gfx::Rect& active_match_rect,
+ int active_match_ordinal,
+ blink::mojom::FindMatchUpdateType update_type) final;
+
+ private:
+ void HandleUpdateType(int request_id,
+ blink::mojom::FindMatchUpdateType update_type);
+ RenderFrameHostImpl* const frame_;
+ FindRequestManager* const find_request_manager_;
+ mojo::Binding<blink::mojom::FindInPageClient> binding_;
+ int number_of_matches_ = 0;
+
+ DISALLOW_COPY_AND_ASSIGN(FindInPageClient);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_FIND_IN_PAGE_CLIENT_H_
diff --git a/chromium/content/browser/find_request_manager.cc b/chromium/content/browser/find_request_manager.cc
index 34c5307b0fa..9ae22e14473 100644
--- a/chromium/content/browser/find_request_manager.cc
+++ b/chromium/content/browser/find_request_manager.cc
@@ -7,9 +7,9 @@
#include <algorithm>
#include "base/containers/queue.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"
-#include "content/common/associated_interface_provider_impl.h"
#include "content/common/frame_messages.h"
#include "content/public/browser/guest_mode.h"
#include "third_party/blink/public/mojom/frame/find_in_page.mojom.h"
@@ -288,86 +288,23 @@ void FindRequestManager::StopFinding(StopFindAction action) {
#endif
}
-void FindRequestManager::OnFindReply(RenderFrameHostImpl* rfh,
- int request_id,
- int number_of_matches,
- const gfx::Rect& selection_rect,
- int active_match_ordinal,
- bool final_update) {
+bool FindRequestManager::ShouldIgnoreReply(RenderFrameHostImpl* rfh,
+ int request_id) {
// Ignore stale replies from abandoned find sessions or dead frames.
- if (current_session_id_ == kInvalidId ||
- request_id < current_session_id_ ||
- !CheckFrame(rfh)) {
- return;
- }
-
- // Update the stored find results.
-
- DCHECK_GE(number_of_matches, -1);
- DCHECK_GE(active_match_ordinal, -1);
-
- // Check for an update to the number of matches.
- if (number_of_matches != -1) {
- DCHECK_GE(number_of_matches, 0);
- auto matches_per_frame_it = matches_per_frame_.find(rfh);
- if (int matches_delta = number_of_matches - matches_per_frame_it->second) {
- // Increment the global number of matches by the number of additional
- // matches found for this frame.
- number_of_matches_ += matches_delta;
- matches_per_frame_it->second = number_of_matches;
-
- // All matches may have been removed since the last find reply.
- if (rfh == active_frame_ && !number_of_matches)
- relative_active_match_ordinal_ = 0;
-
- // The active match ordinal may need updating since the number of matches
- // before the active match may have changed.
- if (rfh != active_frame_ || !number_of_matches)
- UpdateActiveMatchOrdinal();
- }
- }
-
- // Check for an update to the selection rect.
- if (!selection_rect.IsEmpty())
- selection_rect_ = selection_rect;
-
- // Check for an update to the active match ordinal.
- if (active_match_ordinal > 0) {
- if (rfh == active_frame_) {
- active_match_ordinal_ +=
- active_match_ordinal - relative_active_match_ordinal_;
- relative_active_match_ordinal_ = active_match_ordinal;
- } else {
- if (active_frame_) {
- // The new active match is in a different frame than the previous, so
- // the previous active frame needs to be informed (to clear its active
- // match highlighting).
- ClearActiveFindMatch();
- }
- active_frame_ = rfh;
- relative_active_match_ordinal_ = active_match_ordinal;
- UpdateActiveMatchOrdinal();
- }
- if (pending_active_match_ordinal_ && request_id == current_request_.id)
- pending_active_match_ordinal_ = false;
- AdvanceQueue(request_id);
- }
-
- if (!final_update) {
- NotifyFindReply(request_id, false /* final_update */);
- return;
- }
+ return current_session_id_ == kInvalidId ||
+ request_id < current_session_id_ || !CheckFrame(rfh);
+}
+void FindRequestManager::HandleFinalUpdateForFrame(RenderFrameHostImpl* rfh,
+ int request_id) {
// This is the final update for this frame for the current find operation.
-
pending_initial_replies_.erase(rfh);
if (request_id == current_session_id_ && !pending_initial_replies_.empty()) {
NotifyFindReply(request_id, false /* final_update */);
return;
}
- // This is the final update for the current find operation.
-
+ // This is the final update for all frames for the current find operation.
if (request_id == current_request_.id && request_id != current_session_id_) {
DCHECK(current_request_.options.find_next);
DCHECK_EQ(pending_find_next_reply_, rfh);
@@ -377,17 +314,61 @@ void FindRequestManager::OnFindReply(RenderFrameHostImpl* rfh,
FinalUpdateReceived(request_id, rfh);
}
-void FindRequestManager::OnActivateNearestFindResultReply(
- RenderFrameHostImpl* rfh,
- int request_id,
- const gfx::Rect& active_match_rect,
- int number_of_matches,
- int active_match_ordinal,
- bool final_update) {
- if (active_match_ordinal > 0)
- contents_->SetFocusedFrame(rfh->frame_tree_node(), rfh->GetSiteInstance());
- OnFindReply(rfh, request_id, number_of_matches, active_match_rect,
- active_match_ordinal, final_update);
+void FindRequestManager::UpdatedFrameNumberOfMatches(RenderFrameHostImpl* rfh,
+ unsigned int old_count,
+ unsigned int new_count) {
+ if (old_count == new_count)
+ return;
+
+ // Change the number of matches for this frame in the global count.
+ number_of_matches_ -= old_count;
+ number_of_matches_ += new_count;
+
+ // All matches may have been removed since the last find reply.
+ if (rfh == active_frame_ && !new_count)
+ relative_active_match_ordinal_ = 0;
+
+ // The active match ordinal may need updating since the number of matches
+ // before the active match may have changed.
+ UpdateActiveMatchOrdinal();
+}
+
+void FindRequestManager::SetActiveMatchRect(
+ const gfx::Rect& active_match_rect) {
+ selection_rect_ = active_match_rect;
+}
+
+void FindRequestManager::SetActiveMatchOrdinal(RenderFrameHostImpl* rfh,
+ int request_id,
+ int active_match_ordinal) {
+ if (active_match_ordinal > 0) {
+ // Call SetFocusedFrame on the WebContents associated with |rfh| (which
+ // might not be the same as |contents_|, as a WebContents might have
+ // inner WebContents). We need to focus on the frame where the active
+ // match is in, which should be in the |rfh|'s associated WebContents.
+ WebContentsImpl* web_contents =
+ static_cast<WebContentsImpl*>(WebContents::FromRenderFrameHost(rfh));
+ web_contents->SetFocusedFrame(rfh->frame_tree_node(),
+ rfh->GetSiteInstance());
+ }
+ if (rfh == active_frame_) {
+ active_match_ordinal_ +=
+ active_match_ordinal - relative_active_match_ordinal_;
+ relative_active_match_ordinal_ = active_match_ordinal;
+ } else {
+ if (active_frame_) {
+ // The new active match is in a different frame than the previous, so
+ // the previous active frame needs to be informed (to clear its active
+ // match highlighting).
+ ClearActiveFindMatch();
+ }
+ active_frame_ = rfh;
+ relative_active_match_ordinal_ = active_match_ordinal;
+ UpdateActiveMatchOrdinal();
+ }
+ if (pending_active_match_ordinal_ && request_id == current_request_.id)
+ pending_active_match_ordinal_ = false;
+ AdvanceQueue(request_id);
}
void FindRequestManager::RemoveFrame(RenderFrameHost* rfh) {
@@ -396,10 +377,10 @@ void FindRequestManager::RemoveFrame(RenderFrameHost* rfh) {
// If matches are counted for the frame that is being removed, decrement the
// match total before erasing that entry.
- auto it = matches_per_frame_.find(rfh);
- if (it != matches_per_frame_.end()) {
- number_of_matches_ -= it->second;
- matches_per_frame_.erase(it);
+ auto it = find_in_page_clients_.find(rfh);
+ if (it != find_in_page_clients_.end()) {
+ number_of_matches_ -= it->second->number_of_matches();
+ find_in_page_clients_.erase(it);
}
// Update the active match ordinal, since it may have changed.
@@ -547,7 +528,7 @@ void FindRequestManager::Reset(const FindRequest& initial_request) {
pending_initial_replies_.clear();
pending_find_next_reply_ = nullptr;
pending_active_match_ordinal_ = true;
- matches_per_frame_.clear();
+ find_in_page_clients_.clear();
number_of_matches_ = 0;
active_frame_ = nullptr;
relative_active_match_ordinal_ = 0;
@@ -580,7 +561,7 @@ void FindRequestManager::FindInternal(const FindRequest& request) {
if (!target_rfh || !CheckFrame(target_rfh))
target_rfh = GetInitialFrame(request.options.forward);
- SendFindIPC(request, target_rfh);
+ SendFindRequest(request, target_rfh);
current_request_ = request;
pending_active_match_ordinal_ = true;
return;
@@ -607,8 +588,8 @@ void FindRequestManager::AdvanceQueue(int request_id) {
FindInternal(find_request_queue_.front());
}
-void FindRequestManager::SendFindIPC(const FindRequest& request,
- RenderFrameHost* rfh) {
+void FindRequestManager::SendFindRequest(const FindRequest& request,
+ RenderFrameHost* rfh) {
DCHECK(CheckFrame(rfh));
DCHECK(rfh->IsRenderFrameLive());
@@ -617,8 +598,15 @@ void FindRequestManager::SendFindIPC(const FindRequest& request,
else
pending_initial_replies_.insert(rfh);
- rfh->Send(new FrameMsg_Find(rfh->GetRoutingID(), request.id,
- request.search_text, request.options));
+ blink::mojom::FindOptionsPtr options(blink::mojom::FindOptions::New());
+ options->forward = request.options.forward;
+ options->match_case = request.options.match_case;
+ options->find_next = request.options.find_next;
+ options->force = request.options.force;
+ options->run_synchronously_for_testing =
+ request.options.run_synchronously_for_testing;
+ static_cast<RenderFrameHostImpl*>(rfh)->GetFindInPage()->Find(
+ request.id, base::UTF16ToUTF8(request.search_text), std::move(options));
}
void FindRequestManager::NotifyFindReply(int request_id, bool final_update) {
@@ -659,7 +647,8 @@ RenderFrameHost* FindRequestManager::Traverse(RenderFrameHost* from_rfh,
if (!CheckFrame(node->current_frame_host()))
continue;
RenderFrameHost* current_rfh = node->current_frame_host();
- if (!matches_only || matches_per_frame_.find(current_rfh)->second ||
+ if (!matches_only ||
+ find_in_page_clients_.find(current_rfh)->second->number_of_matches() ||
pending_initial_replies_.count(current_rfh)) {
// Note that if there is still a pending reply expected for this frame,
// then it may have unaccounted matches and will not be skipped via
@@ -680,17 +669,18 @@ void FindRequestManager::AddFrame(RenderFrameHost* rfh, bool force) {
// A frame that is already being searched should not normally be added again.
DCHECK(force || !CheckFrame(rfh));
- matches_per_frame_[rfh] = 0;
+ find_in_page_clients_[rfh] = std::make_unique<FindInPageClient>(
+ this, static_cast<RenderFrameHostImpl*>(rfh));
FindRequest request = current_request_;
request.id = current_session_id_;
request.options.find_next = false;
request.options.force = force;
- SendFindIPC(request, rfh);
+ SendFindRequest(request, rfh);
}
bool FindRequestManager::CheckFrame(RenderFrameHost* rfh) const {
- return rfh && matches_per_frame_.count(rfh);
+ return rfh && find_in_page_clients_.count(rfh);
}
void FindRequestManager::UpdateActiveMatchOrdinal() {
@@ -709,7 +699,7 @@ void FindRequestManager::UpdateActiveMatchOrdinal() {
false /* forward */,
true /* matches_only */,
false /* wrap */)) != nullptr) {
- active_match_ordinal_ += matches_per_frame_[frame];
+ active_match_ordinal_ += find_in_page_clients_[frame]->number_of_matches();
}
active_match_ordinal_ += relative_active_match_ordinal_;
}
@@ -751,7 +741,8 @@ void FindRequestManager::FinalUpdateReceived(int request_id,
} else {
// Otherwise, the first frame with matches will have the active match.
target_rfh = GetInitialFrame(current_request_.options.forward);
- if (!CheckFrame(target_rfh) || !matches_per_frame_[target_rfh]) {
+ if (!CheckFrame(target_rfh) ||
+ !find_in_page_clients_[target_rfh]->number_of_matches()) {
target_rfh = Traverse(target_rfh,
current_request_.options.forward,
true /* matches_only */,
@@ -765,7 +756,7 @@ void FindRequestManager::FinalUpdateReceived(int request_id,
NotifyFindReply(request_id, false /* final_update */);
current_request_.options.find_next = true;
- SendFindIPC(current_request_, target_rfh);
+ SendFindRequest(current_request_, target_rfh);
}
#if defined(OS_ANDROID)
@@ -778,14 +769,10 @@ void FindRequestManager::RemoveNearestFindResultPendingReply(
activate_.pending_replies.erase(it);
if (activate_.pending_replies.empty() &&
CheckFrame(activate_.nearest_frame)) {
- // Lifetime of FindRequestManager > activate_.nearest_frame > Mojo
- // connection, so it's safe to bind |this| and |activate_.nearest_frame|
- activate_.nearest_frame->GetFindInPage()->ActivateNearestFindResult(
- activate_.point,
- base::BindOnce(&FindRequestManager::OnActivateNearestFindResultReply,
- base::Unretained(this),
- base::Unretained(activate_.nearest_frame),
- current_session_id_));
+ const auto client_it = find_in_page_clients_.find(activate_.nearest_frame);
+ if (client_it != find_in_page_clients_.end())
+ client_it->second->ActivateNearestFindResult(current_session_id_,
+ activate_.point);
}
}
diff --git a/chromium/content/browser/find_request_manager.h b/chromium/content/browser/find_request_manager.h
index ae95c1325af..62050f4611a 100644
--- a/chromium/content/browser/find_request_manager.h
+++ b/chromium/content/browser/find_request_manager.h
@@ -20,6 +20,7 @@
namespace content {
+class FindInPageClient;
class RenderFrameHost;
class RenderFrameHostImpl;
class WebContentsImpl;
@@ -46,22 +47,29 @@ class CONTENT_EXPORT FindRequestManager {
// activated, cleared, or remain highlighted.
void StopFinding(StopFindAction action);
- // Called when a reply is received from a frame with the results from a
- // find request.
- void OnFindReply(RenderFrameHostImpl* rfh,
- int request_id,
- int number_of_matches,
- const gfx::Rect& selection_rect,
- int active_match_ordinal,
- bool final_update);
-
- // Called when a reply for ActivateNearestFindResult is received.
- void OnActivateNearestFindResultReply(RenderFrameHostImpl* rfh,
- int request_id,
- const gfx::Rect& active_match_rect,
- int number_of_matches,
- int active_match_ordinal,
- bool final_update);
+ // Handles the final update from |rfh| for the find request with id
+ // |request_id|.
+ void HandleFinalUpdateForFrame(RenderFrameHostImpl* rfh, int request_id);
+
+ // The number of matches on |rfh| has changed from |old_count| to |new_count|.
+ // This method updates the total number of matches and also updates
+ // |active_match_ordinal_| accordingly.
+ void UpdatedFrameNumberOfMatches(RenderFrameHostImpl* rfh,
+ unsigned int old_count,
+ unsigned int new_count);
+
+ bool ShouldIgnoreReply(RenderFrameHostImpl* rfh, int request_id);
+
+ void SetActiveMatchRect(const gfx::Rect& active_match_rect);
+
+ void SetActiveMatchOrdinal(RenderFrameHostImpl* rfh,
+ int request_id,
+ int active_match_ordinal);
+
+ // Sends the find results (as they currently are) to the WebContents.
+ // |final_update| is true if we have received all of the updates from
+ // every frame for this request.
+ void NotifyFindReply(int request_id, bool final_update);
// Removes a frame from the set of frames being searched. This should be
// called whenever a frame is discovered to no longer exist.
@@ -128,12 +136,9 @@ class CONTENT_EXPORT FindRequestManager {
// with ID |request_id|. Advances the |find_request_queue_| if appropriate.
void AdvanceQueue(int request_id);
- // Sends a find IPC containing the find request |request| to the RenderFrame
- // associated with |rfh|.
- void SendFindIPC(const FindRequest& request, RenderFrameHost* rfh);
-
- // Sends the find results (as they currently are) to the WebContents.
- void NotifyFindReply(int request_id, bool final_update);
+ // Sends find request |request| through mojo to the RenderFrame associated
+ // with |rfh|.
+ void SendFindRequest(const FindRequest& request, RenderFrameHost* rfh);
// Returns the initial frame in search order. This will be either the first
// frame, if searching forward, or the last frame, if searching backward.
@@ -283,10 +288,11 @@ class CONTENT_EXPORT FindRequestManager {
// |current_request_.id| (the latest request).
bool pending_active_match_ordinal_;
- // The number of matches found in each frame. There will necessarily be
+ // The FindInPageClient associated with each frame. There will necessarily be
// entries in this map for every frame that is being (or has been) searched in
// the current find session, and no other frames.
- std::unordered_map<RenderFrameHost*, int> matches_per_frame_;
+ std::unordered_map<RenderFrameHost*, std::unique_ptr<FindInPageClient>>
+ find_in_page_clients_;
// The total number of matches found in the current find-in-page session. This
// should always be equal to the sum of all the entries in
diff --git a/chromium/content/browser/find_request_manager_browsertest.cc b/chromium/content/browser/find_request_manager_browsertest.cc
index f0d21d59c56..0217e5ac7d0 100644
--- a/chromium/content/browser/find_request_manager_browsertest.cc
+++ b/chromium/content/browser/find_request_manager_browsertest.cc
@@ -168,6 +168,7 @@ IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, MAYBE(Basic)) {
MakeChildFrameCrossProcess();
blink::WebFindOptions options;
+ options.run_synchronously_for_testing = true;
Find("result", options);
delegate()->WaitForFinalReply();
@@ -251,6 +252,7 @@ IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, ScrollAndZoomIntoView) {
// Search for a result further down in the iframe.
blink::WebFindOptions options;
+ options.run_synchronously_for_testing = true;
Find("result 17", options);
delegate()->WaitForFinalReply();
@@ -312,6 +314,7 @@ IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, MAYBE(CharacterByCharacter)) {
MakeChildFrameCrossProcess();
blink::WebFindOptions default_options;
+ default_options.run_synchronously_for_testing = true;
Find("r", default_options);
Find("re", default_options);
Find("res", default_options);
@@ -336,6 +339,7 @@ IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, DISABLED_RapidFire) {
MakeChildFrameCrossProcess();
blink::WebFindOptions options;
+ options.run_synchronously_for_testing = true;
Find("result", options);
options.find_next = true;
@@ -356,6 +360,7 @@ IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, DISABLED_RemoveFrame) {
LoadMultiFramePage(2 /* height */, GetParam() /* cross_process */);
blink::WebFindOptions options;
+ options.run_synchronously_for_testing = true;
Find("result", options);
delegate()->WaitForFinalReply();
options.find_next = true;
@@ -389,6 +394,7 @@ IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, DISABLED_AddFrame) {
LoadMultiFramePage(2 /* height */, GetParam() /* cross_process */);
blink::WebFindOptions options;
+ options.run_synchronously_for_testing = true;
Find("result", options);
options.find_next = true;
Find("result", options);
@@ -428,6 +434,7 @@ IN_PROC_BROWSER_TEST_F(FindRequestManagerTest, MAYBE(AddFrameAfterNoMatches)) {
EXPECT_TRUE(navigation_observer.last_navigation_succeeded());
blink::WebFindOptions default_options;
+ default_options.run_synchronously_for_testing = true;
Find("result", default_options);
delegate()->WaitForFinalReply();
@@ -460,6 +467,7 @@ IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, MAYBE(NavigateFrame)) {
LoadMultiFramePage(2 /* height */, GetParam() /* cross_process */);
blink::WebFindOptions options;
+ options.run_synchronously_for_testing = true;
Find("result", options);
options.find_next = true;
options.forward = false;
@@ -508,6 +516,7 @@ IN_PROC_BROWSER_TEST_F(FindRequestManagerTest, MAYBE(HiddenFrame)) {
LoadAndWait("/find_in_hidden_frame.html");
blink::WebFindOptions default_options;
+ default_options.run_synchronously_for_testing = true;
Find("hello", default_options);
delegate()->WaitForFinalReply();
FindResults results = delegate()->GetFindResults();
@@ -522,6 +531,7 @@ IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, MAYBE(FindNewMatches)) {
LoadAndWait("/find_in_dynamic_page.html");
blink::WebFindOptions options;
+ options.run_synchronously_for_testing = true;
Find("result", options);
options.find_next = true;
Find("result", options);
@@ -548,7 +558,8 @@ IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, MAYBE(FindNewMatches)) {
// TODO(crbug.com/615291): These tests frequently fail on Android.
// TODO(crbug.com/779912): Flaky timeout on Win7 (dbg).
-#if defined(OS_ANDROID) || (defined(OS_WIN) && !defined(NDEBUG))
+// TODO(crbug.com/875306): Flaky on Win10.
+#if defined(OS_ANDROID) || defined(OS_WIN)
#define MAYBE_FindInPage_Issue627799 DISABLED_FindInPage_Issue627799
#else
#define MAYBE_FindInPage_Issue627799 FindInPage_Issue627799
@@ -558,6 +569,7 @@ IN_PROC_BROWSER_TEST_F(FindRequestManagerTest, MAYBE_FindInPage_Issue627799) {
LoadAndWait("/find_in_long_page.html");
blink::WebFindOptions options;
+ options.run_synchronously_for_testing = true;
Find("42", options);
delegate()->WaitForFinalReply();
@@ -589,6 +601,7 @@ IN_PROC_BROWSER_TEST_F(FindRequestManagerTest, MAYBE(FindInPage_Issue644448)) {
EXPECT_TRUE(navigation_observer.last_navigation_succeeded());
blink::WebFindOptions default_options;
+ default_options.run_synchronously_for_testing = true;
Find("result", default_options);
delegate()->WaitForFinalReply();
@@ -617,6 +630,7 @@ IN_PROC_BROWSER_TEST_F(FindRequestManagerTest, MAYBE(FindMatchRects)) {
LoadAndWait("/find_in_page.html");
blink::WebFindOptions default_options;
+ default_options.run_synchronously_for_testing = true;
Find("result", default_options);
delegate()->WaitForFinalReply();
EXPECT_EQ(19, delegate()->GetFindResults().number_of_matches);
@@ -699,6 +713,7 @@ IN_PROC_BROWSER_TEST_F(FindRequestManagerTest,
LoadAndWait("/find_in_page.html");
blink::WebFindOptions default_options;
+ default_options.run_synchronously_for_testing = true;
Find("result", default_options);
delegate()->WaitForFinalReply();
EXPECT_EQ(19, delegate()->GetFindResults().number_of_matches);
diff --git a/chromium/content/browser/font_unique_name_lookup/OWNERS b/chromium/content/browser/font_unique_name_lookup/OWNERS
new file mode 100644
index 00000000000..58196726758
--- /dev/null
+++ b/chromium/content/browser/font_unique_name_lookup/OWNERS
@@ -0,0 +1,3 @@
+drott@chromium.org
+
+# COMPONENT: Blink>Fonts
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
new file mode 100644
index 00000000000..4708110a0f7
--- /dev/null
+++ b/chromium/content/browser/font_unique_name_lookup/font_unique_name_browsertest.cc
@@ -0,0 +1,140 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/stl_util.h"
+#include "base/test/scoped_feature_list.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"
+#include "content/public/common/content_features.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "content/public/test/test_navigation_observer.h"
+#include "content/shell/browser/shell.h"
+
+namespace content {
+namespace {
+
+const char* kExpectedFontFamilyNames[] = {"AndroidClock",
+ "Roboto",
+ "Droid Sans Mono",
+ "Roboto",
+ "Noto Color Emoji",
+ "Noto Sans Bengali",
+ "Noto Sans Bengali",
+ "Noto Sans Bengali UI",
+ "Noto Sans Bengali UI",
+ "Noto Sans Devanagari",
+ "Noto Sans Devanagari",
+ "Noto Sans Devanagari UI",
+ "Noto Sans Devanagari UI",
+ "Noto Sans Kannada",
+ "Noto Sans Kannada",
+ "Noto Sans Kannada UI",
+ "Noto Sans Kannada UI",
+ "Noto Sans Lao",
+ "Noto Sans Lao",
+ "Noto Sans Lao UI",
+ "Noto Sans Lao UI",
+ "Noto Sans Malayalam",
+ "Noto Sans Malayalam",
+ "Noto Sans Malayalam UI",
+ "Noto Sans Malayalam UI",
+ "Noto Sans Tamil",
+ "Noto Sans Tamil",
+ "Noto Sans Tamil UI",
+ "Noto Sans Tamil UI",
+ "Noto Sans Telugu",
+ "Noto Sans Telugu",
+ "Noto Sans Telugu UI",
+ "Noto Sans Telugu UI",
+ "Noto Sans Thai",
+ "Noto Sans Thai",
+ "Noto Sans Thai UI",
+ "Noto Sans Thai UI",
+ "Roboto",
+ "Roboto Condensed",
+ "Roboto Condensed",
+ "Roboto Condensed",
+ "Roboto Condensed",
+ "Roboto"};
+
+} // namespace
+
+class FontUniqueNameBrowserTest : public DevToolsProtocolTest {
+ public:
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ feature_list_.InitAndEnableFeature(features::kFontSrcLocalMatching);
+ }
+
+ void LoadAndWait(const std::string& url) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+ TestNavigationObserver navigation_observer(
+ static_cast<WebContentsImpl*>(shell()->web_contents()));
+ NavigateToURL(shell(), embedded_test_server()->GetURL("a.com", url));
+ ASSERT_TRUE(navigation_observer.last_navigation_succeeded());
+ }
+
+ private:
+ base::test::ScopedFeatureList feature_list_;
+};
+
+#if defined(OS_ANDROID)
+#define MAYBE_ContentLocalFontsMatching ContentLocalFontsMatching
+#else
+#define MAYBE_ContentLocalFontsMatching DISABLED_ContentLocalFontsMatching
+#endif
+IN_PROC_BROWSER_TEST_F(FontUniqueNameBrowserTest,
+ MAYBE_ContentLocalFontsMatching) {
+ LoadAndWait("/font_src_local_matching.html");
+ Attach();
+
+ base::Value* dom_enable_result = SendCommand("DOM.enable", nullptr, true);
+ ASSERT_TRUE(dom_enable_result);
+
+ base::Value* css_enable_result = SendCommand("CSS.enable", nullptr, true);
+ ASSERT_TRUE(css_enable_result);
+
+ unsigned num_added_nodes = static_cast<unsigned>(
+ content::EvalJs(shell(), "addTestNodes()").ExtractInt());
+ ASSERT_EQ(num_added_nodes, base::size(kExpectedFontFamilyNames));
+
+ std::unique_ptr<base::DictionaryValue> params =
+ std::make_unique<base::DictionaryValue>();
+ params->SetInteger("depth", 0);
+ base::Value* result = SendCommand("DOM.getDocument", std::move(params));
+ result = result->FindPath({"root", "nodeId"});
+ ASSERT_TRUE(result);
+ ASSERT_TRUE(result->is_int());
+
+ params.reset(new base::DictionaryValue());
+ params->SetInteger("nodeId", result->GetInt());
+ params->SetString("selector", ".testnode");
+ result = SendCommand("DOM.querySelectorAll", std::move(params));
+ // This needs a Clone() because node_list otherwise gets invalid after the
+ // next SendCommand call.
+ base::Value node_list =
+ result->FindKeyOfType("nodeIds", base::Value::Type::LIST)->Clone();
+ std::vector<base::Value>& nodes_vector = node_list.GetList();
+ ASSERT_EQ(nodes_vector.size(), num_added_nodes);
+ ASSERT_EQ(nodes_vector.size(), base::size(kExpectedFontFamilyNames));
+ for (size_t i = 0; i < nodes_vector.size(); ++i) {
+ base::Value& nodeId = nodes_vector[i];
+ params.reset(new base::DictionaryValue());
+ params->SetInteger("nodeId", nodeId.GetInt());
+ base::Value* font_info =
+ SendCommand("CSS.getPlatformFontsForNode", std::move(params));
+ ASSERT_TRUE(font_info->is_dict());
+ base::Value* font_list = font_info->FindKey("fonts");
+ ASSERT_TRUE(font_list->is_list());
+ base::Value& first_font_info = font_list->GetList()[0];
+ ASSERT_TRUE(first_font_info.is_dict());
+ base::Value* first_font_name = first_font_info.FindKey("familyName");
+ ASSERT_TRUE(first_font_name->is_string());
+ ASSERT_GT(first_font_name->GetString().size(), 0u);
+ ASSERT_EQ(first_font_name->GetString(), kExpectedFontFamilyNames[i]);
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/browser/font_unique_name_lookup/font_unique_name_lookup.cc b/chromium/content/browser/font_unique_name_lookup/font_unique_name_lookup.cc
new file mode 100644
index 00000000000..5199a965cee
--- /dev/null
+++ b/chromium/content/browser/font_unique_name_lookup/font_unique_name_lookup.cc
@@ -0,0 +1,347 @@
+// 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/font_unique_name_lookup/font_unique_name_lookup.h"
+
+#include "base/android/build_info.h"
+#include "base/files/file.h"
+#include "base/files/file_enumerator.h"
+#include "base/files/file_util.h"
+#include "base/logging.h"
+#include "base/no_destructor.h"
+#include "base/path_service.h"
+#include "base/strings/utf_string_conversions.h"
+#include "third_party/blink/public/common/font_unique_name_lookup/font_unique_name_table.pb.h"
+#include "third_party/blink/public/common/font_unique_name_lookup/icu_fold_case_util.h"
+
+#include <set>
+#include <vector>
+#include "third_party/icu/source/common/unicode/unistr.h"
+
+#include FT_TRUETYPE_IDS_H
+
+namespace {
+
+using namespace ::icu_62;
+
+const char kProtobufFilename[] = "font_unique_name_table.pb";
+static const char* const kAndroidFontPaths[] = {"/system/fonts",
+ "/vendor/fonts"};
+
+bool SfntNameIsEnglish(const FT_SfntName& sfnt_name) {
+ if (sfnt_name.platform_id == TT_PLATFORM_MICROSOFT)
+ return sfnt_name.language_id == TT_MS_LANGID_ENGLISH_UNITED_STATES;
+ if (sfnt_name.platform_id == TT_PLATFORM_MACINTOSH)
+ return sfnt_name.language_id == TT_MAC_LANGID_ENGLISH;
+ return false;
+}
+
+// Convenience scoped wrapper for FT_Face instances. Takes care of handling
+// FreeType memory by calling FT_Done_Face on destruction.
+class ScopedFtFace {
+ public:
+ // Create a new FT_Face instance that will be wrapped by this object.
+ // Call IsValid() after construction to check for errors.
+ // |library| is the parent FT_Library instance, |font_path| the input font
+ // file path, and |ttc_index| the font file index (for TrueType collections).
+ ScopedFtFace(FT_Library library,
+ const std::string& font_path,
+ int32_t ttc_index)
+ : ft_face_(nullptr),
+ ft_error_(
+ FT_New_Face(library, font_path.c_str(), ttc_index, &ft_face_)) {}
+
+ // Destructor will destroy the FT_Face instance automatically.
+ ~ScopedFtFace() {
+ if (IsValid()) {
+ FT_Done_Face(ft_face_);
+ }
+ }
+
+ // Returns true iff instance is valid, i.e. construction did not fail.
+ bool IsValid() const { return ft_error_ == FT_Err_Ok; }
+
+ // Return FreeType error code from construction.
+ FT_Error error() const { return ft_error_; }
+
+ // Returns FT_Face value.
+ FT_Face get() const { return ft_face_; }
+
+ private:
+ FT_Face ft_face_ = nullptr;
+ FT_Error ft_error_ = FT_Err_Ok;
+};
+
+} // namespace
+
+namespace content {
+
+class PlatformFontUniqueNameLookup : public FontUniqueNameLookup {
+ public:
+ PlatformFontUniqueNameLookup() : FontUniqueNameLookup(GetCacheDirectory()) {
+ // Error from LoadFromFile() is ignored: Loading the cache file could be
+ // recovered from by rebuilding the font table. UpdateTableIfNeeded() checks
+ // whether the internal base::MappedReadOnlyRegion has a size, which it
+ // doesn't if the LoadFromFile() failed. If it doesn't have a size, the
+ // table is rebuild by calling UpdateTable().
+ LoadFromFile();
+ if (UpdateTableIfNeeded()) {
+ // TODO(drott): Add UMA histograms for recording cache read and write
+ // failures.
+ PersistToFile();
+ }
+ }
+
+ private:
+ static base::FilePath GetCacheDirectory() {
+ base::FilePath cache_directory;
+ base::PathService::Get(base::DIR_CACHE, &cache_directory);
+ return cache_directory;
+ }
+};
+
+FontUniqueNameLookup& FontUniqueNameLookup::GetInstance() {
+ static base::NoDestructor<PlatformFontUniqueNameLookup> sInstance;
+ return *sInstance.get();
+}
+
+FontUniqueNameLookup::FontUniqueNameLookup(FontUniqueNameLookup&&) = default;
+
+FontUniqueNameLookup::FontUniqueNameLookup(
+ const base::FilePath& cache_directory)
+ : cache_directory_(cache_directory) {
+ if (!DirectoryExists(cache_directory_) ||
+ !base::PathIsWritable(cache_directory_)) {
+ DCHECK(false) << "Error accessing cache directory for writing: "
+ << cache_directory_.value();
+ cache_directory_ = base::FilePath();
+ }
+ FT_Init_FreeType(&ft_library_);
+}
+
+FontUniqueNameLookup::~FontUniqueNameLookup() {
+ FT_Done_FreeType(ft_library_);
+}
+
+base::ReadOnlySharedMemoryRegion
+FontUniqueNameLookup::GetUniqueNameTableAsSharedMemoryRegion() const {
+ return proto_storage_.region.Duplicate();
+}
+
+bool FontUniqueNameLookup::IsValid() {
+ return proto_storage_.IsValid() && proto_storage_.mapping.size();
+}
+
+bool FontUniqueNameLookup::UpdateTableIfNeeded() {
+ blink::FontUniqueNameTable font_table;
+ bool update_needed =
+ !proto_storage_.IsValid() || !proto_storage_.mapping.size() ||
+ !font_table.ParseFromArray(proto_storage_.mapping.memory(),
+ proto_storage_.mapping.size()) ||
+ font_table.stored_for_android_build_fp() != GetAndroidBuildFingerprint();
+ if (update_needed)
+ UpdateTable();
+ return update_needed;
+}
+
+bool FontUniqueNameLookup::UpdateTable() {
+ std::vector<std::string> font_files_to_index = GetFontFilePaths();
+
+ blink::FontUniqueNameTable font_table;
+ font_table.set_stored_for_android_build_fp(GetAndroidBuildFingerprint());
+ for (const auto& font_file : font_files_to_index) {
+ int32_t number_of_faces = NumberOfFacesInFontFile(font_file);
+ for (int32_t i = 0; i < number_of_faces; ++i) {
+ if (!IndexFile(font_table.add_font_entries(), font_file, i)) {
+ // TODO(drott): Track file scanning failures in UMA.
+ font_table.mutable_font_entries()->RemoveLast();
+ }
+ }
+ }
+
+ proto_storage_ =
+ base::ReadOnlySharedMemoryRegion::Create(font_table.ByteSizeLong());
+ if (!IsValid())
+ return false;
+
+ if (!font_table.SerializeToArray(proto_storage_.mapping.memory(),
+ proto_storage_.mapping.size())) {
+ proto_storage_ = base::MappedReadOnlyRegion();
+ return false;
+ }
+ return true;
+}
+
+bool FontUniqueNameLookup::LoadFromFile() {
+ // Reset to empty to ensure IsValid() is false if reading fails.
+ proto_storage_ = base::MappedReadOnlyRegion();
+ base::File table_cache_file(
+ TableCacheFilePath(),
+ base::File::FLAG_OPEN | base::File::Flags::FLAG_READ);
+ if (!table_cache_file.IsValid())
+ return false;
+ proto_storage_ =
+ base::ReadOnlySharedMemoryRegion::Create(table_cache_file.GetLength());
+ if (!IsValid())
+ return false;
+ int read_result = table_cache_file.Read(
+ 0, static_cast<char*>(proto_storage_.mapping.memory()),
+ table_cache_file.GetLength());
+ // If no bytes were read or Read() returned -1 we are not able to reconstruct
+ // a font table from the cached file.
+ if (read_result <= 0) {
+ proto_storage_ = base::MappedReadOnlyRegion();
+ return false;
+ }
+
+ blink::FontUniqueNameTable font_table;
+ if (!font_table.ParseFromArray(proto_storage_.mapping.memory(),
+ proto_storage_.mapping.size())) {
+ proto_storage_ = base::MappedReadOnlyRegion();
+ return false;
+ }
+
+ return true;
+}
+
+bool FontUniqueNameLookup::PersistToFile() {
+ DCHECK(IsValid());
+ if (!IsValid())
+ return false;
+ base::File table_cache_file(
+ TableCacheFilePath(),
+ base::File::FLAG_CREATE_ALWAYS | base::File::Flags::FLAG_WRITE);
+ if (!table_cache_file.IsValid())
+ return false;
+ if (table_cache_file.Write(
+ 0, static_cast<char*>(proto_storage_.mapping.memory()),
+ proto_storage_.mapping.size()) == -1) {
+ table_cache_file.SetLength(0);
+ proto_storage_ = base::MappedReadOnlyRegion();
+ return false;
+ }
+ return true;
+}
+
+base::FilePath FontUniqueNameLookup::TableCacheFilePath() {
+ return base::FilePath(
+ cache_directory_.Append(base::FilePath(kProtobufFilename)));
+}
+
+bool FontUniqueNameLookup::IndexFile(
+ blink::FontUniqueNameTable_FontUniqueNameEntry* font_entry,
+ const std::string& font_file_path,
+ uint32_t ttc_index) {
+ ScopedFtFace face(ft_library_, font_file_path.c_str(), ttc_index);
+ if (!face.IsValid()) {
+ LOG(ERROR) << "Unable to open font file for indexing: "
+ << font_file_path.c_str()
+ << " - FreeType FT_Error code: " << face.error();
+ return false;
+ }
+
+ if (!FT_Get_Sfnt_Name_Count(face.get())) {
+ LOG(ERROR) << "Zero name table entries in font file: "
+ << font_file_path.c_str();
+ return false;
+ }
+
+ // Get file attributes
+ base::File font_file_for_info(
+ base::FilePath(font_file_path.c_str()),
+ base::File::FLAG_OPEN | base::File::Flags::FLAG_READ);
+ if (!font_file_for_info.IsValid()) {
+ LOG(ERROR) << "Unable to open font file: " << font_file_path.c_str();
+ return false;
+ }
+ base::File::Info font_file_info;
+ if (!font_file_for_info.GetInfo(&font_file_info)) {
+ LOG(ERROR) << "Unable to get font file attributes for: "
+ << font_file_path.c_str();
+ return false;
+ }
+ font_entry->set_file_path(font_file_path);
+ font_entry->set_ttc_index(ttc_index);
+
+ for (size_t i = 0; i < FT_Get_Sfnt_Name_Count(face.get()); ++i) {
+ FT_SfntName sfnt_name;
+ if (FT_Get_Sfnt_Name(face.get(), i, &sfnt_name) != 0) {
+ LOG(ERROR) << "Unable to retrieve Sfnt Name table for font file: "
+ << font_file_path.c_str();
+ return false;
+ }
+
+ if (!SfntNameIsEnglish(sfnt_name))
+ continue;
+
+ std::string sfnt_name_string = "";
+ std::string codepage_name;
+ // Codepage names from http://demo.icu-project.org/icu-bin/convexp
+ if (sfnt_name.platform_id == TT_PLATFORM_MICROSOFT &&
+ sfnt_name.encoding_id == TT_MS_ID_UNICODE_CS) {
+ codepage_name = "UTF16-BE";
+ } else if (sfnt_name.platform_id == TT_PLATFORM_MACINTOSH &&
+ sfnt_name.encoding_id == TT_MAC_ID_ROMAN) {
+ codepage_name = "macintosh";
+ }
+ UnicodeString sfnt_name_unicode(reinterpret_cast<char*>(sfnt_name.string),
+ sfnt_name.string_len,
+ codepage_name.c_str());
+ if (sfnt_name_unicode.isBogus())
+ return false;
+ // Firefox performs case insensitive matching for src: local().
+ sfnt_name_unicode.foldCase();
+ sfnt_name_unicode.toUTF8String(sfnt_name_string);
+
+ switch (sfnt_name.name_id) {
+ case TT_NAME_ID_PS_NAME:
+ font_entry->set_postscript_name(blink::IcuFoldCase(sfnt_name_string));
+ break;
+ case TT_NAME_ID_FULL_NAME:
+ font_entry->set_full_name(blink::IcuFoldCase(sfnt_name_string));
+ break;
+ default:
+ break;
+ }
+ }
+ return true;
+}
+
+int32_t FontUniqueNameLookup::NumberOfFacesInFontFile(
+ const std::string& font_filename) const {
+ // According to FreeType documentation calling FT_Open_Face with a negative
+ // index value allows us to probe how many fonts can be found in a font file
+ // (which can be a single font ttf or a TrueType collection (.ttc).
+ ScopedFtFace probe_face(ft_library_, font_filename.c_str(), -1);
+ if (!probe_face.IsValid())
+ return 0;
+ return probe_face.get()->num_faces;
+}
+
+std::string FontUniqueNameLookup::GetAndroidBuildFingerprint() const {
+ return android_build_fingerprint_for_testing_.size()
+ ? android_build_fingerprint_for_testing_
+ : base::android::BuildInfo::GetInstance()->android_build_fp();
+}
+
+std::vector<std::string> FontUniqueNameLookup::GetFontFilePaths() const {
+ if (font_file_paths_for_testing_.size())
+ return font_file_paths_for_testing_;
+ std::vector<std::string> font_files;
+ for (const char* font_dir_path : kAndroidFontPaths) {
+ base::FileEnumerator files_enumerator(
+ base::MakeAbsoluteFilePath(base::FilePath(font_dir_path)), true,
+ base::FileEnumerator::FILES);
+ for (base::FilePath name = files_enumerator.Next(); !name.empty();
+ name = files_enumerator.Next()) {
+ if (name.Extension() == ".ttf" || name.Extension() == ".ttc" ||
+ name.Extension() == ".otf") {
+ font_files.push_back(name.value());
+ }
+ }
+ }
+ return font_files;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/font_unique_name_lookup/font_unique_name_lookup.h b/chromium/content/browser/font_unique_name_lookup/font_unique_name_lookup.h
new file mode 100644
index 00000000000..5cf38306c49
--- /dev/null
+++ b/chromium/content/browser/font_unique_name_lookup/font_unique_name_lookup.h
@@ -0,0 +1,138 @@
+// 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_FONT_UNIQUE_NAME_LOOKUP_FONT_UNIQUE_NAME_LOOKUP_H_
+#define CONTENT_BROWSER_FONT_UNIQUE_NAME_LOOKUP_FONT_UNIQUE_NAME_LOOKUP_H_
+
+#include "base/files/file_path.h"
+#include "base/memory/read_only_shared_memory_region.h"
+#include "content/common/content_export.h"
+
+#include <ft2build.h>
+#include FT_SYSTEM_H
+#include FT_TRUETYPE_TABLES_H
+#include FT_SFNT_NAMES_H
+
+#include <string>
+
+namespace blink {
+class FontUniqueNameTable_FontUniqueNameEntry;
+}
+
+namespace content {
+
+// Scans a set of font files for the full font name and postscript name
+// information in the name table and builds a Protobuf lookup structure from
+// it. The protobuf can be persisted to disk to the Android cache directory, and
+// it can be read from disk as well. Provides the lookup structure as a
+// ReadOnlySharedMemoryRegion. Performing lookup on it is done through
+// FontTableMatcher.
+class CONTENT_EXPORT FontUniqueNameLookup {
+ public:
+ FontUniqueNameLookup() = delete;
+
+ // Retrieve an initialized instance of FontUniqueNameLookup that has read the
+ // table from cache if there was one, updated the lookup table if needed
+ // (i.e. if there was an Android firmware update) from the standard Android
+ // font directories, and written the updated lookup table back to file. It is
+ // ready to use with FontTableMatcher.
+ static FontUniqueNameLookup& GetInstance();
+
+ // Construct a FontUniqueNameLookup given a cache directory path
+ // |cache_directory| to persist the internal lookup table, a
+ // FontFilesCollector to enumerate font files and a BuildFingerprintProvider
+ // to access the Android build fingerprint.
+ FontUniqueNameLookup(const base::FilePath& cache_directory);
+ ~FontUniqueNameLookup();
+
+ // Default move contructor.
+ FontUniqueNameLookup(FontUniqueNameLookup&&);
+ // Default move assigment operator.
+ FontUniqueNameLookup& operator=(FontUniqueNameLookup&&) = default;
+
+ // Return a ReadOnlySharedMemoryRegion to access the serialized form of the
+ // current lookup table. To be used with FontTableMatcher.
+ base::ReadOnlySharedMemoryRegion GetUniqueNameTableAsSharedMemoryRegion()
+ const;
+
+ // Returns true if an up-to-date, consistent font table is present.
+ bool IsValid();
+
+ // If an Android firmware update was detected by checking
+ // BuildFingerprintProvider, call UpdateTable(). Do not use this method.
+ // Instead, call GetInstance() to get an initialized instance. Publicly
+ // exposed for testing.
+ bool UpdateTableIfNeeded();
+ // Rescan the files returned by the FontFilesCollector and rebuild the lookup
+ // table by indexing them. Do not use this method. Instead, call GetInstance()
+ // to get an initialized instance. Returns true if instance is valid after
+ // updating, returns false if an error occured in acquiring memory or
+ // serializing the scanned files to the shared memory region. Publicly exposed
+ // for testing.
+ bool UpdateTable();
+ // Try to find a serialized lookup table in the directory specified at
+ // construction and load it into memory. Do not use this method. Instead, call
+ // GetInstance() to get an initialized instance. Publicly exposed for testing.
+ bool LoadFromFile();
+ // Serialize the current lookup table into a file in the the cache directory
+ // specified at construction time. If an up to date table is present and
+ // persisting fails, discard the internal table, as it might be that we were
+ // not able to update the file the previous time. Do not use this
+ // method. Instead, call GetInstance() to get an initialized
+ // instance. Publicly exposed for testing.
+ bool PersistToFile();
+
+ // Override the internal font files enumeration with an explicit set of fonts
+ // to be scanned in |font_file_paths|. Only used for testing.
+ void SetFontFilePathsForTesting(
+ const std::vector<std::string> font_file_paths) {
+ font_file_paths_for_testing_ = font_file_paths;
+ }
+
+ // Override the Android build fingerprint for testing.
+ void SetAndroidBuildFingerprintForTesting(
+ const std::string& build_fingerprint_override) {
+ android_build_fingerprint_for_testing_ = build_fingerprint_override;
+ }
+
+ // Returns the storage location of the table cache protobuf file.
+ base::FilePath TableCacheFilePathForTesting() {
+ return TableCacheFilePath();
+ };
+
+ private:
+ // Scan the font file at |font_file_path| and given |ttc_index| and extract
+ // full font name and postscript name from the font and store it into the
+ // font_index_entry protobuf object.
+ bool IndexFile(
+ blink::FontUniqueNameTable_FontUniqueNameEntry* font_index_entry,
+ const std::string& font_file_path,
+ uint32_t ttc_index);
+ // For a TrueType font collection, determine how many font faces are
+ // available in a file.
+ int32_t NumberOfFacesInFontFile(const std::string& font_filename) const;
+
+ // If an Android build fingerprint override is set through
+ // SetAndroidBuildFingerprint() return that, otherwise return the actual
+ // platform's Android build fingerprint.
+ std::string GetAndroidBuildFingerprint() const;
+
+ // If an override is set through SetFontFilePathsForTesting() return those
+ // fonts, otherwise enumerate font files in the the Android platform font
+ // directories.
+ std::vector<std::string> GetFontFilePaths() const;
+
+ base::FilePath TableCacheFilePath();
+
+ base::FilePath cache_directory_;
+ FT_Library ft_library_;
+ base::MappedReadOnlyRegion proto_storage_;
+
+ std::string android_build_fingerprint_for_testing_ = "";
+ std::vector<std::string> font_file_paths_for_testing_ =
+ std::vector<std::string>();
+};
+} // namespace content
+
+#endif // CONTENT_BROWSER_FONT_UNIQUE_NAME_LOOKUP_FONT_UNIQUE_NAME_LOOKUP_H_
diff --git a/chromium/content/browser/font_unique_name_lookup/font_unique_name_lookup_service.cc b/chromium/content/browser/font_unique_name_lookup/font_unique_name_lookup_service.cc
new file mode 100644
index 00000000000..79c4fa1ac5e
--- /dev/null
+++ b/chromium/content/browser/font_unique_name_lookup/font_unique_name_lookup_service.cc
@@ -0,0 +1,50 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/font_unique_name_lookup/font_unique_name_lookup_service.h"
+
+#include "base/feature_list.h"
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/task/post_task.h"
+#include "content/browser/font_unique_name_lookup/font_unique_name_lookup.h"
+#include "content/public/common/content_features.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+
+namespace content {
+
+FontUniqueNameLookupService::FontUniqueNameLookupService()
+ : font_unique_name_lookup_(::content::FontUniqueNameLookup::GetInstance()) {
+ DCHECK(base::FeatureList::IsEnabled(features::kFontSrcLocalMatching));
+}
+
+FontUniqueNameLookupService::~FontUniqueNameLookupService() {}
+
+// static
+void FontUniqueNameLookupService::Create(
+ blink::mojom::FontUniqueNameLookupRequest request) {
+ mojo::MakeStrongBinding(std::make_unique<FontUniqueNameLookupService>(),
+ std::move(request));
+}
+
+// static
+scoped_refptr<base::SequencedTaskRunner>
+FontUniqueNameLookupService::GetTaskRunner() {
+ CR_DEFINE_STATIC_LOCAL(
+ scoped_refptr<base::SequencedTaskRunner>, runner,
+ (base::CreateSequencedTaskRunnerWithTraits(
+ {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN,
+ base::TaskPriority::USER_BLOCKING})));
+ return runner;
+}
+
+void FontUniqueNameLookupService::GetUniqueNameLookupTable(
+ GetUniqueNameLookupTableCallback callback) {
+ DCHECK(GetTaskRunner()->RunsTasksInCurrentSequence());
+ std::move(callback).Run(
+ font_unique_name_lookup_.GetUniqueNameTableAsSharedMemoryRegion());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/font_unique_name_lookup/font_unique_name_lookup_service.h b/chromium/content/browser/font_unique_name_lookup/font_unique_name_lookup_service.h
new file mode 100644
index 00000000000..01aac221714
--- /dev/null
+++ b/chromium/content/browser/font_unique_name_lookup/font_unique_name_lookup_service.h
@@ -0,0 +1,36 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_FONT_UNIQUE_NAME_LOOKUP_FONT_UNIQUE_NAME_LOOKUP_SERVICE_H_
+#define CONTENT_BROWSER_FONT_UNIQUE_NAME_LOOKUP_FONT_UNIQUE_NAME_LOOKUP_SERVICE_H_
+
+#include "base/files/file_path.h"
+#include "base/macros.h"
+#include "mojo/public/cpp/bindings/interface_request.h"
+#include "third_party/blink/public/platform/modules/font_unique_name_lookup/font_unique_name_lookup.mojom.h"
+
+namespace content {
+
+class FontUniqueNameLookup;
+
+class FontUniqueNameLookupService : public blink::mojom::FontUniqueNameLookup {
+ public:
+ FontUniqueNameLookupService();
+ ~FontUniqueNameLookupService() override;
+
+ static void Create(blink::mojom::FontUniqueNameLookupRequest);
+
+ static scoped_refptr<base::SequencedTaskRunner> GetTaskRunner();
+
+ void GetUniqueNameLookupTable(
+ GetUniqueNameLookupTableCallback callback) override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(FontUniqueNameLookupService);
+ ::content::FontUniqueNameLookup& font_unique_name_lookup_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_FONT_UNIQUE_NAME_LOOKUP_FONT_UNIQUE_NAME_LOOKUP_SERVICE_H_
diff --git a/chromium/content/browser/font_unique_name_lookup/font_unique_name_lookup_unittest.cc b/chromium/content/browser/font_unique_name_lookup/font_unique_name_lookup_unittest.cc
new file mode 100644
index 00000000000..bc13d1ea346
--- /dev/null
+++ b/chromium/content/browser/font_unique_name_lookup/font_unique_name_lookup_unittest.cc
@@ -0,0 +1,334 @@
+// 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 "testing/gtest/include/gtest/gtest.h"
+
+#include "base/android/build_info.h"
+#include "base/files/file.h"
+#include "base/files/file_enumerator.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/stl_util.h"
+#include "base/strings/string_util.h"
+#include "content/browser/font_unique_name_lookup/font_unique_name_lookup.h"
+#include "third_party/blink/public/common/font_unique_name_lookup/font_table_matcher.h"
+
+#include <functional>
+#include <memory>
+
+namespace {
+
+static const char* const kAndroidFontPaths[] = {"/system/fonts",
+ "/vendor/fonts"};
+
+// Full font name, postscript name, filename.
+static const char* const kRobotoCondensedBoldItalicNames[] = {
+ "Roboto Condensed Bold Italic", "RobotoCondensed-BoldItalic",
+ "RobotoCondensed-BoldItalic.ttf"};
+
+std::vector<std::string> AndroidFontFilesList() {
+ std::vector<std::string> font_files;
+ for (const char* font_dir_path : kAndroidFontPaths) {
+ base::FileEnumerator files_enumerator(
+ base::MakeAbsoluteFilePath(base::FilePath(font_dir_path)), true,
+ base::FileEnumerator::FILES);
+ for (base::FilePath name = files_enumerator.Next(); !name.empty();
+ name = files_enumerator.Next()) {
+ if (name.Extension() == ".ttf" || name.Extension() == ".ttc" ||
+ name.Extension() == ".otf") {
+ font_files.push_back(name.value());
+ }
+ }
+ }
+ return font_files;
+}
+
+std::vector<std::string> SplitFontFilesList(
+ const std::vector<std::string> font_files,
+ bool return_second_half) {
+ CHECK_GT(font_files.size(), 2u);
+ auto start_copy = font_files.begin();
+ auto end_copy = font_files.begin() + (font_files.size() / 2);
+ if (return_second_half) {
+ start_copy = end_copy;
+ end_copy = font_files.end();
+ }
+ return std::vector<std::string>(start_copy, end_copy);
+}
+
+enum class TruncateLength { TruncateToZero, TruncateHalf };
+
+void TruncateFile(const base::FilePath& file_path,
+ TruncateLength truncate_length) {
+ base::File file_to_truncate(
+ file_path, base::File::FLAG_OPEN | base::File::Flags::FLAG_WRITE);
+ size_t truncate_to = truncate_length == TruncateLength::TruncateHalf
+ ? file_to_truncate.GetLength() / 2
+ : 0;
+ file_to_truncate.SetLength(truncate_to);
+}
+
+} // namespace
+
+namespace content {
+
+class FontUniqueNameLookupTest : public ::testing::Test {
+ protected:
+ void SetUp() override {
+ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+ font_unique_name_lookup_ =
+ std::make_unique<FontUniqueNameLookup>(temp_dir_.GetPath());
+ }
+
+ base::ScopedTempDir temp_dir_;
+ std::unique_ptr<FontUniqueNameLookup> font_unique_name_lookup_;
+};
+
+TEST_F(FontUniqueNameLookupTest, TestBuildLookup) {
+ ASSERT_TRUE(font_unique_name_lookup_->UpdateTable());
+ base::ReadOnlySharedMemoryMapping mapping =
+ font_unique_name_lookup_->GetUniqueNameTableAsSharedMemoryRegion().Map();
+ blink::FontTableMatcher matcher(mapping);
+ ASSERT_GT(matcher.AvailableFonts(), 0u);
+ ASSERT_TRUE(font_unique_name_lookup_->PersistToFile());
+ ASSERT_TRUE(font_unique_name_lookup_->LoadFromFile());
+ blink::FontTableMatcher matcher_after_load(
+ font_unique_name_lookup_->GetUniqueNameTableAsSharedMemoryRegion().Map());
+ ASSERT_GT(matcher_after_load.AvailableFonts(), 0u);
+}
+
+TEST_F(FontUniqueNameLookupTest, TestHandleFailedRead) {
+ base::DeleteFile(font_unique_name_lookup_->TableCacheFilePathForTesting(),
+ false);
+ ASSERT_FALSE(font_unique_name_lookup_->LoadFromFile());
+ ASSERT_FALSE(font_unique_name_lookup_->IsValid());
+ ASSERT_TRUE(font_unique_name_lookup_->UpdateTable());
+ ASSERT_TRUE(font_unique_name_lookup_->IsValid());
+ base::ReadOnlySharedMemoryMapping mapping =
+ font_unique_name_lookup_->GetUniqueNameTableAsSharedMemoryRegion().Map();
+ blink::FontTableMatcher matcher(mapping);
+ ASSERT_GT(matcher.AvailableFonts(), 0u);
+ ASSERT_TRUE(font_unique_name_lookup_->PersistToFile());
+ ASSERT_TRUE(font_unique_name_lookup_->LoadFromFile());
+ ASSERT_TRUE(font_unique_name_lookup_->IsValid());
+ TruncateFile(font_unique_name_lookup_->TableCacheFilePathForTesting(),
+ TruncateLength::TruncateHalf);
+ ASSERT_FALSE(font_unique_name_lookup_->LoadFromFile());
+ ASSERT_FALSE(font_unique_name_lookup_->IsValid());
+ TruncateFile(font_unique_name_lookup_->TableCacheFilePathForTesting(),
+ TruncateLength::TruncateToZero);
+ ASSERT_FALSE(font_unique_name_lookup_->LoadFromFile());
+ ASSERT_FALSE(font_unique_name_lookup_->IsValid());
+}
+
+TEST_F(FontUniqueNameLookupTest, TestMatchPostScriptName) {
+ ASSERT_TRUE(font_unique_name_lookup_->UpdateTable());
+ blink::FontTableMatcher matcher(
+ font_unique_name_lookup_->GetUniqueNameTableAsSharedMemoryRegion().Map());
+ ASSERT_GT(matcher.AvailableFonts(), 0u);
+ auto match_result = matcher.MatchName(kRobotoCondensedBoldItalicNames[1]);
+ ASSERT_TRUE(match_result);
+ ASSERT_TRUE(EndsWith(match_result->font_path,
+ kRobotoCondensedBoldItalicNames[2],
+ base::CompareCase::SENSITIVE));
+ base::File found_file(base::FilePath(match_result->font_path),
+ base::File::FLAG_OPEN | base::File::FLAG_READ);
+ ASSERT_TRUE(found_file.IsValid());
+ ASSERT_EQ(match_result->ttc_index, 0u);
+}
+
+TEST_F(FontUniqueNameLookupTest, TestMatchPostScriptNameTtc) {
+ if (base::android::BuildInfo::GetInstance()->sdk_int() <
+ base::android::SdkVersion::SDK_VERSION_NOUGAT) {
+ // Pre-Nougat Android does not contain any .ttc files as system fonts.
+ return;
+ }
+ ASSERT_TRUE(font_unique_name_lookup_->UpdateTable());
+ blink::FontTableMatcher matcher(
+ font_unique_name_lookup_->GetUniqueNameTableAsSharedMemoryRegion().Map());
+ std::vector<std::string> ttc_postscript_names = {
+ "NotoSansCJKjp-Regular", "NotoSansCJKkr-Regular",
+ "NotoSansCJKsc-Regular", "NotoSansCJKtc-Regular",
+ "NotoSansMonoCJKjp-Regular", "NotoSansMonoCJKkr-Regular",
+ "NotoSansMonoCJKsc-Regular", "NotoSansMonoCJKtc-Regular",
+ };
+ for (size_t i = 0; i < ttc_postscript_names.size(); ++i) {
+ auto match_result = matcher.MatchName(ttc_postscript_names[i]);
+ ASSERT_TRUE(match_result);
+ ASSERT_TRUE(EndsWith(match_result->font_path, "NotoSansCJK-Regular.ttc",
+ base::CompareCase::SENSITIVE));
+ base::File found_file(base::FilePath(match_result->font_path),
+ base::File::FLAG_OPEN | base::File::FLAG_READ);
+ ASSERT_TRUE(found_file.IsValid());
+ ASSERT_EQ(match_result->ttc_index, i);
+ }
+}
+
+TEST_F(FontUniqueNameLookupTest, TestMatchFullFontName) {
+ ASSERT_TRUE(font_unique_name_lookup_->UpdateTable());
+ blink::FontTableMatcher matcher(
+ font_unique_name_lookup_->GetUniqueNameTableAsSharedMemoryRegion().Map());
+ auto match_result = matcher.MatchName(kRobotoCondensedBoldItalicNames[0]);
+ ASSERT_TRUE(match_result);
+ ASSERT_TRUE(EndsWith(match_result->font_path,
+ kRobotoCondensedBoldItalicNames[2],
+ base::CompareCase::SENSITIVE));
+ base::File found_file(base::FilePath(match_result->font_path),
+ base::File::FLAG_OPEN | base::File::Flags::FLAG_READ);
+ ASSERT_TRUE(found_file.IsValid());
+ ASSERT_EQ(match_result->ttc_index, 0u);
+}
+
+namespace {
+size_t GetNumTables(base::File& font_file) {
+ font_file.Seek(base::File::FROM_BEGIN, 5);
+ uint8_t num_tables_bytes[2] = {};
+ font_file.ReadAtCurrentPos(reinterpret_cast<char*>(num_tables_bytes),
+ base::size(num_tables_bytes));
+ uint16_t num_tables =
+ static_cast<uint16_t>(num_tables_bytes[0] + (num_tables_bytes[1] << 8));
+ return num_tables;
+};
+
+const size_t kOffsetTableRecords = 13;
+const size_t kSizeOneTableRecord = 16;
+
+} // namespace
+
+// Creates a temp directory and copies Android font files to this
+// directory. Provides two methods to inject faults into the font files 1)
+// ZeroOutTableRecords writes a sequence of 0 to where the font table offset
+// should be stored in the font file. 2) ZeroAfterTableIndex writes 0 from after
+// the table records until the end of the file.
+class FontFileCorruptor {
+ public:
+ FontFileCorruptor() {
+ CHECK(temp_dir_.CreateUniqueTempDir());
+ CopyPlatformFilesToTempDir();
+ }
+
+ // Overwrite the list of table records with 0.
+ void ZeroOutTableRecords() {
+ ForEachCopiedFontFile([](base::File& font_file) {
+ // Read number of font tables, then zero out the table record structure.
+ // https://docs.microsoft.com/en-us/typography/opentype/spec/font-file
+ size_t num_tables = GetNumTables(font_file);
+ CHECK_GT(num_tables, 0u);
+ char garbage[kSizeOneTableRecord] = {0};
+ for (size_t i = 0; i < num_tables; ++i) {
+ CHECK_EQ(static_cast<int>(kSizeOneTableRecord),
+ font_file.Write(kOffsetTableRecords + i * kSizeOneTableRecord,
+ garbage, base::size(garbage)));
+ }
+ });
+ }
+
+ // Overwrite the data in the font file with zeroes from after the table
+ // records until the end of the file.
+ void ZeroAfterTableIndex() {
+ ForEachCopiedFontFile([](base::File& font_file) {
+ size_t num_tables = GetNumTables(font_file);
+ CHECK_GT(num_tables, 0u);
+ const size_t offset_after_table_records =
+ kOffsetTableRecords + num_tables * kSizeOneTableRecord;
+ std::vector<char> zeroes;
+ zeroes.resize(font_file.GetLength() - offset_after_table_records);
+ std::fill(zeroes.begin(), zeroes.end(), 0);
+ CHECK_EQ(static_cast<int>(zeroes.size()),
+ font_file.Write(offset_after_table_records, zeroes.data(),
+ zeroes.size()));
+ });
+ }
+
+ // Get the list of filenames copied to the temporary directory.
+ std::vector<std::string> GetFontFilesList() { return copied_files_; }
+
+ private:
+ void ForEachCopiedFontFile(std::function<void(base::File&)> manipulate_file) {
+ for (const auto& filename : copied_files_) {
+ base::File font_file(base::FilePath(filename),
+ base::File::FLAG_OPEN | base::File::FLAG_READ |
+ base::File::FLAG_WRITE);
+ manipulate_file(font_file);
+ }
+ }
+
+ void CopyPlatformFilesToTempDir() {
+ std::vector<std::string> platform_files = AndroidFontFilesList();
+ for (auto& font_file : platform_files) {
+ base::FilePath source_path(font_file);
+ base::FilePath destination_path(temp_dir_.GetPath());
+ destination_path = destination_path.Append(source_path.BaseName());
+ if (base::CopyFile(source_path, destination_path))
+ copied_files_.push_back(destination_path.value());
+ }
+ }
+ base::ScopedTempDir temp_dir_;
+ std::vector<std::string> copied_files_;
+};
+
+class FaultInjectingFontUniqueNameLookupTest : public ::testing::Test {
+ protected:
+ void SetUp() override {
+ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+ font_unique_name_lookup_ =
+ std::make_unique<FontUniqueNameLookup>(temp_dir_.GetPath());
+ font_unique_name_lookup_->SetFontFilePathsForTesting(
+ font_file_corruptor_.GetFontFilesList());
+ }
+
+ base::ScopedTempDir temp_dir_;
+ FontFileCorruptor font_file_corruptor_;
+ std::unique_ptr<FontUniqueNameLookup> font_unique_name_lookup_;
+};
+
+TEST_F(FaultInjectingFontUniqueNameLookupTest, TestZeroedTableContents) {
+ font_file_corruptor_.ZeroAfterTableIndex();
+ ASSERT_TRUE(font_unique_name_lookup_->UpdateTable());
+ blink::FontTableMatcher matcher_after_update(
+ font_unique_name_lookup_->GetUniqueNameTableAsSharedMemoryRegion().Map());
+ ASSERT_EQ(matcher_after_update.AvailableFonts(), 0u);
+}
+
+TEST_F(FaultInjectingFontUniqueNameLookupTest, TestZeroedTableIndex) {
+ font_file_corruptor_.ZeroOutTableRecords();
+ ASSERT_TRUE(font_unique_name_lookup_->UpdateTable());
+ blink::FontTableMatcher matcher_after_update(
+ font_unique_name_lookup_->GetUniqueNameTableAsSharedMemoryRegion().Map());
+ ASSERT_EQ(matcher_after_update.AvailableFonts(), 0u);
+}
+
+class FontUniqueNameLookupUpdateTest : public ::testing::Test {
+ protected:
+ void SetUp() override {
+ ASSERT_TRUE(lookup_table_storage_dir.CreateUniqueTempDir());
+ font_unique_name_lookup_ = std::make_unique<FontUniqueNameLookup>(
+ lookup_table_storage_dir.GetPath());
+ font_unique_name_lookup_->SetFontFilePathsForTesting(
+ SplitFontFilesList(AndroidFontFilesList(), false));
+ font_unique_name_lookup_->SetAndroidBuildFingerprintForTesting("A");
+ }
+
+ base::ScopedTempDir lookup_table_storage_dir;
+ std::unique_ptr<FontUniqueNameLookup> font_unique_name_lookup_;
+};
+
+TEST_F(FontUniqueNameLookupUpdateTest, CompareSets) {
+ ASSERT_TRUE(font_unique_name_lookup_->UpdateTable());
+ blink::FontTableMatcher matcher_initial(
+ font_unique_name_lookup_->GetUniqueNameTableAsSharedMemoryRegion().Map());
+ ASSERT_GT(matcher_initial.AvailableFonts(), 0u);
+ font_unique_name_lookup_->SetFontFilePathsForTesting(
+ SplitFontFilesList(AndroidFontFilesList(), true));
+ // Set the Android build fingerprint to something different from what it's set
+ // to in the test's SetUp method to trigger re-indexing.
+ font_unique_name_lookup_->SetAndroidBuildFingerprintForTesting("B");
+ font_unique_name_lookup_->UpdateTableIfNeeded();
+ blink::FontTableMatcher matcher_second_half(
+ font_unique_name_lookup_->GetUniqueNameTableAsSharedMemoryRegion().Map());
+ ASSERT_GT(matcher_initial.AvailableFonts(), 0u);
+ ASSERT_TRUE(matcher_initial.FontListIsDisjointFrom(matcher_second_half));
+}
+
+} // namespace content
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 146a166e410..4bd20a223cd 100644
--- a/chromium/content/browser/frame_host/cross_process_frame_connector.cc
+++ b/chromium/content/browser/frame_host/cross_process_frame_connector.cc
@@ -6,6 +6,7 @@
#include "base/bind.h"
#include "base/metrics/histogram_macros.h"
+#include "components/viz/common/features.h"
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
#include "components/viz/service/surfaces/surface.h"
#include "components/viz/service/surfaces/surface_hittest.h"
@@ -118,7 +119,7 @@ void CrossProcessFrameConnector::SetView(RenderWidgetHostViewChildFrame* view) {
if (is_hidden_)
OnVisibilityChanged(false);
FrameMsg_ViewChanged_Params params;
- if (features::IsAshInBrowserProcess())
+ if (!features::IsUsingWindowService())
params.frame_sink_id = view_->GetFrameSinkId();
frame_proxy_in_parent_renderer_->Send(new FrameMsg_ViewChanged(
frame_proxy_in_parent_renderer_->GetRoutingID(), params));
@@ -147,8 +148,10 @@ void CrossProcessFrameConnector::RenderProcessGone() {
void CrossProcessFrameConnector::FirstSurfaceActivation(
const viz::SurfaceInfo& surface_info) {
- frame_proxy_in_parent_renderer_->Send(new FrameMsg_FirstSurfaceActivation(
- frame_proxy_in_parent_renderer_->GetRoutingID(), surface_info));
+ if (!features::IsSurfaceSynchronizationEnabled()) {
+ frame_proxy_in_parent_renderer_->Send(new FrameMsg_FirstSurfaceActivation(
+ frame_proxy_in_parent_renderer_->GetRoutingID(), surface_info));
+ }
}
void CrossProcessFrameConnector::SendIntrinsicSizingInfoToParent(
@@ -225,17 +228,6 @@ bool CrossProcessFrameConnector::TransformPointToCoordSpaceForView(
*transformed_point, target_view, transformed_point, source);
}
-void CrossProcessFrameConnector::ForwardProcessAckedTouchEvent(
- const TouchEventWithLatencyInfo& touch,
- InputEventAckState ack_result) {
- auto* main_view = GetRootRenderWidgetHostView();
- // Note that the event's coordinates are in |view_|'s coordinate space, but
- // since |ProcessAckedTouchEvent| doesn't use the coordinates, we don't
- // bother to transform them back to the root coordinate space.
- if (main_view)
- main_view->ProcessAckedTouchEvent(touch, ack_result);
-}
-
void CrossProcessFrameConnector::ForwardAckedTouchpadPinchGestureEvent(
const blink::WebGestureEvent& event,
InputEventAckState ack_result) {
@@ -255,7 +247,8 @@ void CrossProcessFrameConnector::BubbleScrollEvent(
DCHECK(event.GetType() == blink::WebInputEvent::kGestureScrollBegin ||
event.GetType() == blink::WebInputEvent::kGestureScrollUpdate ||
event.GetType() == blink::WebInputEvent::kGestureScrollEnd ||
- event.GetType() == blink::WebInputEvent::kGestureFlingStart);
+ event.GetType() == blink::WebInputEvent::kGestureFlingStart ||
+ event.GetType() == blink::WebInputEvent::kGestureFlingCancel);
auto* parent_view = GetParentRenderWidgetHostView();
if (!parent_view)
@@ -278,7 +271,9 @@ void CrossProcessFrameConnector::BubbleScrollEvent(
if (event.GetType() == blink::WebInputEvent::kGestureScrollBegin) {
event_router->BubbleScrollEvent(parent_view, resent_gesture_event, view_);
is_scroll_bubbling_ = true;
- } else if (is_scroll_bubbling_) {
+ } else if (is_scroll_bubbling_ ||
+ event.GetType() == blink::WebInputEvent::kGestureFlingCancel) {
+ // For GFC events the router decides whether to bubble them or not.
event_router->BubbleScrollEvent(parent_view, resent_gesture_event, view_);
}
if (event.GetType() == blink::WebInputEvent::kGestureScrollEnd ||
@@ -336,12 +331,14 @@ void CrossProcessFrameConnector::OnSynchronizeVisualProperties(
void CrossProcessFrameConnector::OnUpdateViewportIntersection(
const gfx::Rect& viewport_intersection,
- const gfx::Rect& compositor_visible_rect) {
+ const gfx::Rect& compositor_visible_rect,
+ bool occluded_or_obscured) {
viewport_intersection_rect_ = viewport_intersection;
compositor_visible_rect_ = compositor_visible_rect;
+ occluded_or_obscured_ = occluded_or_obscured;
if (view_)
- view_->UpdateViewportIntersection(viewport_intersection,
- compositor_visible_rect);
+ view_->UpdateViewportIntersection(
+ viewport_intersection, compositor_visible_rect, occluded_or_obscured);
if (IsVisible()) {
// MaybeLogCrash will check 1) if there was a crash or not and 2) if the
@@ -461,7 +458,7 @@ bool CrossProcessFrameConnector::IsHidden() const {
#if defined(USE_AURA)
void CrossProcessFrameConnector::EmbedRendererWindowTreeClientInParent(
- ui::mojom::WindowTreeClientPtr window_tree_client) {
+ ws::mojom::WindowTreeClientPtr window_tree_client) {
RenderWidgetHostViewBase* root = GetRootRenderWidgetHostView();
RenderWidgetHostViewBase* parent = GetParentRenderWidgetHostView();
if (!parent || !root)
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 b0dc031915c..203b8a42831 100644
--- a/chromium/content/browser/frame_host/cross_process_frame_connector.h
+++ b/chromium/content/browser/frame_host/cross_process_frame_connector.h
@@ -96,8 +96,6 @@ class CONTENT_EXPORT CrossProcessFrameConnector
const viz::SurfaceId& local_surface_id,
gfx::PointF* transformed_point,
viz::EventSource source = viz::EventSource::ANY) override;
- void ForwardProcessAckedTouchEvent(const TouchEventWithLatencyInfo& touch,
- InputEventAckState ack_result) override;
void ForwardAckedTouchpadPinchGestureEvent(
const blink::WebGestureEvent& event,
InputEventAckState ack_result) override;
@@ -116,7 +114,7 @@ class CONTENT_EXPORT CrossProcessFrameConnector
bool IsSubtreeThrottled() const override;
#if defined(USE_AURA)
void EmbedRendererWindowTreeClientInParent(
- ui::mojom::WindowTreeClientPtr window_tree_client) override;
+ ws::mojom::WindowTreeClientPtr window_tree_client) override;
#endif
void DidUpdateVisualProperties(
const cc::RenderFrameMetadata& metadata) override;
@@ -164,7 +162,8 @@ class CONTENT_EXPORT CrossProcessFrameConnector
const viz::SurfaceId& surface_id,
const FrameVisualProperties& visual_properties);
void OnUpdateViewportIntersection(const gfx::Rect& viewport_intersection,
- const gfx::Rect& compositor_visible_rect);
+ const gfx::Rect& compositor_visible_rect,
+ bool occluded_or_obscured);
void OnVisibilityChanged(bool visible);
void OnSetIsInert(bool);
void OnSetInheritedEffectiveTouchAction(cc::TouchAction);
diff --git a/chromium/content/browser/frame_host/debug_urls.cc b/chromium/content/browser/frame_host/debug_urls.cc
index f66e16a2ebc..78868e2664b 100644
--- a/chromium/content/browser/frame_host/debug_urls.cc
+++ b/chromium/content/browser/frame_host/debug_urls.cc
@@ -26,6 +26,10 @@
#include "ppapi/proxy/ppapi_messages.h" // nogncheck
#endif
+#if defined(OS_WIN)
+#include "base/debug/invalid_access_win.h"
+#endif
+
namespace content {
class ScopedAllowWaitForDebugURL {
@@ -142,6 +146,14 @@ bool HandleDebugURL(const GURL& url, ui::PageTransition transition) {
return true;
}
+#if defined(OS_WIN)
+ if (url == kChromeUIBrowserHeapCorruptionURL) {
+ // Induce an intentional heap corruption in the browser process.
+ base::debug::win::TerminateWithHeapCorruption();
+ return true;
+ }
+#endif
+
if (url == kChromeUIBrowserUIHang) {
HangCurrentThread();
return true;
diff --git a/chromium/content/browser/frame_host/frame_tree_browsertest.cc b/chromium/content/browser/frame_host/frame_tree_browsertest.cc
index 13d191c9ebd..e0be5c94511 100644
--- a/chromium/content/browser/frame_host/frame_tree_browsertest.cc
+++ b/chromium/content/browser/frame_host/frame_tree_browsertest.cc
@@ -31,11 +31,8 @@ namespace content {
namespace {
-std::string GetOriginFromRenderer(FrameTreeNode* node) {
- std::string origin;
- EXPECT_TRUE(ExecuteScriptAndExtractString(
- node, "window.domAutomationController.send(document.origin);", &origin));
- return origin;
+EvalJsResult GetOriginFromRenderer(FrameTreeNode* node) {
+ return EvalJs(node, "document.origin");
}
} // namespace
@@ -314,22 +311,24 @@ IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, NavigateGrandchildToBlob) {
// target of the navigation.
FrameTreeNode* target = root->child_at(0)->child_at(0);
- std::string blob_url_string;
RenderFrameDeletedObserver deleted_observer(target->current_frame_host());
- EXPECT_TRUE(ExecuteScriptAndExtractString(
- root,
- "function receiveMessage(event) {"
+ std::string html =
+ "<html><body><div>This is blob content.</div>"
+ "<script>"
+ "window.parent.parent.postMessage('HI', document.origin);"
+ "</script></body></html>";
+ std::string script = JsReplace(
+ "new Promise((resolve) => {"
+ " window.addEventListener('message', resolve, false);"
+ " var blob = new Blob([$1], {type: 'text/html'});"
+ " var blob_url = URL.createObjectURL(blob);"
+ " frames[0][0].location.href = blob_url;"
+ "}).then((event) => {"
" document.body.appendChild(document.createTextNode(event.data));"
- " domAutomationController.send(event.source.location.href);"
- "}"
- "window.addEventListener('message', receiveMessage, false);"
- "var blob = new Blob(["
- " '<html><body><div>This is blob content.</div><script>"
- " window.parent.parent.postMessage(\"HI\", document.origin);"
- " </script></body></html>'], {type: 'text/html'});"
- "var blob_url = URL.createObjectURL(blob);"
- "frames[0][0].location.href = blob_url;",
- &blob_url_string));
+ " return event.source.location.href;"
+ "});",
+ html);
+ std::string blob_url_string = EvalJs(root, script).ExtractString();
// Wait for the RenderFrame to go away, if this will be cross-process.
if (AreAllSitesIsolatedForTesting())
deleted_observer.WaitUntilDeleted();
@@ -338,13 +337,8 @@ IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, NavigateGrandchildToBlob) {
EXPECT_FALSE(target->current_origin().unique());
EXPECT_EQ("a.com", target->current_origin().host());
EXPECT_EQ(url::kHttpScheme, target->current_origin().scheme());
-
- std::string document_body;
- EXPECT_TRUE(ExecuteScriptAndExtractString(
- target,
- "domAutomationController.send(document.body.children[0].innerHTML);",
- &document_body));
- EXPECT_EQ("This is blob content.", document_body);
+ EXPECT_EQ("This is blob content.",
+ EvalJs(target, "document.body.children[0].innerHTML"));
EXPECT_EQ(reference_tree, FrameTreeVisualizer().DepictFrameTree(root));
}
@@ -362,38 +356,34 @@ IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, NavigateChildToAboutBlank) {
FrameTreeNode* initiator = target->parent();
// Give the target a name.
- EXPECT_TRUE(ExecuteScript(target, "window.name = 'target';"));
+ EXPECT_TRUE(ExecJs(target, "window.name = 'target';"));
// Use window.open(about:blank), then poll the document for access.
- std::string about_blank_origin;
- EXPECT_TRUE(ExecuteScriptAndExtractString(
+ EvalJsResult about_blank_origin = EvalJs(
initiator,
- "var didNavigate = false;"
- "var intervalID = setInterval(function() {"
- " if (!didNavigate) {"
- " didNavigate = true;"
- " window.open('about:blank', 'target');"
- " }"
- " // Poll the document until it doesn't throw a SecurityError.\n"
- " try {"
- " frames[0].document.write('Hi from ' + document.domain);"
- " } catch (e) { return; }"
- " clearInterval(intervalID);"
- " domAutomationController.send(frames[0].document.origin);"
- "}, 16);",
- &about_blank_origin));
+ "new Promise(resolve => {"
+ " var didNavigate = false;"
+ " var intervalID = setInterval(function() {"
+ " if (!didNavigate) {"
+ " didNavigate = true;"
+ " window.open('about:blank', 'target');"
+ " }"
+ " // Poll the document until it doesn't throw a SecurityError.\n"
+ " try {"
+ " frames[0].document.write('Hi from ' + document.domain);"
+ " } catch (e) { return; }"
+ " clearInterval(intervalID);"
+ " resolve(frames[0].document.origin);"
+ " }, 16);"
+ "});");
+ EXPECT_EQ(target->current_origin(), about_blank_origin);
EXPECT_EQ(GURL(url::kAboutBlankURL), target->current_url());
EXPECT_EQ(url::kAboutScheme, target->current_url().scheme());
EXPECT_FALSE(target->current_origin().unique());
EXPECT_EQ("b.com", target->current_origin().host());
EXPECT_EQ(url::kHttpScheme, target->current_origin().scheme());
- EXPECT_EQ(target->current_origin().Serialize(), about_blank_origin);
- std::string document_body;
- EXPECT_TRUE(ExecuteScriptAndExtractString(
- target, "domAutomationController.send(document.body.innerHTML);",
- &document_body));
- EXPECT_EQ("Hi from b.com", document_body);
+ EXPECT_EQ("Hi from b.com", EvalJs(target, "document.body.innerHTML"));
}
// Nested iframes, three origins: A(B(C)). Frame A navigates C to about:blank
@@ -414,36 +404,34 @@ IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest,
FrameTreeNode* initiator = target->parent()->parent();
// Give the target a name.
- EXPECT_TRUE(ExecuteScript(target, "window.name = 'target';"));
+ EXPECT_TRUE(ExecJs(target, "window.name = 'target';"));
// Use window.open(about:blank), then poll the document for access.
- std::string about_blank_origin;
- EXPECT_TRUE(ExecuteScriptAndExtractString(
- initiator,
- "var didNavigate = false;"
- "var intervalID = setInterval(function() {"
- " if (!didNavigate) {"
- " didNavigate = true;"
- " window.open('about:blank', 'target');"
- " }"
- " // May raise a SecurityError, that's expected.\n"
- " frames[0][0].document.write('Hi from ' + document.domain);"
- " clearInterval(intervalID);"
- " domAutomationController.send(frames[0][0].document.origin);"
- "}, 16);",
- &about_blank_origin));
+ EvalJsResult about_blank_origin =
+ EvalJs(initiator,
+ "new Promise((resolve) => {"
+ " var didNavigate = false;"
+ " var intervalID = setInterval(() => {"
+ " if (!didNavigate) {"
+ " didNavigate = true;"
+ " window.open('about:blank', 'target');"
+ " }"
+ " // May raise a SecurityError, that's expected.\n"
+ " try {"
+ " frames[0][0].document.write('Hi from ' + document.domain);"
+ " } catch (e) { return; }"
+ " clearInterval(intervalID);"
+ " resolve(frames[0][0].document.origin);"
+ " }, 16);"
+ "});");
+ EXPECT_EQ(target->current_origin(), about_blank_origin);
EXPECT_EQ(GURL(url::kAboutBlankURL), target->current_url());
EXPECT_EQ(url::kAboutScheme, target->current_url().scheme());
EXPECT_FALSE(target->current_origin().unique());
EXPECT_EQ("a.com", target->current_origin().host());
EXPECT_EQ(url::kHttpScheme, target->current_origin().scheme());
- EXPECT_EQ(target->current_origin().Serialize(), about_blank_origin);
- std::string document_body;
- EXPECT_TRUE(ExecuteScriptAndExtractString(
- target, "domAutomationController.send(document.body.innerHTML);",
- &document_body));
- EXPECT_EQ("Hi from a.com", document_body);
+ EXPECT_EQ("Hi from a.com", EvalJs(target, "document.body.innerHTML"));
}
// Ensures that iframe with srcdoc is always put in the same origin as its
@@ -458,9 +446,7 @@ IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, ChildFrameWithSrcdoc) {
EXPECT_EQ(1U, root->child_count());
FrameTreeNode* child = root->child_at(0);
- std::string frame_origin;
- EXPECT_TRUE(ExecuteScriptAndExtractString(
- child, "domAutomationController.send(document.origin);", &frame_origin));
+ std::string frame_origin = EvalJs(child, "document.origin;").ExtractString();
EXPECT_TRUE(
child->current_frame_host()->GetLastCommittedOrigin().IsSameOriginWith(
url::Origin::Create(GURL(frame_origin))));
@@ -475,18 +461,16 @@ IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, ChildFrameWithSrcdoc) {
"f.srcdoc = 'some content';"
"document.body.appendChild(f)");
TestNavigationObserver observer(shell()->web_contents());
- EXPECT_TRUE(ExecuteScript(root, script));
+ EXPECT_TRUE(ExecJs(root, script));
EXPECT_EQ(2U, root->child_count());
observer.Wait();
EXPECT_EQ(GURL(kAboutSrcDocURL), root->child_at(1)->current_url());
- EXPECT_TRUE(ExecuteScriptAndExtractString(
- root->child_at(1), "domAutomationController.send(document.origin);",
- &frame_origin));
+ EvalJsResult frame_origin = EvalJs(root->child_at(1), "document.origin");
EXPECT_EQ(root->current_frame_host()->GetLastCommittedURL().GetOrigin(),
- GURL(frame_origin));
+ GURL(frame_origin.ExtractString()));
EXPECT_NE(child->current_frame_host()->GetLastCommittedURL().GetOrigin(),
- GURL(frame_origin));
+ GURL(frame_origin.ExtractString()));
}
// Set srcdoc on the existing cross-site frame. It should navigate the frame
@@ -495,15 +479,14 @@ IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, ChildFrameWithSrcdoc) {
std::string script("var f = document.getElementById('child-0');"
"f.srcdoc = 'some content';");
TestNavigationObserver observer(shell()->web_contents());
- EXPECT_TRUE(ExecuteScript(root, script));
+ EXPECT_TRUE(ExecJs(root, script));
observer.Wait();
EXPECT_EQ(GURL(kAboutSrcDocURL), child->current_url());
- EXPECT_TRUE(ExecuteScriptAndExtractString(
- child, "domAutomationController.send(document.origin);",
- &frame_origin));
- EXPECT_EQ(root->current_frame_host()->GetLastCommittedURL().GetOrigin(),
- GURL(frame_origin));
+ EXPECT_EQ(
+ url::Origin::Create(root->current_frame_host()->GetLastCommittedURL())
+ .Serialize(),
+ EvalJs(child, "document.origin"));
}
}
@@ -687,8 +670,8 @@ IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, SubframeOpenerSetForNewWindow) {
// Open a new window from a subframe.
ShellAddedObserver new_shell_observer;
GURL popup_url(embedded_test_server()->GetURL("foo.com", "/title1.html"));
- EXPECT_TRUE(ExecuteScript(root->child_at(0),
- "window.open('" + popup_url.spec() + "');"));
+ EXPECT_TRUE(
+ ExecJs(root->child_at(0), JsReplace("window.open($1);", popup_url)));
Shell* new_shell = new_shell_observer.GetShell();
WebContents* new_contents = new_shell->web_contents();
WaitForLoadStop(new_contents);
@@ -897,15 +880,15 @@ IN_PROC_BROWSER_TEST_F(IsolateIcelandFrameTreeBrowserTest,
// The navigation targets an invalid blob url; that's intentional to trigger
// an error response. The response should commit in a process dedicated to
// http://b.is.
- std::string result;
- EXPECT_TRUE(ExecuteScriptAndExtractString(
- root,
- "var iframe_element = document.getElementsByTagName('iframe')[0];"
- "iframe_element.onload = () => {"
- " domAutomationController.send('done');"
- "};"
- "iframe_element.src = 'blob:http://b.is:2932/';",
- &result));
+ EXPECT_EQ(
+ "done",
+ EvalJs(
+ root,
+ "new Promise((resolve) => {"
+ " var iframe_element = document.getElementsByTagName('iframe')[0];"
+ " iframe_element.onload = () => resolve('done');"
+ " iframe_element.src = 'blob:http://b.is:2932/';"
+ "});"));
WaitForLoadStop(contents);
// Make sure we did a process transfer back to "b.is".
diff --git a/chromium/content/browser/frame_host/frame_tree_node.h b/chromium/content/browser/frame_host/frame_tree_node.h
index 4e589ac428f..cee8a19d6dd 100644
--- a/chromium/content/browser/frame_host/frame_tree_node.h
+++ b/chromium/content/browser/frame_host/frame_tree_node.h
@@ -510,7 +510,7 @@ class CONTENT_EXPORT FrameTreeNode {
std::unique_ptr<NavigationRequest> navigation_request_;
// List of objects observing this FrameTreeNode.
- base::ObserverList<Observer> observers_;
+ base::ObserverList<Observer>::Unchecked observers_;
base::TimeTicks last_focus_time_;
diff --git a/chromium/content/browser/frame_host/interstitial_page_impl.cc b/chromium/content/browser/frame_host/interstitial_page_impl.cc
index f839f62061b..6a26f13d246 100644
--- a/chromium/content/browser/frame_host/interstitial_page_impl.cc
+++ b/chromium/content/browser/frame_host/interstitial_page_impl.cc
@@ -528,6 +528,7 @@ void InterstitialPageImpl::DidNavigate(
if (!controller_->delegate()->IsHidden())
render_view_host_->GetWidget()->GetView()->Show();
controller_->delegate()->AttachInterstitialPage(this);
+ render_view_host_->GetWidget()->GetView()->OnInterstitialPageAttached();
RenderWidgetHostView* rwh_view =
controller_->delegate()->GetRenderViewHost()->GetWidget()->GetView();
@@ -580,6 +581,20 @@ KeyboardEventProcessingResult InterstitialPageImpl::PreHandleKeyboardEvent(
return render_widget_host_delegate_->PreHandleKeyboardEvent(event);
}
+bool InterstitialPageImpl::PreHandleMouseEvent(
+ const blink::WebMouseEvent& event) {
+ if (!enabled())
+ return false;
+
+ if (event.GetType() == blink::WebInputEvent::Type::kMouseUp &&
+ event.button == blink::WebPointerProperties::Button::kBack &&
+ controller_->CanGoBack()) {
+ controller_->GoBack();
+ return true;
+ }
+ return false;
+}
+
void InterstitialPageImpl::HandleKeyboardEvent(
const NativeWebKeyboardEvent& event) {
if (enabled())
@@ -750,6 +765,8 @@ RenderWidgetHostView* InterstitialPageImpl::GetView() {
}
RenderFrameHost* InterstitialPageImpl::GetMainFrame() const {
+ if (!render_view_host_)
+ return nullptr;
return render_view_host_->GetMainFrame();
}
@@ -1073,4 +1090,16 @@ InterstitialPageImpl::GetOrCreateRootBrowserAccessibilityManager() {
return web_contents_impl->GetOrCreateRootBrowserAccessibilityManager();
}
+void InterstitialPageImpl::AudioContextPlaybackStarted(RenderFrameHost* host,
+ int context_id) {
+ // Interstitial pages should not be playing any sound via WebAudio
+ NOTREACHED();
+}
+
+void InterstitialPageImpl::AudioContextPlaybackStopped(RenderFrameHost* host,
+ int context_id) {
+ // Interstitial pages should not be playing any sound via WebAudio.
+ NOTREACHED();
+}
+
} // namespace content
diff --git a/chromium/content/browser/frame_host/interstitial_page_impl.h b/chromium/content/browser/frame_host/interstitial_page_impl.h
index d23262f505e..bb4b5f7771d 100644
--- a/chromium/content/browser/frame_host/interstitial_page_impl.h
+++ b/chromium/content/browser/frame_host/interstitial_page_impl.h
@@ -138,6 +138,10 @@ class CONTENT_EXPORT InterstitialPageImpl : public InterstitialPage,
bool user_gesture) override;
void SetFocusedFrame(FrameTreeNode* node, SiteInstance* source) override;
Visibility GetVisibility() const override;
+ void AudioContextPlaybackStarted(RenderFrameHost* host,
+ int context_id) override;
+ void AudioContextPlaybackStopped(RenderFrameHost* host,
+ int context_id) override;
// RenderViewHostDelegate implementation:
RenderViewHostDelegateView* GetDelegateView() override;
@@ -170,6 +174,7 @@ class CONTENT_EXPORT InterstitialPageImpl : public InterstitialPage,
void RenderWidgetDeleted(RenderWidgetHostImpl* render_widget_host) override;
KeyboardEventProcessingResult PreHandleKeyboardEvent(
const NativeWebKeyboardEvent& event) override;
+ bool PreHandleMouseEvent(const blink::WebMouseEvent& event) override;
void HandleKeyboardEvent(const NativeWebKeyboardEvent& event) override;
TextInputManager* GetTextInputManager() override;
RenderWidgetHostInputEventRouter* GetInputEventRouter() override;
diff --git a/chromium/content/browser/frame_host/interstitial_page_impl_browsertest.cc b/chromium/content/browser/frame_host/interstitial_page_impl_browsertest.cc
index 37108eea53e..edf5170facb 100644
--- a/chromium/content/browser/frame_host/interstitial_page_impl_browsertest.cc
+++ b/chromium/content/browser/frame_host/interstitial_page_impl_browsertest.cc
@@ -199,6 +199,15 @@ class InterstitialPageImplTest : public ContentBrowserTest {
EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
}
+ void PerformBack() {
+ RenderFrameHostImpl* rfh =
+ static_cast<RenderFrameHostImpl*>(interstitial_->GetMainFrame());
+ rfh->GetRenderWidgetHost()->ForwardMouseEvent(blink::WebMouseEvent(
+ blink::WebInputEvent::Type::kMouseUp, blink::WebFloatPoint(),
+ blink::WebFloatPoint(), blink::WebPointerProperties::Button::kBack, 0,
+ 0, base::TimeTicks::Now()));
+ }
+
private:
std::unique_ptr<InterstitialPageImpl> interstitial_;
@@ -351,4 +360,19 @@ IN_PROC_BROWSER_TEST_F(InterstitialPageImplTest, UnderlyingSubframeCommit) {
TearDownInterstitialPage();
}
+IN_PROC_BROWSER_TEST_F(InterstitialPageImplTest, BackMouseButton) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ // Load something into the WebContents.
+ EXPECT_TRUE(NavigateToURL(
+ shell(), GURL(embedded_test_server()->GetURL("/title1.html"))));
+ SetUpInterstitialPage();
+
+ EXPECT_TRUE(shell()->web_contents()->ShowingInterstitialPage());
+ PerformBack();
+ EXPECT_FALSE(shell()->web_contents()->ShowingInterstitialPage());
+
+ TearDownInterstitialPage();
+}
+
} // namespace content
diff --git a/chromium/content/browser/frame_host/navigation_controller_android.cc b/chromium/content/browser/frame_host/navigation_controller_android.cc
index 7136ac7c8df..00e4c80e4f6 100644
--- a/chromium/content/browser/frame_host/navigation_controller_android.cc
+++ b/chromium/content/browser/frame_host/navigation_controller_android.cc
@@ -47,14 +47,16 @@ JNI_NavigationControllerImpl_CreateJavaNavigationEntry(
ConvertUTF8ToJavaString(env, entry->GetOriginalRequestURL().spec()));
ScopedJavaLocalRef<jstring> j_title(
ConvertUTF16ToJavaString(env, entry->GetTitle()));
+ ScopedJavaLocalRef<jstring> j_referrer_url(
+ ConvertUTF8ToJavaString(env, entry->GetReferrer().url.spec()));
ScopedJavaLocalRef<jobject> j_bitmap;
const content::FaviconStatus& status = entry->GetFavicon();
if (status.valid && status.image.ToSkBitmap()->computeByteSize() > 0)
j_bitmap = gfx::ConvertToJavaBitmap(status.image.ToSkBitmap());
return content::Java_NavigationControllerImpl_createNavigationEntry(
- env, index, j_url, j_virtual_url, j_original_url, j_title, j_bitmap,
- entry->GetTransitionType());
+ env, index, j_url, j_virtual_url, j_original_url, j_referrer_url, j_title,
+ j_bitmap, entry->GetTransitionType());
}
static void JNI_NavigationControllerImpl_AddNavigationEntryToHistory(
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 b1ed11f1561..06e52b458db 100644
--- a/chromium/content/browser/frame_host/navigation_controller_impl_browsertest.cc
+++ b/chromium/content/browser/frame_host/navigation_controller_impl_browsertest.cc
@@ -42,6 +42,7 @@
#include "content/public/browser/resource_dispatcher_host.h"
#include "content/public/browser/resource_dispatcher_host_delegate.h"
#include "content/public/browser/resource_throttle.h"
+#include "content/public/browser/site_isolation_policy.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_contents_observer.h"
@@ -55,8 +56,10 @@
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/download_test_observer.h"
+#include "content/public/test/navigation_handle_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/shell/browser/shell_download_manager_delegate.h"
#include "content/shell/common/shell_switches.h"
@@ -259,7 +262,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
"var xhr = new XMLHttpRequest();\n"
"xhr.open('GET', url);\n"
"xhr.send();\n";
- EXPECT_TRUE(ExecuteScript(shell()->web_contents(), script));
+ EXPECT_TRUE(ExecJs(shell()->web_contents(), script));
// The renderer may not be killed immediately (if it is indeed killed), so
// reload, block and verify its liveness.
ReloadBlockUntilNavigationsComplete(shell(), 1);
@@ -325,10 +328,9 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// Navigate with Javascript.
{
GURL navigate_url = embedded_test_server()->base_url();
- std::string script = "document.location = '" +
- navigate_url.spec() + "';";
+ std::string script = JsReplace("document.location = $1", navigate_url);
TestNavigationObserver same_tab_observer(shell()->web_contents(), 1);
- EXPECT_TRUE(ExecuteScript(shell(), script));
+ EXPECT_TRUE(ExecJs(shell(), script));
same_tab_observer.Wait();
EXPECT_EQ(2, controller.GetEntryCount());
NavigationEntryImpl* entry = controller.GetLastCommittedEntry();
@@ -377,7 +379,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
EXPECT_EQ(data_url, entry->GetURL());
// Passes if renderer is still alive.
- EXPECT_TRUE(ExecuteScript(shell(), "console.log('Success');"));
+ EXPECT_TRUE(ExecJs(shell(), "console.log('Success');"));
}
IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, UniqueIDs) {
@@ -392,7 +394,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, UniqueIDs) {
// Use JavaScript to click the link and load the iframe.
std::string script = "document.getElementById('link').click()";
- EXPECT_TRUE(ExecuteScript(shell(), script));
+ EXPECT_TRUE(ExecJs(shell(), script));
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
ASSERT_EQ(2, controller.GetEntryCount());
@@ -494,21 +496,13 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
namespace {
-int RendererHistoryLength(Shell* shell) {
- int value = 0;
- EXPECT_TRUE(ExecuteScriptAndExtractInt(
- shell, "domAutomationController.send(history.length)", &value));
- return value;
-}
-
// Does a renderer-initiated location.replace navigation to |url|, replacing the
// current entry.
bool RendererLocationReplace(Shell* shell, const GURL& url) {
WebContents* web_contents = shell->web_contents();
WaitForLoadStop(web_contents);
TestNavigationObserver same_tab_observer(web_contents, 1);
- EXPECT_TRUE(
- ExecuteScript(shell, "window.location.replace('" + url.spec() + "');"));
+ EXPECT_TRUE(ExecJs(shell, JsReplace("window.location.replace($1)", url)));
same_tab_observer.Wait();
if (!IsLastCommittedEntryOfPageType(web_contents, PAGE_TYPE_NORMAL))
return false;
@@ -527,24 +521,24 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
EXPECT_TRUE(NavigateToURL(
shell(), embedded_test_server()->GetURL("/simple_page.html")));
EXPECT_EQ(1, controller.GetEntryCount());
- EXPECT_EQ(1, RendererHistoryLength(shell()));
+ EXPECT_EQ(1, EvalJs(shell(), "history.length"));
EXPECT_TRUE(RendererLocationReplace(
shell(), embedded_test_server()->GetURL("/title1.html")));
EXPECT_EQ(1, controller.GetEntryCount());
- EXPECT_EQ(1, RendererHistoryLength(shell()));
+ EXPECT_EQ(1, EvalJs(shell(), "history.length"));
// Now create two more entries and go back, to test replacing an entry without
// pruning the forward history.
EXPECT_TRUE(
NavigateToURL(shell(), embedded_test_server()->GetURL("/title2.html")));
EXPECT_EQ(2, controller.GetEntryCount());
- EXPECT_EQ(2, RendererHistoryLength(shell()));
+ EXPECT_EQ(2, EvalJs(shell(), "history.length"));
EXPECT_TRUE(
NavigateToURL(shell(), embedded_test_server()->GetURL("/title3.html")));
EXPECT_EQ(3, controller.GetEntryCount());
- EXPECT_EQ(3, RendererHistoryLength(shell()));
+ EXPECT_EQ(3, EvalJs(shell(), "history.length"));
controller.GoBack();
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
@@ -555,7 +549,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
EXPECT_TRUE(RendererLocationReplace(
shell(), embedded_test_server()->GetURL("/simple_page.html?page1b")));
EXPECT_EQ(3, controller.GetEntryCount());
- EXPECT_EQ(3, RendererHistoryLength(shell()));
+ EXPECT_EQ(3, EvalJs(shell(), "history.length"));
EXPECT_TRUE(controller.CanGoForward());
// Note that there's no way to access the renderer's notion of the history
@@ -576,15 +570,15 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
shell()->web_contents()->GetMainFrame()->GetEnabledBindings());
ShellAddedObserver observer;
- std::string page_url = embedded_test_server()->GetURL(
- "/navigation_controller/simple_page_1.html").spec();
+ GURL page_url = embedded_test_server()->GetURL(
+ "/navigation_controller/simple_page_1.html");
EXPECT_TRUE(
- ExecuteScript(shell(), "window.open('" + page_url + "', '_blank')"));
+ ExecJs(shell(), JsReplace("window.open($1, '_blank');", page_url)));
Shell* shell2 = observer.GetShell();
EXPECT_TRUE(WaitForLoadStop(shell2->web_contents()));
EXPECT_EQ(1, shell2->web_contents()->GetController().GetEntryCount());
- EXPECT_EQ(1, RendererHistoryLength(shell2));
+ EXPECT_EQ(1, EvalJs(shell2, "history.length"));
// Again, as above, there's no way to access the renderer's notion of the
// history offset via JavaScript. Checking just the history length, again,
@@ -850,7 +844,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, SubframeOnEmptyPage) {
ShellAddedObserver new_shell_observer;
{
std::string script = "window.open()";
- EXPECT_TRUE(ExecuteScript(root, script));
+ EXPECT_TRUE(ExecJs(root, script));
}
Shell* new_shell = new_shell_observer.GetShell();
ASSERT_NE(new_shell->web_contents(), shell()->web_contents());
@@ -868,7 +862,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, SubframeOnEmptyPage) {
std::string script = "var iframe = document.createElement('iframe');"
"iframe.src = 'data:text/html,<p>some page</p>';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(new_root, script));
+ EXPECT_TRUE(ExecJs(new_root, script));
capturer.Wait();
}
ASSERT_EQ(1U, new_root->child_count());
@@ -879,8 +873,8 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, SubframeOnEmptyPage) {
"foo.com", "/navigation_controller/simple_page_2.html");
{
LoadCommittedCapturer capturer(new_shell->web_contents());
- std::string script = "location.assign('" + frame_url.spec() + "')";
- EXPECT_TRUE(ExecuteScript(new_root->child_at(0), script));
+ std::string script = JsReplace("location.assign($1);", frame_url);
+ EXPECT_TRUE(ExecJs(new_root->child_at(0), script));
capturer.Wait();
}
@@ -896,7 +890,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, SubframeOnEmptyPage) {
std::string script = "var iframe = document.createElement('iframe');"
"iframe.src = '" + grandchild_url.spec() + "';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(new_root->child_at(0), script));
+ EXPECT_TRUE(ExecJs(new_root->child_at(0), script));
capturer.Wait();
}
ASSERT_EQ(1U, new_root->child_at(0)->child_count());
@@ -917,7 +911,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// Pop open a new window to about:blank.
ShellAddedObserver new_shell_observer;
- EXPECT_TRUE(ExecuteScript(root, "var w = window.open('about:blank')"));
+ EXPECT_TRUE(ExecJs(root, "var w = window.open('about:blank')"));
Shell* new_shell = new_shell_observer.GetShell();
ASSERT_NE(new_shell->web_contents(), shell()->web_contents());
FrameTreeNode* new_root =
@@ -930,10 +924,12 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// Make a new iframe in it using document.write from the opener.
{
LoadCommittedCapturer capturer(new_shell->web_contents());
- std::string script = "w.document.write("
- "\"<iframe src='" + url1.spec() + "'></iframe>\");"
- "w.document.close();";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ std::string html = "<iframe src='" + url1.spec() + "'></iframe>";
+ std::string script = JsReplace(
+ "w.document.write($1);"
+ "w.document.close();",
+ html);
+ EXPECT_TRUE(ExecJs(root->current_frame_host(), script));
capturer.Wait();
}
ASSERT_EQ(1U, new_root->child_count());
@@ -946,7 +942,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
{
LoadCommittedCapturer capturer(new_root->child_at(0));
std::string script = "location.href = '" + url2.spec() + "';";
- EXPECT_TRUE(ExecuteScript(new_root->child_at(0), script));
+ EXPECT_TRUE(ExecJs(new_root->child_at(0), script));
capturer.Wait();
}
EXPECT_EQ(blank_url, new_root->current_url());
@@ -958,7 +954,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
{
LoadCommittedCapturer capturer(new_root);
std::string script = "history.replaceState({}, 'foo', 'foo');";
- EXPECT_TRUE(ExecuteScript(new_root, script));
+ EXPECT_TRUE(ExecJs(new_root, script));
capturer.Wait();
}
EXPECT_EQ(embedded_test_server()->GetURL("/navigation_controller/foo"),
@@ -1093,7 +1089,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// Load via a fragment link click.
FrameNavigateParamsCapturer capturer(root);
std::string script = "document.getElementById('fraglink').click()";
- EXPECT_TRUE(ExecuteScript(root, script));
+ EXPECT_TRUE(ExecJs(root, script));
capturer.Wait();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
capturer.transition(), ui::PAGE_TRANSITION_LINK));
@@ -1105,7 +1101,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// Load via link click.
FrameNavigateParamsCapturer capturer(root);
std::string script = "document.getElementById('thelink').click()";
- EXPECT_TRUE(ExecuteScript(root, script));
+ EXPECT_TRUE(ExecJs(root, script));
capturer.Wait();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
capturer.transition(), ui::PAGE_TRANSITION_LINK));
@@ -1118,8 +1114,8 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
FrameNavigateParamsCapturer capturer(root);
GURL frame_url(embedded_test_server()->GetURL(
"/navigation_controller/simple_page_2.html"));
- std::string script = "location.assign('" + frame_url.spec() + "')";
- EXPECT_TRUE(ExecuteScript(root, script));
+ std::string script = JsReplace("location.assign($1);", frame_url);
+ EXPECT_TRUE(ExecJs(root, script));
capturer.Wait();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
capturer.transition(),
@@ -1134,7 +1130,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
FrameNavigateParamsCapturer capturer(root);
std::string script =
"history.pushState({}, 'page 1', 'simple_page_1.html')";
- EXPECT_TRUE(ExecuteScript(root, script));
+ EXPECT_TRUE(ExecJs(root, script));
capturer.Wait();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
capturer.transition(),
@@ -1148,8 +1144,8 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
FrameNavigateParamsCapturer capturer(root);
GURL frame_url(embedded_test_server()->GetURL(
"foo.com", "/navigation_controller/simple_page_1.html"));
- std::string script = "location.replace('" + frame_url.spec() + "')";
- EXPECT_TRUE(ExecuteScript(root, script));
+ std::string script = JsReplace("location.replace($1);", frame_url);
+ EXPECT_TRUE(ExecJs(root, script));
capturer.Wait();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
capturer.transition(),
@@ -1206,7 +1202,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
{
// Back from the renderer side.
FrameNavigateParamsCapturer capturer(root);
- EXPECT_TRUE(ExecuteScript(root, "history.back()"));
+ EXPECT_TRUE(ExecJs(root, "history.back()"));
capturer.Wait();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
capturer.transition(),
@@ -1220,7 +1216,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
{
// Forward from the renderer side.
FrameNavigateParamsCapturer capturer(root);
- EXPECT_TRUE(ExecuteScript(root, "history.forward()"));
+ EXPECT_TRUE(ExecJs(root, "history.forward()"));
capturer.Wait();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
capturer.transition(),
@@ -1234,7 +1230,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
{
// Back from the renderer side via history.go().
FrameNavigateParamsCapturer capturer(root);
- EXPECT_TRUE(ExecuteScript(root, "history.go(-1)"));
+ EXPECT_TRUE(ExecJs(root, "history.go(-1)"));
capturer.Wait();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
capturer.transition(),
@@ -1248,7 +1244,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
{
// Forward from the renderer side via history.go().
FrameNavigateParamsCapturer capturer(root);
- EXPECT_TRUE(ExecuteScript(root, "history.go(1)"));
+ EXPECT_TRUE(ExecJs(root, "history.go(1)"));
capturer.Wait();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
capturer.transition(),
@@ -1273,7 +1269,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
{
// Reload from the renderer side.
FrameNavigateParamsCapturer capturer(root);
- EXPECT_TRUE(ExecuteScript(root, "location.reload()"));
+ EXPECT_TRUE(ExecJs(root, "location.reload()"));
capturer.Wait();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
capturer.transition(),
@@ -1288,8 +1284,8 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
FrameNavigateParamsCapturer capturer(root);
GURL frame_url(embedded_test_server()->GetURL(
"/navigation_controller/simple_page_1.html"));
- std::string script = "location.replace('" + frame_url.spec() + "')";
- EXPECT_TRUE(ExecuteScript(root, script));
+ std::string script = JsReplace("location.replace($1);", frame_url);
+ EXPECT_TRUE(ExecJs(root, script));
capturer.Wait();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
capturer.transition(),
@@ -1322,7 +1318,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
FrameNavigateParamsCapturer capturer(root);
std::string script =
"history.replaceState({}, 'page 2', 'simple_page_2.html')";
- EXPECT_TRUE(ExecuteScript(root, script));
+ EXPECT_TRUE(ExecJs(root, script));
capturer.Wait();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
capturer.transition(),
@@ -1338,7 +1334,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
"/navigation_controller/page_with_links.html"));
EXPECT_TRUE(NavigateToURL(shell(), url_links));
std::string script = "document.getElementById('fraglink').click()";
- EXPECT_TRUE(ExecuteScript(root, script));
+ EXPECT_TRUE(ExecJs(root, script));
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
{
@@ -1372,7 +1368,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
EXPECT_TRUE(NavigateToURL(shell(), url1));
script = "history.pushState({}, 'page 2', 'simple_page_2.html')";
- EXPECT_TRUE(ExecuteScript(root, script));
+ EXPECT_TRUE(ExecJs(root, script));
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
{
@@ -1434,11 +1430,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, ReloadWithUrlAnchor) {
"/navigation_controller/reload-with-url-anchor.html#center-element"));
EXPECT_TRUE(NavigateToURL(shell(), url));
- double window_scroll_y = 0;
- std::string get_window_scroll_y =
- "domAutomationController.send(window.scrollY);";
- EXPECT_TRUE(ExecuteScriptAndExtractDouble(shell(), get_window_scroll_y,
- &window_scroll_y));
+ double window_scroll_y = EvalJs(shell(), "window.scrollY").ExtractDouble();
// The 'center-element' y-position is 2000px. 2000px is an arbitrary value.
double expected_window_scroll_y = 2000;
@@ -1456,8 +1448,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, ReloadWithUrlAnchor) {
// Reload.
ReloadBlockUntilNavigationsComplete(shell(), 1);
- EXPECT_TRUE(ExecuteScriptAndExtractDouble(shell(), get_window_scroll_y,
- &window_scroll_y));
+ window_scroll_y = EvalJs(shell(), "window.scrollY").ExtractDouble();
EXPECT_FLOAT_EQ(expected_window_scroll_y, window_scroll_y);
}
@@ -1474,11 +1465,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
std::string script_scroll_down = "window.scroll(0, 2100)";
EXPECT_TRUE(ExecuteScript(shell(), script_scroll_down));
- std::string get_window_scroll_y =
- "domAutomationController.send(window.scrollY)";
- double window_scroll_y = 0;
- EXPECT_TRUE(ExecuteScriptAndExtractDouble(shell(), get_window_scroll_y,
- &window_scroll_y));
+ double window_scroll_y = EvalJs(shell(), "window.scrollY").ExtractDouble();
double expected_window_scroll_y = 2100;
if (IsUseZoomForDSFEnabled()) {
@@ -1495,8 +1482,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// Reload.
ReloadBlockUntilNavigationsComplete(shell(), 1);
- EXPECT_TRUE(ExecuteScriptAndExtractDouble(shell(), get_window_scroll_y,
- &window_scroll_y));
+ window_scroll_y = EvalJs(shell(), "window.scrollY").ExtractDouble();
EXPECT_FLOAT_EQ(expected_window_scroll_y, window_scroll_y);
}
@@ -1599,7 +1585,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// Load via a fragment link click.
FrameNavigateParamsCapturer capturer(root->child_at(0));
std::string script = "document.getElementById('fraglink').click()";
- EXPECT_TRUE(ExecuteScript(root->child_at(0), script));
+ EXPECT_TRUE(ExecJs(root->child_at(0), script));
capturer.Wait();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
capturer.transition(), ui::PAGE_TRANSITION_MANUAL_SUBFRAME));
@@ -1611,8 +1597,8 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
FrameNavigateParamsCapturer capturer(root->child_at(0));
GURL frame_url(embedded_test_server()->GetURL(
"/navigation_controller/simple_page_1.html"));
- std::string script = "location.assign('" + frame_url.spec() + "')";
- EXPECT_TRUE(ExecuteScript(root->child_at(0), script));
+ std::string script = JsReplace("location.assign($1);", frame_url);
+ EXPECT_TRUE(ExecJs(root->child_at(0), script));
capturer.Wait();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
capturer.transition(), ui::PAGE_TRANSITION_MANUAL_SUBFRAME));
@@ -1624,8 +1610,8 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
LoadCommittedCapturer capturer(root->child_at(0));
GURL frame_url(embedded_test_server()->GetURL(
"/navigation_controller/simple_page_2.html"));
- std::string script = "location.replace('" + frame_url.spec() + "')";
- EXPECT_TRUE(ExecuteScript(root->child_at(0), script));
+ std::string script = JsReplace("location.replace($1);", frame_url);
+ EXPECT_TRUE(ExecJs(root->child_at(0), script));
capturer.Wait();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
@@ -1636,7 +1622,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
FrameNavigateParamsCapturer capturer(root->child_at(0));
std::string script =
"history.pushState({}, 'page 1', 'simple_page_1.html')";
- EXPECT_TRUE(ExecuteScript(root->child_at(0), script));
+ EXPECT_TRUE(ExecJs(root->child_at(0), script));
capturer.Wait();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
capturer.transition(), ui::PAGE_TRANSITION_MANUAL_SUBFRAME));
@@ -1648,7 +1634,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
LoadCommittedCapturer capturer(root->child_at(0));
std::string script =
"history.replaceState({}, 'page 2', 'simple_page_2.html')";
- EXPECT_TRUE(ExecuteScript(root->child_at(0), script));
+ EXPECT_TRUE(ExecJs(root->child_at(0), script));
capturer.Wait();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
@@ -1657,7 +1643,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
{
// Reload.
LoadCommittedCapturer capturer(root->child_at(0));
- EXPECT_TRUE(ExecuteScript(root->child_at(0), "location.reload()"));
+ EXPECT_TRUE(ExecJs(root->child_at(0), "location.reload()"));
capturer.Wait();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
@@ -1671,7 +1657,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
std::string script = "var iframe = document.createElement('iframe');"
"iframe.src = '" + frame_url.spec() + "';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root, script));
+ EXPECT_TRUE(ExecJs(root, script));
capturer.Wait();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
@@ -1729,7 +1715,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// Do a fragment link click.
FrameNavigateParamsCapturer capturer(root);
std::string script = "document.getElementById('fraglink').click()";
- EXPECT_TRUE(ExecuteScript(root, script));
+ EXPECT_TRUE(ExecJs(root, script));
capturer.Wait();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
capturer.transition(), ui::PAGE_TRANSITION_LINK));
@@ -1741,7 +1727,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// Do a non-fragment link click.
FrameNavigateParamsCapturer capturer(root);
std::string script = "document.getElementById('thelink').click()";
- EXPECT_TRUE(ExecuteScript(root, script));
+ EXPECT_TRUE(ExecJs(root, script));
capturer.Wait();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
capturer.transition(), ui::PAGE_TRANSITION_LINK));
@@ -1768,7 +1754,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// Do a fragment link click.
FrameNavigateParamsCapturer capturer(root->child_at(0));
std::string script = "document.getElementById('fraglink').click()";
- EXPECT_TRUE(ExecuteScript(root->child_at(0), script));
+ EXPECT_TRUE(ExecJs(root->child_at(0), script));
capturer.Wait();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
capturer.transition(), ui::PAGE_TRANSITION_MANUAL_SUBFRAME));
@@ -1780,7 +1766,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// Do a non-fragment link click.
FrameNavigateParamsCapturer capturer(root->child_at(0));
std::string script = "document.getElementById('thelink').click()";
- EXPECT_TRUE(ExecuteScript(root->child_at(0), script));
+ EXPECT_TRUE(ExecJs(root->child_at(0), script));
capturer.Wait();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
capturer.transition(), ui::PAGE_TRANSITION_MANUAL_SUBFRAME));
@@ -1809,7 +1795,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
LoadCommittedCapturer capturer(shell()->web_contents());
std::string script = "var iframe = document.createElement('iframe');"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root, script));
+ EXPECT_TRUE(ExecJs(root, script));
capturer.Wait();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
@@ -1836,7 +1822,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
LoadCommittedCapturer capturer(shell()->web_contents());
std::string script = "var iframe = document.createElement('iframe');"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root->child_at(0), script));
+ EXPECT_TRUE(ExecJs(root->child_at(0), script));
capturer.Wait();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
@@ -1855,7 +1841,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
std::string script = "var iframe = document.createElement('iframe');"
"iframe.src = 'about:blank';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root, script));
+ EXPECT_TRUE(ExecJs(root, script));
capturer.Wait();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
@@ -1877,9 +1863,11 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
"/navigation_controller/simple_page_1.html"));
{
LoadCommittedCapturer capturer(root->child_at(0)->child_at(0));
- std::string script = "var frames = document.getElementsByTagName('iframe');"
- "frames[0].src = '" + frame_url.spec() + "';";
- EXPECT_TRUE(ExecuteScript(root->child_at(0), script));
+ std::string script = JsReplace(
+ "var frames = document.getElementsByTagName('iframe');"
+ "frames[0].src = $1;",
+ frame_url);
+ EXPECT_TRUE(ExecJs(root->child_at(0), script));
capturer.Wait();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
@@ -1903,9 +1891,11 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
"foo.com", "/navigation_controller/simple_page_2.html"));
{
LoadCommittedCapturer capturer(root->child_at(1));
- std::string script = "var frames = document.getElementsByTagName('iframe');"
- "frames[1].src = '" + foo_url.spec() + "';";
- EXPECT_TRUE(ExecuteScript(root, script));
+ std::string script = JsReplace(
+ "var frames = document.getElementsByTagName('iframe');"
+ "frames[1].src = $1;",
+ foo_url);
+ EXPECT_TRUE(ExecJs(root, script));
capturer.Wait();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
@@ -1930,7 +1920,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
LoadCommittedCapturer capturer(root->child_at(0)->child_at(0));
std::string script = "var frames = document.getElementsByTagName('iframe');"
"frames[0].src = 'about:blank';";
- EXPECT_TRUE(ExecuteScript(root->child_at(0), script));
+ EXPECT_TRUE(ExecJs(root->child_at(0), script));
capturer.Wait();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
capturer.transition_type(), ui::PAGE_TRANSITION_MANUAL_SUBFRAME));
@@ -1980,12 +1970,12 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
GURL slow_url(embedded_test_server()->GetURL(
"/navigation_controller/simple_page_2.html"));
TestNavigationManager subframe_delayer(shell()->web_contents(), slow_url);
- {
- std::string script = "var iframe = document.createElement('iframe');"
- "iframe.src = '" + slow_url.spec() + "';"
- "document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root, script));
- }
+ std::string script_template =
+ "var iframe = document.createElement('iframe');"
+ "iframe.src = $1;"
+ "document.body.appendChild(iframe);";
+
+ EXPECT_TRUE(ExecJs(root, JsReplace(script_template, slow_url)));
EXPECT_TRUE(subframe_delayer.WaitForRequestStart());
// Stop the request so that we can wait for load stop below, without ending up
@@ -1995,13 +1985,8 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// 2. A nested iframe with a cross-site URL should be able to commit.
GURL foo_url(embedded_test_server()->GetURL(
"foo.com", "/navigation_controller/simple_page_1.html"));
- {
- std::string script = "var iframe = document.createElement('iframe');"
- "iframe.src = '" + foo_url.spec() + "';"
- "document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root->child_at(0), script));
- WaitForLoadStopWithoutSuccessCheck(shell()->web_contents());
- }
+ EXPECT_TRUE(ExecJs(root->child_at(0), JsReplace(script_template, foo_url)));
+ WaitForLoadStopWithoutSuccessCheck(shell()->web_contents());
// TODO(creis): Check subframe entries once we create them in this case.
// See https://crbug.com/608402.
@@ -2028,7 +2013,7 @@ IN_PROC_BROWSER_TEST_F(
std::string script = "var iframe = document.createElement('iframe');"
"iframe.src = '" + no_commit_url.spec() + "';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root, script));
+ EXPECT_TRUE(ExecJs(root, script));
}
EXPECT_EQ(GURL(), root->child_at(0)->current_url());
@@ -2040,7 +2025,7 @@ IN_PROC_BROWSER_TEST_F(
std::string script = "var iframe = document.createElement('iframe');"
"iframe.src = '" + foo_url.spec() + "';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root->child_at(0), script));
+ EXPECT_TRUE(ExecJs(root->child_at(0), script));
capturer.Wait();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
@@ -2068,7 +2053,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
{
FrameNavigateParamsCapturer capturer(root);
std::string script = "history.pushState({}, 'foo', 'foo')";
- EXPECT_TRUE(ExecuteScript(root, script));
+ EXPECT_TRUE(ExecJs(root, script));
capturer.Wait();
EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, capturer.navigation_type());
EXPECT_TRUE(capturer.is_same_document());
@@ -2082,7 +2067,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
std::string script = "var iframe = document.createElement('iframe');"
"iframe.src = '" + child_url.spec() + "';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root, script));
+ EXPECT_TRUE(ExecJs(root, script));
capturer.Wait();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
@@ -2103,7 +2088,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
std::string script = "var iframe = document.createElement('iframe');"
"iframe.src = '" + grandchild_url.spec() + "';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root->child_at(0), script));
+ EXPECT_TRUE(ExecJs(root->child_at(0), script));
capturer.Wait();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
@@ -2134,14 +2119,14 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
std::string script = "var iframe = document.createElement('iframe');"
"iframe.src = '" + child_url.spec() + "';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root, script));
+ EXPECT_TRUE(ExecJs(root, script));
capturer.Wait();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
}
// 2. Change the iframe's name.
- EXPECT_TRUE(ExecuteScript(root->child_at(0), "window.name = 'foo';"));
+ EXPECT_TRUE(ExecJs(root->child_at(0), "window.name = 'foo';"));
// 3. A nested iframe with a cross-site URL should be able to commit.
GURL bar_url(embedded_test_server()->GetURL(
@@ -2151,7 +2136,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
std::string script = "var iframe = document.createElement('iframe');"
"iframe.src = '" + bar_url.spec() + "';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root->child_at(0), script));
+ EXPECT_TRUE(ExecJs(root->child_at(0), script));
capturer.Wait();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
@@ -2186,7 +2171,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
std::string script = "var iframe = document.createElement('iframe');"
"iframe.src = '" + frame_url.spec() + "';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root, script));
+ EXPECT_TRUE(ExecJs(root, script));
capturer.Wait();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
@@ -2215,7 +2200,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
std::string script = "var iframe = document.createElement('iframe');"
"iframe.src = '" + foo_url.spec() + "';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root, script));
+ EXPECT_TRUE(ExecJs(root, script));
capturer.Wait();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
@@ -2241,7 +2226,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
std::string script = "var iframe = document.createElement('iframe');"
"iframe.src = '" + foo_url.spec() + "';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root->child_at(1), script));
+ EXPECT_TRUE(ExecJs(root->child_at(1), script));
capturer.Wait();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
@@ -2267,7 +2252,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
std::string script = "var iframe = document.createElement('iframe');"
"iframe.src = '" + foo_url.spec() + "';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root, script));
+ EXPECT_TRUE(ExecJs(root, script));
capturer.Wait();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
@@ -2292,7 +2277,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
"iframe.src = '" + frame_url.spec() + "';"
"document.body.appendChild(iframe);";
FrameTreeNode* child = root->child_at(2);
- EXPECT_TRUE(ExecuteScript(child, script));
+ EXPECT_TRUE(ExecJs(child, script));
capturer.Wait();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
@@ -2349,7 +2334,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
std::string script = "var iframe = document.createElement('iframe');"
"iframe.src = '" + frame_url.spec() + "';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root, script));
+ EXPECT_TRUE(ExecJs(root, script));
capturer.Wait();
}
NavigationEntryImpl* entry = controller.GetLastCommittedEntry();
@@ -2387,7 +2372,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
std::string script = "var iframe = document.createElement('iframe');"
"iframe.src = '" + foo_url.spec() + "';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root, script));
+ EXPECT_TRUE(ExecJs(root, script));
capturer.Wait();
}
@@ -2398,7 +2383,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
std::string script = "var iframe = document.createElement('iframe');"
"iframe.src = '" + foo_url.spec() + "';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root->child_at(1), script));
+ EXPECT_TRUE(ExecJs(root->child_at(1), script));
capturer.Wait();
}
GURL bar_url(embedded_test_server()->GetURL(
@@ -2443,7 +2428,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
root->child_at(1)->current_frame_host());
std::string script = "var frames = document.getElementsByTagName('iframe');"
"frames[1].src = '" + baz_url.spec() + "';";
- EXPECT_TRUE(ExecuteScript(root, script));
+ EXPECT_TRUE(ExecJs(root, script));
// Wait for the RenderFrame to go away, if this will be cross-process.
if (AreAllSitesIsolatedForTesting())
deleted_observer.WaitUntilDeleted();
@@ -2513,7 +2498,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// 2. Same document navigation in the main frame.
std::string push_script = "history.pushState({}, 'page 2', 'page_2.html')";
- EXPECT_TRUE(ExecuteScript(root, push_script));
+ EXPECT_TRUE(ExecJs(root, push_script));
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
// The entry should have a FrameNavigationEntry for the subframe.
@@ -2527,7 +2512,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
std::string script = "var iframe = document.createElement('iframe');"
"iframe.src = '" + subframe_url.spec() + "';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root->child_at(0), script));
+ EXPECT_TRUE(ExecJs(root->child_at(0), script));
capturer.Wait();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
@@ -2564,7 +2549,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
std::string script = "var iframe = document.createElement('iframe');"
"iframe.src = '" + frame_url.spec() + "';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root, script));
+ EXPECT_TRUE(ExecJs(root, script));
capturer.Wait();
}
NavigationEntryImpl* entry1 = controller.GetLastCommittedEntry();
@@ -2810,7 +2795,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
->frame_entry->document_sequence_number());
// Inject a JS value so that we can check for it later.
- EXPECT_TRUE(content::ExecuteScript(root, "foo=3;"));
+ EXPECT_TRUE(ExecJs(root, "foo=3;"));
// 7. Go back again, to the data URL in the nested iframe.
{
@@ -2836,12 +2821,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
entry3->root_node()->children[0]->children[0]->frame_entry->url());
// Verify that we did not reload the main frame. See https://crbug.com/586234.
- {
- int value = 0;
- EXPECT_TRUE(ExecuteScriptAndExtractInt(
- root, "domAutomationController.send(foo)", &value));
- EXPECT_EQ(3, value);
- }
+ EXPECT_EQ(3, EvalJs(root, "foo"));
// 8. Go back again, to the data URL in the first subframe.
{
@@ -3104,14 +3084,8 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
EXPECT_EQ(blank_url, root->child_at(0)->current_url());
// Verify that the parent was able to script the iframe.
- std::string expected_text("Injected text");
- {
- std::string value;
- EXPECT_TRUE(ExecuteScriptAndExtractString(
- root->child_at(0),
- "domAutomationController.send(document.body.innerHTML)", &value));
- EXPECT_EQ(expected_text, value);
- }
+ EXPECT_EQ("Injected text",
+ EvalJs(root->child_at(0), "document.body.innerHTML"));
EXPECT_EQ(1, controller.GetEntryCount());
EXPECT_EQ(0, controller.GetLastCommittedEntryIndex());
@@ -3142,13 +3116,8 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
EXPECT_EQ(blank_url, root->child_at(0)->current_url());
// Verify that the parent was able to script the iframe.
- {
- std::string value;
- EXPECT_TRUE(ExecuteScriptAndExtractString(
- root->child_at(0),
- "domAutomationController.send(document.body.innerHTML)", &value));
- EXPECT_EQ(expected_text, value);
- }
+ EXPECT_EQ("Injected text",
+ EvalJs(root->child_at(0), "document.body.innerHTML"));
EXPECT_EQ(2, controller.GetEntryCount());
EXPECT_EQ(0, controller.GetLastCommittedEntryIndex());
@@ -3197,9 +3166,8 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
entry->root_node()->children[0]->children[0]->frame_entry->url());
// Set a value in the form which will be stored in the PageState.
- EXPECT_TRUE(
- ExecuteScript(root->child_at(0)->child_at(0),
- "document.getElementById('itext').value = 'modified';"));
+ EXPECT_TRUE(ExecJs(root->child_at(0)->child_at(0),
+ "document.getElementById('itext').value = 'modified';"));
// 2. Navigate the main frame same-site, destroying the subframes.
GURL main_url_2(embedded_test_server()->GetURL(
@@ -3241,13 +3209,8 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// With injected about:blank iframes, we never restore form values from
// PageState.
- std::string form_value = "fail";
- EXPECT_TRUE(
- ExecuteScriptAndExtractString(root->child_at(0)->child_at(0),
- "window.domAutomationController.send("
- "document.getElementById('itext').value);",
- &form_value));
- EXPECT_EQ("", form_value);
+ EXPECT_EQ("", EvalJs(root->child_at(0)->child_at(0),
+ "document.getElementById('itext').value"));
}
// Verify that we correctly load a nested iframe created by an injected iframe
@@ -3295,9 +3258,8 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
entry->root_node()->children[0]->children[0]->frame_entry->url());
// Set a value in the form which will be stored in the PageState.
- EXPECT_TRUE(
- ExecuteScript(root->child_at(0)->child_at(0),
- "document.getElementById('itext').value = 'modified';"));
+ EXPECT_TRUE(ExecJs(root->child_at(0)->child_at(0),
+ "document.getElementById('itext').value = 'modified';"));
// 2. Navigate the main frame same-site, destroying the subframes.
GURL main_url_2(embedded_test_server()->GetURL(
@@ -3347,13 +3309,8 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// Note that restoring form values in srcdoc frames created via static html is
// expected to work and is tested by
// RenderFrameHostManagerTest.RestoreSubframeFileAccessForHistoryNavigation.
- std::string form_value = "fail";
- EXPECT_TRUE(
- ExecuteScriptAndExtractString(root->child_at(0)->child_at(0),
- "window.domAutomationController.send("
- "document.getElementById('itext').value);",
- &form_value));
- EXPECT_EQ("", form_value);
+ EXPECT_EQ("", EvalJs(root->child_at(0)->child_at(0),
+ "document.getElementById('itext').value"));
}
// Verify that we can load about:blank in an iframe when going back to a page,
@@ -3461,7 +3418,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
EXPECT_EQ(main_url, root->current_url());
// Check that the renderer is still alive.
- EXPECT_TRUE(ExecuteScript(shell(), "console.log('Success');"));
+ EXPECT_TRUE(ExecJs(shell(), "console.log('Success');"));
EXPECT_EQ(2, controller.GetEntryCount());
EXPECT_EQ(0, controller.GetLastCommittedEntryIndex());
@@ -3531,7 +3488,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
TestNavigationObserver observer(shell()->web_contents());
std::string script = "history.replaceState({}, '', '/server-redirect?" +
frame_redirect_dest_url.spec() + "')";
- EXPECT_TRUE(ExecuteScript(root->child_at(0), script));
+ EXPECT_TRUE(ExecJs(root->child_at(0), script));
observer.Wait();
}
@@ -3587,7 +3544,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
TestNavigationObserver observer(shell()->web_contents());
std::string script = "history.replaceState({}, '', '/server-redirect?" +
frame_redirect_dest_url.spec() + "')";
- EXPECT_TRUE(ExecuteScript(root->child_at(1), script));
+ EXPECT_TRUE(ExecJs(root->child_at(1), script));
observer.Wait();
}
@@ -3635,7 +3592,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
TestNavigationObserver observer(shell()->web_contents());
std::string script = "history.replaceState({}, '', '/server-redirect?" +
redirect_dest_url.spec() + "')";
- EXPECT_TRUE(ExecuteScript(root, script));
+ EXPECT_TRUE(ExecJs(root, script));
observer.Wait();
}
@@ -3703,7 +3660,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
TestNavigationObserver observer(shell()->web_contents());
std::string script = "history.replaceState({}, '', '/server-redirect?" +
frame_redirect_dest_url.spec() + "')";
- EXPECT_TRUE(ExecuteScript(root->child_at(0), script));
+ EXPECT_TRUE(ExecJs(root->child_at(0), script));
observer.Wait();
}
@@ -3752,7 +3709,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
TestNavigationObserver observer(shell()->web_contents());
std::string script = "history.replaceState({}, '', '/server-redirect?" +
redirect_dest_url.spec() + "')";
- EXPECT_TRUE(ExecuteScript(root, script));
+ EXPECT_TRUE(ExecJs(root, script));
observer.Wait();
}
@@ -3943,14 +3900,8 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
EXPECT_EQ(blank_url, new_entry->root_node()->children[0]->frame_entry->url());
// Verify that the parent was able to script the iframe.
- std::string expected_text("Injected text");
- {
- std::string value;
- EXPECT_TRUE(ExecuteScriptAndExtractString(
- root->child_at(0),
- "domAutomationController.send(document.body.innerHTML)", &value));
- EXPECT_EQ(expected_text, value);
- }
+ EXPECT_EQ("Injected text",
+ EvalJs(root->child_at(0), "document.body.innerHTML"));
}
// Verifies that the |frame_unique_name| is set to the correct frame, so that we
@@ -3983,7 +3934,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
std::string script = "var iframe = document.createElement('iframe');"
"iframe.src = '" + url.spec() + "';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root, script));
+ EXPECT_TRUE(ExecJs(root, script));
capturer.Wait();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
@@ -4009,7 +3960,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
"iframe.src = '" + url.spec() + "';"
"iframe.name = 'foo';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root, script));
+ EXPECT_TRUE(ExecJs(root, script));
capturer.Wait();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
@@ -4489,7 +4440,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, CloneNamedWindow) {
EXPECT_TRUE(NavigateToURL(shell(), url_1));
// Name the window.
- EXPECT_TRUE(ExecuteScript(shell(), "window.name = 'foo';"));
+ EXPECT_TRUE(ExecJs(shell(), "window.name = 'foo';"));
// Navigate it.
GURL url_2(embedded_test_server()->GetURL(
@@ -4520,7 +4471,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
EXPECT_TRUE(NavigateToURL(shell(), url_1));
// Name the window.
- EXPECT_TRUE(ExecuteScript(shell(), "window.name = 'foo';"));
+ EXPECT_TRUE(ExecJs(shell(), "window.name = 'foo';"));
// Navigate it.
GURL url_2(embedded_test_server()->GetURL(
@@ -4528,7 +4479,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
EXPECT_TRUE(NavigateToURL(shell(), url_2));
// Clear the name.
- EXPECT_TRUE(ExecuteScript(shell(), "window.name = '';"));
+ EXPECT_TRUE(ExecJs(shell(), "window.name = '';"));
// Navigate it again.
EXPECT_TRUE(NavigateToURL(shell(), url_1));
@@ -4637,7 +4588,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
"document.body.appendChild(iframe);";
{
LoadCommittedCapturer capturer(shell()->web_contents());
- EXPECT_TRUE(ExecuteScript(root, script));
+ EXPECT_TRUE(ExecJs(root, script));
capturer.Wait();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
@@ -4666,7 +4617,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// 4. Add the iframe again.
{
LoadCommittedCapturer capturer(shell()->web_contents());
- EXPECT_TRUE(ExecuteScript(root, script));
+ EXPECT_TRUE(ExecJs(root, script));
capturer.Wait();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
@@ -4702,7 +4653,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// 2. Do a same document fragment navigation.
std::string script = "document.getElementById('fraglink').click()";
- EXPECT_TRUE(ExecuteScript(root, script));
+ EXPECT_TRUE(ExecJs(root, script));
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
frame_entry = controller.GetLastCommittedEntry()->GetFrameEntry(root);
@@ -4718,7 +4669,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
std::string add_script = "var iframe = document.createElement('iframe');"
"iframe.src = '" + url.spec() + "';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root, add_script));
+ EXPECT_TRUE(ExecJs(root, add_script));
capturer.Wait();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
@@ -4739,7 +4690,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
EXPECT_NE(dsn_2, dsn_3);
// 4. Do a same document fragment navigation in the subframe.
- EXPECT_TRUE(ExecuteScript(subframe, script));
+ EXPECT_TRUE(ExecJs(subframe, script));
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
subframe_entry = controller.GetLastCommittedEntry()->GetFrameEntry(subframe);
@@ -4977,7 +4928,7 @@ void DoReplaceStateWhilePending(Shell* shell,
capturer.set_wait_for_load(false);
std::string script =
"history.replaceState({}, '', '" + replace_state_filename + "')";
- EXPECT_TRUE(ExecuteScript(root, script));
+ EXPECT_TRUE(ExecJs(root, script));
capturer.Wait();
// The fact that there was a pending entry shouldn't interfere with the
@@ -5070,7 +5021,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
FrameNavigateParamsCapturer capturer(root);
capturer.set_wait_for_load(false);
std::string script = "history.pushState({}, '', 'pushed')";
- EXPECT_TRUE(ExecuteScript(root, script));
+ EXPECT_TRUE(ExecJs(root, script));
capturer.Wait();
EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, capturer.navigation_type());
EXPECT_TRUE(capturer.is_same_document());
@@ -5107,7 +5058,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// Go to the second page.
std::string script = "document.getElementById('thelink').click()";
- EXPECT_TRUE(ExecuteScript(root, script));
+ EXPECT_TRUE(ExecJs(root, script));
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
EXPECT_EQ(2, controller.GetEntryCount());
EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
@@ -5176,7 +5127,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// location.replace() to cause an inert commit.
TestNavigationObserver replace_load_observer(shell()->web_contents());
std::string script = "location.replace('" + url3.spec() + "')";
- EXPECT_TRUE(ExecuteScript(root, script));
+ EXPECT_TRUE(ExecJs(root, script));
replace_load_observer.Wait();
}
@@ -5258,7 +5209,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
FrameNavigateParamsCapturer capturer(root);
std::string script =
"history.replaceState({}, 'replaced', 'replaced')";
- EXPECT_TRUE(ExecuteScript(root, script));
+ EXPECT_TRUE(ExecJs(root, script));
capturer.Wait();
}
@@ -5387,6 +5338,11 @@ class RenderProcessKilledObserver : public WebContentsObserver {
// not modify the underlying last committed entry.) Not crashing means that
// the test is successful.
IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, ReloadOriginalRequest) {
+ // TODO(lukasza): https://crbug.com/417518: Get tests working with
+ // --site-per-process.
+ if (SiteIsolationPolicy::UseDedicatedProcessesForAllSites())
+ return;
+
GURL original_url(embedded_test_server()->GetURL(
"/navigation_controller/simple_page_1.html"));
EXPECT_TRUE(NavigateToURL(shell(), original_url));
@@ -5401,7 +5357,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, ReloadOriginalRequest) {
{
std::string script = "location.replace('" + redirect_url.spec() + "');";
FrameNavigateParamsCapturer capturer(root);
- EXPECT_TRUE(ExecuteScript(shell(), script));
+ EXPECT_TRUE(ExecJs(shell(), script));
capturer.Wait();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
capturer.transition(),
@@ -5443,7 +5399,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, ReloadOriginalRequest) {
}
// Make sure the renderer is still alive.
- EXPECT_TRUE(ExecuteScript(shell(), "console.log('Success');"));
+ EXPECT_TRUE(ExecJs(shell(), "console.log('Success');"));
}
// This test shows that the initial "about:blank" URL is elided from the
@@ -5466,7 +5422,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
->root();
EXPECT_EQ(1, controller.GetEntryCount());
- EXPECT_EQ(1, RendererHistoryLength(shell()));
+ EXPECT_EQ(1, EvalJs(shell(), "history.length"));
// Add an iframe with no 'src'.
@@ -5474,11 +5430,11 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
"var iframe = document.createElement('iframe');"
"iframe.id = 'frame';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root, script));
+ EXPECT_TRUE(ExecJs(root, script));
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
EXPECT_EQ(1, controller.GetEntryCount());
- EXPECT_EQ(1, RendererHistoryLength(shell()));
+ EXPECT_EQ(1, EvalJs(shell(), "history.length"));
EXPECT_EQ(0, controller.GetLastCommittedEntryIndex());
ASSERT_EQ(1U, root->child_count());
@@ -5492,11 +5448,11 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// "about:blank" as the URL in the iframe.
script = "history.pushState({}, '', 'notarealurl.html')";
- EXPECT_TRUE(ExecuteScript(root, script));
+ EXPECT_TRUE(ExecJs(root, script));
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
EXPECT_EQ(2, controller.GetEntryCount());
- EXPECT_EQ(2, RendererHistoryLength(shell()));
+ EXPECT_EQ(2, EvalJs(shell(), "history.length"));
EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
// Load the iframe; the initial "about:blank" URL should be elided and thus we
@@ -5508,7 +5464,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
EXPECT_EQ(2, controller.GetEntryCount());
- EXPECT_EQ(2, RendererHistoryLength(shell()));
+ EXPECT_EQ(2, EvalJs(shell(), "history.length"));
EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
EXPECT_EQ(frame_url, frame->current_url());
@@ -5522,7 +5478,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
}
EXPECT_EQ(2, controller.GetEntryCount());
- EXPECT_EQ(2, RendererHistoryLength(shell()));
+ EXPECT_EQ(2, EvalJs(shell(), "history.length"));
EXPECT_EQ(0, controller.GetLastCommittedEntryIndex());
// There is some open discussion over whether this should send the iframe
@@ -5540,11 +5496,11 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// Do a same document navigation in the subframe.
std::string fragment_script = "location.href = \"#foo\";";
- EXPECT_TRUE(ExecuteScript(frame->current_frame_host(), fragment_script));
+ EXPECT_TRUE(ExecJs(frame->current_frame_host(), fragment_script));
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
EXPECT_EQ(2, controller.GetEntryCount());
- EXPECT_EQ(2, RendererHistoryLength(shell()));
+ EXPECT_EQ(2, EvalJs(shell(), "history.length"));
EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
GURL frame_url_2 = embedded_test_server()->GetURL(
@@ -5561,7 +5517,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// Verify the process is still alive by running script. We can't just call
// IsRenderFrameLive after the navigation since it might not have disconnected
// yet.
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), "true;"));
+ EXPECT_TRUE(ExecJs(root->current_frame_host(), "true;"));
EXPECT_TRUE(root->current_frame_host()->IsRenderFrameLive());
// TODO(creis): We should probably go back to frame_url here instead of the
@@ -5588,7 +5544,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
->root();
EXPECT_EQ(1, controller.GetEntryCount());
- EXPECT_EQ(1, RendererHistoryLength(shell()));
+ EXPECT_EQ(1, EvalJs(shell(), "history.length"));
// Add an iframe with a 'src'.
@@ -5599,11 +5555,11 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
"iframe.src = '" + frame_url_1.spec() + "';"
"iframe.id = 'frame';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root, script));
+ EXPECT_TRUE(ExecJs(root, script));
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
EXPECT_EQ(1, controller.GetEntryCount());
- EXPECT_EQ(1, RendererHistoryLength(shell()));
+ EXPECT_EQ(1, EvalJs(shell(), "history.length"));
EXPECT_EQ(0, controller.GetLastCommittedEntryIndex());
ASSERT_EQ(1U, root->child_count());
@@ -5616,11 +5572,11 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// old navigation entry has frame_url_1 as the URL in the iframe.
script = "document.getElementById('fraglink').click()";
- EXPECT_TRUE(ExecuteScript(root, script));
+ EXPECT_TRUE(ExecJs(root, script));
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
EXPECT_EQ(2, controller.GetEntryCount());
- EXPECT_EQ(2, RendererHistoryLength(shell()));
+ EXPECT_EQ(2, EvalJs(shell(), "history.length"));
EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
EXPECT_EQ(frame_url_1, frame->current_url());
@@ -5634,7 +5590,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
EXPECT_EQ(3, controller.GetEntryCount());
- EXPECT_EQ(3, RendererHistoryLength(shell()));
+ EXPECT_EQ(3, EvalJs(shell(), "history.length"));
EXPECT_EQ(2, controller.GetLastCommittedEntryIndex());
EXPECT_EQ(frame_url_2, frame->current_url());
@@ -5648,7 +5604,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
}
EXPECT_EQ(3, controller.GetEntryCount());
- EXPECT_EQ(3, RendererHistoryLength(shell()));
+ EXPECT_EQ(3, EvalJs(shell(), "history.length"));
EXPECT_EQ(0, controller.GetLastCommittedEntryIndex());
// There is some open discussion over whether this should send the iframe back
@@ -5666,11 +5622,11 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// Do a same document navigation in the subframe.
std::string fragment_script = "location.href = \"#foo\";";
- EXPECT_TRUE(ExecuteScript(frame->current_frame_host(), fragment_script));
+ EXPECT_TRUE(ExecJs(frame->current_frame_host(), fragment_script));
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
EXPECT_EQ(2, controller.GetEntryCount());
- EXPECT_EQ(2, RendererHistoryLength(shell()));
+ EXPECT_EQ(2, EvalJs(shell(), "history.length"));
EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
// Go back.
@@ -5683,7 +5639,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// Verify the process is still alive by running script. We can't just call
// IsRenderFrameLive after the navigation since it might not have disconnected
// yet.
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), "true;"));
+ EXPECT_TRUE(ExecJs(root->current_frame_host(), "true;"));
EXPECT_TRUE(root->current_frame_host()->IsRenderFrameLive());
// TODO(creis): It's a bit surprising to go to frame_url_1 here instead of
@@ -5713,7 +5669,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
->root();
EXPECT_EQ(1, controller.GetEntryCount());
- EXPECT_EQ(1, RendererHistoryLength(shell()));
+ EXPECT_EQ(1, EvalJs(shell(), "history.length"));
// Add an iframe with a 'src'.
@@ -5724,11 +5680,11 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
"iframe.src = '" + frame_url_1.spec() + "';"
"iframe.id = 'frame';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecJs(root->current_frame_host(), script));
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
EXPECT_EQ(1, controller.GetEntryCount());
- EXPECT_EQ(1, RendererHistoryLength(shell()));
+ EXPECT_EQ(1, EvalJs(shell(), "history.length"));
EXPECT_EQ(0, controller.GetLastCommittedEntryIndex());
ASSERT_EQ(1U, root->child_count());
@@ -5741,19 +5697,19 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
GURL frame_url_2 = embedded_test_server()->GetURL(
"/navigation_controller/simple_page_1.html#foo");
std::string fragment_script = "location.href = \"#foo\";";
- EXPECT_TRUE(ExecuteScript(frame->current_frame_host(), fragment_script));
+ EXPECT_TRUE(ExecJs(frame->current_frame_host(), fragment_script));
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
EXPECT_EQ(2, controller.GetEntryCount());
- EXPECT_EQ(2, RendererHistoryLength(shell()));
+ EXPECT_EQ(2, EvalJs(shell(), "history.length"));
EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
EXPECT_EQ(frame_url_2, frame->current_url());
// Do a fragment navigation at the top level.
std::string link_script = "document.getElementById('fraglink').click()";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), link_script));
+ EXPECT_TRUE(ExecJs(root->current_frame_host(), link_script));
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
EXPECT_EQ(3, controller.GetEntryCount());
- EXPECT_EQ(3, RendererHistoryLength(shell()));
+ EXPECT_EQ(3, EvalJs(shell(), "history.length"));
EXPECT_EQ(2, controller.GetLastCommittedEntryIndex());
EXPECT_EQ(frame_url_2, frame->current_url());
@@ -5763,7 +5719,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
NavigateFrameToURL(frame, frame_url_3);
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
EXPECT_EQ(4, controller.GetEntryCount());
- EXPECT_EQ(4, RendererHistoryLength(shell()));
+ EXPECT_EQ(4, EvalJs(shell(), "history.length"));
EXPECT_EQ(3, controller.GetLastCommittedEntryIndex());
EXPECT_EQ(frame_url_3, frame->current_url());
@@ -5775,7 +5731,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
observer.Wait();
}
EXPECT_EQ(4, controller.GetEntryCount());
- EXPECT_EQ(4, RendererHistoryLength(shell()));
+ EXPECT_EQ(4, EvalJs(shell(), "history.length"));
EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
EXPECT_EQ(links_url, root->current_url());
@@ -5802,7 +5758,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// Verify the process is still alive by running script. We can't just call
// IsRenderFrameLive after the navigation since it might not have disconnected
// yet.
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), "true;"));
+ EXPECT_TRUE(ExecJs(root->current_frame_host(), "true;"));
EXPECT_TRUE(root->current_frame_host()->IsRenderFrameLive());
// TODO(creis): It's a bit surprising to go to frame_url_1 here instead of
@@ -5826,7 +5782,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
->root();
EXPECT_EQ(1, controller.GetEntryCount());
- EXPECT_EQ(1, RendererHistoryLength(shell()));
+ EXPECT_EQ(1, EvalJs(shell(), "history.length"));
// Add an iframe with no 'src'.
GURL blank_url(url::kAboutBlankURL);
@@ -5834,10 +5790,10 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
"var iframe = document.createElement('iframe');"
"iframe.id = 'frame';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecJs(root->current_frame_host(), script));
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
EXPECT_EQ(1, controller.GetEntryCount());
- EXPECT_EQ(1, RendererHistoryLength(shell()));
+ EXPECT_EQ(1, EvalJs(shell(), "history.length"));
EXPECT_EQ(0, controller.GetLastCommittedEntryIndex());
ASSERT_EQ(1U, root->child_count());
FrameTreeNode* frame = root->child_at(0);
@@ -5850,17 +5806,17 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
"iframe.contentWindow.document.write("
" \"<a id='fraglink' href='#frag'>fragment link</a>\");"
"iframe.contentWindow.document.close();";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), document_write_script));
+ EXPECT_TRUE(ExecJs(root->current_frame_host(), document_write_script));
// Click the link to do a same document navigation. Due to the
// document.write, the new URL matches the parent frame's URL.
GURL frame_url_2(embedded_test_server()->GetURL(
"/navigation_controller/page_with_links.html#frag"));
std::string link_script = "document.getElementById('fraglink').click()";
- EXPECT_TRUE(ExecuteScript(frame->current_frame_host(), link_script));
+ EXPECT_TRUE(ExecJs(frame->current_frame_host(), link_script));
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
EXPECT_EQ(2, controller.GetEntryCount());
- EXPECT_EQ(2, RendererHistoryLength(shell()));
+ EXPECT_EQ(2, EvalJs(shell(), "history.length"));
EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
EXPECT_EQ(frame_url_2, frame->current_url());
@@ -5874,7 +5830,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// Verify the process is still alive by running script. We can't just call
// IsRenderFrameLive after the navigation since it might not have disconnected
// yet.
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), "true;"));
+ EXPECT_TRUE(ExecJs(root->current_frame_host(), "true;"));
EXPECT_TRUE(root->current_frame_host()->IsRenderFrameLive());
EXPECT_EQ(blank_url, frame->current_url());
@@ -5896,7 +5852,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
->root();
EXPECT_EQ(1, controller.GetEntryCount());
- EXPECT_EQ(1, RendererHistoryLength(shell()));
+ EXPECT_EQ(1, EvalJs(shell(), "history.length"));
// Add an iframe with no 'src'.
GURL blank_url(url::kAboutBlankURL);
@@ -5904,10 +5860,10 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
"var iframe = document.createElement('iframe');"
"iframe.id = 'frame';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecJs(root->current_frame_host(), script));
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
EXPECT_EQ(1, controller.GetEntryCount());
- EXPECT_EQ(1, RendererHistoryLength(shell()));
+ EXPECT_EQ(1, EvalJs(shell(), "history.length"));
EXPECT_EQ(0, controller.GetLastCommittedEntryIndex());
ASSERT_EQ(1U, root->child_count());
FrameTreeNode* frame = root->child_at(0);
@@ -5915,21 +5871,22 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
EXPECT_EQ(blank_url, frame->current_url());
// Do a document.write in the subframe to create a link to click.
- std::string document_write_script =
+ std::string html = "<a id='fraglink' href='#frag'>fragment link</a>";
+ std::string document_write_script = JsReplace(
"var iframe = document.getElementById('frame');"
- "iframe.contentWindow.document.write("
- " \"<a id='fraglink' href='#frag'>fragment link</a>\");"
- "iframe.contentWindow.document.close();";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), document_write_script));
+ "iframe.contentWindow.document.write($1);"
+ "iframe.contentWindow.document.close();",
+ html);
+ EXPECT_TRUE(ExecJs(root->current_frame_host(), document_write_script));
// Click the link to do a same document navigation. Due to the
// document.write, the new URL matches the parent frame's URL.
GURL frame_url_2("data:text/html,Top level page#frag");
std::string link_script = "document.getElementById('fraglink').click()";
- EXPECT_TRUE(ExecuteScript(frame->current_frame_host(), link_script));
+ EXPECT_TRUE(ExecJs(frame->current_frame_host(), link_script));
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
EXPECT_EQ(2, controller.GetEntryCount());
- EXPECT_EQ(2, RendererHistoryLength(shell()));
+ EXPECT_EQ(2, EvalJs(shell(), "history.length"));
EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
EXPECT_EQ(frame_url_2, frame->current_url());
@@ -5943,7 +5900,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// Verify the process is still alive by running script. We can't just call
// IsRenderFrameLive after the navigation since it might not have disconnected
// yet.
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), "true;"));
+ EXPECT_TRUE(ExecJs(root->current_frame_host(), "true;"));
EXPECT_TRUE(root->current_frame_host()->IsRenderFrameLive());
EXPECT_EQ(blank_url, frame->current_url());
@@ -6108,7 +6065,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
"b.com", "/navigation_controller/simple_page_2.html"));
std::string replace_script = "location.replace('" + url_b.spec() + "')";
TestNavigationObserver replace_observer(shell()->web_contents());
- EXPECT_TRUE(ExecuteScript(shell()->web_contents(), replace_script));
+ EXPECT_TRUE(ExecJs(shell()->web_contents(), replace_script));
replace_observer.Wait();
EXPECT_EQ(3, controller.GetEntryCount());
EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
@@ -6120,8 +6077,8 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// Navigate forward twice using script. In https://crbug.com/623319, this
// caused a mismatch between the NavigationEntry's URL and PageState.
- EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
- "history.forward(); history.forward();"));
+ EXPECT_TRUE(
+ ExecJs(shell()->web_contents(), "history.forward(); history.forward();"));
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
EXPECT_EQ(url_b, root->current_url());
@@ -6193,7 +6150,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
"b.com", "/navigation_controller/page_with_data_iframe.html"));
std::string replace_script = "location.replace('" + url_b.spec() + "')";
TestNavigationObserver replace_observer(shell()->web_contents());
- EXPECT_TRUE(ExecuteScript(shell()->web_contents(), replace_script));
+ EXPECT_TRUE(ExecJs(shell()->web_contents(), replace_script));
replace_observer.Wait();
EXPECT_EQ(3, controller.GetEntryCount());
EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
@@ -6208,8 +6165,8 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// we want to ensure that the subframes target entry index 1 and not 2. In
// https://crbug.com/623319, the subframes targeted the wrong entry, leading
// to a URL spoof and renderer kill.
- EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
- "history.forward(); history.forward();"));
+ EXPECT_TRUE(
+ ExecJs(shell()->web_contents(), "history.forward(); history.forward();"));
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
EXPECT_TRUE(root->current_frame_host()->IsRenderFrameLive());
@@ -6269,7 +6226,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
TestNavigationObserver observer(shell()->web_contents());
std::string script =
"history.replaceState({}, '', '/server-redirect?" + url_3.spec() + "')";
- EXPECT_TRUE(ExecuteScript(root, script));
+ EXPECT_TRUE(ExecJs(root, script));
observer.Wait();
}
@@ -6327,7 +6284,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
TestNavigationObserver observer(shell()->web_contents());
std::string script = "history.replaceState({}, '', '/server-redirect?" +
frame_url2.spec() + "')";
- EXPECT_TRUE(ExecuteScript(root->child_at(0), script));
+ EXPECT_TRUE(ExecJs(root->child_at(0), script));
observer.Wait();
}
@@ -6427,8 +6384,8 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, PostViaOpenUrlMsg) {
// Submit the form.
TestNavigationObserver form_post_observer(shell()->web_contents(), 1);
- EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
- "document.getElementById('form').submit();"));
+ EXPECT_TRUE(ExecJs(shell()->web_contents(),
+ "document.getElementById('form').submit();"));
form_post_observer.Wait();
// Verify that we arrived at the expected location.
@@ -6437,9 +6394,170 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, PostViaOpenUrlMsg) {
// Verify that POST body was correctly passed to the server and ended up in
// the body of the page.
+ EXPECT_EQ(
+ "text=value\n",
+ EvalJs(shell(), "document.getElementsByTagName('pre')[0].innerText"));
+}
+
+// This test verifies that reloading a POST request that is uncacheable won't
+// incorrectly result in a GET request. This is a regression test for
+// https://crbug.com/860807.
+IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, UncacheablePost) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "/form_that_posts_to_echoall_nocache.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+ WebContents* web_contents = shell()->web_contents();
+ EXPECT_EQ(0, web_contents->GetController().GetLastCommittedEntryIndex());
+
+ // Submit the form.
+ TestNavigationObserver form_post_observer(web_contents, 1);
+ EXPECT_TRUE(
+ ExecuteScript(web_contents, "document.getElementById('form').submit();"));
+ form_post_observer.Wait();
+
+ // Verify that we arrived at the expected location.
+ GURL target_url(embedded_test_server()->GetURL("/echoall/nocache"));
+ EXPECT_EQ(target_url, web_contents->GetLastCommittedURL());
+ EXPECT_EQ(1, web_contents->GetController().GetLastCommittedEntryIndex());
+
+ // Verify that this was a POST request.
+ std::string request_headers;
+ EXPECT_TRUE(ExecuteScriptAndExtractString(
+ web_contents,
+ "window.domAutomationController.send("
+ "document.getElementsByTagName('pre')[1].innerText);",
+ &request_headers));
+ EXPECT_THAT(request_headers, ::testing::HasSubstr("POST /echoall/nocache"));
+
+ // Verify that POST body was correctly passed to the server and ended up in
+ // the body of the page.
std::string body;
EXPECT_TRUE(ExecuteScriptAndExtractString(
- shell()->web_contents(),
+ web_contents,
+ "window.domAutomationController.send("
+ "document.getElementsByTagName('pre')[0].innerText);",
+ &body));
+ EXPECT_EQ("text=value\n", body);
+
+ // Extract the response nonce.
+ std::string old_response_nonce;
+ std::string response_nonce_extraction_script = R"(
+ domAutomationController.send(
+ document.getElementById('response-nonce').innerText); )";
+ EXPECT_TRUE(ExecuteScriptAndExtractString(
+ web_contents, response_nonce_extraction_script, &old_response_nonce));
+
+ // Go back.
+ {
+ TestNavigationObserver observer(web_contents);
+ web_contents->GetController().GoBack();
+ observer.Wait();
+ }
+ EXPECT_EQ(main_url, web_contents->GetLastCommittedURL());
+ EXPECT_EQ(0, web_contents->GetController().GetLastCommittedEntryIndex());
+
+ // Go forward.
+ {
+ TestNavigationObserver navigation_observer(web_contents);
+ NavigationHandleObserver handle_observer(web_contents, target_url);
+ web_contents->GetController().GoForward();
+ navigation_observer.Wait();
+
+ // Verify that the previous response response really was treated as
+ // uncacheable.
+ EXPECT_TRUE(handle_observer.is_error());
+ EXPECT_EQ(net::ERR_CACHE_MISS, handle_observer.net_error_code());
+ }
+ EXPECT_EQ(target_url, web_contents->GetLastCommittedURL());
+ EXPECT_EQ(1, web_contents->GetController().GetLastCommittedEntryIndex());
+
+ // Reload
+ {
+ TestNavigationObserver observer(web_contents);
+ web_contents->GetController().Reload(content::ReloadType::NORMAL,
+ false); // check_for_repost
+ observer.Wait();
+ }
+ EXPECT_EQ(target_url, web_contents->GetLastCommittedURL());
+ EXPECT_EQ(1, web_contents->GetController().GetLastCommittedEntryIndex());
+
+ // MAIN VERIFICATION for https://crbug.com/860807: Verify that the reload was
+ // a POST request.
+ EXPECT_TRUE(ExecuteScriptAndExtractString(
+ web_contents,
+ "window.domAutomationController.send("
+ "document.getElementsByTagName('pre')[1].innerText);",
+ &request_headers));
+ EXPECT_THAT(request_headers, ::testing::HasSubstr("POST /echoall/nocache"));
+
+ // Verify that POST body was correctly passed to the server and ended up in
+ // the body of the page. This is supplementary verification against
+ // https://crbug.com/860807.
+ EXPECT_TRUE(ExecuteScriptAndExtractString(
+ web_contents,
+ "window.domAutomationController.send("
+ "document.getElementsByTagName('pre')[0].innerText);",
+ &body));
+ EXPECT_EQ("text=value\n", body);
+
+ // Extract the new response nonce and verify that it did change (e.g. that the
+ // reload did load fresh content).
+ std::string new_response_nonce;
+ EXPECT_TRUE(ExecuteScriptAndExtractString(
+ web_contents, response_nonce_extraction_script, &new_response_nonce));
+ EXPECT_NE(new_response_nonce, old_response_nonce);
+}
+
+// This test verifies that it is possible to reload a POST request that
+// initially failed (e.g. because the network was offline or the host was
+// unreachable during the initial navigation). This is a regression test for
+// https://crbug.com/869117.
+IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
+ ReloadOfInitiallyFailedPost) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "/form_that_posts_to_echoall_nocache.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+ WebContents* web_contents = shell()->web_contents();
+ EXPECT_EQ(0, web_contents->GetController().GetLastCommittedEntryIndex());
+
+ // Submit the form while simulating "network down" conditions.
+ GURL target_url(embedded_test_server()->GetURL("/echoall/nocache"));
+ {
+ std::unique_ptr<URLLoaderInterceptor> interceptor =
+ URLLoaderInterceptor::SetupRequestFailForURL(
+ target_url, net::ERR_INTERNET_DISCONNECTED);
+ TestNavigationObserver form_post_observer(web_contents, 1);
+ EXPECT_TRUE(ExecuteScript(web_contents,
+ "document.getElementById('form').submit();"));
+ form_post_observer.Wait();
+ }
+ EXPECT_EQ(target_url, web_contents->GetLastCommittedURL());
+ EXPECT_EQ(1, web_contents->GetController().GetLastCommittedEntryIndex());
+
+ // Reload
+ {
+ TestNavigationObserver observer(web_contents);
+ web_contents->GetController().Reload(content::ReloadType::NORMAL,
+ false); // check_for_repost
+ observer.Wait();
+ }
+ EXPECT_EQ(target_url, web_contents->GetLastCommittedURL());
+ EXPECT_EQ(1, web_contents->GetController().GetLastCommittedEntryIndex());
+
+ // Verify that the reload was a POST request.
+ std::string request_headers;
+ EXPECT_TRUE(ExecuteScriptAndExtractString(
+ web_contents,
+ "window.domAutomationController.send("
+ "document.getElementsByTagName('pre')[1].innerText);",
+ &request_headers));
+ EXPECT_THAT(request_headers, ::testing::HasSubstr("POST /echoall/nocache"));
+
+ // Verify that POST body was correctly passed to the server and ended up in
+ // the body of the page.
+ std::string body;
+ EXPECT_TRUE(ExecuteScriptAndExtractString(
+ web_contents,
"window.domAutomationController.send("
"document.getElementsByTagName('pre')[0].innerText);",
&body));
@@ -6494,7 +6612,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// Removing the first child of the main frame should remove the corresponding
// FrameTreeNode.
- EXPECT_TRUE(ExecuteScript(root, kRemoveFrameScript));
+ EXPECT_TRUE(ExecJs(root, kRemoveFrameScript));
EXPECT_EQ(2U, root->child_count());
// However, the FrameNavigationEntry objects for the frame that was removed
@@ -6535,7 +6653,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
"f.src = '1-1.html';"
"document.body.appendChild(f);";
TestNavigationObserver observer(web_contents, 1);
- EXPECT_TRUE(ExecuteScript(subframe, add_matching_name_frame_script));
+ EXPECT_TRUE(ExecJs(subframe, add_matching_name_frame_script));
EXPECT_EQ(1U, subframe->child_count());
observer.Wait();
@@ -6575,7 +6693,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// |tree_node| will becoma a dangling pointer when the frame is removed below.
auto* tree_node = nav_entry->root_node()->children[0].get();
- EXPECT_TRUE(ExecuteScript(root, kRemoveFrameScript));
+ EXPECT_TRUE(ExecJs(root, kRemoveFrameScript));
EXPECT_EQ(0U, root->child_count());
EXPECT_EQ(0U, nav_entry->root_node()->children.size());
@@ -6588,7 +6706,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
EXPECT_EQ(1U, nav_entry->root_node()->children.size());
EXPECT_NE(tree_node, nav_entry->root_node()->children[0].get());
- EXPECT_TRUE(ExecuteScript(root, kRemoveFrameScript));
+ EXPECT_TRUE(ExecJs(root, kRemoveFrameScript));
EXPECT_EQ(0U, root->child_count());
}
@@ -6619,7 +6737,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
TestNavigationObserver observer(web_contents);
std::string script = "history.replaceState({}, '', '/server-redirect?" +
redirect_dest_url.spec() + "')";
- EXPECT_TRUE(ExecuteScript(root, script));
+ EXPECT_TRUE(ExecJs(root, script));
observer.Wait();
}
@@ -6646,10 +6764,8 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// Verify the expected origin through JavaScript. It also has the additional
// verification of the process also being still alive.
- std::string origin;
- EXPECT_TRUE(ExecuteScriptAndExtractString(
- web_contents, "domAutomationController.send(document.origin)", &origin));
- EXPECT_EQ(start_url.GetOrigin().spec(), origin + "/");
+ EXPECT_EQ(url::Origin::Create(start_url).Serialize(),
+ EvalJs(web_contents, "document.origin"));
}
// Helper to trigger a history-back navigation in the WebContents after the
@@ -6737,10 +6853,8 @@ IN_PROC_BROWSER_TEST_F(
// Verify the expected origin through JavaScript. It also has the additional
// verification of the process also being still alive.
- std::string origin;
- EXPECT_TRUE(ExecuteScriptAndExtractString(
- web_contents, "domAutomationController.send(document.origin)", &origin));
- EXPECT_EQ(start_url.GetOrigin().spec(), origin + "/");
+ EXPECT_EQ(url::Origin::Create(start_url).Serialize(),
+ EvalJs(web_contents, "document.origin"));
}
// Test that verifies that Referer and Origin http headers are correctly sent
@@ -6764,7 +6878,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// 3. http://x.com:.../echoall/
TestNavigationObserver form_post_observer(shell()->web_contents(), 1);
EXPECT_TRUE(
- ExecuteScript(shell(), "document.getElementById('text-form').submit();"));
+ ExecJs(shell(), "document.getElementById('text-form').submit();"));
form_post_observer.Wait();
// Verify that we arrived at the expected, redirected location.
@@ -6772,12 +6886,9 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
shell()->web_contents()->GetLastCommittedURL());
// Get the http request headers.
- std::string headers;
- EXPECT_TRUE(ExecuteScriptAndExtractString(
- shell(),
- "window.domAutomationController.send("
- "document.getElementsByTagName('pre')[1].innerText);",
- &headers));
+ std::string headers =
+ EvalJs(shell(), "document.getElementsByTagName('pre')[1].innerText")
+ .ExtractString();
// Verify the Origin and Referer headers.
EXPECT_THAT(headers, ::testing::HasSubstr("Origin: null"));
@@ -6919,7 +7030,7 @@ void ExecuteJavaScriptAndWaitForLoadStop(WebContents* web_contents,
// JavaScript asynchronously.
TestNavigationObserver observer(web_contents);
- // ExecuteScript() sets a user gesture flag internally for testing, but we
+ // ExecJs() sets a user gesture flag internally for testing, but we
// want to run JavaScript without the flag. Call ExecuteJavaScriptForTests
// directory.
static_cast<WebContentsImpl*>(web_contents)
@@ -7206,8 +7317,8 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
NavigationHandleCommitObserver push_state_observer(shell()->web_contents(),
kPushStateURL);
std::string push_state =
- "history.pushState({}, \"title 1\", \"" + kPushStateURL.spec() + "\");";
- EXPECT_TRUE(ExecuteScript(shell()->web_contents(), push_state));
+ JsReplace("history.pushState({}, 'title 1', $1);", kPushStateURL);
+ EXPECT_TRUE(ExecJs(shell()->web_contents(), push_state));
NavigationEntry* last_committed =
shell()->web_contents()->GetController().GetLastCommittedEntry();
ASSERT_TRUE(last_committed);
@@ -7471,17 +7582,13 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// The opener should not be able to script the page, which should be another
// error message and not a blank page.
- std::string result;
- EXPECT_TRUE(ExecuteScriptAndExtractString(
- shell(),
- "domAutomationController.send((function() {\n"
- " try {\n"
- " return w.document.body.innerHTML;\n"
- " } catch (e) {\n"
- " return e.toString();\n"
- " }\n"
- "})())",
- &result));
+ std::string result = EvalJs(shell(),
+ "try {\n"
+ " w.document.body.innerHTML;\n"
+ "} catch (e) {\n"
+ " e.toString();\n"
+ "}")
+ .ExtractString();
DLOG(INFO) << "Result: " << result;
EXPECT_THAT(result,
::testing::MatchesRegex("SecurityError: Blocked a frame with "
@@ -7527,8 +7634,12 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
TestNavigationObserver observer(shell()->web_contents());
controller.GoBack();
observer.Wait();
+ GURL x_frame_options_deny_url =
+ embedded_test_server()->GetURL("/x-frame-options-deny.html");
+ EXPECT_EQ(x_frame_options_deny_url, root->child_at(0)->current_url());
+ EXPECT_EQ(net::ERR_BLOCKED_BY_RESPONSE, observer.last_net_error_code());
+ EXPECT_FALSE(observer.last_navigation_succeeded());
}
- EXPECT_EQ(GURL("data:,"), root->child_at(0)->current_url());
// Go back again. This would have been same-document if the prior navigation
// had succeeded.
@@ -7731,25 +7842,19 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
EXPECT_TRUE(NavigateToURL(shell(), main_url));
// Repeatedly create and remove a frame from a script.
- std::string result;
std::string script = R"(
- var iterations_left = 5;
- function runOneIteration() {
- if (iterations_left == 0) {
- domAutomationController.send("done-with-test");
- return;
- }
-
- var iframe = document.createElement("iframe");
- document.body.appendChild(iframe);
- document.body.removeChild(iframe);
-
- iterations_left = iterations_left - 1;
- setTimeout(runOneIteration, 0);
- }
- runOneIteration(); )";
- EXPECT_TRUE(ExecuteScriptAndExtractString(shell(), script, &result));
- EXPECT_EQ("done-with-test", result);
+ (async () => {
+ for (let i = 0; i < 5; i++) {
+ // Create and remove an iframe.
+ let iframe = document.createElement('iframe');
+ document.body.appendChild(iframe);
+ document.body.removeChild(iframe);
+ // Let the message loop run (this works in an async function).
+ await new Promise(resolve => setTimeout(resolve, 0));
+ }
+ return 'done-with-test';
+ })(); )";
+ EXPECT_EQ("done-with-test", EvalJs(shell(), script));
// Grab the last committed entry.
const NavigationControllerImpl& controller =
@@ -8007,13 +8112,8 @@ IN_PROC_BROWSER_TEST_F(ContentBrowserTest, HistoryBackInUnloadCancelsReload) {
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
// Test what is in the loaded document.
- std::string html_content;
- EXPECT_TRUE(ExecuteScriptAndExtractString(
- shell(), "domAutomationController.send(document.body.textContent)",
- &html_content));
-
EXPECT_EQ("First part of the response... ...and the second part!",
- html_content);
+ EvalJs(shell(), "document.body.textContent"));
}
// Data URLs can have a reference fragment like any other URLs. In this test,
diff --git a/chromium/content/browser/frame_host/navigation_entry_screenshot_manager.cc b/chromium/content/browser/frame_host/navigation_entry_screenshot_manager.cc
index 0b8b2df4b80..5930c7d1acf 100644
--- a/chromium/content/browser/frame_host/navigation_entry_screenshot_manager.cc
+++ b/chromium/content/browser/frame_host/navigation_entry_screenshot_manager.cc
@@ -8,7 +8,7 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/ref_counted_memory.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "content/browser/frame_host/navigation_controller_impl.h"
#include "content/browser/frame_host/navigation_entry_impl.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
diff --git a/chromium/content/browser/frame_host/navigation_handle_impl.cc b/chromium/content/browser/frame_host/navigation_handle_impl.cc
index 201f23b9b42..6bc8930b7d8 100644
--- a/chromium/content/browser/frame_host/navigation_handle_impl.cc
+++ b/chromium/content/browser/frame_host/navigation_handle_impl.cc
@@ -6,8 +6,10 @@
#include <iterator>
+#include "base/bind.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
+#include "base/time/time.h"
#include "content/browser/appcache/appcache_navigation_handle.h"
#include "content/browser/appcache/appcache_service_impl.h"
#include "content/browser/child_process_security_policy_impl.h"
@@ -25,6 +27,7 @@
#include "content/browser/frame_host/origin_policy_throttle.h"
#include "content/browser/frame_host/webui_navigation_throttle.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
+#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_navigation_handle.h"
#include "content/common/child_process_host_impl.h"
@@ -46,6 +49,16 @@ namespace content {
namespace {
+// Default timeout for the READY_TO_COMMIT -> COMMIT transition. Chosen
+// initially based on the Navigation.ReadyToCommitUntilCommit UMA, and then
+// refined based on feedback based on CrashExitCodes.Renderer/RESULT_CODE_HUNG.
+constexpr base::TimeDelta kDefaultCommitTimeout =
+ base::TimeDelta::FromSeconds(30);
+
+// Timeout for the READY_TO_COMMIT -> COMMIT transition.
+// Overrideable via SetCommitTimeoutForTesting.
+base::TimeDelta g_commit_timeout = kDefaultCommitTimeout;
+
// Use this to get a new unique ID for a NavigationHandle during construction.
// The returned ID is guaranteed to be nonzero (zero is the "no ID" indicator).
int64_t CreateUniqueHandleID() {
@@ -114,7 +127,7 @@ std::unique_ptr<NavigationHandleImpl> NavigationHandleImpl::Create(
FrameTreeNode* frame_tree_node,
bool is_renderer_initiated,
bool is_same_document,
- const base::TimeTicks& navigation_start,
+ base::TimeTicks navigation_start,
int pending_nav_entry_id,
bool started_from_context_menu,
CSPDisposition should_check_main_world_csp,
@@ -128,7 +141,8 @@ std::unique_ptr<NavigationHandleImpl> NavigationHandleImpl::Create(
ui::PageTransition transition,
bool is_external_protocol,
RequestContextType request_context_type,
- blink::WebMixedContentContextType mixed_content_context_type) {
+ blink::WebMixedContentContextType mixed_content_context_type,
+ base::TimeTicks input_start) {
return std::unique_ptr<NavigationHandleImpl>(new NavigationHandleImpl(
url, redirect_chain, frame_tree_node, is_renderer_initiated,
is_same_document, navigation_start, pending_nav_entry_id,
@@ -136,7 +150,7 @@ std::unique_ptr<NavigationHandleImpl> NavigationHandleImpl::Create(
is_form_submission, std::move(navigation_ui_data), method,
std::move(request_headers), resource_request_body, sanitized_referrer,
has_user_gesture, transition, is_external_protocol, request_context_type,
- mixed_content_context_type));
+ mixed_content_context_type, input_start));
}
NavigationHandleImpl::NavigationHandleImpl(
@@ -145,7 +159,7 @@ NavigationHandleImpl::NavigationHandleImpl(
FrameTreeNode* frame_tree_node,
bool is_renderer_initiated,
bool is_same_document,
- const base::TimeTicks& navigation_start,
+ base::TimeTicks navigation_start,
int pending_nav_entry_id,
bool started_from_context_menu,
CSPDisposition should_check_main_world_csp,
@@ -159,7 +173,8 @@ NavigationHandleImpl::NavigationHandleImpl(
ui::PageTransition transition,
bool is_external_protocol,
RequestContextType request_context_type,
- blink::WebMixedContentContextType mixed_content_context_type)
+ blink::WebMixedContentContextType mixed_content_context_type,
+ base::TimeTicks input_start)
: url_(url),
has_user_gesture_(has_user_gesture),
transition_(transition),
@@ -180,6 +195,7 @@ NavigationHandleImpl::NavigationHandleImpl(
frame_tree_node_(frame_tree_node),
next_index_(0),
navigation_start_(navigation_start),
+ input_start_(input_start),
pending_nav_entry_id_(pending_nav_entry_id),
request_context_type_(request_context_type),
mixed_content_context_type_(mixed_content_context_type),
@@ -343,10 +359,14 @@ RenderFrameHostImpl* NavigationHandleImpl::GetParentFrame() {
return frame_tree_node_->parent()->current_frame_host();
}
-const base::TimeTicks& NavigationHandleImpl::NavigationStart() {
+base::TimeTicks NavigationHandleImpl::NavigationStart() {
return navigation_start_;
}
+base::TimeTicks NavigationHandleImpl::NavigationInputStart() {
+ return input_start_;
+}
+
bool NavigationHandleImpl::IsPost() {
return method_ == "POST";
}
@@ -550,6 +570,11 @@ void NavigationHandleImpl::CallResumeForTesting() {
ResumeInternal();
}
+bool NavigationHandleImpl::IsDeferredForTesting() {
+ return state_ == DEFERRING_START || state_ == DEFERRING_REDIRECT ||
+ state_ == DEFERRING_FAILURE || state_ == DEFERRING_RESPONSE;
+}
+
bool NavigationHandleImpl::WasStartedFromContextMenu() const {
return started_from_context_menu_;
}
@@ -822,6 +847,7 @@ void NavigationHandleImpl::ReadyToCommitNavigation(
render_frame_host_ = render_frame_host;
state_ = READY_TO_COMMIT;
ready_to_commit_time_ = base::TimeTicks::Now();
+ RestartCommitTimeout();
// Record metrics for the time it takes to get to this state from the
// beginning of the navigation.
@@ -897,6 +923,8 @@ void NavigationHandleImpl::DidCommitNavigation(
"DidCommitNavigation");
state_ = DID_COMMIT;
}
+ commit_timeout_timer_.Stop();
+ GetRenderFrameHost()->GetRenderWidgetHost()->RendererIsResponsive();
// Record metrics for the time it took to commit the navigation if it was to
// another document without error.
@@ -1381,4 +1409,31 @@ NavigationThrottle* NavigationHandleImpl::GetDeferringThrottle() const {
return throttles_[next_index_ - 1].get();
}
+void NavigationHandleImpl::RestartCommitTimeout() {
+ commit_timeout_timer_.Stop();
+ if (state_ >= DID_COMMIT)
+ return;
+
+ commit_timeout_timer_.Start(
+ FROM_HERE, g_commit_timeout,
+ base::BindRepeating(&NavigationHandleImpl::OnCommitTimeout,
+ weak_factory_.GetWeakPtr()));
+}
+
+void NavigationHandleImpl::OnCommitTimeout() {
+ DCHECK_EQ(READY_TO_COMMIT, state_);
+ GetRenderFrameHost()->GetRenderWidgetHost()->RendererIsUnresponsive(
+ base::BindRepeating(&NavigationHandleImpl::RestartCommitTimeout,
+ weak_factory_.GetWeakPtr()));
+}
+
+// static
+void NavigationHandleImpl::SetCommitTimeoutForTesting(
+ const base::TimeDelta& timeout) {
+ if (timeout.is_zero())
+ g_commit_timeout = kDefaultCommitTimeout;
+ else
+ g_commit_timeout = timeout;
+}
+
} // namespace content
diff --git a/chromium/content/browser/frame_host/navigation_handle_impl.h b/chromium/content/browser/frame_host/navigation_handle_impl.h
index fe477a944b9..22ecf65f214 100644
--- a/chromium/content/browser/frame_host/navigation_handle_impl.h
+++ b/chromium/content/browser/frame_host/navigation_handle_impl.h
@@ -18,6 +18,8 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/optional.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
#include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/common/content_export.h"
@@ -61,7 +63,7 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
FrameTreeNode* frame_tree_node,
bool is_renderer_initiated,
bool is_same_document,
- const base::TimeTicks& navigation_start,
+ base::TimeTicks navigation_start,
int pending_nav_entry_id,
bool started_from_context_menu,
CSPDisposition should_check_main_world_csp,
@@ -78,7 +80,8 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
RequestContextType request_context_type =
REQUEST_CONTEXT_TYPE_UNSPECIFIED,
blink::WebMixedContentContextType mixed_content_context_type =
- blink::WebMixedContentContextType::kBlockable);
+ blink::WebMixedContentContextType::kBlockable,
+ base::TimeTicks input_start = base::TimeTicks());
~NavigationHandleImpl() override;
@@ -110,7 +113,8 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
const std::vector<GURL>& GetRedirectChain() override;
int GetFrameTreeNodeId() override;
RenderFrameHostImpl* GetParentFrame() override;
- const base::TimeTicks& NavigationStart() override;
+ base::TimeTicks NavigationStart() override;
+ base::TimeTicks NavigationInputStart() override;
bool IsPost() override;
const scoped_refptr<network::ResourceRequestBody>& GetResourceRequestBody()
override;
@@ -150,6 +154,7 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
const std::string& raw_response_header) override;
void CallDidCommitNavigationForTesting(const GURL& url) override;
void CallResumeForTesting() override;
+ bool IsDeferredForTesting() override;
bool WasStartedFromContextMenu() const override;
const GURL& GetSearchableFormURL() override;
const std::string& GetSearchableFormEncoding() override;
@@ -377,6 +382,10 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
return GetDeferringThrottle();
}
+ // Sets the READY_TO_COMMIT -> DID_COMMIT timeout. Resets the timeout to the
+ // default value if |timeout| is zero.
+ static void SetCommitTimeoutForTesting(const base::TimeDelta& timeout);
+
private:
friend class NavigationHandleImplTest;
@@ -386,7 +395,7 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
FrameTreeNode* frame_tree_node,
bool is_renderer_initiated,
bool is_same_document,
- const base::TimeTicks& navigation_start,
+ base::TimeTicks navigation_start,
int pending_nav_entry_id,
bool started_from_context_menu,
CSPDisposition should_check_main_world_csp,
@@ -400,7 +409,8 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
ui::PageTransition transition,
bool is_external_protocol,
RequestContextType request_context_type,
- blink::WebMixedContentContextType mixed_content_context_type);
+ blink::WebMixedContentContextType mixed_content_context_type,
+ base::TimeTicks input_start);
NavigationThrottle::ThrottleCheckResult CheckWillStartRequest();
NavigationThrottle::ThrottleCheckResult CheckWillRedirectRequest();
@@ -440,6 +450,12 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
// nullptr;
NavigationThrottle* GetDeferringThrottle() const;
+ // Called if READY_TO_COMMIT -> COMMIT state transition takes an unusually
+ // long time.
+ void OnCommitTimeout();
+
+ void RestartCommitTimeout();
+
// See NavigationHandle for a description of those member variables.
GURL url_;
scoped_refptr<SiteInstance> starting_site_instance_;
@@ -492,9 +508,17 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
// The time this navigation started.
const base::TimeTicks navigation_start_;
+ // The time the input event that lead to this navigation started.
+ // Currently available only if the navigation was initiated by
+ // the user clicking a link in the renderer.
+ const base::TimeTicks input_start_;
+
// The time this naviagtion was ready to commit.
base::TimeTicks ready_to_commit_time_;
+ // Timer for detecting an unexpectedly long time to commit a navigation.
+ base::OneShotTimer commit_timeout_timer_;
+
// The unique id of the corresponding NavigationEntry.
int pending_nav_entry_id_;
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 c199bfb8bb9..9cd758fa060 100644
--- a/chromium/content/browser/frame_host/navigation_handle_impl_browsertest.cc
+++ b/chromium/content/browser/frame_host/navigation_handle_impl_browsertest.cc
@@ -1444,15 +1444,16 @@ class NavigationHandleImplHttpsUpgradeBrowserTest
// Tests that the start URL is HTTPS upgraded for a same site navigation.
IN_PROC_BROWSER_TEST_F(NavigationHandleImplHttpsUpgradeBrowserTest,
StartUrlIsHttpsUpgradedSameSite) {
- GURL start_url(
- embedded_test_server()->GetURL("/https_upgrade_same_site.html"));
+ GURL start_url(embedded_test_server()->GetURL(
+ "example.com", "/https_upgrade_same_site.html"));
// Builds the expected upgraded same site URL.
GURL::Replacements replace_scheme;
replace_scheme.SetSchemeStr("https");
- GURL cross_site_iframe_secure_url = embedded_test_server()
- ->GetURL("/title1.html")
- .ReplaceComponents(replace_scheme);
+ GURL cross_site_iframe_secure_url =
+ embedded_test_server()
+ ->GetURL("example.com", "/title1.html")
+ .ReplaceComponents(replace_scheme);
CheckHttpsUpgradedIframeNavigation(start_url, cross_site_iframe_secure_url);
}
diff --git a/chromium/content/browser/frame_host/navigation_request.cc b/chromium/content/browser/frame_host/navigation_request.cc
index dd7375c470e..701167c2055 100644
--- a/chromium/content/browser/frame_host/navigation_request.cc
+++ b/chromium/content/browser/frame_host/navigation_request.cc
@@ -210,9 +210,9 @@ void AddAdditionalRequestHeaders(
}
}
std::string value = base::StringPrintf(
- "cause=\"%s\", destination=\"document\", target=\"%s\", site=\"%s\"",
+ "cause=\"%s\", destination=\"%s\", site=\"%s\"",
has_user_gesture ? "user-activated" : "forced",
- frame_tree_node->IsMainFrame() ? "top-level" : "nested",
+ frame_tree_node->IsMainFrame() ? "document" : "nested-document",
site_value.c_str());
headers->SetHeaderIfMissing("Sec-Metadata", value);
}
@@ -693,7 +693,8 @@ void NavigationRequest::CreateNavigationHandle() {
common_params_.referrer),
common_params_.has_user_gesture, common_params_.transition,
is_external_protocol, begin_params_->request_context_type,
- begin_params_->mixed_content_context_type);
+ begin_params_->mixed_content_context_type,
+ common_params_.input_start);
if (!frame_tree_node->navigation_request()) {
// A callback could have cancelled this request synchronously in which case
@@ -925,8 +926,9 @@ void NavigationRequest::OnResponseStarted(
const GlobalRequestID& request_id,
bool is_download,
bool is_stream,
+ PreviewsState previews_state,
base::Optional<SubresourceLoaderParams> subresource_loader_params) {
- DCHECK(state_ == STARTED);
+ DCHECK_EQ(state_, STARTED);
DCHECK(response);
TRACE_EVENT_ASYNC_STEP_INTO0("navigation", "NavigationRequest", this,
"OnResponseStarted");
@@ -993,8 +995,7 @@ void NavigationRequest::OnResponseStarted(
}
// Update the previews state of the request.
- common_params_.previews_state =
- static_cast<PreviewsState>(response->head.previews_state);
+ common_params_.previews_state = previews_state;
// Select an appropriate renderer to commit the navigation.
RenderFrameHostImpl* render_frame_host = nullptr;
@@ -1073,8 +1074,13 @@ void NavigationRequest::OnResponseStarted(
// download.
if (is_download && (response->head.headers.get() &&
(response->head.headers->response_code() / 100 != 2))) {
- navigation_handle_->set_net_error_code(net::ERR_INVALID_RESPONSE);
- frame_tree_node_->ResetNavigationRequest(false, true);
+ OnRequestFailedInternal(
+ network::URLLoaderCompletionStatus(net::ERR_INVALID_RESPONSE),
+ false /* skip_throttles */, base::nullopt /* error_page_content */,
+ false /* collapse_frame */);
+
+ // DO NOT ADD CODE after this. The previous call to OnRequestFailedInternal
+ // has destroyed the NavigationRequest.
return;
}
@@ -1498,6 +1504,7 @@ void NavigationRequest::OnWillProcessResponseChecksComplete(
resource_request->method = common_params_.method;
resource_request->request_initiator = begin_params_->initiator_origin;
resource_request->referrer = common_params_.referrer.url;
+ resource_request->has_user_gesture = common_params_.has_user_gesture;
BrowserContext* browser_context =
frame_tree_node_->navigator()->GetController()->GetBrowserContext();
diff --git a/chromium/content/browser/frame_host/navigation_request.h b/chromium/content/browser/frame_host/navigation_request.h
index 10440a4a70c..5d4aa5cbeab 100644
--- a/chromium/content/browser/frame_host/navigation_request.h
+++ b/chromium/content/browser/frame_host/navigation_request.h
@@ -237,6 +237,7 @@ class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate {
const GlobalRequestID& request_id,
bool is_download,
bool is_stream,
+ PreviewsState previews_state,
base::Optional<SubresourceLoaderParams> subresource_loader_params)
override;
void OnRequestFailed(
diff --git a/chromium/content/browser/frame_host/navigator_impl_unittest.cc b/chromium/content/browser/frame_host/navigator_impl_unittest.cc
index 78c1a044c48..7d748abfede 100644
--- a/chromium/content/browser/frame_host/navigator_impl_unittest.cc
+++ b/chromium/content/browser/frame_host/navigator_impl_unittest.cc
@@ -133,7 +133,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
EXPECT_TRUE(main_test_rfh()->navigation_request());
main_test_rfh()->SendNavigate(entry_id, true, kUrl);
EXPECT_TRUE(main_test_rfh()->is_active());
- EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(browser_context(), kUrl),
+ EXPECT_EQ(SiteInstance::GetSiteForURL(browser_context(), kUrl),
main_test_rfh()->GetSiteInstance()->GetSiteURL());
EXPECT_EQ(kUrl, contents()->GetLastCommittedURL());
@@ -187,7 +187,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
// Commit the navigation.
navigation->Commit();
EXPECT_TRUE(main_test_rfh()->is_active());
- EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(browser_context(), kUrl2),
+ EXPECT_EQ(SiteInstance::GetSiteForURL(browser_context(), kUrl2),
main_test_rfh()->GetSiteInstance()->GetSiteURL());
EXPECT_EQ(kUrl2, contents()->GetLastCommittedURL());
EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
@@ -878,7 +878,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
// Receive the beforeUnload ACK.
main_test_rfh()->SendBeforeUnloadACK(true);
EXPECT_EQ(speculative_rfh, GetSpeculativeRenderFrameHost(node));
- EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(browser_context(), kUrl),
+ EXPECT_EQ(SiteInstance::GetSiteForURL(browser_context(), kUrl),
speculative_rfh->GetSiteInstance()->GetSiteURL());
int32_t site_instance_id = speculative_rfh->GetSiteInstance()->GetId();
int64_t navigation_id =
@@ -923,7 +923,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
EXPECT_NE(init_site_instance_id, site_instance_id);
EXPECT_EQ(init_site_instance_id, main_test_rfh()->GetSiteInstance()->GetId());
EXPECT_NE(speculative_rfh, main_test_rfh());
- EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(browser_context(), kUrl),
+ EXPECT_EQ(SiteInstance::GetSiteForURL(browser_context(), kUrl),
speculative_rfh->GetSiteInstance()->GetSiteURL());
// Receive the beforeUnload ACK.
@@ -960,7 +960,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
// Once commit happens the speculative RenderFrameHost is updated to match the
// known final SiteInstance.
- EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(browser_context(), kUrlRedirect),
+ EXPECT_EQ(SiteInstance::GetSiteForURL(browser_context(), kUrlRedirect),
speculative_rfh->GetSiteInstance()->GetSiteURL());
int32_t redirect_site_instance_id =
speculative_rfh->GetSiteInstance()->GetId();
diff --git a/chromium/content/browser/frame_host/origin_policy_throttle.cc b/chromium/content/browser/frame_host/origin_policy_throttle.cc
index ab137232754..5d2904a633b 100644
--- a/chromium/content/browser/frame_host/origin_policy_throttle.cc
+++ b/chromium/content/browser/frame_host/origin_policy_throttle.cc
@@ -8,14 +8,14 @@
#include "base/feature_list.h"
#include "base/no_destructor.h"
#include "content/browser/frame_host/navigation_handle_impl.h"
+#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_handle.h"
-#include "content/public/browser/network_service_instance.h"
+#include "content/public/browser/storage_partition.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
+#include "net/base/load_flags.h"
#include "net/http/http_request_headers.h"
-#include "services/network/network_context.h"
-#include "services/network/network_service.h"
#include "services/network/public/cpp/simple_url_loader.h"
#include "url/origin.h"
@@ -164,24 +164,6 @@ const url::Origin OriginPolicyThrottle::GetRequestOrigin() {
}
void OriginPolicyThrottle::FetchPolicy(const GURL& url, FetchCallback done) {
- // Obtain a network context from the network service.
- network::mojom::NetworkContextParamsPtr context_params =
- network::mojom::NetworkContextParams::New();
- content::GetNetworkService()->CreateNetworkContext(
- mojo::MakeRequest(&network_context_ptr_), std::move(context_params));
-
- // Create URLLoaderFactory
- network::mojom::URLLoaderFactoryParamsPtr url_loader_factory_params =
- network::mojom::URLLoaderFactoryParams::New();
- url_loader_factory_params->process_id = network::mojom::kBrowserProcessId;
- url_loader_factory_params->is_corb_enabled = false;
- url_loader_factory_params->disable_web_security =
- base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableWebSecurity);
- network_context_ptr_->CreateURLLoaderFactory(
- mojo::MakeRequest(&url_loader_factory_),
- std::move(url_loader_factory_params));
-
// Create the traffic annotation
net::NetworkTrafficAnnotationTag traffic_annotation =
net::DefineNetworkTrafficAnnotation("origin_policy_loader", R"(
@@ -209,14 +191,27 @@ void OriginPolicyThrottle::FetchPolicy(const GURL& url, FetchCallback done) {
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->fetch_credentials_mode =
+ network::mojom::FetchCredentialsMode::kOmit;
policy_request->fetch_redirect_mode =
network::mojom::FetchRedirectMode::kError;
+ 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_->SetAllowHttpErrorResults(false);
+
+ // Obtain the URLLoaderFactory from the NavigationHandle.
+ SiteInstance* site_instance = navigation_handle()->GetStartingSiteInstance();
+ content::StoragePartition* storage_partition =
+ BrowserContext::GetStoragePartition(site_instance->GetBrowserContext(),
+ site_instance);
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory =
+ storage_partition->GetURLLoaderFactoryForBrowserProcess();
// Start the download, and pass the callback for when we're finished.
- url_loader_->DownloadToString(url_loader_factory_.get(), std::move(done),
+ url_loader_->DownloadToString(url_loader_factory.get(), std::move(done),
kMaxPolicySize);
}
@@ -229,8 +224,6 @@ void OriginPolicyThrottle::OnTheGloriousPolicyHasArrived(
std::unique_ptr<std::string> policy_content) {
// Release resources associated with the loading.
url_loader_.reset();
- url_loader_factory_.reset();
- network_context_ptr_.reset();
// Fail hard if the policy could not be loaded.
if (!policy_content) {
diff --git a/chromium/content/browser/frame_host/origin_policy_throttle.h b/chromium/content/browser/frame_host/origin_policy_throttle.h
index ac200046c8c..320558cce4e 100644
--- a/chromium/content/browser/frame_host/origin_policy_throttle.h
+++ b/chromium/content/browser/frame_host/origin_policy_throttle.h
@@ -6,11 +6,13 @@
#define CONTENT_BROWSER_FRAME_HOST_ORIGIN_POLICY_THROTTLE_H_
#include <map>
+#include <memory>
#include <string>
+
#include "base/gtest_prod_util.h"
#include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
#include "content/public/browser/navigation_throttle.h"
-#include "services/network/public/mojom/network_service.mojom.h"
class GURL;
@@ -71,11 +73,8 @@ class CONTENT_EXPORT OriginPolicyThrottle : public NavigationThrottle {
void OnTheGloriousPolicyHasArrived(
std::unique_ptr<std::string> policy_content);
- // We may need the SimpleURLLoader to download the policy.
- // The network context and url loader must be kept alive while the load is
- // ongoing.
- network::mojom::NetworkContextPtr network_context_ptr_;
- network::mojom::URLLoaderFactoryPtr url_loader_factory_;
+ // 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_;
DISALLOW_COPY_AND_ASSIGN(OriginPolicyThrottle);
diff --git a/chromium/content/browser/frame_host/render_frame_host_android.h b/chromium/content/browser/frame_host/render_frame_host_android.h
index 423e1a62778..23ae2410604 100644
--- a/chromium/content/browser/frame_host/render_frame_host_android.h
+++ b/chromium/content/browser/frame_host/render_frame_host_android.h
@@ -52,6 +52,8 @@ class RenderFrameHostAndroid : public base::SupportsUserData::Data {
void NotifyUserActivation(JNIEnv* env,
const base::android::JavaParamRef<jobject>&);
+ RenderFrameHostImpl* render_frame_host() const { return render_frame_host_; }
+
private:
RenderFrameHostImpl* const render_frame_host_;
service_manager::mojom::InterfaceProviderPtr interface_provider_ptr_;
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 26b8eec2bb7..623cd428e20 100644
--- a/chromium/content/browser/frame_host/render_frame_host_delegate.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_delegate.cc
@@ -126,4 +126,9 @@ Visibility RenderFrameHostDelegate::GetVisibility() const {
return Visibility::HIDDEN;
}
+ukm::SourceId RenderFrameHostDelegate::GetUkmSourceIdForLastCommittedSource()
+ const {
+ return ukm::kInvalidSourceId;
+}
+
} // 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 7919ac1e579..9ac81d17f61 100644
--- a/chromium/content/browser/frame_host/render_frame_host_delegate.h
+++ b/chromium/content/browser/frame_host/render_frame_host_delegate.h
@@ -27,6 +27,7 @@
#include "net/http/http_response_headers.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_source_id.h"
#include "ui/base/window_open_disposition.h"
#if defined(OS_WIN)
@@ -69,6 +70,7 @@ struct AXEventNotificationDetails;
struct AXLocationChangeNotificationDetails;
struct ContextMenuParams;
struct FileChooserParams;
+struct GlobalRequestID;
namespace mojom {
class CreateNewWindowParams;
@@ -363,6 +365,7 @@ class CONTENT_EXPORT RenderFrameHostDelegate {
// associated with |render_frame_host|.
virtual void ResourceLoadComplete(
RenderFrameHost* render_frame_host,
+ const GlobalRequestID& request_id,
mojom::ResourceLoadInfoPtr resource_load_info) {}
// Request to print a frame that is in a different process than its parent.
@@ -378,6 +381,18 @@ class CONTENT_EXPORT RenderFrameHostDelegate {
// Returns the visibility of the delegate.
virtual Visibility GetVisibility() const;
+ // Get the UKM source ID for current content. This is used for providing
+ // data about the content to the URL-keyed metrics service.
+ // Note: This is also exposed by the RenderWidgetHostDelegate.
+ virtual ukm::SourceId GetUkmSourceIdForLastCommittedSource() const;
+
+ // Notify observers if WebAudio AudioContext has started (or stopped) playing
+ // audible sounds.
+ virtual void AudioContextPlaybackStarted(RenderFrameHost* host,
+ int context_id){};
+ virtual void AudioContextPlaybackStopped(RenderFrameHost* host,
+ int context_id){};
+
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 8e5af3e3b9c..e67018e0f80 100644
--- a/chromium/content/browser/frame_host/render_frame_host_impl.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_impl.cc
@@ -23,13 +23,15 @@
#include "base/numerics/safe_conversions.h"
#include "base/process/kill.h"
#include "base/stl_util.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
+#include "base/trace_event/trace_event_argument.h"
#include "build/build_config.h"
#include "cc/base/switches.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/browser/accessibility/browser_accessibility_state_impl.h"
+#include "content/browser/background_fetch/background_fetch_service_impl.h"
#include "content/browser/bluetooth/web_bluetooth_service_impl.h"
#include "content/browser/browser_main_loop.h"
#include "content/browser/child_process_security_policy_impl.h"
@@ -64,10 +66,12 @@
#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/payments/payment_app_context_impl.h"
#include "content/browser/permissions/permission_controller_impl.h"
#include "content/browser/permissions/permission_service_context.h"
#include "content/browser/permissions/permission_service_impl.h"
+#include "content/browser/portal/portal.h"
#include "content/browser/presentation/presentation_service_impl.h"
#include "content/browser/quota_dispatcher_host.h"
#include "content/browser/renderer_host/dip_util.h"
@@ -98,8 +102,6 @@
#include "content/browser/webui/web_ui_controller_factory_registry.h"
#include "content/browser/webui/web_ui_url_loader_factory_internal.h"
#include "content/common/accessibility_messages.h"
-#include "content/common/associated_interface_provider_impl.h"
-#include "content/common/associated_interface_registry_impl.h"
#include "content/common/associated_interfaces.mojom.h"
#include "content/common/content_security_policy/content_security_policy.h"
#include "content/common/frame_messages.h"
@@ -163,12 +165,15 @@
#include "services/service_manager/public/cpp/connector.h"
#include "services/service_manager/public/cpp/interface_provider.h"
#include "storage/browser/blob/blob_storage_context.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
#include "third_party/blink/public/common/blob/blob_utils.h"
#include "third_party/blink/public/common/feature_policy/feature_policy.h"
#include "third_party/blink/public/common/frame/frame_policy.h"
#include "third_party/blink/public/mojom/page/page_visibility_state.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h"
-#include "third_party/blink/public/platform/modules/webauth/virtual_authenticator.mojom.h"
+#include "third_party/blink/public/mojom/usb/web_usb_service.mojom.h"
+#include "third_party/blink/public/platform/modules/webauthn/virtual_authenticator.mojom.h"
#include "ui/accessibility/ax_tree.h"
#include "ui/accessibility/ax_tree_id_registry.h"
#include "ui/accessibility/ax_tree_update.h"
@@ -314,7 +319,7 @@ void CreateFrameResourceCoordinator(
std::move(request));
}
-using FrameCallback =
+using FrameNotifyCallback =
base::RepeatingCallback<void(ResourceDispatcherHostImpl*,
const GlobalFrameRoutingId&)>;
@@ -322,7 +327,7 @@ using FrameCallback =
// ResourceDispatcherHostImpl of information pertaining to loading behavior of
// frame hosts.
void NotifyRouteChangesOnIO(
- const FrameCallback& frame_callback,
+ const FrameNotifyCallback& frame_callback,
std::unique_ptr<std::set<GlobalFrameRoutingId>> routing_ids) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
ResourceDispatcherHostImpl* rdh = ResourceDispatcherHostImpl::Get();
@@ -332,13 +337,11 @@ void NotifyRouteChangesOnIO(
frame_callback.Run(rdh, routing_id);
}
-void NotifyForEachFrameFromUI(RenderFrameHost* root_frame_host,
- const FrameCallback& frame_callback) {
+void NotifyForEachFrameFromUI(RenderFrameHostImpl* root_frame_host,
+ const FrameNotifyCallback& frame_callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- FrameTree* frame_tree = static_cast<RenderFrameHostImpl*>(root_frame_host)
- ->frame_tree_node()
- ->frame_tree();
+ FrameTree* frame_tree = root_frame_host->frame_tree_node()->frame_tree();
DCHECK_EQ(root_frame_host, frame_tree->GetMainFrame());
auto routing_ids = std::make_unique<std::set<GlobalFrameRoutingId>>();
@@ -357,6 +360,25 @@ void NotifyForEachFrameFromUI(RenderFrameHost* root_frame_host,
std::move(routing_ids)));
}
+using FrameCallback = base::RepeatingCallback<void(RenderFrameHostImpl*)>;
+void ForEachFrame(RenderFrameHostImpl* root_frame_host,
+ const FrameCallback& frame_callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ FrameTree* frame_tree = root_frame_host->frame_tree_node()->frame_tree();
+ DCHECK_EQ(root_frame_host, frame_tree->GetMainFrame());
+
+ for (FrameTreeNode* node : frame_tree->Nodes()) {
+ RenderFrameHostImpl* frame_host = node->current_frame_host();
+ RenderFrameHostImpl* pending_frame_host =
+ node->render_manager()->speculative_frame_host();
+ if (frame_host)
+ frame_callback.Run(frame_host);
+ if (pending_frame_host)
+ frame_callback.Run(pending_frame_host);
+ }
+}
+
void LookupRenderFrameHostOrProxy(int process_id,
int routing_id,
RenderFrameHostImpl** rfh,
@@ -628,6 +650,8 @@ RenderFrameHostImpl::RenderFrameHostImpl(SiteInstance* site_instance,
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));
@@ -671,6 +695,12 @@ RenderFrameHostImpl::~RenderFrameHostImpl() {
if (delegate_ && render_frame_created_)
delegate_->RenderFrameDeleted(this);
+ // 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
+ // background priority.
+ OnAudibleStateChanged(false);
+
// If this was the last active frame in the SiteInstance, the
// DecrementActiveFrameCount call will trigger the deletion of the
// SiteInstance's proxies.
@@ -759,6 +789,14 @@ void RenderFrameHostImpl::DidCommitProvisionalLoadForTesting(
std::move(interface_provider_request));
}
+void RenderFrameHostImpl::AudioContextPlaybackStarted(int audio_context_id) {
+ delegate_->AudioContextPlaybackStarted(this, audio_context_id);
+}
+
+void RenderFrameHostImpl::AudioContextPlaybackStopped(int audio_context_id) {
+ delegate_->AudioContextPlaybackStopped(this, audio_context_id);
+}
+
SiteInstanceImpl* RenderFrameHostImpl::GetSiteInstance() {
return site_instance_.get();
}
@@ -826,36 +864,10 @@ void RenderFrameHostImpl::ExecuteMediaPlayerActionAtLocation(
Send(new FrameMsg_MediaPlayerActionAt(routing_id_, point_in_view, action));
}
-void RenderFrameHostImpl::CreateNetworkServiceDefaultFactory(
+bool RenderFrameHostImpl::CreateNetworkServiceDefaultFactory(
network::mojom::URLLoaderFactoryRequest default_factory_request) {
- network::mojom::URLLoaderFactoryParamsPtr params =
- network::mojom::URLLoaderFactoryParams::New();
- params->process_id = GetProcess()->GetID();
- params->disable_web_security =
- base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableWebSecurity);
- SiteIsolationPolicy::PopulateURLLoaderFactoryParamsPtrForCORB(params.get());
-
- auto* context = GetSiteInstance()->GetBrowserContext();
- GetContentClient()->browser()->WillCreateURLLoaderFactory(
- context, this, false /* is_navigation */, &default_factory_request);
- // Keep DevTools proxy lasy, i.e. closest to the network.
- RenderFrameDevToolsAgentHost::WillCreateURLLoaderFactory(
- this, false /* is_navigation */, false /* is_download */,
- &default_factory_request);
- StoragePartitionImpl* storage_partition = static_cast<StoragePartitionImpl*>(
- BrowserContext::GetStoragePartition(context, GetSiteInstance()));
- if (g_create_network_factory_callback_for_test.Get().is_null()) {
- storage_partition->GetNetworkContext()->CreateURLLoaderFactory(
- std::move(default_factory_request), std::move(params));
- } else {
- network::mojom::URLLoaderFactoryPtr original_factory;
- storage_partition->GetNetworkContext()->CreateURLLoaderFactory(
- mojo::MakeRequest(&original_factory), std::move(params));
- g_create_network_factory_callback_for_test.Get().Run(
- std::move(default_factory_request), GetProcess()->GetID(),
- original_factory.PassInterface());
- }
+ return CreateNetworkServiceDefaultFactoryInternal(
+ last_committed_url_, std::move(default_factory_request));
}
gfx::NativeView RenderFrameHostImpl::GetNativeView() {
@@ -961,7 +973,7 @@ service_manager::InterfaceProvider* RenderFrameHostImpl::GetRemoteInterfaces() {
blink::AssociatedInterfaceProvider*
RenderFrameHostImpl::GetRemoteAssociatedInterfaces() {
if (!remote_associated_interfaces_) {
- mojom::AssociatedInterfaceProviderAssociatedPtr remote_interfaces;
+ blink::mojom::AssociatedInterfaceProviderAssociatedPtr remote_interfaces;
IPC::ChannelProxy* channel = GetProcess()->GetChannel();
if (channel) {
RenderProcessHostImpl* process =
@@ -973,8 +985,9 @@ RenderFrameHostImpl::GetRemoteAssociatedInterfaces() {
// case we set up a dummy interface provider.
mojo::MakeRequestAssociatedWithDedicatedPipe(&remote_interfaces);
}
- remote_associated_interfaces_.reset(new AssociatedInterfaceProviderImpl(
- std::move(remote_interfaces)));
+ remote_associated_interfaces_ =
+ std::make_unique<blink::AssociatedInterfaceProvider>(
+ std::move(remote_interfaces));
}
return remote_associated_interfaces_.get();
}
@@ -1138,10 +1151,9 @@ void RenderFrameHostImpl::OnAssociatedInterfaceRequest(
const std::string& interface_name,
mojo::ScopedInterfaceEndpointHandle handle) {
ContentBrowserClient* browser_client = GetContentClient()->browser();
- if (associated_registry_->CanBindRequest(interface_name)) {
- associated_registry_->BindRequest(interface_name, std::move(handle));
- } else if (!browser_client->BindAssociatedInterfaceRequestFromFrame(
- this, interface_name, &handle)) {
+ if (!associated_registry_->TryBindInterface(interface_name, &handle) &&
+ !browser_client->BindAssociatedInterfaceRequestFromFrame(
+ this, interface_name, &handle)) {
delegate_->OnAssociatedInterfaceRequest(this, interface_name,
std::move(handle));
}
@@ -1231,14 +1243,14 @@ void RenderFrameHostImpl::RenderProcessGone(SiteInstanceImpl* site_instance) {
// The renderer process is gone, so this frame can no longer be loading.
if (GetNavigationHandle())
GetNavigationHandle()->set_net_error_code(net::ERR_ABORTED);
+ ResetNavigationRequests();
ResetLoadingState();
// Any future UpdateState or UpdateTitle messages from this or a recreated
// process should be ignored until the next commit.
set_nav_entry_id(0);
- if (is_audible_)
- GetProcess()->OnMediaStreamRemoved();
+ OnAudibleStateChanged(false);
}
void RenderFrameHostImpl::ReportContentSecurityPolicyViolation(
@@ -1701,6 +1713,12 @@ void RenderFrameHostImpl::DidCommitProvisionalLoad(
validated_params,
service_manager::mojom::InterfaceProviderRequest
interface_provider_request) {
+ if (GetNavigationHandle()) {
+ main_frame_request_ids_ = {validated_params->request_id,
+ GetNavigationHandle()->GetGlobalRequestID()};
+ if (deferred_main_frame_load_info_)
+ ResourceLoadComplete(std::move(deferred_main_frame_load_info_));
+ }
// DidCommitProvisionalLoad IPC should be associated with the URL being
// committed (not with the *last* committed URL that most other IPCs are
// associated with).
@@ -1712,8 +1730,8 @@ void RenderFrameHostImpl::DidCommitProvisionalLoad(
RenderProcessHost* process = GetProcess();
TRACE_EVENT2("navigation", "RenderFrameHostImpl::DidCommitProvisionalLoad",
- "frame_tree_node", frame_tree_node_->frame_tree_node_id(), "url",
- validated_params->url.possibly_invalid_spec());
+ "url", validated_params->url.possibly_invalid_spec(), "details",
+ CommitAsTracedValue(validated_params.get()));
// Notify the resource scheduler of the navigation committing.
NotifyResourceSchedulerOfNavigation(process->GetID(), *validated_params);
@@ -2103,8 +2121,11 @@ void RenderFrameHostImpl::OnRenderProcessGone(int status, int exit_code) {
// Reset frame tree state associated with this process. This must happen
// before RenderViewTerminated because observers expect the subframes of any
- // affected frames to be cleared first.
- frame_tree_node_->ResetForNewProcess();
+ // affected frames to be cleared first. Only do this if this is the current
+ // RenderFrameHost; if the process goes away for a pending delete or
+ // speculative RFH, we shouldn't remove subframes from the current RFH.
+ if (IsCurrent())
+ frame_tree_node_->ResetForNewProcess();
// Reset state for the current RenderFrameHost once the FrameTreeNode has been
// reset.
@@ -3221,17 +3242,19 @@ void RenderFrameHostImpl::CreateNewWindow(
// be needed if a response ends up creating a plugin. We'll only have a
// single frame at this point. These requests will be resumed either in
// WebContentsImpl::CreateNewWindow or RenderFrameHost::Init.
- // TODO(crbug.com/581037): Now that NPAPI is deprecated we should be able to
- // remove this, but more investigation is needed.
- auto block_requests_for_route = base::Bind(
- [](const GlobalFrameRoutingId& id) {
- auto* rdh = ResourceDispatcherHostImpl::Get();
- if (rdh)
- rdh->BlockRequestsForRoute(id);
- },
- GlobalFrameRoutingId(render_process_id, main_frame_route_id));
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- std::move(block_requests_for_route));
+ // TODO(crbug.com/581037): Even though NPAPI is deleted, other features
+ // depend on this behavior. See the bug for more information.
+ if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ auto block_requests_for_route = base::Bind(
+ [](const GlobalFrameRoutingId& id) {
+ auto* rdh = ResourceDispatcherHostImpl::Get();
+ if (rdh)
+ rdh->BlockRequestsForRoute(id);
+ },
+ GlobalFrameRoutingId(render_process_id, main_frame_route_id));
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ std::move(block_requests_for_route));
+ }
}
DCHECK(IsRenderFrameLive());
@@ -3266,6 +3289,14 @@ void RenderFrameHostImpl::CreateNewWindow(
RenderFrameHostImpl::FromID(GetProcess()->GetID(), main_frame_route_id);
DCHECK(rfh);
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService) &&
+ rfh->waiting_for_init_) {
+ // Need to check |waiting_for_init_| as some paths inside CreateNewWindow
+ // call above (namely, if WebContentsDelegate::ShouldCreateWebContents
+ // returns false) will resume requests by calling RenderFrameHostImpl::Init.
+ rfh->frame_->BlockRequests();
+ }
+
service_manager::mojom::InterfaceProviderPtrInfo
main_frame_interface_provider_info;
rfh->BindInterfaceProviderRequest(
@@ -3379,7 +3410,20 @@ void RenderFrameHostImpl::SubresourceResponseStarted(
void RenderFrameHostImpl::ResourceLoadComplete(
mojom::ResourceLoadInfoPtr resource_load_info) {
- delegate_->ResourceLoadComplete(this, std::move(resource_load_info));
+ GlobalRequestID global_request_id;
+ if (main_frame_request_ids_.first == resource_load_info->request_id) {
+ global_request_id = main_frame_request_ids_.second;
+ } else if (resource_load_info->resource_type ==
+ content::RESOURCE_TYPE_MAIN_FRAME) {
+ // The load complete message for the main resource arrived before
+ // |DidCommitProvisionalLoad()|. We save the load info so
+ // |ResourceLoadComplete()| can be called later in
+ // |DidCommitProvisionalLoad()| when we can map to the global request ID.
+ deferred_main_frame_load_info_ = std::move(resource_load_info);
+ return;
+ }
+ delegate_->ResourceLoadComplete(this, global_request_id,
+ std::move(resource_load_info));
}
void RenderFrameHostImpl::RegisterMojoInterfaces() {
@@ -3436,10 +3480,7 @@ void RenderFrameHostImpl::RegisterMojoInterfaces() {
base::Unretained(this)));
registry_->AddInterface(base::BindRepeating(
- &RenderFrameHostImpl::CreateUsbDeviceManager, base::Unretained(this)));
-
- registry_->AddInterface(base::BindRepeating(
- &RenderFrameHostImpl::CreateUsbChooserService, base::Unretained(this)));
+ &RenderFrameHostImpl::CreateWebUsbService, base::Unretained(this)));
registry_->AddInterface<media::mojom::InterfaceFactory>(
base::Bind(&RenderFrameHostImpl::BindMediaInterfaceFactoryRequest,
@@ -3535,8 +3576,15 @@ void RenderFrameHostImpl::RegisterMojoInterfaces() {
->GetVideoDecodePerfHistory()
->GetSaveCallback();
}
+
registry_->AddInterface(base::BindRepeating(
- &media::MediaMetricsProvider::Create, std::move(save_stats_cb)));
+ &media::MediaMetricsProvider::Create, frame_tree_node_->IsMainFrame(),
+ base::BindRepeating(
+ &RenderFrameHostDelegate::GetUkmSourceIdForLastCommittedSource,
+ // This callback is only executed when Create() is called, during
+ // which the lifetime of the |delegate_| is guaranteed.
+ base::Unretained(delegate_)),
+ std::move(save_stats_cb)));
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
cc::switches::kEnableGpuBenchmarking)) {
@@ -3552,6 +3600,17 @@ void RenderFrameHostImpl::RegisterMojoInterfaces() {
base::BindRepeating(SpeechRecognitionDispatcherHost::Create,
GetProcess()->GetID(), routing_id_),
BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
+
+ if (Portal::IsEnabled()) {
+ registry_->AddInterface(base::BindRepeating(IgnoreResult(&Portal::Create),
+ base::Unretained(this)));
+ }
+
+ registry_->AddInterface(base::BindRepeating(
+ &BackgroundFetchServiceImpl::CreateForFrame, GetProcess(), routing_id_));
+
+ registry_->AddInterface(base::BindRepeating(&AudioContextManagerImpl::Create,
+ base::Unretained(this)));
}
void RenderFrameHostImpl::ResetWaitingState() {
@@ -3973,8 +4032,11 @@ void RenderFrameHostImpl::CommitNavigation(
if (!default_factory_info) {
// Otherwise default to a Network Service-backed loader from the
// appropriate NetworkContext.
- CreateNetworkServiceDefaultFactoryAndObserve(
- mojo::MakeRequest(&default_factory_info));
+ bool bypass_redirect_checks =
+ CreateNetworkServiceDefaultFactoryAndObserve(
+ common_params.url, mojo::MakeRequest(&default_factory_info));
+ subresource_loader_factories->set_bypass_redirect_checks(
+ bypass_redirect_checks);
}
DCHECK(default_factory_info);
@@ -3988,7 +4050,7 @@ void RenderFrameHostImpl::CommitNavigation(
auto file_factory = std::make_unique<FileURLLoaderFactory>(
browser_context->GetPath(),
base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BACKGROUND,
+ {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}));
non_network_url_loader_factories_.emplace(url::kFileScheme,
std::move(file_factory));
@@ -4019,7 +4081,8 @@ void RenderFrameHostImpl::CommitNavigation(
network::mojom::URLLoaderFactoryPtrInfo factory_proxy_info;
auto factory_request = mojo::MakeRequest(&factory_proxy_info);
GetContentClient()->browser()->WillCreateURLLoaderFactory(
- browser_context, this, false /* is_navigation */, &factory_request);
+ browser_context, this, false /* is_navigation */, common_params.url,
+ &factory_request);
// Keep DevTools proxy lasy, i.e. closest to the network.
RenderFrameDevToolsAgentHost::WillCreateURLLoaderFactory(
this, false /* is_navigation */, false /* is_download */,
@@ -4092,7 +4155,9 @@ void RenderFrameHostImpl::CommitNavigation(
head, common_params, request_params,
std::move(url_loader_client_endpoints), CloneSubresourceFactories(),
std::move(subresource_overrides), std::move(controller),
- std::move(prefetch_loader_factory), devtools_navigation_token);
+ std::move(prefetch_loader_factory), devtools_navigation_token,
+ base::BindOnce(&RenderFrameHostImpl::OnCrossDocumentCommitProcessed,
+ base::Unretained(this), navigation_id));
} else {
GetNavigationControl()->CommitNavigation(
head, common_params, request_params,
@@ -4148,11 +4213,12 @@ void RenderFrameHostImpl::FailedNavigation(
std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories;
if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
network::mojom::URLLoaderFactoryPtrInfo default_factory_info;
- CreateNetworkServiceDefaultFactoryAndObserve(
- mojo::MakeRequest(&default_factory_info));
+ bool bypass_redirect_checks = CreateNetworkServiceDefaultFactoryAndObserve(
+ common_params.url, mojo::MakeRequest(&default_factory_info));
subresource_loader_factories = std::make_unique<URLLoaderFactoryBundleInfo>(
std::move(default_factory_info),
- std::map<std::string, network::mojom::URLLoaderFactoryPtrInfo>());
+ std::map<std::string, network::mojom::URLLoaderFactoryPtrInfo>(),
+ bypass_redirect_checks);
}
SaveSubresourceFactories(std::move(subresource_loader_factories));
@@ -4164,7 +4230,9 @@ void RenderFrameHostImpl::FailedNavigation(
request->GetCommitNavigationClient()) {
request->GetCommitNavigationClient()->CommitFailedNavigation(
common_params, request_params, has_stale_copy_in_cache, error_code,
- error_page_content, CloneSubresourceFactories());
+ error_page_content, CloneSubresourceFactories(),
+ base::BindOnce(&RenderFrameHostImpl::OnCrossDocumentCommitProcessed,
+ base::Unretained(this), navigation_id));
} else {
GetNavigationControl()->CommitFailedNavigation(
common_params, request_params, has_stale_copy_in_cache, error_code,
@@ -4199,15 +4267,15 @@ void RenderFrameHostImpl::SetUpMojoIfNeeded() {
if (registry_.get())
return;
- associated_registry_ = std::make_unique<AssociatedInterfaceRegistryImpl>();
+ associated_registry_ = std::make_unique<blink::AssociatedInterfaceRegistry>();
registry_ = std::make_unique<service_manager::BinderRegistry>();
auto make_binding = [](RenderFrameHostImpl* impl,
mojom::FrameHostAssociatedRequest request) {
impl->frame_host_associated_binding_.Bind(std::move(request));
};
- static_cast<blink::AssociatedInterfaceRegistry*>(associated_registry_.get())
- ->AddInterface(base::Bind(make_binding, base::Unretained(this)));
+ associated_registry_->AddInterface(
+ base::BindRepeating(make_binding, base::Unretained(this)));
RegisterMojoInterfaces();
mojom::FrameFactoryPtr frame_factory;
@@ -4418,22 +4486,47 @@ bool RenderFrameHostImpl::CanCommitURL(const GURL& url) {
void RenderFrameHostImpl::BlockRequestsForFrame() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- NotifyForEachFrameFromUI(
- this,
- base::BindRepeating(&ResourceDispatcherHostImpl::BlockRequestsForRoute));
+
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ ForEachFrame(
+ this, base::BindRepeating([](RenderFrameHostImpl* render_frame_host) {
+ if (render_frame_host->frame_)
+ render_frame_host->frame_->BlockRequests();
+ }));
+ } else {
+ NotifyForEachFrameFromUI(
+ this, base::BindRepeating(
+ &ResourceDispatcherHostImpl::BlockRequestsForRoute));
+ }
}
void RenderFrameHostImpl::ResumeBlockedRequestsForFrame() {
- NotifyForEachFrameFromUI(
- this, base::BindRepeating(
- &ResourceDispatcherHostImpl::ResumeBlockedRequestsForRoute));
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ ForEachFrame(
+ this, base::BindRepeating([](RenderFrameHostImpl* render_frame_host) {
+ if (render_frame_host->frame_)
+ render_frame_host->frame_->ResumeBlockedRequests();
+ }));
+ } else {
+ NotifyForEachFrameFromUI(
+ this, base::BindRepeating(
+ &ResourceDispatcherHostImpl::ResumeBlockedRequestsForRoute));
+ }
}
void RenderFrameHostImpl::CancelBlockedRequestsForFrame() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- NotifyForEachFrameFromUI(
- this, base::BindRepeating(
- &ResourceDispatcherHostImpl::CancelBlockedRequestsForRoute));
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ ForEachFrame(
+ this, base::BindRepeating([](RenderFrameHostImpl* render_frame_host) {
+ if (render_frame_host->frame_)
+ render_frame_host->frame_->CancelBlockedRequests();
+ }));
+ } else {
+ NotifyForEachFrameFromUI(
+ this, base::BindRepeating(
+ &ResourceDispatcherHostImpl::CancelBlockedRequestsForRoute));
+ }
}
bool RenderFrameHostImpl::IsSameSiteInstance(
@@ -4661,13 +4754,14 @@ void RenderFrameHostImpl::UpdateSubresourceLoaderFactories() {
DCHECK(network_service_connection_error_handler_holder_.is_bound());
network::mojom::URLLoaderFactoryPtrInfo default_factory_info;
- CreateNetworkServiceDefaultFactoryAndObserve(
- mojo::MakeRequest(&default_factory_info));
+ bool bypass_redirect_checks = CreateNetworkServiceDefaultFactoryAndObserve(
+ last_committed_url_, mojo::MakeRequest(&default_factory_info));
std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories =
- std::make_unique<URLLoaderFactoryBundleInfo>();
- subresource_loader_factories->default_factory_info() =
- std::move(default_factory_info);
+ std::make_unique<URLLoaderFactoryBundleInfo>(
+ std::move(default_factory_info),
+ std::map<std::string, network::mojom::URLLoaderFactoryPtrInfo>(),
+ bypass_redirect_checks);
SaveSubresourceFactories(std::move(subresource_loader_factories));
GetNavigationControl()->UpdateSubresourceLoaderFactories(
CloneSubresourceFactories());
@@ -4682,9 +4776,11 @@ std::set<int> RenderFrameHostImpl::GetNavigationEntryIdsPendingCommit() {
return result;
}
-void RenderFrameHostImpl::CreateNetworkServiceDefaultFactoryAndObserve(
+bool RenderFrameHostImpl::CreateNetworkServiceDefaultFactoryAndObserve(
+ const GURL& url,
network::mojom::URLLoaderFactoryRequest default_factory_request) {
- CreateNetworkServiceDefaultFactory(std::move(default_factory_request));
+ bool bypass_redirect_checks = CreateNetworkServiceDefaultFactoryInternal(
+ url, std::move(default_factory_request));
// Add connection error observer when Network Service is running
// out-of-process.
@@ -4704,6 +4800,48 @@ void RenderFrameHostImpl::CreateNetworkServiceDefaultFactoryAndObserve(
&RenderFrameHostImpl::UpdateSubresourceLoaderFactories,
weak_ptr_factory_.GetWeakPtr()));
}
+ return bypass_redirect_checks;
+}
+
+bool RenderFrameHostImpl::CreateNetworkServiceDefaultFactoryInternal(
+ const GURL& url,
+ network::mojom::URLLoaderFactoryRequest default_factory_request) {
+ network::mojom::URLLoaderFactoryParamsPtr params =
+ network::mojom::URLLoaderFactoryParams::New();
+ params->process_id = GetProcess()->GetID();
+ params->disable_web_security =
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableWebSecurity);
+ SiteIsolationPolicy::PopulateURLLoaderFactoryParamsPtrForCORB(params.get());
+
+ auto* context = GetSiteInstance()->GetBrowserContext();
+ bool bypass_redirect_checks = false;
+
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ bypass_redirect_checks =
+ GetContentClient()->browser()->WillCreateURLLoaderFactory(
+ context, this, false /* is_navigation */, url,
+ &default_factory_request);
+ }
+
+ // Keep DevTools proxy lasy, i.e. closest to the network.
+ RenderFrameDevToolsAgentHost::WillCreateURLLoaderFactory(
+ this, false /* is_navigation */, false /* is_download */,
+ &default_factory_request);
+ StoragePartitionImpl* storage_partition = static_cast<StoragePartitionImpl*>(
+ BrowserContext::GetStoragePartition(context, GetSiteInstance()));
+ if (g_create_network_factory_callback_for_test.Get().is_null()) {
+ storage_partition->GetNetworkContext()->CreateURLLoaderFactory(
+ std::move(default_factory_request), std::move(params));
+ } else {
+ network::mojom::URLLoaderFactoryPtr original_factory;
+ storage_partition->GetNetworkContext()->CreateURLLoaderFactory(
+ mojo::MakeRequest(&original_factory), std::move(params));
+ g_create_network_factory_callback_for_test.Get().Run(
+ std::move(default_factory_request), GetProcess()->GetID(),
+ original_factory.PassInterface());
+ }
+ return bypass_redirect_checks;
}
bool RenderFrameHostImpl::CanExecuteJavaScript() {
@@ -4858,16 +4996,9 @@ void RenderFrameHostImpl::DeleteWebBluetoothService(
web_bluetooth_services_.erase(it);
}
-void RenderFrameHostImpl::CreateUsbDeviceManager(
- device::mojom::UsbDeviceManagerRequest request) {
- GetContentClient()->browser()->CreateUsbDeviceManager(this,
- std::move(request));
-}
-
-void RenderFrameHostImpl::CreateUsbChooserService(
- device::mojom::UsbChooserServiceRequest request) {
- GetContentClient()->browser()->CreateUsbChooserService(this,
- std::move(request));
+void RenderFrameHostImpl::CreateWebUsbService(
+ blink::mojom::WebUsbServiceRequest request) {
+ GetContentClient()->browser()->CreateWebUsbService(this, std::move(request));
}
void RenderFrameHostImpl::ResetFeaturePolicy() {
@@ -5072,6 +5203,9 @@ RenderFrameHostImpl::TakeNavigationHandleForCommit(
navigation_request_ ? navigation_request_->navigation_handle() : nullptr;
// Determine if the current NavigationHandle can be used.
+ //
+ // TODO(lukasza, clamy): https://crbug.com/784904: Match commit IPC to proper
+ // NavigationHandle without requiring URLs to match.
if (navigation_handle && navigation_handle->GetURL() == params.url) {
std::unique_ptr<NavigationHandleImpl> result_navigation_handle =
navigation_request()->TakeNavigationHandle();
@@ -5080,15 +5214,29 @@ RenderFrameHostImpl::TakeNavigationHandleForCommit(
return result_navigation_handle;
}
- // If the URL does not match what the NavigationHandle expects, treat the
- // commit as a new navigation. This can happen when loading a Data
- // navigation with LoadDataWithBaseURL.
+ // At this point we know that the right/matching |navigation_request_| has
+ // already been found based on navigation id look-up performed by
+ // RFHI::OnCrossDocumentCommitProcessed. OTOH, we cannot use
+ // |navigation_handle|, 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.
+ // This mostly works, but there are some remaining issues here tracked
+ // by https://crbug.com/872803.
//
+ // 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 crbug.com/588317.
+ // 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).
+
int entry_id_for_data_nav = 0;
bool is_renderer_initiated = true;
@@ -5112,6 +5260,11 @@ RenderFrameHostImpl::TakeNavigationHandleForCommit(
entry_id_for_data_nav = navigation_handle->pending_nav_entry_id();
is_renderer_initiated = pending_entry->is_renderer_initiated();
}
+
+ // Going forward we'll use the NavigationHandle created below. Therefore we
+ // should destroy the old |navigation_request_| and the NavigationHandle it
+ // owns. This avoids the leak reported in https://crbug.com/872803.
+ navigation_request_.reset();
}
// There is no pending NavigationEntry in these cases, so pass 0 as the
@@ -5265,25 +5418,48 @@ bool RenderFrameHostImpl::ValidateDidCommitParams(
// Error pages may sometimes commit a URL in the wrong process, which requires
// an exception for the CanCommitURL checks. This is ok as long as the origin
// is unique.
- // TODO(creis): Kill the renderer if it claims an error page has a non-unique
- // origin.
bool is_permitted_error_page = false;
- if (validated_params->origin.unique()) {
- if (SiteIsolationPolicy::IsErrorPageIsolationEnabled(
- frame_tree_node_->IsMainFrame())) {
- // With error page isolation, any URL can commit in an error page process.
- if (GetSiteInstance()->GetSiteURL() ==
- GURL(content::kUnreachableWebDataURL)) {
- is_permitted_error_page = true;
+ if (SiteIsolationPolicy::IsErrorPageIsolationEnabled(
+ frame_tree_node_->IsMainFrame())) {
+ if (site_instance_->GetSiteURL() == GURL(content::kUnreachableWebDataURL)) {
+ // Commits in the error page process must only be failures, otherwise
+ // successful navigations could commit documents from origins different
+ // than the chrome-error://chromewebdata/ one and violate expectations.
+ if (!validated_params->url_is_unreachable) {
+ DEBUG_ALIAS_FOR_ORIGIN(origin_debug_alias, validated_params->origin);
+ bad_message::ReceivedBadMessage(
+ process, bad_message::RFH_ERROR_PROCESS_NON_ERROR_COMMIT);
+ return false;
}
- } else {
- // Without error page isolation, a blocked navigation is expected to
- // commit in the old renderer process. This may be true for subframe
- // navigations even when error page isolation is enabled for main frames.
- if (GetNavigationHandle() && GetNavigationHandle()->GetNetErrorCode() ==
- net::ERR_BLOCKED_BY_CLIENT) {
- is_permitted_error_page = true;
+
+ // Error pages must commit in a unique origin. Terminate the renderer
+ // process if this is violated.
+ if (!validated_params->origin.unique()) {
+ DEBUG_ALIAS_FOR_ORIGIN(origin_debug_alias, validated_params->origin);
+ bad_message::ReceivedBadMessage(
+ process, bad_message::RFH_ERROR_PROCESS_NON_UNIQUE_ORIGIN_COMMIT);
+ return false;
}
+
+ // With error page isolation, any URL can commit in an error page process.
+ is_permitted_error_page = true;
+ }
+ } else {
+ // Without error page isolation, a blocked navigation is expected to
+ // commit in the old renderer process. This may be true for subframe
+ // navigations even when error page isolation is enabled for main frames.
+ if (GetNavigationHandle() && GetNavigationHandle()->GetNetErrorCode() ==
+ net::ERR_BLOCKED_BY_CLIENT) {
+ // Since this is known to be an error page commit, verify it happened in
+ // a unique origin, terminating the renderer process otherwise.
+ if (!validated_params->origin.unique()) {
+ DEBUG_ALIAS_FOR_ORIGIN(origin_debug_alias, validated_params->origin);
+ bad_message::ReceivedBadMessage(
+ process, bad_message::RFH_ERROR_PROCESS_NON_UNIQUE_ORIGIN_COMMIT);
+ return false;
+ }
+
+ is_permitted_error_page = true;
}
}
@@ -5460,4 +5636,25 @@ RenderFrameHostImpl::CloneSubresourceFactories() {
return nullptr;
}
+std::unique_ptr<base::trace_event::TracedValue>
+RenderFrameHostImpl::CommitAsTracedValue(
+ FrameHostMsg_DidCommitProvisionalLoad_Params* validated_params) const {
+ auto value = std::make_unique<base::trace_event::TracedValue>();
+
+ value->SetInteger("frame_tree_node", frame_tree_node_->frame_tree_node_id());
+ value->SetInteger("site id", site_instance_->GetId());
+ value->SetString("process lock", ChildProcessSecurityPolicyImpl::GetInstance()
+ ->GetOriginLock(process_->GetID())
+ .spec());
+ value->SetString("origin", validated_params->origin.Serialize());
+ value->SetInteger("transition", validated_params->transition);
+
+ if (!validated_params->base_url.is_empty()) {
+ value->SetString("base_url",
+ validated_params->base_url.possibly_invalid_spec());
+ }
+
+ return value;
+}
+
} // 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 6c6f78fec35..d71a3c050e6 100644
--- a/chromium/content/browser/frame_host/render_frame_host_impl.h
+++ b/chromium/content/browser/frame_host/render_frame_host_impl.h
@@ -30,7 +30,6 @@
#include "build/build_config.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/browser/bad_message.h"
-#include "content/browser/loader/global_routing_id.h"
#include "content/browser/renderer_host/media/old_render_frame_audio_input_stream_factory.h"
#include "content/browser/renderer_host/media/old_render_frame_audio_output_stream_factory.h"
#include "content/browser/renderer_host/media/render_frame_audio_input_stream_factory.h"
@@ -50,6 +49,7 @@
#include "content/common/navigation_params.mojom.h"
#include "content/public/browser/browser_thread.h"
#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/common/javascript_dialog_type.h"
#include "content/public/common/previews_state.h"
@@ -65,10 +65,10 @@
#include "third_party/blink/public/common/feature_policy/feature_policy.h"
#include "third_party/blink/public/common/frame/user_activation_update_type.h"
#include "third_party/blink/public/mojom/frame/find_in_page.mojom.h"
+#include "third_party/blink/public/mojom/presentation/presentation.mojom.h"
#include "third_party/blink/public/platform/dedicated_worker_factory.mojom.h"
#include "third_party/blink/public/platform/modules/bluetooth/web_bluetooth.mojom.h"
-#include "third_party/blink/public/platform/modules/presentation/presentation.mojom.h"
-#include "third_party/blink/public/platform/modules/webauth/authenticator.mojom.h"
+#include "third_party/blink/public/platform/modules/webauthn/authenticator.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"
@@ -103,10 +103,16 @@ class ListValue;
}
namespace blink {
+class AssociatedInterfaceProvider;
+class AssociatedInterfaceRegistry;
struct FramePolicy;
struct WebFullscreenOptions;
struct WebScrollIntoViewParams;
+
+namespace mojom {
+class WebUsbService;
}
+} // namespace blink
namespace gfx {
class Range;
@@ -118,8 +124,6 @@ struct ResourceResponse;
} // namespace network
namespace content {
-class AssociatedInterfaceProviderImpl;
-class AssociatedInterfaceRegistryImpl;
class AuthenticatorImpl;
class FrameTree;
class FrameTreeNode;
@@ -247,7 +251,7 @@ class CONTENT_EXPORT RenderFrameHostImpl
void ExecuteMediaPlayerActionAtLocation(
const gfx::Point&,
const blink::WebMediaPlayerAction& action) override;
- void CreateNetworkServiceDefaultFactory(
+ bool CreateNetworkServiceDefaultFactory(
network::mojom::URLLoaderFactoryRequest default_factory_request) override;
// IPC::Sender
@@ -776,6 +780,15 @@ class CONTENT_EXPORT RenderFrameHostImpl
service_manager::mojom::InterfaceProviderRequest
interface_provider_request);
+ service_manager::BinderRegistry& BinderRegistryForTesting() {
+ return *registry_;
+ }
+
+ // Called when the WebAudio AudioContext given by |audio_context_id| has
+ // started (or stopped) playing audible audio.
+ void AudioContextPlaybackStarted(int audio_context_id);
+ void AudioContextPlaybackStopped(int audio_context_id);
+
protected:
friend class RenderFrameHostFactory;
@@ -819,6 +832,9 @@ class CONTENT_EXPORT RenderFrameHostImpl
FRIEND_TEST_ALL_PREFIXES(RenderFrameHostManagerTest,
WebUIJavascriptDisallowedAfterSwapOut);
FRIEND_TEST_ALL_PREFIXES(RenderFrameHostManagerTest, LastCommittedOrigin);
+ FRIEND_TEST_ALL_PREFIXES(
+ RenderFrameHostManagerUnloadBrowserTest,
+ PendingDeleteRFHProcessShutdownDoesNotRemoveSubframes);
FRIEND_TEST_ALL_PREFIXES(SitePerProcessBrowserTest, CrashSubframe);
FRIEND_TEST_ALL_PREFIXES(SitePerProcessBrowserTest, FindImmediateLocalRoots);
FRIEND_TEST_ALL_PREFIXES(SitePerProcessBrowserTest,
@@ -839,6 +855,8 @@ class CONTENT_EXPORT RenderFrameHostImpl
SwapOutACKArrivesPriorToProcessShutdownRequest);
FRIEND_TEST_ALL_PREFIXES(SecurityExploitBrowserTest,
AttemptDuplicateRenderViewHost);
+ FRIEND_TEST_ALL_PREFIXES(WebContentsImplBrowserTest,
+ FullscreenAfterFrameSwap);
class DroppedInterfaceRequestLogger;
@@ -1037,8 +1055,19 @@ class CONTENT_EXPORT RenderFrameHostImpl
// Creates a Network Service-backed factory from appropriate |NetworkContext|
// and sets a connection error handler to trigger
- // |OnNetworkServiceConnectionError()| if the factory is out-of-process.
- void CreateNetworkServiceDefaultFactoryAndObserve(
+ // |OnNetworkServiceConnectionError()| if the factory is out-of-process. If
+ // this returns true, any redirect safety checks should be bypassed in
+ // downstream loaders.
+ // |url| is the URL that the RenderFrame is either committing (in the case of
+ // navigation) or has last committed (when handling network process crashes).
+ bool CreateNetworkServiceDefaultFactoryAndObserve(
+ const GURL& url,
+ network::mojom::URLLoaderFactoryRequest default_factory_request);
+
+ // |url| is the URL that the RenderFrame is either committing (in the case of
+ // navigation) or has last committed (when handling network process crashes).
+ bool CreateNetworkServiceDefaultFactoryInternal(
+ const GURL& url,
network::mojom::URLLoaderFactoryRequest default_factory_request);
// Returns true if the ExecuteJavaScript() API can be used on this host.
@@ -1084,8 +1113,8 @@ class CONTENT_EXPORT RenderFrameHostImpl
WebBluetoothServiceImpl* web_bluetooth_service);
// Creates connections to WebUSB interfaces bound to this frame.
- void CreateUsbDeviceManager(device::mojom::UsbDeviceManagerRequest request);
- void CreateUsbChooserService(device::mojom::UsbChooserServiceRequest request);
+ void CreateWebUsbService(
+ mojo::InterfaceRequest<blink::mojom::WebUsbService> request);
void CreateAudioInputStreamFactory(
mojom::RendererAudioInputStreamFactoryRequest request);
@@ -1262,6 +1291,11 @@ class CONTENT_EXPORT RenderFrameHostImpl
std::unique_ptr<URLLoaderFactoryBundleInfo> bundle_info);
std::unique_ptr<URLLoaderFactoryBundleInfo> CloneSubresourceFactories();
+ // Creates a TracedValue object containing the details of a committed
+ // navigation, so it can be logged with the tracing system.
+ std::unique_ptr<base::trace_event::TracedValue> CommitAsTracedValue(
+ FrameHostMsg_DidCommitProvisionalLoad_Params* validated_params) const;
+
// 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
@@ -1412,7 +1446,7 @@ class CONTENT_EXPORT RenderFrameHostImpl
// SensorProvider proxy which acts as a gatekeeper to the real SensorProvider.
std::unique_ptr<SensorProviderProxyImpl> sensor_provider_proxy_;
- std::unique_ptr<AssociatedInterfaceRegistryImpl> associated_registry_;
+ std::unique_ptr<blink::AssociatedInterfaceRegistry> associated_registry_;
std::unique_ptr<service_manager::BinderRegistry> registry_;
std::unique_ptr<service_manager::InterfaceProvider> remote_interfaces_;
@@ -1584,7 +1618,7 @@ class CONTENT_EXPORT RenderFrameHostImpl
std::unique_ptr<AuthenticatorImpl> authenticator_impl_;
#endif
- std::unique_ptr<AssociatedInterfaceProviderImpl>
+ std::unique_ptr<blink::AssociatedInterfaceProvider>
remote_associated_interfaces_;
// A bitwise OR of bindings types that have been enabled for this RenderFrame.
@@ -1674,6 +1708,18 @@ class CONTENT_EXPORT RenderFrameHostImpl
network::mojom::URLLoaderFactoryPtr
network_service_connection_error_handler_holder_;
+ // Holds the renderer generated ID and global request ID for the main frame
+ // request.
+ std::pair<int, GlobalRequestID> main_frame_request_ids_;
+
+ // If |ResourceLoadComplete()| is called for the main resource before
+ // |DidCommitProvisionalLoad()|, the load info is saved here to call
+ // |ResourceLoadComplete()| when |DidCommitProvisionalLoad()| is called. This
+ // is necessary so the renderer ID can be mapped to the global ID in
+ // |DidCommitProvisionalLoad()|. This situation should only happen when an
+ // empty document is loaded.
+ mojom::ResourceLoadInfoPtr deferred_main_frame_load_info_;
+
// 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 87210e4c20e..bea486b54d1 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
@@ -17,6 +17,7 @@
#include "content/browser/frame_host/navigation_handle_impl.h"
#include "content/browser/interface_provider_filtering.h"
#include "content/browser/renderer_host/input/timeout_monitor.h"
+#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/frame_messages.h"
#include "content/public/browser/javascript_dialog_manager.h"
@@ -28,6 +29,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/navigation_handle_observer.h"
#include "content/public/test/test_frame_navigation_observer.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/test_utils.h"
@@ -1831,4 +1833,87 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest,
main_frame->GetCanonicalUrlForSharing(base::DoNothing());
}
+// This test makes sure that when a blocked frame commits with a different URL,
+// it doesn't lead to a leaked NavigationHandle. This is a regression test for
+// https://crbug.com/872803.
+IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest,
+ ErrorPagesShouldntLeakNavigationHandles) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "foo.com", "/frame_tree/page_with_one_frame.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ GURL blocked_url(embedded_test_server()->GetURL(
+ "blocked.com", "/frame-ancestors-none.html"));
+ WebContents* web_contents = shell()->web_contents();
+ NavigationHandleObserver nav_handle_observer(web_contents, blocked_url);
+ EXPECT_TRUE(NavigateIframeToURL(web_contents, "child0", blocked_url));
+
+ // Verify that the NavigationHandle / NavigationRequest didn't leak.
+ RenderFrameHostImpl* frame = static_cast<RenderFrameHostImpl*>(
+ shell()->web_contents()->GetAllFrames()[1]);
+ EXPECT_EQ(0u, frame->GetNavigationEntryIdsPendingCommit().size());
+
+ // TODO(lukasza, clamy): https://crbug.com/784904: Verify that
+ // WebContentsObserver::DidFinishNavigation was called with the same
+ // NavigationHandle as WebContentsObserver::DidStartNavigation. This requires
+ // properly matching the commit IPC to the NavigationHandle (ignoring that
+ // their URLs do not match - matching instead using navigation id or mojo
+ // interface identity).
+ //
+ // Subsequent checks don't make sense before WCO::DidFinishNavigation is
+ // called - this is why ASSERT_TRUE is used here.
+ // ASSERT_TRUE(nav_handle_observer.has_committed());
+ // EXPECT_EQ(net::ERR_BLOCKED_BY_RESPONSE,
+ // nav_handle_observer.net_error_code());
+
+ // TODO(lukasza): https://crbug.com/759184: Verify
+ // |nav_handle_observer.last_committed_url()| below - this should be possible
+ // once we handle frame-ancestors CSP in the browser process and commit it
+ // with the original URL.
+ // EXPECT_EQ(blocked_url, nav_handle_observer.last_committed_url());
+}
+
+IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest,
+ NotifiesProcessHostOfAudibleAudio) {
+ const auto RunPostedTasks = []() {
+ base::RunLoop run_loop;
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ run_loop.QuitClosure());
+ run_loop.Run();
+ };
+
+ // Note: Just using the beforeunload.html test document to spin-up a
+ // renderer. Any document will do.
+ EXPECT_TRUE(NavigateToURL(
+ shell(), GetTestUrl("render_frame_host", "beforeunload.html")));
+ EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+
+ auto* frame = static_cast<RenderFrameHostImpl*>(
+ shell()->web_contents()->GetMainFrame());
+ auto* process = static_cast<RenderProcessHostImpl*>(frame->GetProcess());
+ ASSERT_EQ(0, process->get_media_stream_count_for_testing());
+
+ // Audible audio output should cause the media stream count to increment.
+ frame->OnAudibleStateChanged(true);
+ RunPostedTasks();
+ EXPECT_EQ(1, process->get_media_stream_count_for_testing());
+
+ // Silence should cause the media stream count to decrement.
+ frame->OnAudibleStateChanged(false);
+ RunPostedTasks();
+ EXPECT_EQ(0, process->get_media_stream_count_for_testing());
+
+ // Start audible audio output again, and then crash the renderer. Expect the
+ // media stream count to be zero after the crash.
+ frame->OnAudibleStateChanged(true);
+ RunPostedTasks();
+ EXPECT_EQ(1, process->get_media_stream_count_for_testing());
+ RenderProcessHostWatcher crash_observer(
+ process, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
+ process->Shutdown(0);
+ crash_observer.Wait();
+ RunPostedTasks();
+ EXPECT_EQ(0, process->get_media_stream_count_for_testing());
+}
+
} // 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 872e4609c94..49ad391a313 100644
--- a/chromium/content/browser/frame_host/render_frame_host_manager.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_manager.cc
@@ -1218,7 +1218,8 @@ RenderFrameHostManager::DetermineSiteInstanceForURL(
// thus use the correct process.
bool use_process_per_site =
RenderProcessHost::ShouldUseProcessPerSite(browser_context, dest_url) &&
- RenderProcessHostImpl::GetProcessHostForSite(browser_context, dest_url);
+ RenderProcessHostImpl::GetSoleProcessHostForURL(browser_context,
+ dest_url);
if (current_instance_impl->HasRelatedSiteInstance(dest_url) ||
use_process_per_site) {
return SiteInstanceDescriptor(browser_context, dest_url,
@@ -1540,22 +1541,22 @@ bool RenderFrameHostManager::IsCurrentlySameSite(RenderFrameHostImpl* candidate,
const GURL& dest_url) {
BrowserContext* browser_context =
delegate_->GetControllerForRenderManager().GetBrowserContext();
- // Don't compare effective URLs for all subframe navigations, since we don't
- // want to create OOPIFs based on that mechanism (e.g., for hosted apps). For
- // main frames, don't compare effective URLs when transitioning from app to
- // non-app URLs if there exists another app WebContents that might script
- // this one. These navigations should stay in the app process to not break
- // scripting when a hosted app opens a same-site popup. See
- // https://crbug.com/718516 and https://crbug.com/828720.
+
+ // Ask embedder whether effective URLs should be used when determining if
+ // |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 =
+ GetContentClient()
+ ->browser()
+ ->ShouldCompareEffectiveURLsForSiteInstanceSelection(
+ browser_context, candidate->GetSiteInstance(),
+ frame_tree_node_->IsMainFrame(),
+ candidate->GetSiteInstance()->original_url(), dest_url);
+
bool src_has_effective_url = SiteInstanceImpl::HasEffectiveURL(
browser_context, candidate->GetSiteInstance()->original_url());
bool dest_has_effective_url =
SiteInstanceImpl::HasEffectiveURL(browser_context, dest_url);
- bool should_compare_effective_urls = true;
- if (!frame_tree_node_->IsMainFrame() ||
- (src_has_effective_url && !dest_has_effective_url &&
- candidate->GetSiteInstance()->GetRelatedActiveContentsCount() > 1u))
- should_compare_effective_urls = false;
// If the process type is incorrect, reject the candidate even if |dest_url|
// is same-site. (The URL may have been installed as an app since
@@ -2163,6 +2164,13 @@ void RenderFrameHostManager::CommitPending() {
render_frame_host_->GetView() &&
render_frame_host_->GetView()->HasFocus();
+ // Remove the current frame and its descendants from the set of fullscreen
+ // frames immediately. They can stay in pending deletion for some time.
+ // Removing them when they are deleted is too late.
+ // This needs to be done before updating the frame tree structure, else it
+ // will have trouble removing the descendants.
+ render_frame_delegate_->FullscreenStateChanged(current_frame_host(), false);
+
// While the old frame is still current, remove its children from the tree.
frame_tree_node_->ResetForNewProcess();
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 c49de36a819..a6821503c3e 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
@@ -12,12 +12,14 @@
#include "base/json/json_reader.h"
#include "base/location.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_split.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "base/time/time.h"
#include "base/values.h"
#include "build/build_config.h"
#include "content/browser/child_process_security_policy_impl.h"
@@ -30,6 +32,8 @@
#include "content/browser/webui/web_ui_controller_factory_registry.h"
#include "content/browser/webui/web_ui_impl.h"
#include "content/common/content_constants_internal.h"
+#include "content/public/browser/browser_child_process_host.h"
+#include "content/public/browser/child_process_launcher_utils.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/render_process_host.h"
@@ -181,17 +185,8 @@ class RenderFrameHostManagerTest : public ContentBrowserTest {
std::unique_ptr<content::URLLoaderInterceptor> SetupRequestFailForURL(
const GURL& url) {
- return std::make_unique<content::URLLoaderInterceptor>(base::BindRepeating(
- [](const GURL& url,
- content::URLLoaderInterceptor::RequestParams* params) {
- if (params->url_request.url != url)
- return false;
- network::URLLoaderCompletionStatus status;
- status.error_code = net::ERR_DNS_TIMED_OUT;
- params->client->OnComplete(status);
- return true;
- },
- url));
+ return URLLoaderInterceptor::SetupRequestFailForURL(url,
+ net::ERR_DNS_TIMED_OUT);
}
// Returns a URL on foo.com with the given path.
@@ -2370,7 +2365,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, WebUIGetsBindings) {
GURL url1(std::string(kChromeUIScheme) + "://" +
std::string(kChromeUIGpuHost));
GURL url2(std::string(kChromeUIScheme) + "://" +
- std::string(kChromeUIAccessibilityHost));
+ std::string(kChromeUIHistogramHost));
// Visit a WebUI page with bindings.
NavigateToURL(shell(), url1);
@@ -4575,6 +4570,103 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
EXPECT_EQ(error_url.spec(), result);
}
+// Test to verify that navigation to existing history entry, which results in
+// an error page, is correctly placed in the error page SiteInstance.
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
+ ErrorPageNavigationHistoryNavigationFailure) {
+ // This test is only valid if error page isolation is enabled.
+ if (!SiteIsolationPolicy::IsErrorPageIsolationEnabled(true))
+ return;
+
+ StartEmbeddedServer();
+
+ // Perform successful navigations to two URLs to establish session history.
+ GURL url1(embedded_test_server()->GetURL("a.com", "/title1.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), url1));
+
+ GURL url2(embedded_test_server()->GetURL("b.com", "/title2.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), url2));
+
+ WebContents* web_contents = shell()->web_contents();
+ NavigationControllerImpl& nav_controller =
+ static_cast<NavigationControllerImpl&>(web_contents->GetController());
+
+ // There should be two NavigationEntries.
+ EXPECT_EQ(2, nav_controller.GetEntryCount());
+
+ // Create an interceptor to cause navigations to url1 to fail and go back
+ // in session history.
+ std::unique_ptr<URLLoaderInterceptor> url_interceptor =
+ SetupRequestFailForURL(url1);
+ TestNavigationObserver back_observer(web_contents);
+ nav_controller.GoBack();
+ back_observer.Wait();
+ EXPECT_FALSE(back_observer.last_navigation_succeeded());
+ EXPECT_EQ(2, nav_controller.GetEntryCount());
+ EXPECT_EQ(0, nav_controller.GetLastCommittedEntryIndex());
+
+ EXPECT_EQ(GURL(kUnreachableWebDataURL),
+ web_contents->GetMainFrame()->GetSiteInstance()->GetSiteURL());
+ EXPECT_EQ(GURL(kUnreachableWebDataURL),
+ ChildProcessSecurityPolicyImpl::GetInstance()->GetOriginLock(
+ web_contents->GetSiteInstance()->GetProcess()->GetID()));
+}
+
+// Test to verify that a successful navigation to existing history entry,
+// which initially resulted in an error page, is correctly placed in a
+// SiteInstance different than the error page one.
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
+ ErrorPageNavigationHistoryNavigationSuccess) {
+ // This test is only valid if error page isolation is enabled.
+ if (!SiteIsolationPolicy::IsErrorPageIsolationEnabled(true))
+ return;
+
+ StartEmbeddedServer();
+ WebContents* web_contents = shell()->web_contents();
+
+ // Start with a successful navigation.
+ GURL url1(embedded_test_server()->GetURL("a.com", "/title1.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), url1));
+
+ // Navigate to URL that results in an error page and verify its SiteInstance.
+ GURL url2(embedded_test_server()->GetURL("b.com", "/title2.html"));
+ std::unique_ptr<URLLoaderInterceptor> url_interceptor =
+ SetupRequestFailForURL(url2);
+
+ EXPECT_FALSE(NavigateToURL(shell(), url2));
+ EXPECT_EQ(GURL(kUnreachableWebDataURL),
+ web_contents->GetMainFrame()->GetSiteInstance()->GetSiteURL());
+ EXPECT_EQ(GURL(kUnreachableWebDataURL),
+ ChildProcessSecurityPolicyImpl::GetInstance()->GetOriginLock(
+ web_contents->GetSiteInstance()->GetProcess()->GetID()));
+
+ // There should be two NavigationEntries.
+ NavigationControllerImpl& nav_controller =
+ static_cast<NavigationControllerImpl&>(web_contents->GetController());
+ EXPECT_EQ(2, nav_controller.GetEntryCount());
+
+ // Navigate once more to create another session history entry.
+ GURL url3(embedded_test_server()->GetURL("c.com", "/title3.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), url3));
+ EXPECT_EQ(3, nav_controller.GetEntryCount());
+
+ // Navigate back, this time remove the interceptor so the navigation will
+ // succeed.
+ url_interceptor.reset();
+ TestNavigationObserver back_observer(web_contents);
+ nav_controller.GoBack();
+ back_observer.Wait();
+ EXPECT_TRUE(back_observer.last_navigation_succeeded());
+ EXPECT_EQ(3, nav_controller.GetEntryCount());
+ EXPECT_EQ(1, nav_controller.GetLastCommittedEntryIndex());
+
+ EXPECT_NE(GURL(kUnreachableWebDataURL),
+ web_contents->GetMainFrame()->GetSiteInstance()->GetSiteURL());
+ EXPECT_NE(GURL(kUnreachableWebDataURL),
+ ChildProcessSecurityPolicyImpl::GetInstance()->GetOriginLock(
+ web_contents->GetSiteInstance()->GetProcess()->GetID()));
+}
+
// A NavigationThrottle implementation that blocks all outgoing navigation
// requests for a specific WebContents. It is used to block navigations to
// WebUI URLs in the following test.
@@ -5001,4 +5093,286 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerUnloadBrowserTest,
EXPECT_EQ("bar", message);
}
+// Ensure that when a pending delete RenderFrameHost's process dies, the
+// current RenderFrameHost does not lose its child frames. See
+// https://crbug.com/867274.
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerUnloadBrowserTest,
+ PendingDeleteRFHProcessShutdownDoesNotRemoveSubframes) {
+ GURL first_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), first_url));
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+ RenderFrameHostImpl* rfh = root->current_frame_host();
+
+ // Set up an unload handler which never finishes to force |rfh| to stay
+ // around in pending delete state and never receive the swapout ACK.
+ EXPECT_TRUE(
+ ExecuteScript(rfh, "window.onunload = function(e) { while(1); };\n"));
+ rfh->DisableSwapOutTimerForTesting();
+
+ // Navigate to another page with two subframes.
+ RenderFrameDeletedObserver rfh_observer(rfh);
+ GURL second_url(embedded_test_server()->GetURL(
+ "b.com", "/cross_site_iframe_factory.html?b(c,b)"));
+ EXPECT_TRUE(NavigateToURL(shell(), second_url));
+
+ // At this point, |rfh| should still be live and pending deletion.
+ EXPECT_FALSE(rfh_observer.deleted());
+ EXPECT_FALSE(rfh->is_active());
+ EXPECT_TRUE(rfh->IsRenderFrameLive());
+
+ // Meanwhile, the new page should have two subframes.
+ EXPECT_EQ(2U, root->child_count());
+
+ // Kill the pending delete RFH's process.
+ RenderProcessHostWatcher crash_observer(
+ rfh->GetProcess(), RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
+ rfh->GetProcess()->Shutdown(0);
+ crash_observer.Wait();
+
+ // The process kill should simulate a swapout ACK and trigger destruction of
+ // the pending delete RFH.
+ rfh_observer.WaitUntilDeleted();
+
+ // Ensure that the process kill didn't incorrectly remove subframes from the
+ // new page.
+ ASSERT_EQ(2U, root->child_count());
+ EXPECT_TRUE(root->child_at(0)->current_frame_host()->IsRenderFrameLive());
+ EXPECT_TRUE(root->child_at(1)->current_frame_host()->IsRenderFrameLive());
+}
+
+namespace {
+
+// A helper to post a recurring check that a renderer process is foregrounded.
+// The recurring check uses WeakPtr semantic and will die when this class goes
+// out of scope.
+class AssertForegroundHelper {
+ public:
+ AssertForegroundHelper() : weak_ptr_factory_(this) {}
+
+#if defined(OS_MACOSX)
+ // Asserts that |renderer_process| isn't backgrounded and reposts self to
+ // check again shortly. |renderer_process| must outlive this
+ // AssertForegroundHelper instance.
+ void AssertForegroundAndRepost(const base::Process& renderer_process,
+ base::PortProvider* port_provider) {
+ ASSERT_FALSE(renderer_process.IsProcessBackgrounded(port_provider));
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE,
+ base::BindOnce(&AssertForegroundHelper::AssertForegroundAndRepost,
+ weak_ptr_factory_.GetWeakPtr(),
+ base::ConstRef(renderer_process), port_provider),
+ base::TimeDelta::FromMilliseconds(1));
+ }
+#else // defined(OS_MACOSX)
+ // Same as above without the Mac specific base::PortProvider.
+ void AssertForegroundAndRepost(const base::Process& renderer_process) {
+ ASSERT_FALSE(renderer_process.IsProcessBackgrounded());
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE,
+ base::BindOnce(&AssertForegroundHelper::AssertForegroundAndRepost,
+ weak_ptr_factory_.GetWeakPtr(),
+ base::ConstRef(renderer_process)),
+ base::TimeDelta::FromMilliseconds(1));
+ }
+#endif // defined(OS_MACOSX)
+
+ private:
+ base::WeakPtrFactory<AssertForegroundHelper> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(AssertForegroundHelper);
+};
+
+// Observer class that waits until the OS process for a specific
+// RenderProcessHost is ready to be used.
+// TODO(nasko): Consider moving this into RenderProcessHostWatcher.
+class RenderProcessReadyObserver : public RenderProcessHostObserver {
+ public:
+ RenderProcessReadyObserver(RenderProcessHost* render_process_host)
+ : render_process_host_(render_process_host),
+ quit_closure_(run_loop_.QuitClosure()) {
+ render_process_host_->AddObserver(this);
+ }
+ ~RenderProcessReadyObserver() override {
+ render_process_host_->RemoveObserver(this);
+ }
+
+ // Waits until the renderer process is ready.
+ void Wait() { run_loop_.Run(); }
+
+ private:
+ // RenderProcessHostObserver overrides.
+ void RenderProcessReady(RenderProcessHost* host) override {
+ std::move(quit_closure_).Run();
+ }
+
+ RenderProcessHost* render_process_host_;
+ base::RunLoop run_loop_;
+ base::OnceClosure quit_closure_;
+
+ DISALLOW_COPY_AND_ASSIGN(RenderProcessReadyObserver);
+};
+
+} // namespace
+
+// This is a regression test for https://crbug.com/560446. It ensures the
+// newly launched process for cross-process navigation in the foreground
+// WebContents isn't backgrounded prior to the navigation committing and a
+// "visible" widget being added to the process. This test discards the spare
+// RenderProcessHost if present, to ensure that it is not used in the
+// cross-process navigation.
+IN_PROC_BROWSER_TEST_F(
+ RenderFrameHostManagerTest,
+ ForegroundNavigationIsNeverBackgroundedWithoutSpareProcess) {
+ StartEmbeddedServer();
+ WebContentsImpl* web_contents =
+ static_cast<WebContentsImpl*>(shell()->web_contents());
+
+#if defined(OS_MACOSX)
+ base::PortProvider* port_provider =
+ BrowserChildProcessHost::GetPortProvider();
+#endif // defined(OS_MACOSX)
+
+ // Start off navigating to a.com and capture the process used to commit.
+ EXPECT_TRUE(NavigateToURL(
+ shell(), embedded_test_server()->GetURL("a.com", "/title1.html")));
+ RenderProcessHost* start_rph = web_contents->GetMainFrame()->GetProcess();
+
+ // Discard the spare RenderProcessHost to ensure a new RenderProcessHost
+ // is created and has the right prioritization.
+ RenderProcessHostImpl::DiscardSpareRenderProcessHostForTesting();
+ EXPECT_FALSE(RenderProcessHostImpl::GetSpareRenderProcessHostForTesting());
+
+ // Start a navigation to b.com to ensure a cross-process navigation is
+ // in progress and ensure the process for the speculative host is different.
+ GURL url(embedded_test_server()->GetURL("b.com", "/title2.html"));
+ content::TestNavigationManager navigation_manager(web_contents, url);
+
+ shell()->LoadURL(url);
+ RenderProcessHost* speculative_rph = web_contents->GetFrameTree()
+ ->root()
+ ->render_manager()
+ ->speculative_frame_host()
+ ->GetProcess();
+ EXPECT_NE(start_rph, speculative_rph);
+ EXPECT_FALSE(speculative_rph->IsReady());
+
+#if !defined(OS_ANDROID)
+ // TODO(gab, nasko): On Android IsProcessBackgrounded is currently giving
+ // incorrect value at this stage of the process lifetime. This should be
+ // fixed in follow up cleanup work. See https://crbug.com/560446.
+ EXPECT_FALSE(speculative_rph->IsProcessBackgrounded());
+#endif
+
+ // Wait for the underlying OS process to have launched and be ready to
+ // receive IPCs.
+ RenderProcessReadyObserver process_observer(speculative_rph);
+ process_observer.Wait();
+
+ // Kick off an infinite check against self that the process used for
+ // navigation is never backgrounded. The WaitForNavigationFinished will wait
+ // inside a RunLoop() and hence perform this check regularly throughout the
+ // navigation.
+ const base::Process& process = speculative_rph->GetProcess();
+ EXPECT_TRUE(process.IsValid());
+ AssertForegroundHelper assert_foreground_helper;
+#if defined(OS_MACOSX)
+ assert_foreground_helper.AssertForegroundAndRepost(process, port_provider);
+#else
+ assert_foreground_helper.AssertForegroundAndRepost(process);
+#endif
+
+ // The process should be foreground priority before commit because it is
+ // pending, and foreground after commit because it has a visible widget.
+ navigation_manager.WaitForNavigationFinished();
+ EXPECT_NE(start_rph, web_contents->GetMainFrame()->GetProcess());
+ EXPECT_EQ(speculative_rph, web_contents->GetMainFrame()->GetProcess());
+}
+
+// Similar to the test above, but verifies the spare RenderProcessHost uses the
+// right priority.
+IN_PROC_BROWSER_TEST_F(
+ RenderFrameHostManagerTest,
+ ForegroundNavigationIsNeverBackgroundedWithSpareProcess) {
+ // This test applies only when spare RenderProcessHost is enabled and in use.
+ if (!RenderProcessHostImpl::IsSpareProcessKeptAtAllTimes())
+ return;
+
+ StartEmbeddedServer();
+ WebContentsImpl* web_contents =
+ static_cast<WebContentsImpl*>(shell()->web_contents());
+
+#if defined(OS_MACOSX)
+ base::PortProvider* port_provider =
+ BrowserChildProcessHost::GetPortProvider();
+#endif // defined(OS_MACOSX)
+
+ // Start off navigating to a.com and capture the process used to commit.
+ EXPECT_TRUE(NavigateToURL(
+ shell(), embedded_test_server()->GetURL("a.com", "/title1.html")));
+ RenderProcessHost* start_rph = web_contents->GetMainFrame()->GetProcess();
+
+ // At this time, there should be a spare RenderProcesHost. Capture it for
+ // testing expectations later.
+ RenderProcessHost* spare_rph =
+ RenderProcessHostImpl::GetSpareRenderProcessHostForTesting();
+ EXPECT_TRUE(spare_rph);
+ EXPECT_TRUE(spare_rph->IsProcessBackgrounded());
+
+ // Start a navigation to b.com to ensure a cross-process navigation is
+ // in progress and ensure the process for the speculative host is
+ // different, but matches the spare RenderProcessHost.
+ GURL url(embedded_test_server()->GetURL("b.com", "/title2.html"));
+ content::TestNavigationManager navigation_manager(web_contents, url);
+
+ shell()->LoadURL(url);
+ RenderProcessHost* speculative_rph = web_contents->GetFrameTree()
+ ->root()
+ ->render_manager()
+ ->speculative_frame_host()
+ ->GetProcess();
+ EXPECT_NE(start_rph, speculative_rph);
+
+ // In this test case, the spare RenderProcessHost will be used, so verify it
+ // and ensure it is ready.
+ EXPECT_EQ(spare_rph, speculative_rph);
+ EXPECT_TRUE(spare_rph->IsReady());
+
+ // The creation of the speculative RenderFrameHost should change the
+ // RenderProcessHost's copy of the priority of the spare process from
+ // background to foreground.
+ EXPECT_FALSE(spare_rph->IsProcessBackgrounded());
+
+ // The OS process itself is updated on the process launcher thread, so it
+ // cannot be observed immediately here. Perform a thread hop to and back to
+ // allow for the priority change to occur before using the
+ // AssertForegroundHelper object to check the OS process priority.
+ {
+ base::RunLoop run_loop;
+ GetProcessLauncherTaskRunner()->PostTaskAndReply(
+ FROM_HERE, base::DoNothing(), run_loop.QuitWhenIdleClosure());
+ run_loop.Run();
+ }
+
+ // Kick off an infinite check against self that the process used for
+ // navigation is never backgrounded. The WaitForNavigationFinished will wait
+ // inside a RunLoop() and hence perform this check regularly throughout the
+ // navigation.
+ const base::Process& process = spare_rph->GetProcess();
+ EXPECT_TRUE(process.IsValid());
+ AssertForegroundHelper assert_foreground_helper;
+#if defined(OS_MACOSX)
+ assert_foreground_helper.AssertForegroundAndRepost(process, port_provider);
+#else
+ assert_foreground_helper.AssertForegroundAndRepost(process);
+#endif
+
+ // The process should be foreground priority before commit because it is
+ // pending, and foreground after commit because it has a visible widget.
+ navigation_manager.WaitForNavigationFinished();
+ EXPECT_NE(start_rph, web_contents->GetMainFrame()->GetProcess());
+ EXPECT_EQ(speculative_rph, web_contents->GetMainFrame()->GetProcess());
+}
+
} // namespace content
diff --git a/chromium/content/browser/frame_host/render_frame_host_manager_unittest.cc b/chromium/content/browser/frame_host/render_frame_host_manager_unittest.cc
index b4fb251d110..bc5e48e26e0 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
@@ -3159,13 +3159,17 @@ TEST_F(RenderFrameHostManagerTest,
// Simulate a browser-initiated navigation to an app URL, which should swap
// processes and create a new SiteInstance in a new BrowsingInstance.
- // This new SiteInstance should have correct site URL and |original_url()|.
+ // This new SiteInstance should have correct |original_url()| and site URL.
+ // The site URL should include both the |original_url()|'s site and the
+ // translated URL's site.
NavigationSimulator::NavigateAndCommitFromBrowser(contents(), kOriginalUrl);
EXPECT_NE(initial_instance.get(), main_test_rfh()->GetSiteInstance());
EXPECT_FALSE(initial_instance->IsRelatedSiteInstance(
main_test_rfh()->GetSiteInstance()));
EXPECT_EQ(kOriginalUrl, main_test_rfh()->GetSiteInstance()->original_url());
- EXPECT_EQ(kTranslatedUrl, main_test_rfh()->GetSiteInstance()->GetSiteURL());
+ GURL expected_site_url(kTranslatedUrl.spec() + "#" + kOriginalUrl.spec());
+ EXPECT_EQ(expected_site_url,
+ main_test_rfh()->GetSiteInstance()->GetSiteURL());
SetBrowserClientForTesting(regular_client);
}
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 2f32390f0b4..dfd9bb1aa8c 100644
--- a/chromium/content/browser/frame_host/render_frame_message_filter.cc
+++ b/chromium/content/browser/frame_host/render_frame_message_filter.cc
@@ -271,19 +271,6 @@ RenderFrameMessageFilter::RenderFrameMessageFilter(
render_widget_helper_(render_widget_helper),
incognito_(browser_context->IsOffTheRecord()),
render_process_id_(render_process_id) {
- network::mojom::CookieManagerPtr cookie_manager;
- storage_partition->GetNetworkContext()->GetCookieManager(
- mojo::MakeRequest(&cookie_manager));
-
- // The PostTask below could finish before the constructor returns which would
- // lead to this object being destructed prematurely.
- AddRef();
- base::ThreadTaskRunnerHandle::Get()->ReleaseSoon(FROM_HERE, this);
-
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&RenderFrameMessageFilter::InitializeOnIO, this,
- cookie_manager.PassInterface()));
}
RenderFrameMessageFilter::~RenderFrameMessageFilter() {
@@ -291,9 +278,26 @@ RenderFrameMessageFilter::~RenderFrameMessageFilter() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
}
-void RenderFrameMessageFilter::InitializeOnIO(
- network::mojom::CookieManagerPtrInfo cookie_manager) {
- cookie_manager_.Bind(std::move(cookie_manager));
+network::mojom::CookieManagerPtr* RenderFrameMessageFilter::GetCookieManager() {
+ if (!cookie_manager_ || cookie_manager_.encountered_error()) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&RenderFrameMessageFilter::InitializeCookieManager, this,
+ mojo::MakeRequest(&cookie_manager_)));
+ }
+ return &cookie_manager_;
+}
+
+void RenderFrameMessageFilter::InitializeCookieManager(
+ network::mojom::CookieManagerRequest cookie_manager_request) {
+ RenderProcessHost* render_process_host =
+ RenderProcessHost::FromID(render_process_id_);
+ if (!render_process_host)
+ return;
+
+ render_process_host->GetStoragePartition()
+ ->GetNetworkContext()
+ ->GetCookieManager(std::move(cookie_manager_request));
}
bool RenderFrameMessageFilter::OnMessageReceived(const IPC::Message& message) {
@@ -556,9 +560,10 @@ void RenderFrameMessageFilter::SetCookie(int32_t render_frame_id,
// this process' StoragePartition.
if (base::FeatureList::IsEnabled(network::features::kNetworkService) &&
context == request_context_->GetURLRequestContext()) {
- cookie_manager_->SetCanonicalCookie(*cookie, url.SchemeIsCryptographic(),
- !options.exclude_httponly(),
- net::CookieStore::SetCookiesCallback());
+ (*GetCookieManager())
+ ->SetCanonicalCookie(*cookie, url.SchemeIsCryptographic(),
+ !options.exclude_httponly(),
+ net::CookieStore::SetCookiesCallback());
return;
}
@@ -605,11 +610,12 @@ void RenderFrameMessageFilter::GetCookies(int render_frame_id,
context == request_context_->GetURLRequestContext()) {
// TODO(jam): modify GetRequestContextForURL to work with network service.
// Merge this with code path below for non-network service.
- cookie_manager_->GetCookieList(
- url, options,
- base::BindOnce(&RenderFrameMessageFilter::CheckPolicyForCookies, this,
- render_frame_id, url, site_for_cookies,
- std::move(callback)));
+ (*GetCookieManager())
+ ->GetCookieList(
+ url, options,
+ base::BindOnce(&RenderFrameMessageFilter::CheckPolicyForCookies,
+ this, render_frame_id, url, site_for_cookies,
+ std::move(callback)));
return;
}
diff --git a/chromium/content/browser/frame_host/render_frame_message_filter.h b/chromium/content/browser/frame_host/render_frame_message_filter.h
index 9716b200806..a661ac52665 100644
--- a/chromium/content/browser/frame_host/render_frame_message_filter.h
+++ b/chromium/content/browser/frame_host/render_frame_message_filter.h
@@ -73,6 +73,8 @@ class CONTENT_EXPORT RenderFrameMessageFilter
bool OnMessageReceived(const IPC::Message& message) override;
void OnDestruct() const override;
+ network::mojom::CookieManagerPtr* GetCookieManager();
+
protected:
friend class TestSaveImageFromDataURL;
@@ -97,7 +99,8 @@ class CONTENT_EXPORT RenderFrameMessageFilter
~RenderFrameMessageFilter() override;
- void InitializeOnIO(network::mojom::CookieManagerPtrInfo cookie_manager);
+ void InitializeCookieManager(
+ network::mojom::CookieManagerRequest cookie_manager_request);
// |new_render_frame_id| and |devtools_frame_token| are out parameters.
// Browser process defines them for the renderer process.
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 b06a4b9242d..bad4c9fc4eb 100644
--- a/chromium/content/browser/frame_host/render_frame_proxy_host.cc
+++ b/chromium/content/browser/frame_host/render_frame_proxy_host.cc
@@ -8,8 +8,6 @@
#include <vector>
#include "base/callback.h"
-#include "base/debug/alias.h"
-#include "base/debug/dump_without_crashing.h"
#include "base/lazy_instance.h"
#include "content/browser/bad_message.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
@@ -204,30 +202,6 @@ bool RenderFrameProxyHost::InitRenderFrameProxy() {
site_instance_.get());
}
- // Temporary debugging code for https://crbug.com/794625 to see if we're ever
- // sending a message to create a RenderFrameProxy when one already exists.
- // TODO(alexmos): Remove after the investigation.
- if (render_frame_proxy_created_) {
- SiteInstanceImpl* site_instance =
- static_cast<SiteInstanceImpl*>(site_instance_.get());
- GURL site_url(site_instance->GetSiteURL());
- DEBUG_ALIAS_FOR_GURL(site_url_copy, site_url);
- GURL current_rfh_site_url(frame_tree_node_->render_manager()
- ->current_frame_host()
- ->GetSiteInstance()
- ->GetSiteURL());
- DEBUG_ALIAS_FOR_GURL(current_rfh_site_url_copy, current_rfh_site_url);
-
- int routing_id_copy = routing_id_;
- base::debug::Alias(&routing_id_copy);
- int parent_routing_id_copy = parent_routing_id;
- base::debug::Alias(&parent_routing_id_copy);
- int active_frame_count = site_instance->active_frame_count();
- base::debug::Alias(&active_frame_count);
-
- base::debug::DumpWithoutCrashing();
- }
-
int view_routing_id = frame_tree_node_->frame_tree()
->GetRenderViewHost(site_instance_.get())->GetRoutingID();
GetProcess()->GetRendererInterface()->CreateFrameProxy(
@@ -235,7 +209,7 @@ bool RenderFrameProxyHost::InitRenderFrameProxy() {
frame_tree_node_->current_replication_state(),
frame_tree_node_->devtools_frame_token());
- render_frame_proxy_created_ = true;
+ set_render_frame_proxy_created(true);
// For subframes, initialize the proxy's FrameOwnerProperties only if they
// differ from default values.
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 7c08ae7a4ee..86c4876e2d4 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
@@ -186,15 +186,6 @@ bool RenderWidgetHostViewGuest::HasFocus() const {
return guest_->focused();
}
-#if defined(USE_AURA)
-void RenderWidgetHostViewGuest::ProcessAckedTouchEvent(
- const TouchEventWithLatencyInfo& touch, InputEventAckState ack_result) {
- // TODO(tdresser): Since all ProcessAckedTouchEvent() uses is the event id,
- // don't pass the full event object here. https://crbug.com/550581.
- GetOwnerRenderWidgetHostView()->ProcessAckedTouchEvent(touch, ack_result);
-}
-#endif
-
void RenderWidgetHostViewGuest::PreProcessMouseEvent(
const blink::WebMouseEvent& event) {
if (event.GetType() == blink::WebInputEvent::kMouseDown) {
@@ -354,6 +345,10 @@ gfx::Range RenderWidgetHostViewGuest::GetSelectedRange() {
return platform_view_->GetSelectedRange();
}
+size_t RenderWidgetHostViewGuest::GetOffsetForSurroundingText() {
+ return platform_view_->GetOffsetForSurroundingText();
+}
+
void RenderWidgetHostViewGuest::SetNeedsBeginFrames(bool needs_begin_frames) {
if (platform_view_)
platform_view_->SetNeedsBeginFrames(needs_begin_frames);
@@ -392,7 +387,7 @@ void RenderWidgetHostViewGuest::OnDidUpdateVisualPropertiesComplete(
void RenderWidgetHostViewGuest::OnAttached() {
RegisterFrameSinkId();
#if defined(USE_AURA)
- if (!features::IsAshInBrowserProcess()) {
+ if (features::IsUsingWindowService()) {
aura::Env::GetInstance()->ScheduleEmbed(
GetWindowTreeClientFromRenderer(),
base::BindOnce(&RenderWidgetHostViewGuest::OnGotEmbedToken,
@@ -412,6 +407,10 @@ bool RenderWidgetHostViewGuest::OnMessageReceived(const IPC::Message& msg) {
return platform_view_->OnMessageReceived(msg);
}
+RenderWidgetHostViewBase* RenderWidgetHostViewGuest::GetRootView() {
+ return GetRootView(this);
+}
+
void RenderWidgetHostViewGuest::InitAsChild(
gfx::NativeView parent_view) {
// This should never get called.
@@ -616,11 +615,17 @@ RenderWidgetHostViewGuest::GetOwnerRenderWidgetHostView() const {
: nullptr;
}
+void RenderWidgetHostViewGuest::MaybeSendSyntheticTapGestureForTest(
+ const blink::WebFloatPoint& position,
+ const blink::WebFloatPoint& screen_position) const {
+ MaybeSendSyntheticTapGesture(position, screen_position);
+}
+
// TODO(wjmaclean): When we remove BrowserPlugin, delete this code.
// http://crbug.com/533069
void RenderWidgetHostViewGuest::MaybeSendSyntheticTapGesture(
const blink::WebFloatPoint& position,
- const blink::WebFloatPoint& screenPosition) const {
+ const blink::WebFloatPoint& screen_position) const {
if (!HasFocus()) {
// We need to a account for the position of the guest view within the
// embedder, as well as the fact that the embedder's host will add its
@@ -636,7 +641,14 @@ void RenderWidgetHostViewGuest::MaybeSendSyntheticTapGesture(
blink::kWebGestureDeviceTouchscreen);
gesture_tap_event.SetPositionInWidget(
blink::WebFloatPoint(position.x + offset.x(), position.y + offset.y()));
- gesture_tap_event.SetPositionInScreen(screenPosition);
+ gesture_tap_event.SetPositionInScreen(screen_position);
+ // The touch action may not be set yet because this is still at the
+ // Pre-processing stage of a mouse or a touch event. In this case, set the
+ // touch action to Auto to prevent crashing.
+ static_cast<RenderWidgetHostImpl*>(
+ GetOwnerRenderWidgetHostView()->GetRenderWidgetHost())
+ ->input_router()
+ ->ForceSetTouchActionAuto();
GetOwnerRenderWidgetHostView()->ProcessGestureEvent(
gesture_tap_event, ui::LatencyInfo(ui::SourceEventType::TOUCH));
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 864dd4bed93..db521ae67fb 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
@@ -82,6 +82,7 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest
base::string16 GetSelectedText() override;
base::string16 GetSurroundingText() override;
gfx::Range GetSelectedRange() override;
+ size_t GetOffsetForSurroundingText() override;
void SetNeedsBeginFrames(bool needs_begin_frames) override;
TouchSelectionControllerClientManager*
GetTouchSelectionControllerClientManager() override;
@@ -95,6 +96,7 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest
const gfx::PointF& point) override;
// RenderWidgetHostViewBase implementation.
+ RenderWidgetHostViewBase* GetRootView() override;
void InitAsPopup(RenderWidgetHostView* parent_host_view,
const gfx::Rect& bounds) override;
void InitAsFullscreen(RenderWidgetHostView* reference_host_view) override;
@@ -117,10 +119,6 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest
const gfx::Range& range) override;
void SelectionBoundsChanged(
const ViewHostMsg_SelectionBounds_Params& params) override;
-#if defined(USE_AURA)
- void ProcessAckedTouchEvent(const TouchEventWithLatencyInfo& touch,
- InputEventAckState ack_result) override;
-#endif
void PreProcessMouseEvent(const blink::WebMouseEvent& event) override;
void PreProcessTouchEvent(const blink::WebTouchEvent& event) override;
@@ -161,6 +159,10 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest
viz::ScopedSurfaceIdAllocator DidUpdateVisualProperties(
const cc::RenderFrameMetadata& metadata) override;
+ void MaybeSendSyntheticTapGestureForTest(
+ const blink::WebFloatPoint& position,
+ const blink::WebFloatPoint& screen_position) const;
+
private:
friend class RenderWidgetHostView;
@@ -182,7 +184,7 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest
// http://crbug.com/533069
void MaybeSendSyntheticTapGesture(
const blink::WebFloatPoint& position,
- const blink::WebFloatPoint& screenPosition) const;
+ const blink::WebFloatPoint& screen_position) const;
void OnHandleInputEvent(RenderWidgetHostImpl* embedder,
int browser_plugin_instance_id,
diff --git a/chromium/content/browser/frame_host/render_widget_host_view_guest_unittest.cc b/chromium/content/browser/frame_host/render_widget_host_view_guest_unittest.cc
index fa97ccfa39b..bfa0b5f3cf9 100644
--- a/chromium/content/browser/frame_host/render_widget_host_view_guest_unittest.cc
+++ b/chromium/content/browser/frame_host/render_widget_host_view_guest_unittest.cc
@@ -198,6 +198,12 @@ class RenderWidgetHostViewGuestSurfaceTest
};
TEST_F(RenderWidgetHostViewGuestSurfaceTest, TestGuestSurface) {
+ // Early out because RenderWidgetHostViewChildFrame::SendSurfaceInfoToEmbedder
+ // is no-op on mash and the test expects it call into FirstSurfaceActivation
+ // of BrowserPluginGuest.
+ if (features::IsUsingWindowService())
+ return;
+
gfx::Size view_size(100, 100);
gfx::Rect view_rect(view_size);
float scale_factor = 1.f;
diff --git a/chromium/content/browser/geolocation/geolocation_service_impl.cc b/chromium/content/browser/geolocation/geolocation_service_impl.cc
index 342e68a8317..6bd741016f3 100644
--- a/chromium/content/browser/geolocation/geolocation_service_impl.cc
+++ b/chromium/content/browser/geolocation/geolocation_service_impl.cc
@@ -7,7 +7,6 @@
#include "content/browser/permissions/permission_controller_impl.h"
#include "content/public/browser/permission_type.h"
#include "content/public/browser/render_frame_host.h"
-#include "content/public/common/content_features.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom.h"
namespace content {
@@ -72,8 +71,7 @@ void GeolocationServiceImpl::Bind(
void GeolocationServiceImpl::CreateGeolocation(
mojo::InterfaceRequest<device::mojom::Geolocation> request,
bool user_gesture) {
- if (base::FeatureList::IsEnabled(features::kUseFeaturePolicyForPermissions) &&
- !render_frame_host_->IsFeatureEnabled(
+ if (!render_frame_host_->IsFeatureEnabled(
blink::mojom::FeaturePolicyFeature::kGeolocation)) {
return;
}
diff --git a/chromium/content/browser/geolocation/geolocation_service_impl_unittest.cc b/chromium/content/browser/geolocation/geolocation_service_impl_unittest.cc
index bb1ec33adf4..9499af1083b 100644
--- a/chromium/content/browser/geolocation/geolocation_service_impl_unittest.cc
+++ b/chromium/content/browser/geolocation/geolocation_service_impl_unittest.cc
@@ -6,11 +6,9 @@
#include "base/bind_helpers.h"
#include "base/run_loop.h"
-#include "base/test/scoped_feature_list.h"
#include "content/browser/permissions/permission_controller_impl.h"
#include "content/public/browser/permission_controller.h"
#include "content/public/browser/permission_type.h"
-#include "content/public/common/content_features.h"
#include "content/public/common/service_manager_connection.h"
#include "content/public/test/mock_permission_manager.h"
#include "content/public/test/navigation_simulator.h"
@@ -27,7 +25,6 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom.h"
-using base::test::ScopedFeatureList;
using blink::mojom::PermissionStatus;
using device::mojom::GeolocationPtr;
using device::mojom::GeopositionPtr;
@@ -155,9 +152,6 @@ class GeolocationServiceTest : public RenderViewHostImplTestHarness {
TEST_F(GeolocationServiceTest, PermissionGrantedPolicyViolation) {
// The embedded frame is not whitelisted.
- ScopedFeatureList feature_list;
- feature_list.InitFromCommandLine(
- features::kUseFeaturePolicyForPermissions.name, std::string());
CreateEmbeddedFrameAndGeolocationService(/*allow_via_feature_policy=*/false);
permission_manager()->SetRequestCallback(
@@ -178,9 +172,6 @@ TEST_F(GeolocationServiceTest, PermissionGrantedPolicyViolation) {
TEST_F(GeolocationServiceTest, PermissionGrantedNoPolicyViolation) {
// Whitelist the embedded frame.
- ScopedFeatureList feature_list;
- feature_list.InitFromCommandLine(
- features::kUseFeaturePolicyForPermissions.name, std::string());
CreateEmbeddedFrameAndGeolocationService(/*allow_via_feature_policy=*/true);
permission_manager()->SetRequestCallback(
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 ca32413b3f3..f141ce1abbd 100644
--- a/chromium/content/browser/gpu/browser_gpu_channel_host_factory.cc
+++ b/chromium/content/browser/gpu/browser_gpu_channel_host_factory.cc
@@ -4,6 +4,8 @@
#include "content/browser/gpu/browser_gpu_channel_host_factory.h"
+#include <utility>
+
#include "base/android/orderfile/orderfile_buildflags.h"
#include "base/bind.h"
#include "base/command_line.h"
@@ -17,8 +19,9 @@
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "components/viz/common/features.h"
-#include "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
+#include "components/viz/host/gpu_host_impl.h"
#include "content/browser/gpu/gpu_data_manager_impl.h"
+#include "content/browser/gpu/gpu_memory_buffer_manager_singleton.h"
#include "content/browser/gpu/gpu_process_host.h"
#include "content/browser/gpu/shader_cache_factory.h"
#include "content/common/child_process_host_impl.h"
@@ -28,6 +31,8 @@
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
#include "gpu/command_buffer/service/gpu_switches.h"
+#include "gpu/config/gpu_finch_features.h"
+#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 "services/service_manager/runner/common/client_util.h"
@@ -74,7 +79,7 @@ class BrowserGpuChannelHostFactory::EstablishRequest
void OnEstablishedOnIO(mojo::ScopedMessagePipeHandle channel_handle,
const gpu::GPUInfo& gpu_info,
const gpu::GpuFeatureInfo& gpu_feature_info,
- GpuProcessHost::EstablishChannelStatus status);
+ viz::GpuHostImpl::EstablishChannelStatus status);
void FinishOnIO();
void FinishAndRunCallbacksOnMain();
void FinishOnMain();
@@ -134,13 +139,10 @@ void BrowserGpuChannelHostFactory::EstablishRequest::EstablishOnIO() {
return;
}
- bool preempts = true;
- bool allow_view_command_buffers = true;
- bool allow_real_time_streams = true;
- host->EstablishGpuChannel(
- gpu_client_id_, gpu_client_tracing_id_, preempts,
- allow_view_command_buffers, allow_real_time_streams,
- base::Bind(
+ bool is_gpu_host = true;
+ host->gpu_host()->EstablishGpuChannel(
+ gpu_client_id_, gpu_client_tracing_id_, is_gpu_host,
+ base::BindOnce(
&BrowserGpuChannelHostFactory::EstablishRequest::OnEstablishedOnIO,
this));
}
@@ -149,9 +151,9 @@ void BrowserGpuChannelHostFactory::EstablishRequest::OnEstablishedOnIO(
mojo::ScopedMessagePipeHandle channel_handle,
const gpu::GPUInfo& gpu_info,
const gpu::GpuFeatureInfo& gpu_feature_info,
- GpuProcessHost::EstablishChannelStatus status) {
+ viz::GpuHostImpl::EstablishChannelStatus status) {
if (!channel_handle.is_valid() &&
- status == GpuProcessHost::EstablishChannelStatus::GPU_HOST_INVALID &&
+ status == viz::GpuHostImpl::EstablishChannelStatus::kGpuHostInvalid &&
// Ask client every time instead of passing this down from UI thread to
// avoid having the value be stale.
GetContentClient()->browser()->AllowGpuLaunchRetryOnIOThread()) {
@@ -229,14 +231,6 @@ void BrowserGpuChannelHostFactory::EstablishRequest::Cancel() {
established_callbacks_.clear();
}
-void BrowserGpuChannelHostFactory::CloseChannel() {
- DCHECK(instance_);
- if (instance_->gpu_channel_) {
- instance_->gpu_channel_->DestroyChannel();
- instance_->gpu_channel_ = nullptr;
- }
-}
-
void BrowserGpuChannelHostFactory::Initialize(bool establish_gpu_channel) {
DCHECK(!instance_);
instance_ = new BrowserGpuChannelHostFactory();
@@ -251,13 +245,20 @@ void BrowserGpuChannelHostFactory::Terminate() {
instance_ = nullptr;
}
+void BrowserGpuChannelHostFactory::CloseChannel() {
+ if (gpu_channel_) {
+ gpu_channel_->DestroyChannel();
+ gpu_channel_ = nullptr;
+ }
+ gpu_memory_buffer_manager_ = nullptr;
+}
+
BrowserGpuChannelHostFactory::BrowserGpuChannelHostFactory()
: gpu_client_id_(ChildProcessHostImpl::GenerateChildProcessUniqueId()),
gpu_client_tracing_id_(
memory_instrumentation::mojom::kServiceTracingProcessId),
gpu_memory_buffer_manager_(
- new BrowserGpuMemoryBufferManager(gpu_client_id_,
- gpu_client_tracing_id_)) {
+ new GpuMemoryBufferManagerSingleton(gpu_client_id_)) {
if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableGpuShaderDiskCache)) {
DCHECK(GetContentClient());
@@ -270,6 +271,19 @@ BrowserGpuChannelHostFactory::BrowserGpuChannelHostFactory()
&BrowserGpuChannelHostFactory::InitializeShaderDiskCacheOnIO,
gpu_client_id_, cache_dir));
}
+
+ if (base::FeatureList::IsEnabled(
+ features::kDefaultEnableOopRasterization)) {
+ base::FilePath gr_cache_dir =
+ GetContentClient()->browser()->GetGrShaderDiskCacheDirectory();
+ if (!gr_cache_dir.empty()) {
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(
+ &BrowserGpuChannelHostFactory::InitializeGrShaderDiskCacheOnIO,
+ gr_cache_dir));
+ }
+ }
}
}
@@ -286,7 +300,7 @@ BrowserGpuChannelHostFactory::~BrowserGpuChannelHostFactory() {
void BrowserGpuChannelHostFactory::EstablishGpuChannel(
gpu::GpuChannelEstablishedCallback callback) {
#if defined(USE_AURA)
- DCHECK(features::IsAshInBrowserProcess());
+ DCHECK(!features::IsMultiProcessMash());
#endif
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (gpu_channel_.get() && gpu_channel_->IsLost()) {
@@ -386,8 +400,15 @@ void BrowserGpuChannelHostFactory::InitializeShaderDiskCacheOnIO(
GetShaderCacheFactorySingleton()->SetCacheInfo(gpu_client_id, cache_dir);
if (base::FeatureList::IsEnabled(features::kVizDisplayCompositor)) {
GetShaderCacheFactorySingleton()->SetCacheInfo(
- gpu::InProcessCommandBuffer::kGpuClientId, cache_dir);
+ gpu::kInProcessCommandBufferClientId, cache_dir);
}
}
+// static
+void BrowserGpuChannelHostFactory::InitializeGrShaderDiskCacheOnIO(
+ const base::FilePath& cache_dir) {
+ GetShaderCacheFactorySingleton()->SetCacheInfo(gpu::kGrShaderCacheClientId,
+ cache_dir);
+}
+
} // namespace content
diff --git a/chromium/content/browser/gpu/browser_gpu_channel_host_factory.h b/chromium/content/browser/gpu/browser_gpu_channel_host_factory.h
index 12aa00c7bb0..6386420710d 100644
--- a/chromium/content/browser/gpu/browser_gpu_channel_host_factory.h
+++ b/chromium/content/browser/gpu/browser_gpu_channel_host_factory.h
@@ -17,11 +17,15 @@
#include "base/single_thread_task_runner.h"
#include "build/build_config.h"
#include "content/common/content_export.h"
+#include "content/public/browser/browser_thread.h"
#include "gpu/ipc/client/gpu_channel_host.h"
#include "ipc/message_filter.h"
+namespace gpu {
+class GpuMemoryBufferManager;
+}
+
namespace content {
-class BrowserGpuMemoryBufferManager;
class CONTENT_EXPORT BrowserGpuChannelHostFactory
: public gpu::GpuChannelEstablishFactory {
@@ -57,11 +61,13 @@ class CONTENT_EXPORT BrowserGpuChannelHostFactory
static void InitializeShaderDiskCacheOnIO(int gpu_client_id,
const base::FilePath& cache_dir);
+ static void InitializeGrShaderDiskCacheOnIO(const base::FilePath& cache_dir);
const int gpu_client_id_;
const uint64_t gpu_client_tracing_id_;
scoped_refptr<gpu::GpuChannelHost> gpu_channel_;
- std::unique_ptr<BrowserGpuMemoryBufferManager> gpu_memory_buffer_manager_;
+ std::unique_ptr<gpu::GpuMemoryBufferManager, BrowserThread::DeleteOnIOThread>
+ gpu_memory_buffer_manager_;
scoped_refptr<EstablishRequest> pending_request_;
base::OneShotTimer timeout_;
diff --git a/chromium/content/browser/gpu/browser_gpu_client_delegate.cc b/chromium/content/browser/gpu/browser_gpu_client_delegate.cc
new file mode 100644
index 00000000000..20da7388187
--- /dev/null
+++ b/chromium/content/browser/gpu/browser_gpu_client_delegate.cc
@@ -0,0 +1,82 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/gpu/browser_gpu_client_delegate.h"
+
+#include <utility>
+
+#include "components/viz/host/gpu_host_impl.h"
+#include "content/browser/gpu/gpu_memory_buffer_manager_singleton.h"
+#include "content/browser/gpu/gpu_process_host.h"
+#include "gpu/config/gpu_feature_info.h"
+#include "gpu/config/gpu_info.h"
+#include "mojo/public/cpp/system/message_pipe.h"
+
+namespace content {
+namespace {
+
+void OnEstablishGpuChannel(
+ viz::GpuClientDelegate::EstablishGpuChannelCallback callback,
+ mojo::ScopedMessagePipeHandle channel_handle,
+ const gpu::GPUInfo& gpu_info,
+ const gpu::GpuFeatureInfo& gpu_feature_info,
+ viz::GpuHostImpl::EstablishChannelStatus status) {
+ if (!callback)
+ return;
+
+ viz::GpuClientDelegate::EstablishGpuChannelStatus delegate_status;
+ switch (status) {
+ case viz::GpuHostImpl::EstablishChannelStatus::kGpuAccessDenied:
+ delegate_status =
+ viz::GpuClientDelegate::EstablishGpuChannelStatus::kGpuAccessDenied;
+ break;
+ case viz::GpuHostImpl::EstablishChannelStatus::kGpuHostInvalid:
+ delegate_status =
+ viz::GpuClientDelegate::EstablishGpuChannelStatus::kGpuHostInvalid;
+ break;
+ case viz::GpuHostImpl::EstablishChannelStatus::kSuccess:
+ delegate_status =
+ viz::GpuClientDelegate::EstablishGpuChannelStatus::kSuccess;
+ break;
+ }
+ std::move(callback).Run(std::move(channel_handle), gpu_info, gpu_feature_info,
+ delegate_status);
+}
+
+} // namespace
+
+BrowserGpuClientDelegate::BrowserGpuClientDelegate() = default;
+
+BrowserGpuClientDelegate::~BrowserGpuClientDelegate() = default;
+
+viz::mojom::GpuService* BrowserGpuClientDelegate::EnsureGpuService() {
+ if (auto* host = GpuProcessHost::Get())
+ return host->gpu_service();
+ return nullptr;
+}
+
+void BrowserGpuClientDelegate::EstablishGpuChannel(
+ int client_id,
+ uint64_t client_tracing_id,
+ EstablishGpuChannelCallback callback) {
+ auto* host = GpuProcessHost::Get();
+ if (!host) {
+ std::move(callback).Run(mojo::ScopedMessagePipeHandle(), gpu::GPUInfo(),
+ gpu::GpuFeatureInfo(),
+ EstablishGpuChannelStatus::kGpuAccessDenied);
+ return;
+ }
+
+ const bool is_gpu_host = false;
+ host->gpu_host()->EstablishGpuChannel(
+ client_id, client_tracing_id, is_gpu_host,
+ base::BindOnce(&OnEstablishGpuChannel, std::move(callback)));
+}
+
+viz::HostGpuMemoryBufferManager*
+BrowserGpuClientDelegate::GetGpuMemoryBufferManager() {
+ return GpuMemoryBufferManagerSingleton::GetInstance();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/gpu/browser_gpu_client_delegate.h b/chromium/content/browser/gpu/browser_gpu_client_delegate.h
new file mode 100644
index 00000000000..18150dc6e19
--- /dev/null
+++ b/chromium/content/browser/gpu/browser_gpu_client_delegate.h
@@ -0,0 +1,30 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_GPU_BROWSER_GPU_CLIENT_DELEGATE_H_
+#define CONTENT_BROWSER_GPU_BROWSER_GPU_CLIENT_DELEGATE_H_
+
+#include "components/viz/host/gpu_client_delegate.h"
+
+namespace content {
+
+class BrowserGpuClientDelegate : public viz::GpuClientDelegate {
+ public:
+ BrowserGpuClientDelegate();
+ ~BrowserGpuClientDelegate() override;
+
+ // GpuClientDelegate:
+ viz::mojom::GpuService* EnsureGpuService() override;
+ void EstablishGpuChannel(int client_id,
+ uint64_t client_tracing_id,
+ EstablishGpuChannelCallback callback) override;
+ viz::HostGpuMemoryBufferManager* GetGpuMemoryBufferManager() override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BrowserGpuClientDelegate);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_GPU_BROWSER_GPU_CLIENT_DELEGATE_H_
diff --git a/chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.cc b/chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.cc
deleted file mode 100644
index 8568d3f5885..00000000000
--- a/chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.cc
+++ /dev/null
@@ -1,498 +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/gpu/browser_gpu_memory_buffer_manager.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/single_thread_task_runner.h"
-#include "base/strings/stringprintf.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/threading/thread_restrictions.h"
-#include "base/trace_event/memory_dump_manager.h"
-#include "base/trace_event/process_memory_dump.h"
-#include "base/trace_event/trace_event.h"
-#include "build/build_config.h"
-#include "content/browser/gpu/gpu_process_host.h"
-#include "content/common/child_process_host_impl.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/common/content_switches.h"
-#include "gpu/ipc/common/gpu_memory_buffer_impl.h"
-#include "gpu/ipc/common/gpu_memory_buffer_impl_shared_memory.h"
-#include "gpu/ipc/common/gpu_memory_buffer_support.h"
-#include "ui/gfx/buffer_format_util.h"
-#include "ui/gl/gl_switches.h"
-
-namespace content {
-namespace {
-
-void GpuMemoryBufferDeleted(
- scoped_refptr<base::SingleThreadTaskRunner> destruction_task_runner,
- const gpu::GpuMemoryBufferImpl::DestructionCallback& destruction_callback,
- const gpu::SyncToken& sync_token) {
- destruction_task_runner->PostTask(
- FROM_HERE, base::BindOnce(destruction_callback, sync_token));
-}
-
-BrowserGpuMemoryBufferManager* g_gpu_memory_buffer_manager = nullptr;
-
-} // namespace
-
-struct BrowserGpuMemoryBufferManager::CreateGpuMemoryBufferRequest {
- CreateGpuMemoryBufferRequest(const gfx::Size& size,
- gfx::BufferFormat format,
- gfx::BufferUsage usage,
- int client_id,
- gpu::SurfaceHandle surface_handle)
- : event(base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED),
- size(size),
- format(format),
- usage(usage),
- client_id(client_id),
- surface_handle(surface_handle) {}
- ~CreateGpuMemoryBufferRequest() {}
- base::WaitableEvent event;
- gfx::Size size;
- gfx::BufferFormat format;
- gfx::BufferUsage usage;
- int client_id;
- gpu::SurfaceHandle surface_handle;
- std::unique_ptr<gfx::GpuMemoryBuffer> result;
-};
-
-BrowserGpuMemoryBufferManager::BrowserGpuMemoryBufferManager(
- int gpu_client_id,
- uint64_t gpu_client_tracing_id)
- : gpu_memory_buffer_support_(new gpu::GpuMemoryBufferSupport()),
- native_configurations_(gpu::GetNativeGpuMemoryBufferConfigurations(
- gpu_memory_buffer_support_.get())),
- gpu_client_id_(gpu_client_id),
- gpu_client_tracing_id_(gpu_client_tracing_id) {
- DCHECK(!g_gpu_memory_buffer_manager);
- g_gpu_memory_buffer_manager = this;
-
- // Enable the dump provider with IO thread affinity. Note that
- // unregistration happens on the IO thread (See
- // BrowserProcessSubThread::IOThreadPreCleanUp).
- DCHECK(BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
- base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
- this, "BrowserGpuMemoryBufferManager",
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
-}
-
-BrowserGpuMemoryBufferManager::~BrowserGpuMemoryBufferManager() {
- g_gpu_memory_buffer_manager = nullptr;
-}
-
-// static
-BrowserGpuMemoryBufferManager* BrowserGpuMemoryBufferManager::current() {
- return g_gpu_memory_buffer_manager;
-}
-
-std::unique_ptr<gfx::GpuMemoryBuffer>
-BrowserGpuMemoryBufferManager::CreateGpuMemoryBuffer(
- const gfx::Size& size,
- gfx::BufferFormat format,
- gfx::BufferUsage usage,
- gpu::SurfaceHandle surface_handle) {
- return AllocateGpuMemoryBufferForSurface(size, format, usage, surface_handle);
-}
-
-void BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferForChildProcess(
- gfx::GpuMemoryBufferId id,
- const gfx::Size& size,
- gfx::BufferFormat format,
- gfx::BufferUsage usage,
- int child_client_id,
- AllocationCallback callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- // Use service side allocation for native configurations.
- if (IsNativeGpuMemoryBufferConfiguration(format, usage)) {
- CreateGpuMemoryBufferOnIO(id, size, format, usage, gpu::kNullSurfaceHandle,
- child_client_id, std::move(callback));
- return;
- }
-
- // Early out if we cannot fallback to shared memory buffer.
- if (!gpu::GpuMemoryBufferImplSharedMemory::IsUsageSupported(usage) ||
- !gpu::GpuMemoryBufferImplSharedMemory::IsSizeValidForFormat(size,
- format)) {
- std::move(callback).Run(gfx::GpuMemoryBufferHandle());
- return;
- }
-
- BufferMap& buffers = clients_[child_client_id];
-
- // Allocate shared memory buffer as fallback.
- auto insert_result = buffers.insert(std::make_pair(
- id, BufferInfo(size, gfx::SHARED_MEMORY_BUFFER, format, usage, 0)));
- if (!insert_result.second) {
- DLOG(ERROR) << "Child process attempted to allocate a GpuMemoryBuffer with "
- "an existing ID.";
- std::move(callback).Run(gfx::GpuMemoryBufferHandle());
- return;
- }
-
- auto handle = gpu::GpuMemoryBufferImplSharedMemory::CreateGpuMemoryBuffer(
- id, size, format, usage);
- buffers.find(id)->second.shared_memory_guid = handle.handle.GetGUID();
- std::move(callback).Run(std::move(handle));
-}
-
-void BrowserGpuMemoryBufferManager::SetDestructionSyncToken(
- gfx::GpuMemoryBuffer* buffer,
- const gpu::SyncToken& sync_token) {
- static_cast<gpu::GpuMemoryBufferImpl*>(buffer)->set_destruction_sync_token(
- sync_token);
-}
-
-bool BrowserGpuMemoryBufferManager::OnMemoryDump(
- const base::trace_event::MemoryDumpArgs& args,
- base::trace_event::ProcessMemoryDump* pmd) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- for (const auto& client : clients_) {
- int client_id = client.first;
-
- for (const auto& buffer : client.second) {
- if (buffer.second.type == gfx::EMPTY_BUFFER)
- continue;
-
- gfx::GpuMemoryBufferId buffer_id = buffer.first;
- base::trace_event::MemoryAllocatorDump* dump =
- pmd->CreateAllocatorDump(base::StringPrintf(
- "gpumemorybuffer/client_%d/buffer_%d", client_id, buffer_id.id));
- if (!dump)
- return false;
-
- size_t buffer_size_in_bytes = gfx::BufferSizeForBufferFormat(
- buffer.second.size, buffer.second.format);
- dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
- base::trace_event::MemoryAllocatorDump::kUnitsBytes,
- buffer_size_in_bytes);
-
- // Create the cross-process ownership edge. If the client creates a
- // corresponding dump for the same buffer, this will avoid to
- // double-count them in tracing. If, instead, no other process will emit a
- // dump with the same guid, the segment will be accounted to the browser.
- uint64_t client_tracing_process_id =
- ClientIdToTracingProcessId(client_id);
-
- if (buffer.second.type == gfx::SHARED_MEMORY_BUFFER) {
- pmd->CreateSharedMemoryOwnershipEdge(
- dump->guid(), buffer.second.shared_memory_guid, 0 /* importance */);
- } else {
- auto shared_buffer_guid = gfx::GetGenericSharedGpuMemoryGUIDForTracing(
- client_tracing_process_id, buffer_id);
- pmd->CreateSharedGlobalAllocatorDump(shared_buffer_guid);
- pmd->AddOwnershipEdge(dump->guid(), shared_buffer_guid);
- }
- }
- }
-
- return true;
-}
-
-void BrowserGpuMemoryBufferManager::ChildProcessDeletedGpuMemoryBuffer(
- gfx::GpuMemoryBufferId id,
- int child_client_id,
- const gpu::SyncToken& sync_token) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- DestroyGpuMemoryBufferOnIO(id, child_client_id, sync_token);
-}
-
-void BrowserGpuMemoryBufferManager::ProcessRemoved(
- int client_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- ClientMap::iterator client_it = clients_.find(client_id);
- if (client_it == clients_.end())
- return;
-
- for (const auto& buffer : client_it->second) {
- // This might happen if buffer is currenlty in the process of being
- // allocated. The buffer will in that case be cleaned up when allocation
- // completes.
- if (buffer.second.type == gfx::EMPTY_BUFFER)
- continue;
-
- GpuProcessHost* host = GpuProcessHost::FromID(buffer.second.gpu_host_id);
- if (host)
- host->DestroyGpuMemoryBuffer(buffer.first, client_id, gpu::SyncToken());
- }
-
- clients_.erase(client_it);
-}
-
-bool BrowserGpuMemoryBufferManager::IsNativeGpuMemoryBufferConfiguration(
- gfx::BufferFormat format,
- gfx::BufferUsage usage) const {
- return native_configurations_.find(std::make_pair(format, usage)) !=
- native_configurations_.end();
-}
-
-std::unique_ptr<gfx::GpuMemoryBuffer>
-BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferForSurface(
- const gfx::Size& size,
- gfx::BufferFormat format,
- gfx::BufferUsage usage,
- gpu::SurfaceHandle surface_handle) {
- DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
-
- CreateGpuMemoryBufferRequest request(size, format, usage, gpu_client_id_,
- surface_handle);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(
- &BrowserGpuMemoryBufferManager::HandleCreateGpuMemoryBufferOnIO,
- base::Unretained(this), // Safe as we wait for result below.
- base::Unretained(&request)));
-
- // We're blocking the UI thread, which is generally undesirable.
- TRACE_EVENT0(
- "browser",
- "BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferForSurface");
- base::ThreadRestrictions::ScopedAllowWait allow_wait;
- request.event.Wait();
- return std::move(request.result);
-}
-
-void BrowserGpuMemoryBufferManager::HandleCreateGpuMemoryBufferOnIO(
- CreateGpuMemoryBufferRequest* request) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- gfx::GpuMemoryBufferId new_id(next_gpu_memory_id_++);
- // Use service side allocation for native configurations.
- if (IsNativeGpuMemoryBufferConfiguration(request->format, request->usage)) {
- // Note: Unretained is safe as this is only used for synchronous allocation
- // from a non-IO thread.
- CreateGpuMemoryBufferOnIO(
- new_id, request->size, request->format, request->usage,
- request->surface_handle, request->client_id,
- base::BindOnce(
- &BrowserGpuMemoryBufferManager::HandleGpuMemoryBufferCreatedOnIO,
- base::Unretained(this), base::Unretained(request)));
- return;
- }
-
- DCHECK(gpu::GpuMemoryBufferImplSharedMemory::IsUsageSupported(request->usage))
- << static_cast<int>(request->usage);
-
- BufferMap& buffers = clients_[request->client_id];
-
- // Allocate shared memory buffer as fallback.
- auto insert_result = buffers.insert(std::make_pair(
- new_id, BufferInfo(request->size, gfx::SHARED_MEMORY_BUFFER,
- request->format, request->usage, 0)));
- DCHECK(insert_result.second);
-
- // Note: Unretained is safe as IO thread is stopped before manager is
- // destroyed.
- request->result = gpu::GpuMemoryBufferImplSharedMemory::Create(
- new_id, request->size, request->format, request->usage,
- base::Bind(
- &GpuMemoryBufferDeleted,
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO),
- base::Bind(&BrowserGpuMemoryBufferManager::DestroyGpuMemoryBufferOnIO,
- base::Unretained(this), new_id, request->client_id)));
- if (request->result) {
- buffers.find(new_id)->second.shared_memory_guid =
- request->result->GetHandle().handle.GetGUID();
- }
- request->event.Signal();
-}
-
-void BrowserGpuMemoryBufferManager::HandleGpuMemoryBufferCreatedOnIO(
- CreateGpuMemoryBufferRequest* request,
- gfx::GpuMemoryBufferHandle handle) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- // Early out if factory failed to create the buffer.
- if (handle.is_null()) {
- request->event.Signal();
- return;
- }
-
- // Note: Unretained is safe as IO thread is stopped before manager is
- // destroyed.
- auto handle_id = handle.id;
- request->result =
- gpu_memory_buffer_support_->CreateGpuMemoryBufferImplFromHandle(
- std::move(handle), request->size, request->format, request->usage,
- base::Bind(
- &GpuMemoryBufferDeleted,
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO),
- base::Bind(
- &BrowserGpuMemoryBufferManager::DestroyGpuMemoryBufferOnIO,
- base::Unretained(this), handle_id, request->client_id)));
- request->event.Signal();
-}
-
-void BrowserGpuMemoryBufferManager::CreateGpuMemoryBufferOnIO(
- gfx::GpuMemoryBufferId id,
- const gfx::Size& size,
- gfx::BufferFormat format,
- gfx::BufferUsage usage,
- gpu::SurfaceHandle surface_handle,
- int client_id,
- CreateCallback callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- BufferMap& buffers = clients_[client_id];
-
- // Note: Handling of cases where the client is removed before the allocation
- // completes is less subtle if we set the buffer type to EMPTY_BUFFER here
- // and verify that this has not changed when creation completes.
- auto insert_result = buffers.insert(std::make_pair(
- id, BufferInfo(size, gfx::EMPTY_BUFFER, format, usage, 0)));
- if (!insert_result.second) {
- DLOG(ERROR) << "Child process attempted to create a GpuMemoryBuffer with "
- "an existing ID.";
- std::move(callback).Run(gfx::GpuMemoryBufferHandle());
- return;
- }
-
- GpuProcessHost* host = GpuProcessHost::Get();
- if (!host) {
- DLOG(ERROR) << "Cannot allocate GpuMemoryBuffer with no GpuProcessHost.";
- std::move(callback).Run(gfx::GpuMemoryBufferHandle());
- return;
- }
- // Note: Unretained is safe as IO thread is stopped before manager is
- // destroyed.
- host->CreateGpuMemoryBuffer(
- id, size, format, usage, client_id, surface_handle,
- base::BindOnce(&BrowserGpuMemoryBufferManager::GpuMemoryBufferCreatedOnIO,
- base::Unretained(this), id, surface_handle, client_id,
- host->host_id(), std::move(callback)));
-}
-
-void BrowserGpuMemoryBufferManager::GpuMemoryBufferCreatedOnIO(
- gfx::GpuMemoryBufferId id,
- gpu::SurfaceHandle surface_handle,
- int client_id,
- int gpu_host_id,
- CreateCallback callback,
- gfx::GpuMemoryBufferHandle handle,
- GpuProcessHost::BufferCreationStatus status) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- ClientMap::iterator client_it = clients_.find(client_id);
-
- // This can happen if client is removed while the buffer is being allocated.
- if (client_it == clients_.end()) {
- if (!handle.is_null()) {
- GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id);
- if (host)
- host->DestroyGpuMemoryBuffer(handle.id, client_id, gpu::SyncToken());
- }
- std::move(callback).Run(gfx::GpuMemoryBufferHandle());
- return;
- }
-
- BufferMap& buffers = client_it->second;
-
- BufferMap::iterator buffer_it = buffers.find(id);
- DCHECK(buffer_it != buffers.end());
- DCHECK_EQ(buffer_it->second.type, gfx::EMPTY_BUFFER);
-
- // If the handle isn't valid, that means that the GPU process crashed or is
- // misbehaving.
- bool valid_handle = !handle.is_null() && handle.id == id;
- if (!valid_handle) {
- // If we failed after re-using the GPU process, it may have died in the
- // mean time. Retry to have a chance to create a fresh GPU process.
- if (handle.is_null() &&
- status == GpuProcessHost::BufferCreationStatus::GPU_HOST_INVALID) {
- DVLOG(1) << "Failed to create buffer through existing GPU process. "
- "Trying to restart GPU process.";
- gfx::Size size = buffer_it->second.size;
- gfx::BufferFormat format = buffer_it->second.format;
- gfx::BufferUsage usage = buffer_it->second.usage;
- // Remove the buffer entry and call CreateGpuMemoryBufferOnIO again.
- buffers.erase(buffer_it);
- CreateGpuMemoryBufferOnIO(id, size, format, usage, surface_handle,
- client_id, std::move(callback));
- } else {
- // Remove the buffer entry and run the allocation callback with an empty
- // handle to indicate failure.
- buffers.erase(buffer_it);
- std::move(callback).Run(gfx::GpuMemoryBufferHandle());
- }
- return;
- }
-
- // Store the type and host id of this buffer so it can be cleaned up if the
- // client is removed.
- buffer_it->second.type = handle.type;
- buffer_it->second.gpu_host_id = gpu_host_id;
- buffer_it->second.shared_memory_guid = handle.handle.GetGUID();
-
- std::move(callback).Run(std::move(handle));
-}
-
-void BrowserGpuMemoryBufferManager::DestroyGpuMemoryBufferOnIO(
- gfx::GpuMemoryBufferId id,
- int client_id,
- const gpu::SyncToken& sync_token) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(clients_.find(client_id) != clients_.end());
-
- BufferMap& buffers = clients_[client_id];
-
- BufferMap::iterator buffer_it = buffers.find(id);
- if (buffer_it == buffers.end()) {
- LOG(ERROR) << "Invalid GpuMemoryBuffer ID for client.";
- return;
- }
-
- // This can happen if a client managed to call this while a buffer is in the
- // process of being allocated.
- if (buffer_it->second.type == gfx::EMPTY_BUFFER) {
- LOG(ERROR) << "Invalid GpuMemoryBuffer type.";
- return;
- }
-
- GpuProcessHost* host = GpuProcessHost::FromID(buffer_it->second.gpu_host_id);
- if (host)
- host->DestroyGpuMemoryBuffer(id, client_id, sync_token);
-
- buffers.erase(buffer_it);
-}
-
-uint64_t BrowserGpuMemoryBufferManager::ClientIdToTracingProcessId(
- int client_id) const {
- if (client_id == gpu_client_id_) {
- // The gpu_client uses a fixed tracing ID.
- return gpu_client_tracing_id_;
- }
-
- // In normal cases, |client_id| is a child process id, so we can perform
- // the standard conversion.
- return ChildProcessHostImpl::ChildProcessUniqueIdToTracingProcessId(
- client_id);
-}
-
-BrowserGpuMemoryBufferManager::BufferInfo::BufferInfo(
- const gfx::Size& size,
- gfx::GpuMemoryBufferType type,
- gfx::BufferFormat format,
- gfx::BufferUsage usage,
- int gpu_host_id)
- : size(size),
- type(type),
- format(format),
- usage(usage),
- gpu_host_id(gpu_host_id) {}
-
-BrowserGpuMemoryBufferManager::BufferInfo::BufferInfo(const BufferInfo& other) =
- default;
-
-BrowserGpuMemoryBufferManager::BufferInfo::~BufferInfo() {}
-
-} // namespace content
diff --git a/chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.h b/chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.h
deleted file mode 100644
index 4cf2b632fb0..00000000000
--- a/chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.h
+++ /dev/null
@@ -1,143 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_GPU_BROWSER_GPU_MEMORY_BUFFER_MANAGER_H_
-#define CONTENT_BROWSER_GPU_BROWSER_GPU_MEMORY_BUFFER_MANAGER_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <memory>
-#include <utility>
-
-#include "base/callback.h"
-#include "base/containers/hash_tables.h"
-#include "base/hash.h"
-#include "base/macros.h"
-#include "base/trace_event/memory_dump_provider.h"
-#include "content/browser/gpu/gpu_process_host.h"
-#include "content/common/content_export.h"
-#include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
-#include "gpu/ipc/common/surface_handle.h"
-#include "gpu/ipc/host/gpu_memory_buffer_support.h"
-
-namespace gpu {
-class GpuMemoryBufferSupport;
-}
-
-namespace content {
-
-class CONTENT_EXPORT BrowserGpuMemoryBufferManager
- : public gpu::GpuMemoryBufferManager,
- public base::trace_event::MemoryDumpProvider {
- public:
- using CreateCallback =
- base::OnceCallback<void(gfx::GpuMemoryBufferHandle handle)>;
- using AllocationCallback = CreateCallback;
-
- BrowserGpuMemoryBufferManager(int gpu_client_id,
- uint64_t gpu_client_tracing_id);
- ~BrowserGpuMemoryBufferManager() override;
-
- static BrowserGpuMemoryBufferManager* current();
-
- // Overridden from gpu::GpuMemoryBufferManager:
- std::unique_ptr<gfx::GpuMemoryBuffer> CreateGpuMemoryBuffer(
- const gfx::Size& size,
- gfx::BufferFormat format,
- gfx::BufferUsage usage,
- gpu::SurfaceHandle surface_handle) override;
- void SetDestructionSyncToken(gfx::GpuMemoryBuffer* buffer,
- const gpu::SyncToken& sync_token) override;
-
- // Overridden from base::trace_event::MemoryDumpProvider:
- bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
- base::trace_event::ProcessMemoryDump* pmd) override;
-
- void AllocateGpuMemoryBufferForChildProcess(gfx::GpuMemoryBufferId id,
- const gfx::Size& size,
- gfx::BufferFormat format,
- gfx::BufferUsage usage,
- int child_client_id,
- AllocationCallback callback);
- void ChildProcessDeletedGpuMemoryBuffer(
- gfx::GpuMemoryBufferId id,
- int child_client_id,
- const gpu::SyncToken& sync_token);
- void ProcessRemoved(int client_id);
-
- bool IsNativeGpuMemoryBufferConfiguration(gfx::BufferFormat format,
- gfx::BufferUsage usage) const;
-
- private:
- struct BufferInfo {
- BufferInfo(const gfx::Size& size,
- gfx::GpuMemoryBufferType type,
- gfx::BufferFormat format,
- gfx::BufferUsage usage,
- int gpu_host_id);
- BufferInfo(const BufferInfo& other);
- ~BufferInfo();
-
- gfx::Size size;
- gfx::GpuMemoryBufferType type = gfx::EMPTY_BUFFER;
- gfx::BufferFormat format = gfx::BufferFormat::RGBA_8888;
- gfx::BufferUsage usage = gfx::BufferUsage::GPU_READ;
- int gpu_host_id = 0;
- base::UnguessableToken shared_memory_guid;
- };
-
- struct CreateGpuMemoryBufferRequest;
-
- std::unique_ptr<gfx::GpuMemoryBuffer> AllocateGpuMemoryBufferForSurface(
- const gfx::Size& size,
- gfx::BufferFormat format,
- gfx::BufferUsage usage,
- gpu::SurfaceHandle surface_handle);
-
- // Functions that handle synchronous buffer creation requests.
- void HandleCreateGpuMemoryBufferOnIO(CreateGpuMemoryBufferRequest* request);
- void HandleGpuMemoryBufferCreatedOnIO(CreateGpuMemoryBufferRequest* request,
- gfx::GpuMemoryBufferHandle handle);
-
- // Functions that implement asynchronous buffer creation.
- void CreateGpuMemoryBufferOnIO(gfx::GpuMemoryBufferId id,
- const gfx::Size& size,
- gfx::BufferFormat format,
- gfx::BufferUsage usage,
- gpu::SurfaceHandle surface_handle,
- int client_id,
- CreateCallback callback);
- void GpuMemoryBufferCreatedOnIO(gfx::GpuMemoryBufferId id,
- gpu::SurfaceHandle surface_handle,
- int client_id,
- int gpu_host_id,
- CreateCallback callback,
- gfx::GpuMemoryBufferHandle handle,
- GpuProcessHost::BufferCreationStatus status);
- void DestroyGpuMemoryBufferOnIO(gfx::GpuMemoryBufferId id,
- int client_id,
- const gpu::SyncToken& sync_token);
-
- uint64_t ClientIdToTracingProcessId(int client_id) const;
-
- std::unique_ptr<gpu::GpuMemoryBufferSupport> gpu_memory_buffer_support_;
-
- const gpu::GpuMemoryBufferConfigurationSet native_configurations_;
- const int gpu_client_id_;
- const uint64_t gpu_client_tracing_id_;
- int next_gpu_memory_id_ = 1;
-
- // Stores info about buffers for all clients. This should only be accessed
- // on the IO thread.
- using BufferMap = base::hash_map<gfx::GpuMemoryBufferId, BufferInfo>;
- using ClientMap = base::hash_map<int, BufferMap>;
- ClientMap clients_;
-
- DISALLOW_COPY_AND_ASSIGN(BrowserGpuMemoryBufferManager);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_GPU_BROWSER_GPU_MEMORY_BUFFER_MANAGER_H_
diff --git a/chromium/content/browser/gpu/compositor_util.cc b/chromium/content/browser/gpu/compositor_util.cc
index 9773ec885ea..9bcf1916304 100644
--- a/chromium/content/browser/gpu/compositor_util.cc
+++ b/chromium/content/browser/gpu/compositor_util.cc
@@ -17,6 +17,7 @@
#include "base/metrics/field_trial.h"
#include "base/numerics/ranges.h"
#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_split.h"
#include "base/sys_info.h"
#include "build/build_config.h"
#include "cc/base/switches.h"
@@ -334,6 +335,25 @@ std::vector<std::string> GetDriverBugWorkaroundsImpl(GpuFeatureInfoType type) {
workarounds.push_back(gpu::GpuDriverBugWorkaroundTypeToString(
static_cast<gpu::GpuDriverBugWorkaroundType>(workaround)));
}
+ // Tell clients about the disabled extensions and disabled WebGL
+ // extensions as well, to avoid confusion. Do this in a way that's
+ // compatible with the current reporting of driver bug workarounds
+ // to DevTools and Telemetry, and from there to the GPU tests.
+ //
+ // This code must be kept in sync with
+ // GpuBenchmarking::GetGpuDriverBugWorkarounds.
+ for (auto ext : base::SplitString(gpu_feature_info.disabled_extensions,
+ " ",
+ base::TRIM_WHITESPACE,
+ base::SPLIT_WANT_NONEMPTY)) {
+ workarounds.push_back("disabled_extension_" + ext);
+ }
+ for (auto ext : base::SplitString(gpu_feature_info.disabled_webgl_extensions,
+ " ",
+ base::TRIM_WHITESPACE,
+ base::SPLIT_WANT_NONEMPTY)) {
+ workarounds.push_back("disabled_webgl_extension_" + ext);
+ }
return workarounds;
}
diff --git a/chromium/content/browser/gpu/gpu_client.cc b/chromium/content/browser/gpu/gpu_client.cc
new file mode 100644
index 00000000000..abd24754947
--- /dev/null
+++ b/chromium/content/browser/gpu/gpu_client.cc
@@ -0,0 +1,28 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/public/browser/gpu_client.h"
+
+#include "content/browser/gpu/browser_gpu_client_delegate.h"
+#include "content/common/child_process_host_impl.h"
+
+namespace content {
+
+std::unique_ptr<viz::GpuClient, base::OnTaskRunnerDeleter> CreateGpuClient(
+ ws::mojom::GpuRequest request,
+ viz::GpuClient::ConnectionErrorHandlerClosure connection_error_handler,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
+ const int client_id = ChildProcessHostImpl::GenerateChildProcessUniqueId();
+ const uint64_t client_tracing_id =
+ ChildProcessHostImpl::ChildProcessUniqueIdToTracingProcessId(client_id);
+ std::unique_ptr<viz::GpuClient, base::OnTaskRunnerDeleter> gpu_client(
+ new viz::GpuClient(std::make_unique<BrowserGpuClientDelegate>(),
+ client_id, client_tracing_id, task_runner),
+ base::OnTaskRunnerDeleter(task_runner));
+ gpu_client->SetConnectionErrorHandler(std::move(connection_error_handler));
+ gpu_client->Add(std::move(request));
+ return gpu_client;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/gpu/gpu_client_impl.cc b/chromium/content/browser/gpu/gpu_client_impl.cc
deleted file mode 100644
index c2ef9591cd3..00000000000
--- a/chromium/content/browser/gpu/gpu_client_impl.cc
+++ /dev/null
@@ -1,220 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/gpu/gpu_client_impl.h"
-
-#include "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
-#include "content/browser/gpu/gpu_process_host.h"
-#include "content/common/child_process_host_impl.h"
-#include "gpu/ipc/client/gpu_channel_host.h"
-#include "gpu/ipc/common/gpu_memory_buffer_impl.h"
-#include "gpu/ipc/common/gpu_memory_buffer_impl_shared_memory.h"
-
-namespace content {
-
-// static
-std::unique_ptr<GpuClient, base::OnTaskRunnerDeleter> GpuClient::Create(
- ui::mojom::GpuRequest request,
- ConnectionErrorHandlerClosure connection_error_handler,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
- const int client_id = ChildProcessHostImpl::GenerateChildProcessUniqueId();
- const uint64_t client_tracing_id =
- ChildProcessHostImpl::ChildProcessUniqueIdToTracingProcessId(client_id);
- std::unique_ptr<GpuClientImpl, base::OnTaskRunnerDeleter> gpu_client(
- new GpuClientImpl(client_id, client_tracing_id, task_runner),
- base::OnTaskRunnerDeleter(task_runner));
- gpu_client->SetConnectionErrorHandler(std::move(connection_error_handler));
- gpu_client->Add(std::move(request));
- return gpu_client;
-}
-
-GpuClientImpl::GpuClientImpl(
- int client_id,
- uint64_t client_tracing_id,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner)
- : client_id_(client_id),
- client_tracing_id_(client_tracing_id),
- task_runner_(std::move(task_runner)),
- weak_factory_(this) {
- gpu_bindings_.set_connection_error_handler(
- base::BindRepeating(&GpuClientImpl::OnError, base::Unretained(this),
- ErrorReason::kConnectionLost));
-}
-
-GpuClientImpl::~GpuClientImpl() {
- DCHECK(task_runner_->RunsTasksInCurrentSequence());
- gpu_bindings_.CloseAllBindings();
- OnError(ErrorReason::kInDestructor);
-}
-
-void GpuClientImpl::Add(ui::mojom::GpuRequest request) {
- DCHECK(task_runner_->RunsTasksInCurrentSequence());
- gpu_bindings_.AddBinding(this, std::move(request));
-}
-
-void GpuClientImpl::OnError(ErrorReason reason) {
- DCHECK(task_runner_->RunsTasksInCurrentSequence());
- ClearCallback();
- if (gpu_bindings_.empty()) {
- BrowserGpuMemoryBufferManager* gpu_memory_buffer_manager =
- BrowserGpuMemoryBufferManager::current();
- if (gpu_memory_buffer_manager)
- gpu_memory_buffer_manager->ProcessRemoved(client_id_);
- }
- if (reason == ErrorReason::kConnectionLost && connection_error_handler_)
- std::move(connection_error_handler_).Run(this);
-}
-
-void GpuClientImpl::PreEstablishGpuChannel() {
- if (task_runner_->RunsTasksInCurrentSequence()) {
- EstablishGpuChannel(EstablishGpuChannelCallback());
- } else {
- task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&GpuClientImpl::EstablishGpuChannel,
- base::Unretained(this), EstablishGpuChannelCallback()));
- }
-}
-
-void GpuClientImpl::SetConnectionErrorHandler(
- ConnectionErrorHandlerClosure connection_error_handler) {
- connection_error_handler_ = std::move(connection_error_handler);
-}
-
-void GpuClientImpl::OnEstablishGpuChannel(
- mojo::ScopedMessagePipeHandle channel_handle,
- const gpu::GPUInfo& gpu_info,
- const gpu::GpuFeatureInfo& gpu_feature_info,
- GpuProcessHost::EstablishChannelStatus status) {
- DCHECK_EQ(channel_handle.is_valid(),
- status == GpuProcessHost::EstablishChannelStatus::SUCCESS);
- gpu_channel_requested_ = false;
- EstablishGpuChannelCallback callback = std::move(callback_);
- DCHECK(!callback_);
-
- if (status == GpuProcessHost::EstablishChannelStatus::GPU_HOST_INVALID) {
- // GPU process may have crashed or been killed. Try again.
- EstablishGpuChannel(std::move(callback));
- return;
- }
- if (callback) {
- // A request is waiting.
- std::move(callback).Run(client_id_, std::move(channel_handle), gpu_info,
- gpu_feature_info);
- return;
- }
- if (status == GpuProcessHost::EstablishChannelStatus::SUCCESS) {
- // This is the case we pre-establish a channel before a request arrives.
- // Cache the channel for a future request.
- channel_handle_ = std::move(channel_handle);
- gpu_info_ = gpu_info;
- gpu_feature_info_ = gpu_feature_info;
- }
-}
-
-void GpuClientImpl::OnCreateGpuMemoryBuffer(
- CreateGpuMemoryBufferCallback callback,
- gfx::GpuMemoryBufferHandle handle) {
- std::move(callback).Run(std::move(handle));
-}
-
-void GpuClientImpl::ClearCallback() {
- if (!callback_)
- return;
- EstablishGpuChannelCallback callback = std::move(callback_);
- std::move(callback).Run(client_id_, mojo::ScopedMessagePipeHandle(),
- gpu::GPUInfo(), gpu::GpuFeatureInfo());
- DCHECK(!callback_);
-}
-
-void GpuClientImpl::EstablishGpuChannel(EstablishGpuChannelCallback callback) {
- DCHECK(task_runner_->RunsTasksInCurrentSequence());
- // At most one channel should be requested. So clear previous request first.
- ClearCallback();
- if (channel_handle_.is_valid()) {
- // If a channel has been pre-established and cached,
- // 1) if callback is valid, return it right away.
- // 2) if callback is empty, it's PreEstablishGpyChannel() being called
- // more than once, no need to do anything.
- if (callback) {
- std::move(callback).Run(client_id_, std::move(channel_handle_), gpu_info_,
- gpu_feature_info_);
- DCHECK(!channel_handle_.is_valid());
- }
- return;
- }
- GpuProcessHost* host = GpuProcessHost::Get();
- if (!host) {
- if (callback) {
- std::move(callback).Run(client_id_, mojo::ScopedMessagePipeHandle(),
- gpu::GPUInfo(), gpu::GpuFeatureInfo());
- }
- return;
- }
- callback_ = std::move(callback);
- if (gpu_channel_requested_)
- return;
- gpu_channel_requested_ = true;
- bool preempts = false;
- bool allow_view_command_buffers = false;
- bool allow_real_time_streams = false;
- host->EstablishGpuChannel(
- client_id_, client_tracing_id_, preempts, allow_view_command_buffers,
- allow_real_time_streams,
- base::BindRepeating(&GpuClientImpl::OnEstablishGpuChannel,
- weak_factory_.GetWeakPtr()));
-}
-
-void GpuClientImpl::CreateJpegDecodeAccelerator(
- media::mojom::JpegDecodeAcceleratorRequest jda_request) {
- GpuProcessHost* host = GpuProcessHost::Get();
- if (host)
- host->gpu_service()->CreateJpegDecodeAccelerator(std::move(jda_request));
-}
-
-void GpuClientImpl::CreateVideoEncodeAcceleratorProvider(
- media::mojom::VideoEncodeAcceleratorProviderRequest vea_provider_request) {
- GpuProcessHost* host = GpuProcessHost::Get();
- if (!host)
- return;
- host->gpu_service()->CreateVideoEncodeAcceleratorProvider(
- std::move(vea_provider_request));
-}
-
-void GpuClientImpl::CreateGpuMemoryBuffer(
- gfx::GpuMemoryBufferId id,
- const gfx::Size& size,
- gfx::BufferFormat format,
- gfx::BufferUsage usage,
- ui::mojom::GpuMemoryBufferFactory::CreateGpuMemoryBufferCallback callback) {
- DCHECK(BrowserGpuMemoryBufferManager::current());
-
- base::CheckedNumeric<int> bytes = size.width();
- bytes *= size.height();
- if (!bytes.IsValid()) {
- OnCreateGpuMemoryBuffer(std::move(callback), gfx::GpuMemoryBufferHandle());
- return;
- }
-
- BrowserGpuMemoryBufferManager::current()
- ->AllocateGpuMemoryBufferForChildProcess(
- id, size, format, usage, client_id_,
- base::BindOnce(&GpuClientImpl::OnCreateGpuMemoryBuffer,
- weak_factory_.GetWeakPtr(), std::move(callback)));
-}
-
-void GpuClientImpl::DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferId id,
- const gpu::SyncToken& sync_token) {
- DCHECK(BrowserGpuMemoryBufferManager::current());
-
- BrowserGpuMemoryBufferManager::current()->ChildProcessDeletedGpuMemoryBuffer(
- id, client_id_, sync_token);
-}
-
-void GpuClientImpl::CreateGpuMemoryBufferFactory(
- ui::mojom::GpuMemoryBufferFactoryRequest request) {
- gpu_memory_buffer_factory_bindings_.AddBinding(this, std::move(request));
-}
-
-} // namespace content
diff --git a/chromium/content/browser/gpu/gpu_client_impl.h b/chromium/content/browser/gpu/gpu_client_impl.h
deleted file mode 100644
index 70e684a68be..00000000000
--- a/chromium/content/browser/gpu/gpu_client_impl.h
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_GPU_GPU_CLIENT_IMPL_H_
-#define CONTENT_BROWSER_GPU_GPU_CLIENT_IMPL_H_
-
-#include "base/callback_forward.h"
-#include "base/memory/weak_ptr.h"
-#include "content/browser/gpu/gpu_process_host.h"
-#include "content/public/browser/gpu_client.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
-
-namespace content {
-
-class GpuClientImpl : public ui::mojom::GpuMemoryBufferFactory,
- public ui::mojom::Gpu,
- public GpuClient {
- public:
- // GpuClientImpl must be destroyed on the thread associated with
- // |task_runner|.
- GpuClientImpl(int client_id,
- uint64_t client_tracing_id,
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
-
- ~GpuClientImpl() override;
-
- // This needs to be run on the thread associated with |task_runner_|.
- void Add(ui::mojom::GpuRequest request);
-
- void PreEstablishGpuChannel();
-
- void SetConnectionErrorHandler(
- ConnectionErrorHandlerClosure connection_error_handler);
-
- // ui::mojom::GpuMemoryBufferFactory overrides:
- void CreateGpuMemoryBuffer(
- gfx::GpuMemoryBufferId id,
- const gfx::Size& size,
- gfx::BufferFormat format,
- gfx::BufferUsage usage,
- ui::mojom::GpuMemoryBufferFactory::CreateGpuMemoryBufferCallback callback)
- override;
- void DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferId id,
- const gpu::SyncToken& sync_token) override;
-
- // ui::mojom::Gpu overrides:
- void CreateGpuMemoryBufferFactory(
- ui::mojom::GpuMemoryBufferFactoryRequest request) override;
- void EstablishGpuChannel(EstablishGpuChannelCallback callback) override;
- void CreateJpegDecodeAccelerator(
- media::mojom::JpegDecodeAcceleratorRequest jda_request) override;
- void CreateVideoEncodeAcceleratorProvider(
- media::mojom::VideoEncodeAcceleratorProviderRequest vea_provider_request)
- override;
-
- private:
- enum class ErrorReason {
- // OnError() is being called from the destructor.
- kInDestructor,
- // OnError() is being called because the connection was lost.
- kConnectionLost
- };
- void OnError(ErrorReason reason);
- void OnEstablishGpuChannel(mojo::ScopedMessagePipeHandle channel_handle,
- const gpu::GPUInfo& gpu_info,
- const gpu::GpuFeatureInfo& gpu_feature_info,
- GpuProcessHost::EstablishChannelStatus status);
- void OnCreateGpuMemoryBuffer(CreateGpuMemoryBufferCallback callback,
- gfx::GpuMemoryBufferHandle handle);
- void ClearCallback();
-
- const int client_id_;
- const uint64_t client_tracing_id_;
- mojo::BindingSet<ui::mojom::GpuMemoryBufferFactory>
- gpu_memory_buffer_factory_bindings_;
- mojo::BindingSet<ui::mojom::Gpu> gpu_bindings_;
- bool gpu_channel_requested_ = false;
- EstablishGpuChannelCallback callback_;
- mojo::ScopedMessagePipeHandle channel_handle_;
- gpu::GPUInfo gpu_info_;
- gpu::GpuFeatureInfo gpu_feature_info_;
- ConnectionErrorHandlerClosure connection_error_handler_;
- // |task_runner_| is associated with the thread |gpu_bindings_| is bound on.
- // GpuClientImpl instance is bound to this thread, and must be destroyed on
- // this thread.
- scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
- base::WeakPtrFactory<GpuClientImpl> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(GpuClientImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_GPU_GPU_CLIENT_IMPL_H_
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 63797576500..4541da4f15c 100644
--- a/chromium/content/browser/gpu/gpu_data_manager_impl_private.cc
+++ b/chromium/content/browser/gpu/gpu_data_manager_impl_private.cc
@@ -23,7 +23,7 @@
#include "build/build_config.h"
#include "cc/base/switches.h"
#include "components/viz/common/features.h"
-#include "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
+#include "content/browser/gpu/gpu_memory_buffer_manager_singleton.h"
#include "content/browser/gpu/gpu_process_host.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/gpu_data_manager_observer.h"
@@ -584,11 +584,10 @@ void GpuDataManagerImplPrivate::UpdateGpuPreferences(
gpu::GpuPreferences* gpu_preferences) const {
DCHECK(gpu_preferences);
- BrowserGpuMemoryBufferManager* gpu_memory_buffer_manager =
- BrowserGpuMemoryBufferManager::current();
// For performance reasons, discourage storing VideoFrames in a biplanar
// GpuMemoryBuffer if this is not native, see https://crbug.com/791676.
- if (gpu_memory_buffer_manager) {
+ if (auto* gpu_memory_buffer_manager =
+ GpuMemoryBufferManagerSingleton::GetInstance()) {
gpu_preferences->disable_biplanar_gpu_memory_buffers_for_video_frames =
!gpu_memory_buffer_manager->IsNativeGpuMemoryBufferConfiguration(
gfx::BufferFormat::YUV_420_BIPLANAR,
diff --git a/chromium/content/browser/gpu/gpu_internals_ui.cc b/chromium/content/browser/gpu/gpu_internals_ui.cc
index a64a4419064..02779864950 100644
--- a/chromium/content/browser/gpu/gpu_internals_ui.cc
+++ b/chromium/content/browser/gpu/gpu_internals_ui.cc
@@ -226,6 +226,9 @@ std::unique_ptr<base::ListValue> BasicGpuInfoAsListValue(
NewDescriptionValuePair("Driver version", active_gpu.driver_version));
basic_info->Append(
NewDescriptionValuePair("Driver date", active_gpu.driver_date));
+ basic_info->Append(NewDescriptionValuePair(
+ "GPU CUDA compute capability major version",
+ std::make_unique<base::Value>(active_gpu.cuda_compute_capability_major)));
basic_info->Append(NewDescriptionValuePair("Pixel shader version",
gpu_info.pixel_shader_version));
basic_info->Append(NewDescriptionValuePair("Vertex shader version",
diff --git a/chromium/content/browser/gpu/gpu_ipc_browsertests.cc b/chromium/content/browser/gpu/gpu_ipc_browsertests.cc
index 31f2ab76871..5c930b2e7da 100644
--- a/chromium/content/browser/gpu/gpu_ipc_browsertests.cc
+++ b/chromium/content/browser/gpu/gpu_ipc_browsertests.cc
@@ -17,8 +17,8 @@
#include "content/test/gpu_browsertest_helpers.h"
#include "gpu/ipc/client/command_buffer_proxy_impl.h"
#include "gpu/ipc/client/gpu_channel_host.h"
-#include "services/ui/public/cpp/gpu/context_provider_command_buffer.h"
#include "services/viz/privileged/interfaces/gl/gpu_service.mojom.h"
+#include "services/ws/public/cpp/gpu/context_provider_command_buffer.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkPaint.h"
#include "third_party/skia/include/core/SkSurface.h"
@@ -81,7 +81,7 @@ class ContextTestBase : public content::ContentBrowserTest {
gpu::ContextSupport* context_support_ = nullptr;
private:
- scoped_refptr<ui::ContextProviderCommandBuffer> provider_;
+ scoped_refptr<ws::ContextProviderCommandBuffer> provider_;
};
} // namespace
@@ -221,7 +221,7 @@ IN_PROC_BROWSER_TEST_F(BrowserGpuChannelHostFactoryTest,
MAYBE_GrContextKeepsGpuChannelAlive) {
// Test for crbug.com/551143
// This test verifies that holding a reference to the GrContext created by
- // a ui::ContextProviderCommandBuffer will keep the gpu channel alive after
+ // a ws::ContextProviderCommandBuffer will keep the gpu channel alive after
// the
// provider has been destroyed. Without this behavior, user code would have
// to be careful to destroy objects in the right order to avoid using freed
@@ -231,7 +231,7 @@ IN_PROC_BROWSER_TEST_F(BrowserGpuChannelHostFactoryTest,
// Step 2: verify that holding onto the provider's GrContext will
// retain the host after provider is destroyed.
- scoped_refptr<ui::ContextProviderCommandBuffer> provider =
+ scoped_refptr<ws::ContextProviderCommandBuffer> provider =
content::GpuBrowsertestCreateContext(GetGpuChannel());
ASSERT_EQ(provider->BindToCurrentThread(), gpu::ContextResult::kSuccess);
@@ -278,7 +278,7 @@ IN_PROC_BROWSER_TEST_F(BrowserGpuChannelHostFactoryTest,
EstablishAndWait();
scoped_refptr<gpu::GpuChannelHost> host = GetGpuChannel();
- scoped_refptr<ui::ContextProviderCommandBuffer> provider =
+ scoped_refptr<ws::ContextProviderCommandBuffer> provider =
content::GpuBrowsertestCreateContext(GetGpuChannel());
ContextLostRunLoop run_loop(provider.get());
ASSERT_EQ(provider->BindToCurrentThread(), gpu::ContextResult::kSuccess);
@@ -367,4 +367,24 @@ IN_PROC_BROWSER_TEST_F(BrowserGpuChannelHostFactoryTest, CreateTransferBuffer) {
}
#endif
+class GpuProcessHostDisableGLBrowserTest : public GpuProcessHostBrowserTest {
+ public:
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ GpuProcessHostBrowserTest::SetUpCommandLine(command_line);
+ command_line->AppendSwitchASCII(switches::kUseGL,
+ gl::kGLImplementationDisabledName);
+ }
+};
+
+// Android and CrOS don't support disabling GL.
+#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+IN_PROC_BROWSER_TEST_F(GpuProcessHostDisableGLBrowserTest, CreateAndDestroy) {
+ DCHECK(!IsChannelEstablished());
+ EstablishAndWait();
+ base::RunLoop run_loop;
+ StopGpuProcess(run_loop.QuitClosure());
+ run_loop.Run();
+}
+#endif
+
} // namespace content
diff --git a/chromium/content/browser/gpu/gpu_memory_buffer_manager_singleton.cc b/chromium/content/browser/gpu/gpu_memory_buffer_manager_singleton.cc
new file mode 100644
index 00000000000..780450a72bc
--- /dev/null
+++ b/chromium/content/browser/gpu/gpu_memory_buffer_manager_singleton.cc
@@ -0,0 +1,50 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/gpu/gpu_memory_buffer_manager_singleton.h"
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "content/browser/gpu/gpu_process_host.h"
+#include "content/public/browser/browser_thread.h"
+#include "gpu/ipc/common/gpu_memory_buffer_support.h"
+
+namespace content {
+namespace {
+
+GpuMemoryBufferManagerSingleton* g_gpu_memory_buffer_manager;
+
+viz::mojom::GpuService* GetGpuService(
+ base::OnceClosure connection_error_handler) {
+ if (auto* host = GpuProcessHost::Get()) {
+ host->AddConnectionErrorHandler(std::move(connection_error_handler));
+ return host->gpu_service();
+ }
+ return nullptr;
+}
+
+} // namespace
+
+GpuMemoryBufferManagerSingleton::GpuMemoryBufferManagerSingleton(int client_id)
+ : HostGpuMemoryBufferManager(
+ base::BindRepeating(&content::GetGpuService),
+ client_id,
+ std::make_unique<gpu::GpuMemoryBufferSupport>(),
+ BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)) {
+ DCHECK(!g_gpu_memory_buffer_manager);
+ g_gpu_memory_buffer_manager = this;
+}
+
+GpuMemoryBufferManagerSingleton::~GpuMemoryBufferManagerSingleton() {
+ DCHECK_EQ(this, g_gpu_memory_buffer_manager);
+ g_gpu_memory_buffer_manager = nullptr;
+}
+
+// static
+GpuMemoryBufferManagerSingleton*
+GpuMemoryBufferManagerSingleton::GetInstance() {
+ return g_gpu_memory_buffer_manager;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/gpu/gpu_memory_buffer_manager_singleton.h b/chromium/content/browser/gpu/gpu_memory_buffer_manager_singleton.h
new file mode 100644
index 00000000000..3a662ef1536
--- /dev/null
+++ b/chromium/content/browser/gpu/gpu_memory_buffer_manager_singleton.h
@@ -0,0 +1,28 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_GPU_GPU_MEMORY_BUFFER_MANAGER_SINGLETON_H_
+#define CONTENT_BROWSER_GPU_GPU_MEMORY_BUFFER_MANAGER_SINGLETON_H_
+
+#include "components/viz/host/host_gpu_memory_buffer_manager.h"
+
+namespace content {
+
+// This class ensures that there is at most one instance of
+// |viz::HostGpuMemoryBufferManager| in content at any given time. Code in
+// content must use this class to access the instance.
+class GpuMemoryBufferManagerSingleton : public viz::HostGpuMemoryBufferManager {
+ public:
+ explicit GpuMemoryBufferManagerSingleton(int client_id);
+ ~GpuMemoryBufferManagerSingleton() override;
+
+ static GpuMemoryBufferManagerSingleton* GetInstance();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(GpuMemoryBufferManagerSingleton);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_GPU_GPU_MEMORY_BUFFER_MANAGER_SINGLETON_H_
diff --git a/chromium/content/browser/gpu/gpu_process_host.cc b/chromium/content/browser/gpu/gpu_process_host.cc
index bdecceea7e6..9511100e607 100644
--- a/chromium/content/browser/gpu/gpu_process_host.cc
+++ b/chromium/content/browser/gpu/gpu_process_host.cc
@@ -41,6 +41,7 @@
#include "content/browser/gpu/compositor_util.h"
#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "content/browser/gpu/gpu_main_thread_factory.h"
+#include "content/browser/gpu/gpu_memory_buffer_manager_singleton.h"
#include "content/browser/gpu/shader_cache_factory.h"
#include "content/browser/memory/memory_coordinator_impl.h"
#include "content/browser/service_manager/service_manager_context.h"
@@ -63,7 +64,9 @@
#include "gpu/command_buffer/service/gpu_switches.h"
#include "gpu/config/gpu_driver_bug_list.h"
#include "gpu/config/gpu_driver_bug_workaround_type.h"
+#include "gpu/config/gpu_finch_features.h"
#include "gpu/config/gpu_preferences.h"
+#include "gpu/ipc/common/gpu_client_ids.h"
#include "gpu/ipc/host/shader_disk_cache.h"
#include "gpu/ipc/in_process_command_buffer.h"
#include "media/base/media_switches.h"
@@ -74,7 +77,7 @@
#include "services/service_manager/runner/common/client_util.h"
#include "services/service_manager/sandbox/sandbox_type.h"
#include "services/service_manager/sandbox/switches.h"
-#include "services/ui/public/interfaces/constants.mojom.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"
@@ -84,7 +87,6 @@
#include "ui/latency/latency_info.h"
#if defined(OS_ANDROID)
-#include "base/android/build_info.h"
#include "content/public/browser/android/java_interfaces.h"
#include "media/mojo/interfaces/android_overlay.mojom.h"
#endif
@@ -92,7 +94,6 @@
#if defined(OS_WIN)
#include "sandbox/win/src/sandbox_policy.h"
#include "services/service_manager/sandbox/win/sandbox_win.h"
-#include "ui/gfx/switches.h"
#include "ui/gfx/win/rendering_window_manager.h"
#endif
@@ -237,7 +238,6 @@ static const char* const kSwitchNames[] = {
switches::kShowMacOverlayBorders,
#endif
#if defined(USE_OZONE)
- switches::kEnableDrmMojo,
switches::kOzonePlatform,
switches::kOzoneDumpFile,
#endif
@@ -305,7 +305,7 @@ void OzoneRegisterStartupCallbackHelper(
}
},
base::RetainedRef(base::ThreadTaskRunnerHandle::Get()),
- base::Passed(&io_callback));
+ std::move(io_callback));
ui::OzonePlatform::RegisterStartupCallback(std::move(bounce_callback));
}
#endif // defined(USE_OZONE)
@@ -471,9 +471,9 @@ void BindDiscardableMemoryRequestOnUI(
DCHECK_CURRENTLY_ON(BrowserThread::UI);
#if defined(USE_AURA)
- if (!features::IsAshInBrowserProcess()) {
+ if (features::IsMultiProcessMash()) {
ServiceManagerConnection::GetForProcess()->GetConnector()->BindInterface(
- ui::mojom::kServiceName, std::move(request));
+ ws::mojom::kServiceName, std::move(request));
return;
}
#endif
@@ -484,16 +484,6 @@ void BindDiscardableMemoryRequestOnUI(
BrowserMainLoop::GetInstance()->discardable_shared_memory_manager()));
}
-struct FontRenderParamsOnIO {
- bool initialized = false;
- gfx::FontRenderParams params;
-};
-
-FontRenderParamsOnIO& GetFontRenderParamsOnIO() {
- static base::NoDestructor<FontRenderParamsOnIO> instance;
- return *instance;
-}
-
void CreateMemoryCoordinatorHandleForGpuProcess(
int gpu_process_id,
mojom::MemoryCoordinatorHandleRequest request) {
@@ -539,16 +529,6 @@ class GpuProcessHost::ConnectionFilterImpl : public ConnectionFilter {
};
// static
-void GpuProcessHost::InitFontRenderParamsOnIO(
- const gfx::FontRenderParams& params) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(!GetFontRenderParamsOnIO().initialized);
-
- GetFontRenderParamsOnIO().initialized = true;
- GetFontRenderParamsOnIO().params = params;
-}
-
-// static
bool GpuProcessHost::ValidateHost(GpuProcessHost* host) {
// The Gpu process is invalid if it's not using SwiftShader, the card is
// blacklisted, and we can kill it and start over.
@@ -654,6 +634,14 @@ void GpuProcessHost::BindInterface(
std::move(interface_pipe));
}
+void GpuProcessHost::TerminateGpuProcess(const std::string& message) {
+ // At the moment, this path is only used by Ozone/Wayland. Once others start
+ // to use this, start to distinguish the origin of termination. By default,
+ // it's unknown.
+ termination_origin_ = GpuTerminationOrigin::kOzoneWaylandProxy;
+ process_->TerminateOnBadMessageReceived(message);
+}
+
// static
GpuProcessHost* GpuProcessHost::FromID(int host_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -700,8 +688,6 @@ GpuProcessHost::GpuProcessHost(int host_id, GpuProcessKind kind)
in_process_(false),
kind_(kind),
process_launched_(false),
- status_(UNKNOWN),
- gpu_host_binding_(this),
weak_ptr_factory_(this) {
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kSingleProcess) ||
@@ -725,7 +711,7 @@ GpuProcessHost::~GpuProcessHost() {
if (in_process_gpu_thread_)
DCHECK(process_);
- SendOutstandingReplies(EstablishChannelStatus::GPU_HOST_INVALID);
+ SendOutstandingReplies();
#if defined(OS_MACOSX)
if (ca_transaction_gpu_coordinator_) {
@@ -734,12 +720,6 @@ GpuProcessHost::~GpuProcessHost() {
}
#endif
- if (status_ == UNKNOWN) {
- RunRequestGPUInfoCallbacks(gpu::GPUInfo());
- } else {
- DCHECK(request_gpu_info_callbacks_.empty());
- }
-
// In case we never started, clean up.
while (!queued_messages_.empty()) {
delete queued_messages_.front();
@@ -758,7 +738,8 @@ GpuProcessHost::~GpuProcessHost() {
std::string message;
bool block_offscreen_contexts = true;
- if (!in_process_ && process_launched_) {
+ if (!in_process_ && process_launched_ &&
+ kind_ == GPU_PROCESS_KIND_SANDBOXED) {
ChildProcessTerminationInfo info =
process_->GetTerminationInfo(false /* known_dead */);
UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessTerminationStatus2",
@@ -791,6 +772,9 @@ GpuProcessHost::~GpuProcessHost() {
info.exit_code);
break;
case base::TERMINATION_STATUS_PROCESS_WAS_KILLED:
+ UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessTerminationOrigin",
+ termination_origin_,
+ GpuTerminationOrigin::kMax);
message = "You killed the GPU process! Why?";
break;
#if defined(OS_CHROMEOS)
@@ -809,11 +793,11 @@ GpuProcessHost::~GpuProcessHost() {
}
}
- // If there are any remaining offscreen contexts at the point the
- // GPU process exits, assume something went wrong, and block their
- // URLs from accessing client 3D APIs without prompting.
- if (block_offscreen_contexts)
- BlockLiveOffscreenContexts();
+ // If there are any remaining offscreen contexts at the point the GPU process
+ // exits, assume something went wrong, and block their URLs from accessing
+ // client 3D APIs without prompting.
+ if (block_offscreen_contexts && gpu_host_)
+ gpu_host_->BlockLiveOffscreenContexts();
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
@@ -826,26 +810,31 @@ void GpuProcessHost::InitOzone() {
// possible to ensure the latter always has a valid device. crbug.com/608839
// When running with mus, the OzonePlatform may not have been created yet. So
// defer the callback until OzonePlatform instance is created.
- base::CommandLine* browser_command_line =
- base::CommandLine::ForCurrentProcess();
- if (browser_command_line->HasSwitch(switches::kEnableDrmMojo)) {
+ bool using_mojo = true;
+#if defined(OS_CHROMEOS)
+ using_mojo = features::IsOzoneDrmMojo();
+#endif
+ if (using_mojo) {
// TODO(rjkroege): Remove the legacy IPC code paths when no longer
// necessary. https://crbug.com/806092
auto interface_binder = base::BindRepeating(&GpuProcessHost::BindInterface,
weak_ptr_factory_.GetWeakPtr());
+ auto terminate_cb = base::BindOnce(&GpuProcessHost::TerminateGpuProcess,
+ weak_ptr_factory_.GetWeakPtr());
auto io_callback = base::BindOnce(
[](const base::RepeatingCallback<void(const std::string&,
mojo::ScopedMessagePipeHandle)>&
interface_binder,
+ base::OnceCallback<void(const std::string&)> terminate_cb,
ui::OzonePlatform* platform) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
platform->GetGpuPlatformSupportHost()->OnGpuServiceLaunched(
BrowserThread::GetTaskRunnerForThread(BrowserThread::UI),
BrowserThread::GetTaskRunnerForThread(BrowserThread::IO),
- interface_binder);
+ interface_binder, std::move(terminate_cb));
},
- interface_binder);
+ interface_binder, std::move(terminate_cb));
OzoneRegisterStartupCallbackHelper(std::move(io_callback));
} else {
@@ -911,24 +900,17 @@ bool GpuProcessHost::Init() {
return false;
}
- process_->child_channel()
- ->GetAssociatedInterfaceSupport()
- ->GetRemoteAssociatedInterface(&gpu_main_ptr_);
- viz::mojom::GpuHostPtr host_proxy;
- gpu_host_binding_.Bind(mojo::MakeRequest(&host_proxy));
-
- discardable_memory::mojom::DiscardableSharedMemoryManagerPtr
- discardable_manager_ptr;
- auto discardable_request = mojo::MakeRequest(&discardable_manager_ptr);
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(&BindDiscardableMemoryRequestOnUI,
- std::move(discardable_request)));
-
- DCHECK(GetFontRenderParamsOnIO().initialized);
- gpu_main_ptr_->CreateGpuService(
- mojo::MakeRequest(&gpu_service_ptr_), std::move(host_proxy),
- std::move(discardable_manager_ptr), activity_flags_.CloneHandle(),
- GetFontRenderParamsOnIO().params.subpixel_rendering);
+ viz::GpuHostImpl::InitParams params;
+ params.restart_id = host_id_;
+ params.in_process = in_process_;
+ params.disable_gpu_shader_disk_cache =
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableGpuShaderDiskCache);
+ params.product = GetContentClient()->GetProduct();
+ params.deadline_to_synchronize_surfaces =
+ switches::GetDeadlineToSynchronizeSurfaces();
+ gpu_host_ = std::make_unique<viz::GpuHostImpl>(
+ this, process_->child_channel(), std::move(params));
#if defined(USE_OZONE)
InitOzone();
@@ -953,7 +935,7 @@ bool GpuProcessHost::Send(IPC::Message* msg) {
// Channel is hosed, but we may not get destroyed for a while. Send
// outstanding channel creation failures now so that the caller can restart
// with a new process/channel without waiting.
- SendOutstandingReplies(EstablishChannelStatus::GPU_HOST_INVALID);
+ SendOutstandingReplies();
}
return result;
}
@@ -977,144 +959,8 @@ void GpuProcessHost::OnChannelConnected(int32_t peer_pid) {
}
}
-void GpuProcessHost::EstablishGpuChannel(
- int client_id,
- uint64_t client_tracing_id,
- bool preempts,
- bool allow_view_command_buffers,
- bool allow_real_time_streams,
- const EstablishChannelCallback& callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- TRACE_EVENT0("gpu", "GpuProcessHost::EstablishGpuChannel");
-
- // If GPU features are already blacklisted, no need to establish the channel.
- if (!GpuDataManagerImpl::GetInstance()->GpuAccessAllowed(nullptr)) {
- DVLOG(1) << "GPU blacklisted, refusing to open a GPU channel.";
- callback.Run(mojo::ScopedMessagePipeHandle(), gpu::GPUInfo(),
- gpu::GpuFeatureInfo(),
- EstablishChannelStatus::GPU_ACCESS_DENIED);
- return;
- }
-
- bool oopd_enabled =
- base::FeatureList::IsEnabled(features::kVizDisplayCompositor);
- if (oopd_enabled && client_id == gpu::InProcessCommandBuffer::kGpuClientId) {
- // The display-compositor in the gpu process uses this special client id.
- callback.Run(mojo::ScopedMessagePipeHandle(), gpu::GPUInfo(),
- gpu::GpuFeatureInfo(),
- EstablishChannelStatus::GPU_ACCESS_DENIED);
- return;
- }
-
- DCHECK_EQ(preempts, allow_view_command_buffers);
- DCHECK_EQ(preempts, allow_real_time_streams);
- bool is_gpu_host = preempts;
-
- channel_requests_.push(callback);
- gpu_service_ptr_->EstablishGpuChannel(
- client_id, client_tracing_id, is_gpu_host,
- base::BindOnce(&GpuProcessHost::OnChannelEstablished,
- weak_ptr_factory_.GetWeakPtr(), client_id, callback));
-
- if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableGpuShaderDiskCache)) {
- CreateChannelCache(client_id);
- if (oopd_enabled)
- CreateChannelCache(gpu::InProcessCommandBuffer::kGpuClientId);
- }
-}
-
-void GpuProcessHost::CreateGpuMemoryBuffer(
- gfx::GpuMemoryBufferId id,
- const gfx::Size& size,
- gfx::BufferFormat format,
- gfx::BufferUsage usage,
- int client_id,
- gpu::SurfaceHandle surface_handle,
- CreateGpuMemoryBufferCallback callback) {
- TRACE_EVENT0("gpu", "GpuProcessHost::CreateGpuMemoryBuffer");
-
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- create_gpu_memory_buffer_requests_.push(std::move(callback));
- gpu_service_ptr_->CreateGpuMemoryBuffer(
- id, size, format, usage, client_id, surface_handle,
- base::BindOnce(&GpuProcessHost::OnGpuMemoryBufferCreated,
- weak_ptr_factory_.GetWeakPtr()));
-}
-
-void GpuProcessHost::DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferId id,
- int client_id,
- const gpu::SyncToken& sync_token) {
- TRACE_EVENT0("gpu", "GpuProcessHost::DestroyGpuMemoryBuffer");
- gpu_service_ptr_->DestroyGpuMemoryBuffer(id, client_id, sync_token);
-}
-
-void GpuProcessHost::ConnectFrameSinkManager(
- viz::mojom::FrameSinkManagerRequest request,
- viz::mojom::FrameSinkManagerClientPtrInfo client) {
- TRACE_EVENT0("gpu", "GpuProcessHost::ConnectFrameSinkManager");
- viz::mojom::FrameSinkManagerParamsPtr params =
- viz::mojom::FrameSinkManagerParams::New();
- params->restart_id = host_id_;
- base::Optional<uint32_t> activation_deadline_in_frames =
- switches::GetDeadlineToSynchronizeSurfaces();
- params->use_activation_deadline = activation_deadline_in_frames.has_value();
- params->activation_deadline_in_frames =
- activation_deadline_in_frames.value_or(0u);
- params->frame_sink_manager = std::move(request);
- params->frame_sink_manager_client = std::move(client);
- gpu_main_ptr_->CreateFrameSinkManager(std::move(params));
-}
-
-void GpuProcessHost::RequestGPUInfo(RequestGPUInfoCallback request_cb) {
- if (status_ == SUCCESS || status_ == FAILURE) {
- std::move(request_cb).Run(GpuDataManagerImpl::GetInstance()->GetGPUInfo());
- return;
- }
-
- request_gpu_info_callbacks_.push_back(std::move(request_cb));
-}
-
-void GpuProcessHost::RequestHDRStatus(RequestHDRStatusCallback request_cb) {
- gpu_service_ptr_->RequestHDRStatus(std::move(request_cb));
-}
-
-void GpuProcessHost::OnChannelEstablished(
- int client_id,
- const EstablishChannelCallback& callback,
- mojo::ScopedMessagePipeHandle channel_handle) {
- TRACE_EVENT0("gpu", "GpuProcessHost::OnChannelEstablished");
- DCHECK(!channel_requests_.empty());
- DCHECK(channel_requests_.front().Equals(callback));
- channel_requests_.pop();
-
- auto* gpu_data_manager = GpuDataManagerImpl::GetInstance();
- // Currently if any of the GPU features are blacklisted, we don't establish a
- // GPU channel.
- if (channel_handle.is_valid() &&
- !gpu_data_manager->GpuAccessAllowed(nullptr)) {
- gpu_service_ptr_->CloseChannel(client_id);
- callback.Run(mojo::ScopedMessagePipeHandle(), gpu::GPUInfo(),
- gpu::GpuFeatureInfo(),
- EstablishChannelStatus::GPU_ACCESS_DENIED);
- RecordLogMessage(logging::LOG_WARNING, "WARNING",
- "Hardware acceleration is unavailable.");
- return;
- }
-
- callback.Run(std::move(channel_handle), gpu_data_manager->GetGPUInfo(),
- gpu_data_manager->GetGpuFeatureInfo(),
- EstablishChannelStatus::SUCCESS);
-}
-
-void GpuProcessHost::OnGpuMemoryBufferCreated(
- gfx::GpuMemoryBufferHandle handle) {
- TRACE_EVENT0("gpu", "GpuProcessHost::OnGpuMemoryBufferCreated");
-
- DCHECK(!create_gpu_memory_buffer_requests_.empty());
- auto callback = std::move(create_gpu_memory_buffer_requests_.front());
- create_gpu_memory_buffer_requests_.pop();
- std::move(callback).Run(std::move(handle), BufferCreationStatus::SUCCESS);
+void GpuProcessHost::AddConnectionErrorHandler(base::OnceClosure handler) {
+ connection_error_handlers_.push_back(std::move(handler));
}
#if defined(OS_ANDROID)
@@ -1132,6 +978,12 @@ void GpuProcessHost::OnProcessLaunched() {
if (kind_ == GPU_PROCESS_KIND_SANDBOXED)
RecordAppContainerStatus(sandbox::SBOX_ALL_OK, crashed_before_);
#endif // defined(OS_WIN)
+
+ if (!in_process_) {
+ process_id_ = process_->GetProcess().Pid();
+ DCHECK_NE(base::kNullProcessId, process_id_);
+ gpu_host_->OnProcessLaunched(process_id_);
+ }
}
void GpuProcessHost::OnProcessLaunchFailed(int error_code) {
@@ -1156,61 +1008,40 @@ void GpuProcessHost::OnProcessCrashed(int exit_code) {
// Record crash before doing anything that could start a new GPU process.
RecordProcessCrash();
- // If the GPU process crashed while compiling a shader, we may have invalid
- // cached binaries. Completely clear the shader cache to force shader binaries
- // to be re-created.
- if (activity_flags_.IsFlagSet(
- gpu::ActivityFlagsBase::FLAG_LOADING_PROGRAM_BINARY)) {
- for (auto cache_key : client_id_to_shader_cache_) {
- // This call will temporarily extend the lifetime of the cache (kept
- // alive in the factory), and may drop loads of cached shader binaries if
- // it takes a while to complete. As we are intentionally dropping all
- // binaries, this behavior is fine.
- GetShaderCacheFactorySingleton()->ClearByClientId(
- cache_key.first, base::Time(), base::Time::Max(), base::Bind([] {}));
- }
- }
- SendOutstandingReplies(EstablishChannelStatus::GPU_HOST_INVALID);
+ gpu_host_->OnProcessCrashed();
+
+ SendOutstandingReplies();
ChildProcessTerminationInfo info =
process_->GetTerminationInfo(true /* known_dead */);
GpuDataManagerImpl::GetInstance()->ProcessCrashed(info.status);
}
-void GpuProcessHost::DidInitialize(
+gpu::GPUInfo GpuProcessHost::GetGPUInfo() const {
+ return GpuDataManagerImpl::GetInstance()->GetGPUInfo();
+}
+
+gpu::GpuFeatureInfo GpuProcessHost::GetGpuFeatureInfo() const {
+ return GpuDataManagerImpl::GetInstance()->GetGpuFeatureInfo();
+}
+
+void GpuProcessHost::UpdateGpuInfo(
const gpu::GPUInfo& gpu_info,
const gpu::GpuFeatureInfo& gpu_feature_info,
const base::Optional<gpu::GPUInfo>& gpu_info_for_hardware_gpu,
const base::Optional<gpu::GpuFeatureInfo>&
gpu_feature_info_for_hardware_gpu) {
- UMA_HISTOGRAM_BOOLEAN("GPU.GPUProcessInitialized", true);
- status_ = SUCCESS;
-
- // Set GPU driver bug workaround flags that are checked on the browser side.
- if (gpu_feature_info.IsWorkaroundEnabled(gpu::WAKE_UP_GPU_BEFORE_DRAWING)) {
- wake_up_gpu_before_drawing_ = true;
- }
- if (gpu_feature_info.IsWorkaroundEnabled(
- gpu::DONT_DISABLE_WEBGL_WHEN_COMPOSITOR_CONTEXT_LOST)) {
- dont_disable_webgl_when_compositor_context_lost_ = true;
- }
-
- GpuDataManagerImpl* gpu_data_manager = GpuDataManagerImpl::GetInstance();
+ auto* gpu_data_manager = GpuDataManagerImpl::GetInstance();
// Update GpuFeatureInfo first, because UpdateGpuInfo() will notify all
// listeners.
gpu_data_manager->UpdateGpuFeatureInfo(gpu_feature_info,
gpu_feature_info_for_hardware_gpu);
gpu_data_manager->UpdateGpuInfo(gpu_info, gpu_info_for_hardware_gpu);
- RunRequestGPUInfoCallbacks(gpu_data_manager->GetGPUInfo());
}
void GpuProcessHost::DidFailInitialize() {
- UMA_HISTOGRAM_BOOLEAN("GPU.GPUProcessInitialized", false);
- status_ = FAILURE;
- GpuDataManagerImpl* gpu_data_manager = GpuDataManagerImpl::GetInstance();
if (kind_ == GPU_PROCESS_KIND_SANDBOXED)
- gpu_data_manager->FallBackToNextGpuMode();
- RunRequestGPUInfoCallbacks(gpu_data_manager->GetGPUInfo());
+ GpuDataManagerImpl::GetInstance()->FallBackToNextGpuMode();
}
void GpuProcessHost::DidCreateContextSuccessfully() {
@@ -1222,67 +1053,22 @@ void GpuProcessHost::DidCreateContextSuccessfully() {
#endif
}
-void GpuProcessHost::DidCreateOffscreenContext(const GURL& url) {
- urls_with_live_offscreen_contexts_.insert(url);
-}
-
-void GpuProcessHost::DidDestroyOffscreenContext(const GURL& url) {
- // We only want to remove *one* of the entries in the multiset for
- // this particular URL, so can't use the erase method taking a key.
- auto candidate = urls_with_live_offscreen_contexts_.find(url);
- if (candidate != urls_with_live_offscreen_contexts_.end()) {
- urls_with_live_offscreen_contexts_.erase(candidate);
- }
-}
-
-void GpuProcessHost::DidDestroyChannel(int32_t client_id) {
- TRACE_EVENT0("gpu", "GpuProcessHost::DidDestroyChannel");
- client_id_to_shader_cache_.erase(client_id);
-}
-
-void GpuProcessHost::DidLoseContext(bool offscreen,
- gpu::error::ContextLostReason reason,
- const GURL& active_url) {
- // TODO(kbr): would be nice to see the "offscreen" flag too.
- TRACE_EVENT2("gpu", "GpuProcessHost::DidLoseContext", "reason", reason, "url",
- active_url.possibly_invalid_spec());
-
- if (!offscreen || active_url.is_empty()) {
- // Assume that the loss of the compositor's or accelerated canvas'
- // context is a serious event and blame the loss on all live
- // offscreen contexts. This more robustly handles situations where
- // the GPU process may not actually detect the context loss in the
- // offscreen context. However, situations have been seen where the
- // compositor's context can be lost due to driver bugs (as of this
- // writing, on Android), so allow that possibility.
- if (!dont_disable_webgl_when_compositor_context_lost_) {
- BlockLiveOffscreenContexts();
- }
- return;
- }
-
- GpuDataManagerImpl::DomainGuilt guilt =
- GpuDataManagerImpl::DOMAIN_GUILT_UNKNOWN;
- switch (reason) {
- case gpu::error::kGuilty:
- guilt = GpuDataManagerImpl::DOMAIN_GUILT_KNOWN;
+void GpuProcessHost::BlockDomainFrom3DAPIs(const GURL& url,
+ Delegate::DomainGuilt guilt) {
+ GpuDataManagerImpl::DomainGuilt gpu_data_manager_guilt;
+ switch (guilt) {
+ case Delegate::DomainGuilt::kKnown:
+ gpu_data_manager_guilt = GpuDataManagerImpl::DOMAIN_GUILT_KNOWN;
break;
- // Treat most other error codes as though they had unknown provenance.
- // In practice this doesn't affect the user experience. A lost context
- // of either known or unknown guilt still causes user-level 3D APIs
- // (e.g. WebGL) to be blocked on that domain until the user manually
- // reenables them.
- case gpu::error::kUnknown:
- case gpu::error::kOutOfMemory:
- case gpu::error::kMakeCurrentFailed:
- case gpu::error::kGpuChannelLost:
- case gpu::error::kInvalidGpuMessage:
- break;
- case gpu::error::kInnocent:
- return;
+ case Delegate::DomainGuilt::kUnknown:
+ gpu_data_manager_guilt = GpuDataManagerImpl::DOMAIN_GUILT_UNKNOWN;
}
+ GpuDataManagerImpl::GetInstance()->BlockDomainFrom3DAPIs(
+ url, gpu_data_manager_guilt);
+}
- GpuDataManagerImpl::GetInstance()->BlockDomainFrom3DAPIs(active_url, guilt);
+bool GpuProcessHost::GpuAccessAllowed() const {
+ return GpuDataManagerImpl::GetInstance()->GpuAccessAllowed(nullptr);
}
void GpuProcessHost::DisableGpuCompositing() {
@@ -1297,47 +1083,8 @@ void GpuProcessHost::DisableGpuCompositing() {
#endif
}
-void GpuProcessHost::SetChildSurface(gpu::SurfaceHandle parent_handle,
- gpu::SurfaceHandle window_handle) {
-#if defined(OS_WIN)
- constexpr char kBadMessageError[] = "Bad parenting request from gpu process.";
- if (!in_process_) {
- DCHECK(process_);
-
- DWORD parent_process_id = 0;
- DWORD parent_thread_id =
- GetWindowThreadProcessId(parent_handle, &parent_process_id);
- if (!parent_thread_id || parent_process_id != ::GetCurrentProcessId()) {
- LOG(ERROR) << kBadMessageError;
- return;
- }
-
- DWORD child_process_id = 0;
- DWORD child_thread_id =
- GetWindowThreadProcessId(window_handle, &child_process_id);
- if (!child_thread_id || child_process_id != process_->GetProcess().Pid()) {
- LOG(ERROR) << kBadMessageError;
- return;
- }
- }
-
- if (!gfx::RenderingWindowManager::GetInstance()->RegisterChild(
- parent_handle, window_handle)) {
- LOG(ERROR) << kBadMessageError;
- }
-#endif
-}
-
-void GpuProcessHost::StoreShaderToDisk(int32_t client_id,
- const std::string& key,
- const std::string& shader) {
- TRACE_EVENT0("gpu", "GpuProcessHost::StoreShaderToDisk");
- ClientIdToShaderCacheMap::iterator iter =
- client_id_to_shader_cache_.find(client_id);
- // If the cache doesn't exist then this is an off the record profile.
- if (iter == client_id_to_shader_cache_.end())
- return;
- iter->second->Cache(GetShaderPrefixKey() + ":" + key, shader);
+gpu::ShaderCacheFactory* GpuProcessHost::GetShaderCacheFactory() {
+ return GetShaderCacheFactorySingleton();
}
void GpuProcessHost::RecordLogMessage(int32_t severity,
@@ -1346,6 +1093,13 @@ void GpuProcessHost::RecordLogMessage(int32_t severity,
GpuDataManagerImpl::GetInstance()->AddLogMessage(severity, header, message);
}
+void GpuProcessHost::BindDiscardableMemoryRequest(
+ discardable_memory::mojom::DiscardableSharedMemoryManagerRequest request) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&BindDiscardableMemoryRequestOnUI, std::move(request)));
+}
+
GpuProcessHost::GpuProcessKind GpuProcessHost::kind() {
return kind_;
}
@@ -1460,46 +1214,20 @@ bool GpuProcessHost::LaunchGpuProcess() {
return true;
}
-void GpuProcessHost::SendOutstandingReplies(
- EstablishChannelStatus failure_status) {
- DCHECK_NE(failure_status, EstablishChannelStatus::SUCCESS);
+void GpuProcessHost::SendOutstandingReplies() {
valid_ = false;
- // First send empty channel handles for all EstablishChannel requests.
- while (!channel_requests_.empty()) {
- auto callback = channel_requests_.front();
- channel_requests_.pop();
- std::move(callback).Run(mojo::ScopedMessagePipeHandle(), gpu::GPUInfo(),
- gpu::GpuFeatureInfo(), failure_status);
- }
+ for (auto& handler : connection_error_handlers_)
+ std::move(handler).Run();
+ connection_error_handlers_.clear();
- while (!create_gpu_memory_buffer_requests_.empty()) {
- auto callback = std::move(create_gpu_memory_buffer_requests_.front());
- create_gpu_memory_buffer_requests_.pop();
- std::move(callback).Run(gfx::GpuMemoryBufferHandle(),
- BufferCreationStatus::GPU_HOST_INVALID);
- }
+ if (gpu_host_)
+ gpu_host_->SendOutstandingReplies();
if (!send_destroying_video_surface_done_cb_.is_null())
base::ResetAndReturn(&send_destroying_video_surface_done_cb_).Run();
}
-void GpuProcessHost::RunRequestGPUInfoCallbacks(const gpu::GPUInfo& gpu_info) {
- for (auto& callback : request_gpu_info_callbacks_)
- std::move(callback).Run(gpu_info);
-
- request_gpu_info_callbacks_.clear();
-}
-
-void GpuProcessHost::BlockLiveOffscreenContexts() {
- for (std::multiset<GURL>::iterator iter =
- urls_with_live_offscreen_contexts_.begin();
- iter != urls_with_live_offscreen_contexts_.end(); ++iter) {
- GpuDataManagerImpl::GetInstance()->BlockDomainFrom3DAPIs(
- *iter, GpuDataManagerImpl::DOMAIN_GUILT_UNKNOWN);
- }
-}
-
void GpuProcessHost::RecordProcessCrash() {
#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
// Maximum number of times the GPU process can crash before we try something
@@ -1559,7 +1287,7 @@ void GpuProcessHost::RecordProcessCrash() {
base::debug::Alias(&display_compositor_crash_count);
// GPU process initialization failed and fallback already happened.
- if (status_ == FAILURE)
+ if (!gpu_host_ || !gpu_host_->initialized())
return;
bool disable_crash_limit = base::CommandLine::ForCurrentProcess()->HasSwitch(
@@ -1571,57 +1299,9 @@ void GpuProcessHost::RecordProcessCrash() {
GpuDataManagerImpl::GetInstance()->FallBackToNextGpuMode();
}
-std::string GpuProcessHost::GetShaderPrefixKey() {
- if (shader_prefix_key_.empty()) {
- const gpu::GPUInfo info = GpuDataManagerImpl::GetInstance()->GetGPUInfo();
- const gpu::GPUInfo::GPUDevice& active_gpu = info.active_gpu();
-
- shader_prefix_key_ = GetContentClient()->GetProduct() + "-" +
- info.gl_vendor + "-" + info.gl_renderer + "-" +
- active_gpu.driver_version + "-" +
- active_gpu.driver_vendor;
-
-#if defined(OS_ANDROID)
- std::string build_fp =
- base::android::BuildInfo::GetInstance()->android_build_fp();
- // TODO(ericrk): Remove this after it's up for a few days. crbug.com/699122
- CHECK(!build_fp.empty());
- shader_prefix_key_ += "-" + build_fp;
-#endif
- }
-
- return shader_prefix_key_;
-}
-
-void GpuProcessHost::LoadedShader(const std::string& key,
- const std::string& data) {
- std::string prefix = GetShaderPrefixKey();
- bool prefix_ok = !key.compare(0, prefix.length(), prefix);
- UMA_HISTOGRAM_BOOLEAN("GPU.ShaderLoadPrefixOK", prefix_ok);
- if (prefix_ok) {
- // Remove the prefix from the key before load.
- std::string key_no_prefix = key.substr(prefix.length() + 1);
- gpu_service_ptr_->LoadedShader(key_no_prefix, data);
- }
-}
-
viz::mojom::GpuService* GpuProcessHost::gpu_service() {
- DCHECK(gpu_service_ptr_.is_bound());
- return gpu_service_ptr_.get();
-}
-
-void GpuProcessHost::CreateChannelCache(int32_t client_id) {
- TRACE_EVENT0("gpu", "GpuProcessHost::CreateChannelCache");
-
- scoped_refptr<gpu::ShaderDiskCache> cache =
- GetShaderCacheFactorySingleton()->Get(client_id);
- if (!cache.get())
- return;
-
- cache->set_shader_loaded_callback(base::Bind(&GpuProcessHost::LoadedShader,
- weak_ptr_factory_.GetWeakPtr()));
-
- client_id_to_shader_cache_[client_id] = cache;
+ DCHECK(gpu_host_);
+ return gpu_host_->gpu_service();
}
int GpuProcessHost::GetIDForTesting() const {
diff --git a/chromium/content/browser/gpu/gpu_process_host.h b/chromium/content/browser/gpu/gpu_process_host.h
index 3ca9cf5c561..d79907844e1 100644
--- a/chromium/content/browser/gpu/gpu_process_host.h
+++ b/chromium/content/browser/gpu/gpu_process_host.h
@@ -11,6 +11,7 @@
#include <memory>
#include <set>
#include <string>
+#include <vector>
#include "base/atomicops.h"
#include "base/callback.h"
@@ -21,6 +22,7 @@
#include "base/sequence_checker.h"
#include "base/time/time.h"
#include "build/build_config.h"
+#include "components/viz/host/gpu_host_impl.h"
#include "content/common/content_export.h"
#include "content/public/browser/browser_child_process_host_delegate.h"
#include "content/public/browser/gpu_data_manager.h"
@@ -36,23 +38,12 @@
#include "services/viz/privileged/interfaces/gl/gpu_host.mojom.h"
#include "services/viz/privileged/interfaces/gl/gpu_service.mojom.h"
#include "services/viz/privileged/interfaces/viz_main.mojom.h"
-#include "ui/gfx/geometry/size.h"
-#include "ui/gfx/gpu_memory_buffer.h"
#include "url/gurl.h"
namespace base {
class Thread;
}
-namespace gfx {
-struct FontRenderParams;
-}
-
-namespace gpu {
-class ShaderDiskCache;
-struct SyncToken;
-}
-
namespace content {
class BrowserChildProcessHostImpl;
@@ -62,7 +53,7 @@ class CATransactionGPUCoordinator;
class GpuProcessHost : public BrowserChildProcessHostDelegate,
public IPC::Sender,
- public viz::mojom::GpuHost {
+ public viz::GpuHostImpl::Delegate {
public:
enum GpuProcessKind {
GPU_PROCESS_KIND_UNSANDBOXED,
@@ -70,31 +61,6 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
GPU_PROCESS_KIND_COUNT
};
- enum class EstablishChannelStatus {
- GPU_ACCESS_DENIED, // GPU access was not allowed.
- GPU_HOST_INVALID, // Request failed because the gpu host became invalid
- // while processing the request (e.g. the gpu process
- // may have been killed). The caller should normally
- // make another request to establish a new channel.
- SUCCESS
- };
- using EstablishChannelCallback =
- base::Callback<void(mojo::ScopedMessagePipeHandle channel_handle,
- const gpu::GPUInfo&,
- const gpu::GpuFeatureInfo&,
- EstablishChannelStatus status)>;
-
- enum class BufferCreationStatus {
- GPU_HOST_INVALID,
- SUCCESS,
- };
- using CreateGpuMemoryBufferCallback =
- base::OnceCallback<void(gfx::GpuMemoryBufferHandle handle,
- BufferCreationStatus status)>;
-
- using RequestGPUInfoCallback = base::Callback<void(const gpu::GPUInfo&)>;
- using RequestHDRStatusCallback = base::RepeatingCallback<void(bool)>;
-
static int GetGpuCrashCount();
// Creates a new GpuProcessHost (if |force_create| is turned on) or gets an
@@ -119,52 +85,21 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
bool force_create,
const base::Callback<void(GpuProcessHost*)>& callback);
- static void InitFontRenderParamsOnIO(const gfx::FontRenderParams& params);
-
void BindInterface(const std::string& interface_name,
mojo::ScopedMessagePipeHandle interface_pipe);
+ void TerminateGpuProcess(const std::string& message);
// Get the GPU process host for the GPU process with the given ID. Returns
// null if the process no longer exists.
static GpuProcessHost* FromID(int host_id);
int host_id() const { return host_id_; }
+ base::ProcessId process_id() const { return process_id_; }
// IPC::Sender implementation.
bool Send(IPC::Message* msg) override;
- // Tells the GPU process to create a new channel for communication with a
- // client. Once the GPU process responds asynchronously with the IPC handle
- // and GPUInfo, we call the callback.
- void EstablishGpuChannel(int client_id,
- uint64_t client_tracing_id,
- bool preempts,
- bool allow_view_command_buffers,
- bool allow_real_time_streams,
- const EstablishChannelCallback& callback);
-
- // Tells the GPU process to create a new GPU memory buffer.
- void CreateGpuMemoryBuffer(gfx::GpuMemoryBufferId id,
- const gfx::Size& size,
- gfx::BufferFormat format,
- gfx::BufferUsage usage,
- int client_id,
- gpu::SurfaceHandle surface_handle,
- CreateGpuMemoryBufferCallback callback);
-
- // Tells the GPU process to destroy GPU memory buffer.
- void DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferId id,
- int client_id,
- const gpu::SyncToken& sync_token);
-
- // Connects to FrameSinkManager running in the viz process. In this
- // configuration the display compositor runs in the viz process and the
- // browser must submit CompositorFrames over IPC.
- void ConnectFrameSinkManager(
- viz::mojom::FrameSinkManagerRequest request,
- viz::mojom::FrameSinkManagerClientPtrInfo client);
-
- void RequestGPUInfo(RequestGPUInfoCallback request_cb);
- void RequestHDRStatus(RequestHDRStatusCallback request_cb);
+ // Adds a connection error handler for the GpuService.
+ void AddConnectionErrorHandler(base::OnceClosure handler);
// What kind of GPU process, e.g. sandboxed or unsandboxed.
GpuProcessKind kind();
@@ -172,20 +107,20 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
// Forcefully terminates the GPU process.
void ForceShutdown();
- void LoadedShader(const std::string& key, const std::string& data);
-
CONTENT_EXPORT viz::mojom::GpuService* gpu_service();
- bool wake_up_gpu_before_drawing() const {
- return wake_up_gpu_before_drawing_;
- }
-
CONTENT_EXPORT int GetIDForTesting() const;
+ viz::GpuHostImpl* gpu_host() { return gpu_host_.get(); }
+
private:
class ConnectionFilterImpl;
- enum GpuInitializationStatus { UNKNOWN, SUCCESS, FAILURE };
+ enum class GpuTerminationOrigin {
+ kUnknownOrigin = 0,
+ kOzoneWaylandProxy = 1,
+ kMax = 2,
+ };
static bool ValidateHost(GpuProcessHost* host);
@@ -210,8 +145,10 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
void OnProcessLaunchFailed(int error_code) override;
void OnProcessCrashed(int exit_code) override;
- // viz::mojom::GpuHost:
- void DidInitialize(
+ // viz::GpuHostImpl::Delegate:
+ gpu::GPUInfo GetGPUInfo() const override;
+ gpu::GpuFeatureInfo GetGpuFeatureInfo() const override;
+ void UpdateGpuInfo(
const gpu::GPUInfo& gpu_info,
const gpu::GpuFeatureInfo& gpu_feature_info,
const base::Optional<gpu::GPUInfo>& gpu_info_for_hardware_gpu,
@@ -219,26 +156,17 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
gpu_feature_info_for_hardware_gpu) override;
void DidFailInitialize() override;
void DidCreateContextSuccessfully() override;
- void DidCreateOffscreenContext(const GURL& url) override;
- void DidDestroyOffscreenContext(const GURL& url) override;
- void DidDestroyChannel(int32_t client_id) override;
- void DidLoseContext(bool offscreen,
- gpu::error::ContextLostReason reason,
- const GURL& active_url) override;
+ void BlockDomainFrom3DAPIs(const GURL& url,
+ Delegate::DomainGuilt guilt) override;
void DisableGpuCompositing() override;
- void SetChildSurface(gpu::SurfaceHandle parent,
- gpu::SurfaceHandle child) override;
- void StoreShaderToDisk(int32_t client_id,
- const std::string& key,
- const std::string& shader) override;
+ bool GpuAccessAllowed() const override;
+ gpu::ShaderCacheFactory* GetShaderCacheFactory() override;
void RecordLogMessage(int32_t severity,
const std::string& header,
const std::string& message) override;
-
- void OnChannelEstablished(int client_id,
- const EstablishChannelCallback& callback,
- mojo::ScopedMessagePipeHandle channel_handle);
- void OnGpuMemoryBufferCreated(gfx::GpuMemoryBufferHandle handle);
+ void BindDiscardableMemoryRequest(
+ discardable_memory::mojom::DiscardableSharedMemoryManagerRequest request)
+ override;
// Message handlers.
#if defined(OS_ANDROID)
@@ -246,36 +174,27 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
#endif
void OnFieldTrialActivated(const std::string& trial_name);
- void CreateChannelCache(int32_t client_id);
-
bool LaunchGpuProcess();
- void SendOutstandingReplies(EstablishChannelStatus failure_status);
-
- void RunRequestGPUInfoCallbacks(const gpu::GPUInfo& gpu_info);
+ void SendOutstandingReplies();
void BlockLiveOffscreenContexts();
// Update GPU crash counters. Disable GPU if crash limit is reached.
void RecordProcessCrash();
- std::string GetShaderPrefixKey();
-
// The serial number of the GpuProcessHost / GpuProcessHostUIShim pair.
int host_id_;
- // These are the channel requests that we have already sent to
- // the GPU process, but haven't heard back about yet.
- base::queue<EstablishChannelCallback> channel_requests_;
+ // GPU process id in case GPU is not in-process.
+ base::ProcessId process_id_ = base::kNullProcessId;
- // The pending create gpu memory buffer requests we need to reply to.
- base::queue<CreateGpuMemoryBufferCallback> create_gpu_memory_buffer_requests_;
+ // List of connection error handlers for the GpuService.
+ std::vector<base::OnceClosure> connection_error_handlers_;
// A callback to signal the completion of a SendDestroyingVideoSurface call.
base::Closure send_destroying_video_surface_done_cb_;
- std::vector<RequestGPUInfoCallback> request_gpu_info_callbacks_;
-
// Qeueud messages to send when the process launches.
base::queue<IPC::Message*> queued_messages_;
@@ -293,7 +212,8 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
// Whether we actually launched a GPU process.
bool process_launched_;
- GpuInitializationStatus status_;
+ GpuTerminationOrigin termination_origin_ =
+ GpuTerminationOrigin::kUnknownOrigin;
// Time Init started. Used to log total GPU process startup time to UMA.
base::TimeTicks init_start_time_;
@@ -323,22 +243,7 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
// automatic execution of 3D content from those domains.
std::multiset<GURL> urls_with_live_offscreen_contexts_;
- typedef std::map<int32_t, scoped_refptr<gpu::ShaderDiskCache>>
- ClientIdToShaderCacheMap;
- ClientIdToShaderCacheMap client_id_to_shader_cache_;
-
- std::string shader_prefix_key_;
-
- // The following are a list of driver bug workarounds that will only be
- // set to true in DidInitialize(), where GPU process has started and GPU
- // driver bug workarounds have been computed and sent back.
- bool wake_up_gpu_before_drawing_ = false;
- bool dont_disable_webgl_when_compositor_context_lost_ = false;
-
- viz::mojom::VizMainAssociatedPtr gpu_main_ptr_;
- viz::mojom::GpuServicePtr gpu_service_ptr_;
- mojo::Binding<viz::mojom::GpuHost> gpu_host_binding_;
- gpu::GpuProcessHostActivityFlags activity_flags_;
+ std::unique_ptr<viz::GpuHostImpl> gpu_host_;
SEQUENCE_CHECKER(sequence_checker_);
diff --git a/chromium/content/browser/histogram_controller.cc b/chromium/content/browser/histogram_controller.cc
index 100d8863f89..7d1c1108bb7 100644
--- a/chromium/content/browser/histogram_controller.cc
+++ b/chromium/content/browser/histogram_controller.cc
@@ -153,7 +153,7 @@ void HistogramController::GetHistogramDataFromChildProcesses(
// example, the GPU process may not exist and there may instead just be a
// GPU thread in the browser process). If that's the case, then the process
// handle will be base::kNullProcessHandle and we shouldn't ask it for data.
- if (data.handle == base::kNullProcessHandle)
+ if (!data.IsHandleValid())
continue;
if (auto* child_histogram_fetcher =
diff --git a/chromium/content/browser/hyphenation/hyphenation_impl.cc b/chromium/content/browser/hyphenation/hyphenation_impl.cc
index ab21104f132..8d2cb168722 100644
--- a/chromium/content/browser/hyphenation/hyphenation_impl.cc
+++ b/chromium/content/browser/hyphenation/hyphenation_impl.cc
@@ -13,7 +13,7 @@
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "base/timer/elapsed_timer.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
diff --git a/chromium/content/browser/indexed_db/OWNERS b/chromium/content/browser/indexed_db/OWNERS
index 5a42cf0e75b..2d25ec207c3 100644
--- a/chromium/content/browser/indexed_db/OWNERS
+++ b/chromium/content/browser/indexed_db/OWNERS
@@ -1,6 +1,7 @@
jsbell@chromium.org
cmumford@chromium.org
dmurph@chromium.org
+pwnall@chromium.org
# TEAM: storage-dev@chromium.org
# COMPONENT: Blink>Storage>IndexedDB
diff --git a/chromium/content/browser/indexed_db/cursor_impl.cc b/chromium/content/browser/indexed_db/cursor_impl.cc
index 6506a21219b..536d59b22cb 100644
--- a/chromium/content/browser/indexed_db/cursor_impl.cc
+++ b/chromium/content/browser/indexed_db/cursor_impl.cc
@@ -9,6 +9,8 @@
#include "content/browser/indexed_db/indexed_db_cursor.h"
#include "content/browser/indexed_db/indexed_db_dispatcher_host.h"
+using blink::IndexedDBKey;
+
namespace content {
// Expected to be constructed on IO thread, and used/destroyed on IDB sequence.
@@ -45,7 +47,7 @@ CursorImpl::~CursorImpl() {
void CursorImpl::Advance(
uint32_t count,
- ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks_info) {
+ blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks_info) {
scoped_refptr<IndexedDBCallbacks> callbacks(
new IndexedDBCallbacks(dispatcher_host_->AsWeakPtr(), origin_,
std::move(callbacks_info), idb_runner_));
@@ -54,10 +56,10 @@ void CursorImpl::Advance(
count, std::move(callbacks)));
}
-void CursorImpl::Continue(
+void CursorImpl::CursorContinue(
const IndexedDBKey& key,
const IndexedDBKey& primary_key,
- ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks_info) {
+ blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks_info) {
scoped_refptr<IndexedDBCallbacks> callbacks(
new IndexedDBCallbacks(dispatcher_host_->AsWeakPtr(), origin_,
std::move(callbacks_info), idb_runner_));
@@ -69,7 +71,7 @@ void CursorImpl::Continue(
void CursorImpl::Prefetch(
int32_t count,
- ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks_info) {
+ blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks_info) {
scoped_refptr<IndexedDBCallbacks> callbacks(
new IndexedDBCallbacks(dispatcher_host_->AsWeakPtr(), origin_,
std::move(callbacks_info), idb_runner_));
diff --git a/chromium/content/browser/indexed_db/cursor_impl.h b/chromium/content/browser/indexed_db/cursor_impl.h
index 99f831d0a57..bb661af379b 100644
--- a/chromium/content/browser/indexed_db/cursor_impl.h
+++ b/chromium/content/browser/indexed_db/cursor_impl.h
@@ -8,7 +8,8 @@
#include <memory>
#include "base/memory/ref_counted.h"
-#include "content/common/indexed_db/indexed_db.mojom.h"
+#include "third_party/blink/public/common/indexeddb/indexeddb_key.h"
+#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h"
namespace base {
class SequencedTaskRunner;
@@ -18,10 +19,9 @@ namespace content {
class IndexedDBCursor;
class IndexedDBDispatcherHost;
-class IndexedDBKey;
// Expected to be constructed, called, and destructed on the IO thread.
-class CursorImpl : public ::indexed_db::mojom::Cursor {
+class CursorImpl : public blink::mojom::IDBCursor {
public:
CursorImpl(std::unique_ptr<IndexedDBCursor> cursor,
const url::Origin& origin,
@@ -29,17 +29,15 @@ class CursorImpl : public ::indexed_db::mojom::Cursor {
scoped_refptr<base::SequencedTaskRunner> idb_runner);
~CursorImpl() override;
- // ::indexed_db::mojom::Cursor implementation
- void Advance(
- uint32_t count,
- ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks) override;
- void Continue(
- const IndexedDBKey& key,
- const IndexedDBKey& primary_key,
- ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks) override;
- void Prefetch(
- int32_t count,
- ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks) override;
+ // blink::mojom::IDBCursor implementation
+ void Advance(uint32_t count,
+ blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks) override;
+ void CursorContinue(
+ const blink::IndexedDBKey& key,
+ const blink::IndexedDBKey& primary_key,
+ blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks) override;
+ void Prefetch(int32_t count,
+ blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks) override;
void PrefetchReset(int32_t used_prefetches,
int32_t unused_prefetches) override;
diff --git a/chromium/content/browser/indexed_db/database_impl.cc b/chromium/content/browser/indexed_db/database_impl.cc
index 9c305053f7d..20acdb148b9 100644
--- a/chromium/content/browser/indexed_db/database_impl.cc
+++ b/chromium/content/browser/indexed_db/database_impl.cc
@@ -21,8 +21,16 @@
#include "third_party/blink/public/mojom/quota/quota_types.mojom.h"
#include "third_party/blink/public/platform/modules/indexeddb/web_idb_database_exception.h"
+using blink::IndexedDBIndexKeys;
+using blink::IndexedDBKey;
+using blink::IndexedDBKeyPath;
+using blink::IndexedDBKeyRange;
using std::swap;
+namespace blink {
+class IndexedDBKeyRange;
+}
+
namespace content {
class IndexedDBDatabaseError;
@@ -77,8 +85,7 @@ class DatabaseImpl::IDBSequenceHelper {
scoped_refptr<IndexedDBCallbacks> callbacks);
void Put(int64_t transaction_id,
int64_t object_store_id,
- ::indexed_db::mojom::ValuePtr value,
- std::vector<std::unique_ptr<storage::BlobDataHandle>> handles,
+ blink::mojom::IDBValuePtr value,
std::vector<IndexedDBBlobInfo> blob_info,
const IndexedDBKey& key,
blink::WebIDBPutMode mode,
@@ -237,7 +244,7 @@ void DatabaseImpl::Get(
int64_t index_id,
const IndexedDBKeyRange& key_range,
bool key_only,
- ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks_info) {
+ blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks_info) {
scoped_refptr<IndexedDBCallbacks> callbacks(
new IndexedDBCallbacks(dispatcher_host_->AsWeakPtr(), origin_,
std::move(callbacks_info), idb_runner_));
@@ -255,7 +262,7 @@ void DatabaseImpl::GetAll(
const IndexedDBKeyRange& key_range,
bool key_only,
int64_t max_count,
- ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks_info) {
+ blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks_info) {
scoped_refptr<IndexedDBCallbacks> callbacks(
new IndexedDBCallbacks(dispatcher_host_->AsWeakPtr(), origin_,
std::move(callbacks_info), idb_runner_));
@@ -269,11 +276,11 @@ void DatabaseImpl::GetAll(
void DatabaseImpl::Put(
int64_t transaction_id,
int64_t object_store_id,
- ::indexed_db::mojom::ValuePtr value,
+ blink::mojom::IDBValuePtr value,
const IndexedDBKey& key,
blink::WebIDBPutMode mode,
const std::vector<IndexedDBIndexKeys>& index_keys,
- ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks_info) {
+ blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks_info) {
ChildProcessSecurityPolicyImpl* policy =
ChildProcessSecurityPolicyImpl::GetInstance();
@@ -281,12 +288,10 @@ void DatabaseImpl::Put(
new IndexedDBCallbacks(dispatcher_host_->AsWeakPtr(), origin_,
std::move(callbacks_info), idb_runner_));
- std::vector<std::unique_ptr<storage::BlobDataHandle>> handles(
- value->blob_or_file_info.size());
base::CheckedNumeric<uint64_t> total_blob_size = 0;
std::vector<IndexedDBBlobInfo> blob_info(value->blob_or_file_info.size());
for (size_t i = 0; i < value->blob_or_file_info.size(); ++i) {
- ::indexed_db::mojom::BlobInfoPtr& info = value->blob_or_file_info[i];
+ blink::mojom::IDBBlobInfoPtr& info = value->blob_or_file_info[i];
std::unique_ptr<storage::BlobDataHandle> handle =
dispatcher_host_->blob_storage_context()->GetBlobDataFromUUID(
@@ -309,7 +314,6 @@ void DatabaseImpl::Put(
uint64_t size = handle->size();
UMA_HISTOGRAM_MEMORY_KB("Storage.IndexedDB.PutBlobSizeKB", size / 1024ull);
total_blob_size += size;
- handles[i] = std::move(handle);
if (info->file) {
if (!info->file->path.empty() &&
@@ -318,14 +322,15 @@ void DatabaseImpl::Put(
mojo::ReportBadMessage(kInvalidBlobFilePath);
return;
}
- blob_info[i] = IndexedDBBlobInfo(info->uuid, info->file->path,
+ blob_info[i] = IndexedDBBlobInfo(std::move(handle), info->file->path,
info->file->name, info->mime_type);
if (info->size != -1) {
blob_info[i].set_last_modified(info->file->last_modified);
blob_info[i].set_size(info->size);
}
} else {
- blob_info[i] = IndexedDBBlobInfo(info->uuid, info->mime_type, info->size);
+ blob_info[i] =
+ IndexedDBBlobInfo(std::move(handle), info->mime_type, info->size);
}
}
UMA_HISTOGRAM_COUNTS_1000("WebCore.IndexedDB.PutBlobsCount",
@@ -340,8 +345,8 @@ void DatabaseImpl::Put(
FROM_HERE,
base::BindOnce(&IDBSequenceHelper::Put, base::Unretained(helper_),
transaction_id, object_store_id, std::move(value),
- std::move(handles), std::move(blob_info), key, mode,
- index_keys, std::move(callbacks)));
+ std::move(blob_info), key, mode, index_keys,
+ std::move(callbacks)));
}
void DatabaseImpl::SetIndexKeys(
@@ -372,7 +377,7 @@ void DatabaseImpl::OpenCursor(
blink::WebIDBCursorDirection direction,
bool key_only,
blink::WebIDBTaskType task_type,
- ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks_info) {
+ blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks_info) {
scoped_refptr<IndexedDBCallbacks> callbacks(
new IndexedDBCallbacks(dispatcher_host_->AsWeakPtr(), origin_,
std::move(callbacks_info), idb_runner_));
@@ -388,7 +393,7 @@ void DatabaseImpl::Count(
int64_t object_store_id,
int64_t index_id,
const IndexedDBKeyRange& key_range,
- ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks_info) {
+ blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks_info) {
scoped_refptr<IndexedDBCallbacks> callbacks(
new IndexedDBCallbacks(dispatcher_host_->AsWeakPtr(), origin_,
std::move(callbacks_info), idb_runner_));
@@ -403,7 +408,7 @@ void DatabaseImpl::DeleteRange(
int64_t transaction_id,
int64_t object_store_id,
const IndexedDBKeyRange& key_range,
- ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks_info) {
+ blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks_info) {
scoped_refptr<IndexedDBCallbacks> callbacks(
new IndexedDBCallbacks(dispatcher_host_->AsWeakPtr(), origin_,
std::move(callbacks_info), idb_runner_));
@@ -417,7 +422,7 @@ void DatabaseImpl::DeleteRange(
void DatabaseImpl::Clear(
int64_t transaction_id,
int64_t object_store_id,
- ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks_info) {
+ blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks_info) {
scoped_refptr<IndexedDBCallbacks> callbacks(
new IndexedDBCallbacks(dispatcher_host_->AsWeakPtr(), origin_,
std::move(callbacks_info), idb_runner_));
@@ -656,8 +661,7 @@ void DatabaseImpl::IDBSequenceHelper::GetAll(
void DatabaseImpl::IDBSequenceHelper::Put(
int64_t transaction_id,
int64_t object_store_id,
- ::indexed_db::mojom::ValuePtr mojo_value,
- std::vector<std::unique_ptr<storage::BlobDataHandle>> handles,
+ blink::mojom::IDBValuePtr mojo_value,
std::vector<IndexedDBBlobInfo> blob_info,
const IndexedDBKey& key,
blink::WebIDBPutMode mode,
@@ -681,7 +685,7 @@ void DatabaseImpl::IDBSequenceHelper::Put(
IndexedDBValue value;
swap(value.bits, mojo_value->bits);
swap(value.blob_info, blob_info);
- connection_->database()->Put(transaction, object_store_id, &value, &handles,
+ connection_->database()->Put(transaction, object_store_id, &value,
std::make_unique<IndexedDBKey>(key), mode,
std::move(callbacks), index_keys);
diff --git a/chromium/content/browser/indexed_db/database_impl.h b/chromium/content/browser/indexed_db/database_impl.h
index f0030a604db..2839306e34c 100644
--- a/chromium/content/browser/indexed_db/database_impl.h
+++ b/chromium/content/browser/indexed_db/database_impl.h
@@ -7,19 +7,27 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "content/common/indexed_db/indexed_db.mojom.h"
+#include "third_party/blink/public/common/indexeddb/indexeddb_key.h"
+#include "third_party/blink/public/common/indexeddb/indexeddb_key_path.h"
+#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h"
+
+using blink::IndexedDBKeyRange;
namespace base {
class SequencedTaskRunner;
}
+namespace blink {
+class IndexedDBKeyRange;
+}
+
namespace content {
class IndexedDBConnection;
class IndexedDBDispatcherHost;
// Expected to be constructed, called, and destructed on the IO thread.
-class DatabaseImpl : public ::indexed_db::mojom::Database {
+class DatabaseImpl : public blink::mojom::IDBDatabase {
public:
explicit DatabaseImpl(std::unique_ptr<IndexedDBConnection> connection,
const url::Origin& origin,
@@ -27,11 +35,11 @@ class DatabaseImpl : public ::indexed_db::mojom::Database {
scoped_refptr<base::SequencedTaskRunner> idb_runner);
~DatabaseImpl() override;
- // ::indexed_db::mojom::Database implementation
+ // blink::mojom::IDBDatabase implementation
void CreateObjectStore(int64_t transaction_id,
int64_t object_store_id,
const base::string16& name,
- const IndexedDBKeyPath& key_path,
+ const blink::IndexedDBKeyPath& key_path,
bool auto_increment) override;
void DeleteObjectStore(int64_t transaction_id,
int64_t object_store_id) override;
@@ -55,26 +63,26 @@ class DatabaseImpl : public ::indexed_db::mojom::Database {
int64_t index_id,
const IndexedDBKeyRange& key_range,
bool key_only,
- ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks) override;
- void 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,
- ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks) override;
+ blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks) override;
+ void 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) override;
void Put(int64_t transaction_id,
int64_t object_store_id,
- ::indexed_db::mojom::ValuePtr value,
- const IndexedDBKey& key,
+ blink::mojom::IDBValuePtr value,
+ const blink::IndexedDBKey& key,
blink::WebIDBPutMode mode,
- const std::vector<IndexedDBIndexKeys>& index_keys,
- ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks) override;
- void SetIndexKeys(int64_t transaction_id,
- int64_t object_store_id,
- const IndexedDBKey& primary_key,
- const std::vector<IndexedDBIndexKeys>& index_keys) override;
+ const std::vector<blink::IndexedDBIndexKeys>& index_keys,
+ blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks) override;
+ void SetIndexKeys(
+ int64_t transaction_id,
+ int64_t object_store_id,
+ const blink::IndexedDBKey& primary_key,
+ const std::vector<blink::IndexedDBIndexKeys>& index_keys) override;
void SetIndexesReady(int64_t transaction_id,
int64_t object_store_id,
const std::vector<int64_t>& index_ids) override;
@@ -86,27 +94,25 @@ class DatabaseImpl : public ::indexed_db::mojom::Database {
blink::WebIDBCursorDirection direction,
bool key_only,
blink::WebIDBTaskType task_type,
- ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks_info) override;
- void Count(
- int64_t transaction_id,
- int64_t object_store_id,
- int64_t index_id,
- const IndexedDBKeyRange& key_range,
- ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks) override;
+ blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks_info) override;
+ void Count(int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id,
+ const IndexedDBKeyRange& key_range,
+ blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks) override;
void DeleteRange(
int64_t transaction_id,
int64_t object_store_id,
const IndexedDBKeyRange& key_range,
- ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks) override;
- void Clear(
- int64_t transaction_id,
- int64_t object_store_id,
- ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks) override;
+ blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks) override;
+ void Clear(int64_t transaction_id,
+ int64_t object_store_id,
+ blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks) override;
void CreateIndex(int64_t transaction_id,
int64_t object_store_id,
int64_t index_id,
const base::string16& name,
- const IndexedDBKeyPath& key_path,
+ const blink::IndexedDBKeyPath& key_path,
bool unique,
bool multi_entry) override;
void DeleteIndex(int64_t transaction_id,
diff --git a/chromium/content/browser/indexed_db/fake_indexed_db_metadata_coding.cc b/chromium/content/browser/indexed_db/fake_indexed_db_metadata_coding.cc
index 85d68f6f9d3..f96c3311593 100644
--- a/chromium/content/browser/indexed_db/fake_indexed_db_metadata_coding.cc
+++ b/chromium/content/browser/indexed_db/fake_indexed_db_metadata_coding.cc
@@ -3,9 +3,12 @@
// found in the LICENSE file.
#include "content/browser/indexed_db/fake_indexed_db_metadata_coding.h"
-#include "content/common/indexed_db/indexed_db_key_path.h"
-#include "content/common/indexed_db/indexed_db_metadata.h"
+#include "third_party/blink/public/common/indexeddb/indexeddb_key_path.h"
+#include "third_party/blink/public/common/indexeddb/indexeddb_metadata.h"
+using blink::IndexedDBDatabaseMetadata;
+using blink::IndexedDBIndexMetadata;
+using blink::IndexedDBObjectStoreMetadata;
using leveldb::Status;
namespace content {
@@ -62,7 +65,7 @@ leveldb::Status FakeIndexedDBMetadataCoding::CreateObjectStore(
int64_t database_id,
int64_t object_store_id,
base::string16 name,
- IndexedDBKeyPath key_path,
+ blink::IndexedDBKeyPath key_path,
bool auto_increment,
IndexedDBObjectStoreMetadata* metadata) {
metadata->name = std::move(name);
@@ -97,7 +100,7 @@ leveldb::Status FakeIndexedDBMetadataCoding::CreateIndex(
int64_t object_store_id,
int64_t index_id,
base::string16 name,
- IndexedDBKeyPath key_path,
+ blink::IndexedDBKeyPath key_path,
bool is_unique,
bool is_multi_entry,
IndexedDBIndexMetadata* metadata) {
diff --git a/chromium/content/browser/indexed_db/fake_indexed_db_metadata_coding.h b/chromium/content/browser/indexed_db/fake_indexed_db_metadata_coding.h
index 5129fc0f0b8..86033fe4c68 100644
--- a/chromium/content/browser/indexed_db/fake_indexed_db_metadata_coding.h
+++ b/chromium/content/browser/indexed_db/fake_indexed_db_metadata_coding.h
@@ -13,15 +13,18 @@
#include "base/macros.h"
#include "base/strings/string16.h"
#include "content/browser/indexed_db/indexed_db_metadata_coding.h"
-#include "content/common/indexed_db/indexed_db_key_path.h"
+#include "third_party/blink/public/common/indexeddb/indexeddb_key_path.h"
#include "third_party/leveldatabase/src/include/leveldb/status.h"
+namespace blink {
+struct IndexedDBDatabaseMetadata;
+struct IndexedDBIndexMetadata;
+struct IndexedDBObjectStoreMetadata;
+} // namespace blink
+
namespace content {
class LevelDBDatabase;
class LevelDBTransaction;
-struct IndexedDBDatabaseMetadata;
-struct IndexedDBObjectStoreMetadata;
-struct IndexedDBIndexMetadata;
// A fake implementation of IndexedDBMetadataCoding, for testing.
class FakeIndexedDBMetadataCoding : public IndexedDBMetadataCoding {
@@ -38,18 +41,19 @@ class FakeIndexedDBMetadataCoding : public IndexedDBMetadataCoding {
LevelDBDatabase* db,
const std::string& origin_identifier,
const base::string16& name,
- IndexedDBDatabaseMetadata* metadata,
+ blink::IndexedDBDatabaseMetadata* metadata,
bool* found) override;
- leveldb::Status CreateDatabase(LevelDBDatabase* database,
- const std::string& origin_identifier,
- const base::string16& name,
- int64_t version,
- IndexedDBDatabaseMetadata* metadata) override;
+ leveldb::Status CreateDatabase(
+ LevelDBDatabase* database,
+ const std::string& origin_identifier,
+ const base::string16& name,
+ int64_t version,
+ blink::IndexedDBDatabaseMetadata* metadata) override;
void SetDatabaseVersion(LevelDBTransaction* transaction,
int64_t row_id,
int64_t version,
- IndexedDBDatabaseMetadata* metadata) override;
+ blink::IndexedDBDatabaseMetadata* metadata) override;
leveldb::Status FindDatabaseId(LevelDBDatabase* db,
const std::string& origin_identifier,
@@ -62,43 +66,44 @@ class FakeIndexedDBMetadataCoding : public IndexedDBMetadataCoding {
int64_t database_id,
int64_t object_store_id,
base::string16 name,
- IndexedDBKeyPath key_path,
+ blink::IndexedDBKeyPath key_path,
bool auto_increment,
- IndexedDBObjectStoreMetadata* metadata) override;
+ blink::IndexedDBObjectStoreMetadata* metadata) override;
leveldb::Status RenameObjectStore(
LevelDBTransaction* transaction,
int64_t database_id,
base::string16 new_name,
base::string16* old_name,
- IndexedDBObjectStoreMetadata* metadata) override;
+ blink::IndexedDBObjectStoreMetadata* metadata) override;
leveldb::Status DeleteObjectStore(
LevelDBTransaction* transaction,
int64_t database_id,
- const IndexedDBObjectStoreMetadata& object_store) override;
+ const blink::IndexedDBObjectStoreMetadata& object_store) override;
leveldb::Status CreateIndex(LevelDBTransaction* transaction,
int64_t database_id,
int64_t object_store_id,
int64_t index_id,
base::string16 name,
- IndexedDBKeyPath key_path,
+ blink::IndexedDBKeyPath key_path,
bool is_unique,
bool is_multi_entry,
- IndexedDBIndexMetadata* metadata) override;
+ blink::IndexedDBIndexMetadata* metadata) override;
leveldb::Status RenameIndex(LevelDBTransaction* transaction,
int64_t database_id,
int64_t object_store_id,
base::string16 new_name,
base::string16* old_name,
- IndexedDBIndexMetadata* metadata) override;
+ blink::IndexedDBIndexMetadata* metadata) override;
- leveldb::Status DeleteIndex(LevelDBTransaction* transaction,
- int64_t database_id,
- int64_t object_store_id,
- const IndexedDBIndexMetadata& metadata) override;
+ leveldb::Status DeleteIndex(
+ LevelDBTransaction* transaction,
+ int64_t database_id,
+ int64_t object_store_id,
+ const blink::IndexedDBIndexMetadata& metadata) override;
private:
DISALLOW_COPY_AND_ASSIGN(FakeIndexedDBMetadataCoding);
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 8dc3131ee8a..01c03fae5ce 100644
--- a/chromium/content/browser/indexed_db/indexed_db_backing_store.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_backing_store.cc
@@ -38,9 +38,6 @@
#include "content/browser/indexed_db/leveldb/leveldb_factory.h"
#include "content/browser/indexed_db/leveldb/leveldb_iterator.h"
#include "content/browser/indexed_db/leveldb/leveldb_transaction.h"
-#include "content/common/indexed_db/indexed_db_key.h"
-#include "content/common/indexed_db/indexed_db_key_path.h"
-#include "content/common/indexed_db/indexed_db_key_range.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_features.h"
#include "net/base/load_flags.h"
@@ -52,11 +49,15 @@
#include "storage/browser/fileapi/local_file_stream_writer.h"
#include "storage/common/database/database_identifier.h"
#include "storage/common/fileapi/file_system_mount_option.h"
-#include "third_party/blink/public/platform/modules/indexeddb/web_idb_types.h"
+#include "third_party/blink/public/common/indexeddb/indexeddb_key_range.h"
+#include "third_party/blink/public/common/indexeddb/web_idb_types.h"
#include "third_party/leveldatabase/env_chromium.h"
using base::FilePath;
using base::StringPiece;
+using blink::IndexedDBDatabaseMetadata;
+using blink::IndexedDBKey;
+using blink::IndexedDBKeyRange;
using leveldb::Status;
using storage::FileWriterDelegate;
using url::Origin;
@@ -366,10 +367,6 @@ bool IsPathTooLong(const FilePath& leveldb_dir) {
return false;
}
-GURL GetURLFromUUID(const std::string& uuid) {
- return GURL("blob:uuid/" + uuid);
-}
-
Status DeleteBlobsInRange(IndexedDBBackingStore::Transaction* transaction,
int64_t database_id,
int64_t object_store_id,
@@ -390,8 +387,7 @@ Status DeleteBlobsInRange(IndexedDBBackingStore::Transaction* transaction,
INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_IDBDATABASE_METADATA);
return InternalInconsistencyStatus();
}
- transaction->PutBlobInfo(database_id, object_store_id, user_key, nullptr,
- nullptr);
+ transaction->PutBlobInfo(database_id, object_store_id, user_key, nullptr);
}
return s;
}
@@ -693,6 +689,19 @@ Status IndexedDBBackingStore::AnyDatabaseContainsBlobs(
return Status::OK();
}
+Status IndexedDBBackingStore::RevertSchemaToV2() {
+ DCHECK(task_runner_->RunsTasksInCurrentSequence());
+ const std::string schema_version_key = SchemaVersionKey::Encode();
+ scoped_refptr<LevelDBTransaction> transaction =
+ IndexedDBClassFactory::Get()->CreateLevelDBTransaction(db_.get());
+
+ PutInt(transaction.get(), schema_version_key, 2);
+ Status s = transaction->Commit();
+ if (!s.ok())
+ INTERNAL_WRITE_ERROR_UNTESTED(REVERT_SCHEMA_TO_V2);
+ return s;
+}
+
WARN_UNUSED_RESULT Status IndexedDBBackingStore::SetUpMetadata() {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
@@ -1288,7 +1297,6 @@ Status IndexedDBBackingStore::PutRecord(
int64_t object_store_id,
const IndexedDBKey& key,
IndexedDBValue* value,
- std::vector<std::unique_ptr<storage::BlobDataHandle>>* handles,
RecordIdentifier* record_identifier) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
@@ -1312,14 +1320,10 @@ Status IndexedDBBackingStore::PutRecord(
v.append(value->bits);
leveldb_transaction->Put(object_store_data_key, &v);
- s = transaction->PutBlobInfoIfNeeded(database_id,
- object_store_id,
- object_store_data_key,
- &value->blob_info,
- handles);
+ s = transaction->PutBlobInfoIfNeeded(
+ database_id, object_store_id, object_store_data_key, &value->blob_info);
if (!s.ok())
return s;
- DCHECK(handles->empty());
const std::string exists_entry_key =
ExistsEntryKey::Encode(database_id, object_store_id, key);
@@ -1369,8 +1373,8 @@ Status IndexedDBBackingStore::DeleteRecord(
const std::string object_store_data_key = ObjectStoreDataKey::Encode(
database_id, object_store_id, record_identifier.primary_key());
leveldb_transaction->Remove(object_store_data_key);
- Status s = transaction->PutBlobInfoIfNeeded(
- database_id, object_store_id, object_store_data_key, nullptr, nullptr);
+ Status s = transaction->PutBlobInfoIfNeeded(database_id, object_store_id,
+ object_store_data_key, nullptr);
if (!s.ok())
return s;
@@ -1574,20 +1578,19 @@ class IndexedDBBackingStore::Transaction::ChainedBlobWriterImpl
public:
typedef IndexedDBBackingStore::Transaction::WriteDescriptorVec
WriteDescriptorVec;
- ChainedBlobWriterImpl(
+ static scoped_refptr<ChainedBlobWriterImpl> Create(
int64_t database_id,
IndexedDBBackingStore* backing_store,
WriteDescriptorVec* blobs,
- scoped_refptr<IndexedDBBackingStore::BlobWriteCallback> callback)
- : waiting_for_callback_(false),
- database_id_(database_id),
- backing_store_(backing_store),
- callback_(callback),
- aborted_(false) {
- blobs_.swap(*blobs);
- iter_ = blobs_.begin();
+ scoped_refptr<IndexedDBBackingStore::BlobWriteCallback> callback) {
+ auto writer = base::WrapRefCounted(new ChainedBlobWriterImpl(
+ database_id, backing_store, std::move(callback)));
+ writer->blobs_.swap(*blobs);
+ writer->iter_ = writer->blobs_.begin();
backing_store->task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&ChainedBlobWriterImpl::WriteNextFile, this));
+ FROM_HERE,
+ base::BindOnce(&ChainedBlobWriterImpl::WriteNextFile, writer));
+ return writer;
}
void set_delegate(std::unique_ptr<FileWriterDelegate> delegate) override {
@@ -1623,6 +1626,15 @@ class IndexedDBBackingStore::Transaction::ChainedBlobWriterImpl
}
private:
+ ChainedBlobWriterImpl(
+ int64_t database_id,
+ IndexedDBBackingStore* backing_store,
+ scoped_refptr<IndexedDBBackingStore::BlobWriteCallback> callback)
+ : waiting_for_callback_(false),
+ database_id_(database_id),
+ backing_store_(backing_store),
+ callback_(callback),
+ aborted_(false) {}
~ChainedBlobWriterImpl() override {}
void WriteNextFile() {
@@ -1702,11 +1714,9 @@ class LocalWriteClosure : public FileWriterDelegate::DelegateWriteCallback,
}
}
- void WriteBlobToFileOnIOThread(
- const FilePath& file_path,
- const GURL& blob_url,
- const base::Time& last_modified,
- scoped_refptr<net::URLRequestContextGetter> request_context_getter) {
+ void WriteBlobToFileOnIOThread(const FilePath& file_path,
+ std::unique_ptr<storage::BlobDataHandle> blob,
+ const base::Time& last_modified) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
std::unique_ptr<storage::FileStreamWriter> writer(
storage::FileStreamWriter::CreateForLocalFile(
@@ -1716,43 +1726,11 @@ class LocalWriteClosure : public FileWriterDelegate::DelegateWriteCallback,
std::make_unique<FileWriterDelegate>(
std::move(writer), storage::FlushPolicy::FLUSH_ON_COMPLETION));
- DCHECK(blob_url.is_valid());
- net::URLRequestContext* request_context =
- request_context_getter->GetURLRequestContext();
- net::NetworkTrafficAnnotationTag traffic_annotation =
- net::DefineNetworkTrafficAnnotation("persist_blob_to_indexed_db", R"(
- semantics {
- sender: "Indexed DB"
- description:
- "A web page's script has created a Blob (or File) object (either "
- "directly via constructors, or by using file upload to a form, or "
- "via a fetch()). The script has then made a request to store data "
- "including the Blob via the Indexed DB API. As part of committing "
- "the database transaction, the content of the Blob is being copied "
- "into a file in the database's directory."
- trigger:
- "The script has made a request to store data including a Blob via "
- "the Indexed DB API."
- data:
- "A Blob or File object referenced by script, either created "
- "directly via constructors, or by using file upload to a form, or "
- "drag/drop, or via a fetch() or other APIs that produce Blobs."
- destination: LOCAL
- }
- policy {
- cookies_allowed: NO
- setting: "This feature cannot be disabled by settings."
- policy_exception_justification: "Not implemented."
- })");
- std::unique_ptr<net::URLRequest> blob_request(
- request_context->CreateRequest(blob_url, net::DEFAULT_PRIORITY,
- delegate.get(), traffic_annotation));
- blob_request->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES |
- net::LOAD_DO_NOT_SEND_COOKIES);
+ DCHECK(blob);
this->file_path_ = file_path;
this->last_modified_ = last_modified;
- delegate->Start(std::move(blob_request),
+ delegate->Start(blob->CreateReader(),
base::Bind(&LocalWriteClosure::Run, this));
chained_blob_writer_->set_delegate(std::move(delegate));
}
@@ -1841,14 +1819,15 @@ bool IndexedDBBackingStore::WriteBlobFile(
base::BindOnce(&Transaction::ChainedBlobWriter::ReportWriteCompletion,
chained_blob_writer, true, info.size));
} else {
- DCHECK(descriptor.url().is_valid());
+ DCHECK(descriptor.blob());
scoped_refptr<LocalWriteClosure> write_closure(
new LocalWriteClosure(chained_blob_writer, task_runner_.get()));
content::BrowserThread::PostTask(
content::BrowserThread::IO, FROM_HERE,
- base::BindOnce(&LocalWriteClosure::WriteBlobToFileOnIOThread,
- write_closure, path, descriptor.url(),
- descriptor.last_modified(), request_context_getter_));
+ base::BindOnce(
+ &LocalWriteClosure::WriteBlobToFileOnIOThread, write_closure, path,
+ std::make_unique<storage::BlobDataHandle>(*descriptor.blob()),
+ descriptor.last_modified()));
}
return true;
}
@@ -3131,8 +3110,8 @@ Status IndexedDBBackingStore::Transaction::HandleBlobPreTransaction(
entry.last_modified()));
} else {
new_files_to_write->push_back(
- WriteDescriptor(GetURLFromUUID(entry.uuid()), next_blob_key,
- entry.size(), entry.last_modified()));
+ WriteDescriptor(entry.blob_handle(), next_blob_key, entry.size(),
+ entry.last_modified()));
}
entry.set_key(next_blob_key);
new_blob_keys.push_back(&entry);
@@ -3404,7 +3383,7 @@ void IndexedDBBackingStore::Transaction::WriteNewBlobs(
}
// Creating the writer will start it going asynchronously. The transaction
// can be destructed before the callback is triggered.
- chained_blob_writer_ = new ChainedBlobWriterImpl(
+ chained_blob_writer_ = ChainedBlobWriterImpl::Create(
database_id_, backing_store_, new_files_to_write,
new BlobWriteCallbackWrapper(ptr_factory_.GetWeakPtr(), this, callback));
}
@@ -3446,23 +3425,12 @@ void IndexedDBBackingStore::BlobChangeRecord::SetBlobInfo(
blob_info_.swap(*blob_info);
}
-void IndexedDBBackingStore::BlobChangeRecord::SetHandles(
- std::vector<std::unique_ptr<storage::BlobDataHandle>>* handles) {
- handles_.clear();
- if (handles)
- handles_.swap(*handles);
-}
-
std::unique_ptr<IndexedDBBackingStore::BlobChangeRecord>
IndexedDBBackingStore::BlobChangeRecord::Clone() const {
std::unique_ptr<IndexedDBBackingStore::BlobChangeRecord> record(
new BlobChangeRecord(key_, object_store_id_));
record->blob_info_ = blob_info_;
- for (const auto& handle : handles_) {
- record->handles_.push_back(
- std::make_unique<storage::BlobDataHandle>(*handle));
- }
return record;
}
@@ -3470,8 +3438,7 @@ Status IndexedDBBackingStore::Transaction::PutBlobInfoIfNeeded(
int64_t database_id,
int64_t object_store_id,
const std::string& object_store_data_key,
- std::vector<IndexedDBBlobInfo>* blob_info,
- std::vector<std::unique_ptr<storage::BlobDataHandle>>* handles) {
+ std::vector<IndexedDBBlobInfo>* blob_info) {
if (!blob_info || blob_info->empty()) {
blob_change_map_.erase(object_store_data_key);
incognito_blob_map_.erase(object_store_data_key);
@@ -3491,8 +3458,7 @@ Status IndexedDBBackingStore::Transaction::PutBlobInfoIfNeeded(
if (!found)
return Status::OK();
}
- PutBlobInfo(
- database_id, object_store_id, object_store_data_key, blob_info, handles);
+ PutBlobInfo(database_id, object_store_id, object_store_data_key, blob_info);
return Status::OK();
}
@@ -3504,8 +3470,7 @@ void IndexedDBBackingStore::Transaction::PutBlobInfo(
int64_t database_id,
int64_t object_store_id,
const std::string& object_store_data_key,
- std::vector<IndexedDBBlobInfo>* blob_info,
- std::vector<std::unique_ptr<storage::BlobDataHandle>>* handles) {
+ std::vector<IndexedDBBlobInfo>* blob_info) {
DCHECK(!object_store_data_key.empty());
if (database_id_ < 0)
database_id_ = database_id;
@@ -3524,21 +3489,18 @@ void IndexedDBBackingStore::Transaction::PutBlobInfo(
}
DCHECK_EQ(record->object_store_id(), object_store_id);
record->SetBlobInfo(blob_info);
- record->SetHandles(handles);
- DCHECK(!handles || handles->empty());
}
IndexedDBBackingStore::Transaction::WriteDescriptor::WriteDescriptor(
- const GURL& url,
+ const storage::BlobDataHandle* blob,
int64_t key,
int64_t size,
base::Time last_modified)
: is_file_(false),
- url_(url),
+ blob_(*blob),
key_(key),
size_(size),
- last_modified_(last_modified) {
-}
+ last_modified_(last_modified) {}
IndexedDBBackingStore::Transaction::WriteDescriptor::WriteDescriptor(
const FilePath& file_path,
@@ -3557,7 +3519,7 @@ IndexedDBBackingStore::Transaction::WriteDescriptor::WriteDescriptor(
IndexedDBBackingStore::Transaction::WriteDescriptor::~WriteDescriptor() =
default;
IndexedDBBackingStore::Transaction::WriteDescriptor&
- IndexedDBBackingStore::Transaction::WriteDescriptor::
- operator=(const WriteDescriptor& other) = default;
+IndexedDBBackingStore::Transaction::WriteDescriptor::operator=(
+ const WriteDescriptor& other) = default;
} // namespace content
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 4ec52518ce4..e5540a77658 100644
--- a/chromium/content/browser/indexed_db/indexed_db_backing_store.h
+++ b/chromium/content/browser/indexed_db/indexed_db_backing_store.h
@@ -31,11 +31,8 @@
#include "content/browser/indexed_db/leveldb/leveldb_iterator.h"
#include "content/browser/indexed_db/leveldb/leveldb_transaction.h"
#include "content/common/content_export.h"
-#include "content/common/indexed_db/indexed_db_key.h"
-#include "content/common/indexed_db/indexed_db_key_path.h"
-#include "content/common/indexed_db/indexed_db_key_range.h"
-#include "content/common/indexed_db/indexed_db_metadata.h"
#include "storage/browser/blob/blob_data_handle.h"
+#include "third_party/blink/public/common/indexeddb/indexeddb_key.h"
#include "third_party/leveldatabase/src/include/leveldb/status.h"
#include "url/gurl.h"
#include "url/origin.h"
@@ -44,6 +41,11 @@ namespace base {
class SequencedTaskRunner;
}
+namespace blink {
+class IndexedDBKeyRange;
+struct IndexedDBDatabaseMetadata;
+} // namespace blink
+
namespace storage {
class FileWriterDelegate;
}
@@ -122,15 +124,12 @@ class CONTENT_EXPORT IndexedDBBackingStore
const std::vector<IndexedDBBlobInfo>& blob_info() const {
return blob_info_;
}
- void SetHandles(
- std::vector<std::unique_ptr<storage::BlobDataHandle>>* handles);
std::unique_ptr<BlobChangeRecord> Clone() const;
private:
std::string key_;
int64_t object_store_id_;
std::vector<IndexedDBBlobInfo> blob_info_;
- std::vector<std::unique_ptr<storage::BlobDataHandle>> handles_;
DISALLOW_COPY_AND_ASSIGN(BlobChangeRecord);
};
@@ -164,14 +163,11 @@ class CONTENT_EXPORT IndexedDBBackingStore
int64_t database_id,
int64_t object_store_id,
const std::string& object_store_data_key,
- std::vector<IndexedDBBlobInfo>*,
- std::vector<std::unique_ptr<storage::BlobDataHandle>>* handles);
- void PutBlobInfo(
- int64_t database_id,
- int64_t object_store_id,
- const std::string& object_store_data_key,
- std::vector<IndexedDBBlobInfo>*,
- std::vector<std::unique_ptr<storage::BlobDataHandle>>* handles);
+ std::vector<IndexedDBBlobInfo>*);
+ void PutBlobInfo(int64_t database_id,
+ int64_t object_store_id,
+ const std::string& object_store_data_key,
+ std::vector<IndexedDBBlobInfo>*);
LevelDBTransaction* transaction() { return transaction_.get(); }
@@ -189,7 +185,7 @@ class CONTENT_EXPORT IndexedDBBackingStore
class CONTENT_EXPORT WriteDescriptor {
public:
- WriteDescriptor(const GURL& url,
+ WriteDescriptor(const storage::BlobDataHandle* blob,
int64_t key,
int64_t size,
base::Time last_modified);
@@ -202,9 +198,9 @@ class CONTENT_EXPORT IndexedDBBackingStore
WriteDescriptor& operator=(const WriteDescriptor& other);
bool is_file() const { return is_file_; }
- const GURL& url() const {
+ const storage::BlobDataHandle* blob() const {
DCHECK(!is_file_);
- return url_;
+ return &blob_.value();
}
const base::FilePath& file_path() const {
DCHECK(is_file_);
@@ -216,7 +212,7 @@ class CONTENT_EXPORT IndexedDBBackingStore
private:
bool is_file_;
- GURL url_;
+ base::Optional<storage::BlobDataHandle> blob_;
base::FilePath file_path_;
int64_t key_;
int64_t size_;
@@ -321,22 +317,22 @@ class CONTENT_EXPORT IndexedDBBackingStore
bool unique;
};
- const IndexedDBKey& key() const { return *current_key_; }
+ const blink::IndexedDBKey& key() const { return *current_key_; }
bool Continue(leveldb::Status* s) { return Continue(NULL, NULL, SEEK, s); }
- bool Continue(const IndexedDBKey* key,
+ bool Continue(const blink::IndexedDBKey* key,
IteratorState state,
leveldb::Status* s) {
return Continue(key, NULL, state, s);
}
- bool Continue(const IndexedDBKey* key,
- const IndexedDBKey* primary_key,
+ bool Continue(const blink::IndexedDBKey* key,
+ const blink::IndexedDBKey* primary_key,
IteratorState state,
leveldb::Status*);
bool Advance(uint32_t count, leveldb::Status*);
bool FirstSeek(leveldb::Status*);
virtual std::unique_ptr<Cursor> Clone() const = 0;
- virtual const IndexedDBKey& primary_key() const;
+ virtual const blink::IndexedDBKey& primary_key() const;
virtual IndexedDBValue* value() = 0;
virtual const RecordIdentifier& record_identifier() const;
virtual bool LoadCurrentRow(leveldb::Status* s) = 0;
@@ -348,9 +344,9 @@ class CONTENT_EXPORT IndexedDBBackingStore
const CursorOptions& cursor_options);
explicit Cursor(const IndexedDBBackingStore::Cursor* other);
- virtual std::string EncodeKey(const IndexedDBKey& key) = 0;
- virtual std::string EncodeKey(const IndexedDBKey& key,
- const IndexedDBKey& primary_key) = 0;
+ virtual std::string EncodeKey(const blink::IndexedDBKey& key) = 0;
+ virtual std::string EncodeKey(const blink::IndexedDBKey& key,
+ const blink::IndexedDBKey& primary_key) = 0;
bool IsPastBounds() const;
bool HaveEnteredRange() const;
@@ -360,22 +356,22 @@ class CONTENT_EXPORT IndexedDBBackingStore
int64_t database_id_;
const CursorOptions cursor_options_;
std::unique_ptr<LevelDBIterator> iterator_;
- std::unique_ptr<IndexedDBKey> current_key_;
+ std::unique_ptr<blink::IndexedDBKey> current_key_;
IndexedDBBackingStore::RecordIdentifier record_identifier_;
private:
enum class ContinueResult { LEVELDB_ERROR, DONE, OUT_OF_BOUNDS };
// For cursors with direction Next or NextNoDuplicate.
- ContinueResult ContinueNext(const IndexedDBKey* key,
- const IndexedDBKey* primary_key,
+ ContinueResult ContinueNext(const blink::IndexedDBKey* key,
+ const blink::IndexedDBKey* primary_key,
IteratorState state,
leveldb::Status*);
// For cursors with direction Prev or PrevNoDuplicate. The PrevNoDuplicate
// case has additional complexity of not being symmetric with
// NextNoDuplicate.
- ContinueResult ContinuePrevious(const IndexedDBKey* key,
- const IndexedDBKey* primary_key,
+ ContinueResult ContinuePrevious(const blink::IndexedDBKey* key,
+ const blink::IndexedDBKey* primary_key,
IteratorState state,
leveldb::Status*);
@@ -448,15 +444,14 @@ class CONTENT_EXPORT IndexedDBBackingStore
IndexedDBBackingStore::Transaction* transaction,
int64_t database_id,
int64_t object_store_id,
- const IndexedDBKey& key,
+ const blink::IndexedDBKey& key,
IndexedDBValue* record) WARN_UNUSED_RESULT;
virtual leveldb::Status PutRecord(
IndexedDBBackingStore::Transaction* transaction,
int64_t database_id,
int64_t object_store_id,
- const IndexedDBKey& key,
+ const blink::IndexedDBKey& key,
IndexedDBValue* value,
- std::vector<std::unique_ptr<storage::BlobDataHandle>>* handles,
RecordIdentifier* record) WARN_UNUSED_RESULT;
virtual leveldb::Status ClearObjectStore(
IndexedDBBackingStore::Transaction* transaction,
@@ -471,7 +466,7 @@ class CONTENT_EXPORT IndexedDBBackingStore
IndexedDBBackingStore::Transaction* transaction,
int64_t database_id,
int64_t object_store_id,
- const IndexedDBKeyRange&) WARN_UNUSED_RESULT;
+ const blink::IndexedDBKeyRange&) WARN_UNUSED_RESULT;
virtual leveldb::Status GetKeyGeneratorCurrentNumber(
IndexedDBBackingStore::Transaction* transaction,
int64_t database_id,
@@ -487,7 +482,7 @@ class CONTENT_EXPORT IndexedDBBackingStore
IndexedDBBackingStore::Transaction* transaction,
int64_t database_id,
int64_t object_store_id,
- const IndexedDBKey& key,
+ const blink::IndexedDBKey& key,
RecordIdentifier* found_record_identifier,
bool* found) WARN_UNUSED_RESULT;
@@ -501,22 +496,22 @@ class CONTENT_EXPORT IndexedDBBackingStore
int64_t database_id,
int64_t object_store_id,
int64_t index_id,
- const IndexedDBKey& key,
+ const blink::IndexedDBKey& key,
const RecordIdentifier& record) WARN_UNUSED_RESULT;
virtual leveldb::Status GetPrimaryKeyViaIndex(
IndexedDBBackingStore::Transaction* transaction,
int64_t database_id,
int64_t object_store_id,
int64_t index_id,
- const IndexedDBKey& key,
- std::unique_ptr<IndexedDBKey>* primary_key) WARN_UNUSED_RESULT;
+ const blink::IndexedDBKey& key,
+ std::unique_ptr<blink::IndexedDBKey>* primary_key) WARN_UNUSED_RESULT;
virtual leveldb::Status KeyExistsInIndex(
IndexedDBBackingStore::Transaction* transaction,
int64_t database_id,
int64_t object_store_id,
int64_t index_id,
- const IndexedDBKey& key,
- std::unique_ptr<IndexedDBKey>* found_primary_key,
+ const blink::IndexedDBKey& key,
+ std::unique_ptr<blink::IndexedDBKey>* found_primary_key,
bool* exists) WARN_UNUSED_RESULT;
// Public for IndexedDBActiveBlobRegistry::ReleaseBlobRef.
@@ -528,14 +523,14 @@ class CONTENT_EXPORT IndexedDBBackingStore
IndexedDBBackingStore::Transaction* transaction,
int64_t database_id,
int64_t object_store_id,
- const IndexedDBKeyRange& key_range,
+ const blink::IndexedDBKeyRange& key_range,
blink::WebIDBCursorDirection,
leveldb::Status*);
virtual std::unique_ptr<Cursor> OpenObjectStoreCursor(
IndexedDBBackingStore::Transaction* transaction,
int64_t database_id,
int64_t object_store_id,
- const IndexedDBKeyRange& key_range,
+ const blink::IndexedDBKeyRange& key_range,
blink::WebIDBCursorDirection,
leveldb::Status*);
virtual std::unique_ptr<Cursor> OpenIndexKeyCursor(
@@ -543,7 +538,7 @@ class CONTENT_EXPORT IndexedDBBackingStore
int64_t database_id,
int64_t object_store_id,
int64_t index_id,
- const IndexedDBKeyRange& key_range,
+ const blink::IndexedDBKeyRange& key_range,
blink::WebIDBCursorDirection,
leveldb::Status*);
virtual std::unique_ptr<Cursor> OpenIndexCursor(
@@ -551,7 +546,7 @@ class CONTENT_EXPORT IndexedDBBackingStore
int64_t database_id,
int64_t object_store_id,
int64_t index_id,
- const IndexedDBKeyRange& key_range,
+ const blink::IndexedDBKeyRange& key_range,
blink::WebIDBCursorDirection,
leveldb::Status*);
@@ -585,6 +580,11 @@ class CONTENT_EXPORT IndexedDBBackingStore
// Stops the journal_cleaning_timer_ and runs its pending task.
void ForceRunBlobCleanup();
+ // RevertSchemaToV2() updates a backing store state on disk to override its
+ // metadata version to 2. This allows triggering https://crbug.com/829141 on
+ // an otherwise healthy backing store.
+ leveldb::Status RevertSchemaToV2();
+
protected:
friend class base::RefCounted<IndexedDBBackingStore>;
@@ -607,7 +607,7 @@ class CONTENT_EXPORT IndexedDBBackingStore
// TODO(dmurph): Move this completely to IndexedDBMetadataFactory.
leveldb::Status GetCompleteMetadata(
- std::vector<IndexedDBDatabaseMetadata>* output);
+ std::vector<blink::IndexedDBDatabaseMetadata>* output);
virtual bool WriteBlobFile(
int64_t database_id,
@@ -652,7 +652,7 @@ class CONTENT_EXPORT IndexedDBBackingStore
int64_t database_id,
int64_t object_store_id,
int64_t index_id,
- const IndexedDBKey& key,
+ const blink::IndexedDBKey& key,
std::string* found_encoded_primary_key,
bool* found);
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 eaa915e6d42..6eb906e0216 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
@@ -11,6 +11,7 @@
#include "base/callback.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
+#include "base/guid.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/sequenced_task_runner.h"
@@ -28,14 +29,22 @@
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_utils.h"
#include "net/url_request/url_request_test_util.h"
+#include "storage/browser/blob/blob_data_builder.h"
#include "storage/browser/blob/blob_data_handle.h"
+#include "storage/browser/blob/blob_storage_context.h"
#include "storage/browser/quota/special_storage_policy.h"
#include "storage/browser/test/mock_quota_manager_proxy.h"
#include "storage/browser/test/mock_special_storage_policy.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/modules/indexeddb/web_idb_types.h"
+#include "third_party/blink/public/common/indexeddb/web_idb_types.h"
using base::ASCIIToUTF16;
+using blink::IndexedDBDatabaseMetadata;
+using blink::IndexedDBIndexMetadata;
+using blink::IndexedDBKey;
+using blink::IndexedDBKeyPath;
+using blink::IndexedDBKeyRange;
+using blink::IndexedDBObjectStoreMetadata;
using url::Origin;
namespace content {
@@ -330,13 +339,15 @@ class IndexedDBBackingStoreTestWithBlobs : public IndexedDBBackingStoreTest {
void SetUp() override {
IndexedDBBackingStoreTest::SetUp();
+ blob_context_ = std::make_unique<storage::BlobStorageContext>();
+
// useful keys and values during tests
blob_info_.push_back(
- IndexedDBBlobInfo("uuid 3", base::UTF8ToUTF16("blob type"), 1));
+ IndexedDBBlobInfo(CreateBlob(), base::UTF8ToUTF16("blob type"), 1));
blob_info_.push_back(IndexedDBBlobInfo(
- "uuid 4", base::FilePath(FILE_PATH_LITERAL("path/to/file")),
+ CreateBlob(), base::FilePath(FILE_PATH_LITERAL("path/to/file")),
base::UTF8ToUTF16("file name"), base::UTF8ToUTF16("file type")));
- blob_info_.push_back(IndexedDBBlobInfo("uuid 5", base::FilePath(),
+ blob_info_.push_back(IndexedDBBlobInfo(CreateBlob(), base::FilePath(),
base::UTF8ToUTF16("file name"),
base::UTF8ToUTF16("file type")));
value3_ = IndexedDBValue("value3", blob_info_);
@@ -344,6 +355,11 @@ class IndexedDBBackingStoreTestWithBlobs : public IndexedDBBackingStoreTest {
key3_ = IndexedDBKey(ASCIIToUTF16("key3"));
}
+ std::unique_ptr<storage::BlobDataHandle> CreateBlob() {
+ return blob_context_->AddFinishedBlob(
+ std::make_unique<storage::BlobDataBuilder>(base::GenerateGUID()));
+ }
+
// This just checks the data that survive getting stored and recalled, e.g.
// the file path and UUID will change and thus aren't verified.
bool CheckBlobInfoMatches(const std::vector<IndexedDBBlobInfo>& reads) const {
@@ -403,7 +419,7 @@ class IndexedDBBackingStoreTestWithBlobs : public IndexedDBBackingStoreTest {
if (desc.file_path() != info.file_path())
return false;
} else {
- if (desc.url() != GURL("blob:uuid/" + info.uuid()))
+ if (desc.blob()->uuid() != info.blob_handle()->uuid())
return false;
}
}
@@ -428,6 +444,8 @@ class IndexedDBBackingStoreTestWithBlobs : public IndexedDBBackingStoreTest {
IndexedDBValue value3_;
private:
+ std::unique_ptr<storage::BlobStorageContext> blob_context_;
+
// Blob details referenced by |value3_|. The various CheckBlob*() methods
// can be used to verify the state as a test progresses.
std::vector<IndexedDBBlobInfo> blob_info_;
@@ -470,10 +488,9 @@ TEST_F(IndexedDBBackingStoreTest, PutGetConsistency) {
{
IndexedDBBackingStore::Transaction transaction1(backing_store);
transaction1.Begin();
- std::vector<std::unique_ptr<storage::BlobDataHandle>> handles;
IndexedDBBackingStore::RecordIdentifier record;
leveldb::Status s = backing_store->PutRecord(
- &transaction1, 1, 1, key, &value, &handles, &record);
+ &transaction1, 1, 1, key, &value, &record);
EXPECT_TRUE(s.ok());
scoped_refptr<TestCallback> callback(
base::MakeRefCounted<TestCallback>());
@@ -521,12 +538,10 @@ TEST_F(IndexedDBBackingStoreTestWithBlobs, PutGetConsistencyWithBlobs) {
std::make_unique<IndexedDBBackingStore::Transaction>(
test->backing_store());
state->transaction1->Begin();
- std::vector<std::unique_ptr<storage::BlobDataHandle>> handles;
IndexedDBBackingStore::RecordIdentifier record;
EXPECT_TRUE(test->backing_store()
->PutRecord(state->transaction1.get(), 1, 1,
- test->key3_, &test->value3_, &handles,
- &record)
+ test->key3_, &test->value3_, &record)
.ok());
state->callback1 = base::MakeRefCounted<TestCallback>();
EXPECT_TRUE(
@@ -599,7 +614,7 @@ TEST_F(IndexedDBBackingStoreTestWithBlobs, PutGetConsistencyWithBlobs) {
RunAllTasksUntilIdle();
}
-TEST_F(IndexedDBBackingStoreTest, DeleteRange) {
+TEST_F(IndexedDBBackingStoreTestWithBlobs, DeleteRange) {
const std::vector<IndexedDBKey> keys = {
IndexedDBKey(ASCIIToUTF16("key0")), IndexedDBKey(ASCIIToUTF16("key1")),
IndexedDBKey(ASCIIToUTF16("key2")), IndexedDBKey(ASCIIToUTF16("key3"))};
@@ -620,8 +635,12 @@ TEST_F(IndexedDBBackingStoreTest, DeleteRange) {
scoped_refptr<TestCallback> callback1;
std::unique_ptr<IndexedDBBackingStore::Transaction> transaction2;
scoped_refptr<TestCallback> callback2;
+ std::vector<std::unique_ptr<storage::BlobDataHandle>> blobs;
} state;
+ for (size_t j = 0; j < 4; ++j)
+ state.blobs.push_back(CreateBlob());
+
idb_context_->TaskRunner()->PostTask(
FROM_HERE,
base::BindOnce(
@@ -633,19 +652,26 @@ TEST_F(IndexedDBBackingStoreTest, DeleteRange) {
backing_store->ClearRemovals();
std::vector<IndexedDBValue> values = {
- IndexedDBValue(
- "value0", {IndexedDBBlobInfo(
- "uuid 0", base::UTF8ToUTF16("type 0"), 1)}),
- IndexedDBValue(
- "value1", {IndexedDBBlobInfo(
- "uuid 1", base::UTF8ToUTF16("type 1"), 1)}),
- IndexedDBValue(
- "value2", {IndexedDBBlobInfo(
- "uuid 2", base::UTF8ToUTF16("type 2"), 1)}),
- IndexedDBValue(
- "value3",
- {IndexedDBBlobInfo("uuid 3", base::UTF8ToUTF16("type 3"),
- 1)})};
+ IndexedDBValue("value0",
+ {IndexedDBBlobInfo(
+ std::make_unique<storage::BlobDataHandle>(
+ *state->blobs[0]),
+ base::UTF8ToUTF16("type 0"), 1)}),
+ IndexedDBValue("value1",
+ {IndexedDBBlobInfo(
+ std::make_unique<storage::BlobDataHandle>(
+ *state->blobs[1]),
+ base::UTF8ToUTF16("type 1"), 1)}),
+ IndexedDBValue("value2",
+ {IndexedDBBlobInfo(
+ std::make_unique<storage::BlobDataHandle>(
+ *state->blobs[2]),
+ base::UTF8ToUTF16("type 2"), 1)}),
+ IndexedDBValue("value3",
+ {IndexedDBBlobInfo(
+ std::make_unique<storage::BlobDataHandle>(
+ *state->blobs[3]),
+ base::UTF8ToUTF16("type 3"), 1)})};
ASSERT_GE(keys.size(), values.size());
// Initiate transaction1 - write records.
@@ -653,14 +679,12 @@ TEST_F(IndexedDBBackingStoreTest, DeleteRange) {
std::make_unique<IndexedDBBackingStore::Transaction>(
backing_store);
state->transaction1->Begin();
- std::vector<std::unique_ptr<storage::BlobDataHandle>> handles;
IndexedDBBackingStore::RecordIdentifier record;
for (size_t i = 0; i < values.size(); ++i) {
EXPECT_TRUE(backing_store
->PutRecord(state->transaction1.get(),
database_id, object_store_id,
- keys[i], &values[i], &handles,
- &record)
+ keys[i], &values[i], &record)
.ok());
}
@@ -728,7 +752,7 @@ TEST_F(IndexedDBBackingStoreTest, DeleteRange) {
}
}
-TEST_F(IndexedDBBackingStoreTest, DeleteRangeEmptyRange) {
+TEST_F(IndexedDBBackingStoreTestWithBlobs, DeleteRangeEmptyRange) {
const std::vector<IndexedDBKey> keys = {
IndexedDBKey(ASCIIToUTF16("key0")), IndexedDBKey(ASCIIToUTF16("key1")),
IndexedDBKey(ASCIIToUTF16("key2")), IndexedDBKey(ASCIIToUTF16("key3")),
@@ -748,8 +772,12 @@ TEST_F(IndexedDBBackingStoreTest, DeleteRangeEmptyRange) {
scoped_refptr<TestCallback> callback1;
std::unique_ptr<IndexedDBBackingStore::Transaction> transaction2;
scoped_refptr<TestCallback> callback2;
+ std::vector<std::unique_ptr<storage::BlobDataHandle>> blobs;
} state;
+ for (size_t j = 0; j < 4; ++j)
+ state.blobs.push_back(CreateBlob());
+
idb_context_->TaskRunner()->PostTask(
FROM_HERE,
base::BindOnce(
@@ -761,19 +789,26 @@ TEST_F(IndexedDBBackingStoreTest, DeleteRangeEmptyRange) {
backing_store->ClearRemovals();
std::vector<IndexedDBValue> values = {
- IndexedDBValue(
- "value0", {IndexedDBBlobInfo(
- "uuid 0", base::UTF8ToUTF16("type 0"), 1)}),
- IndexedDBValue(
- "value1", {IndexedDBBlobInfo(
- "uuid 1", base::UTF8ToUTF16("type 1"), 1)}),
- IndexedDBValue(
- "value2", {IndexedDBBlobInfo(
- "uuid 2", base::UTF8ToUTF16("type 2"), 1)}),
- IndexedDBValue(
- "value3",
- {IndexedDBBlobInfo("uuid 3", base::UTF8ToUTF16("type 3"),
- 1)})};
+ IndexedDBValue("value0",
+ {IndexedDBBlobInfo(
+ std::make_unique<storage::BlobDataHandle>(
+ *state->blobs[0]),
+ base::UTF8ToUTF16("type 0"), 1)}),
+ IndexedDBValue("value1",
+ {IndexedDBBlobInfo(
+ std::make_unique<storage::BlobDataHandle>(
+ *state->blobs[1]),
+ base::UTF8ToUTF16("type 1"), 1)}),
+ IndexedDBValue("value2",
+ {IndexedDBBlobInfo(
+ std::make_unique<storage::BlobDataHandle>(
+ *state->blobs[2]),
+ base::UTF8ToUTF16("type 2"), 1)}),
+ IndexedDBValue("value3",
+ {IndexedDBBlobInfo(
+ std::make_unique<storage::BlobDataHandle>(
+ *state->blobs[3]),
+ base::UTF8ToUTF16("type 3"), 1)})};
ASSERT_GE(keys.size(), values.size());
// Initiate transaction1 - write records.
@@ -782,14 +817,12 @@ TEST_F(IndexedDBBackingStoreTest, DeleteRangeEmptyRange) {
backing_store);
state->transaction1->Begin();
- std::vector<std::unique_ptr<storage::BlobDataHandle>> handles;
IndexedDBBackingStore::RecordIdentifier record;
for (size_t i = 0; i < values.size(); ++i) {
EXPECT_TRUE(backing_store
->PutRecord(state->transaction1.get(),
database_id, object_store_id,
- keys[i], &values[i], &handles,
- &record)
+ keys[i], &values[i], &record)
.ok());
}
// Start committing transaction1.
@@ -869,12 +902,10 @@ TEST_F(IndexedDBBackingStoreTestWithBlobs, BlobJournalInterleavedTransactions) {
std::make_unique<IndexedDBBackingStore::Transaction>(
test->backing_store());
state->transaction1->Begin();
- std::vector<std::unique_ptr<storage::BlobDataHandle>> handles1;
IndexedDBBackingStore::RecordIdentifier record1;
EXPECT_TRUE(test->backing_store()
->PutRecord(state->transaction1.get(), 1, 1,
- test->key3_, &test->value3_, &handles1,
- &record1)
+ test->key3_, &test->value3_, &record1)
.ok());
state->callback1 = base::MakeRefCounted<TestCallback>();
EXPECT_TRUE(
@@ -898,12 +929,10 @@ TEST_F(IndexedDBBackingStoreTestWithBlobs, BlobJournalInterleavedTransactions) {
std::make_unique<IndexedDBBackingStore::Transaction>(
test->backing_store());
state->transaction2->Begin();
- std::vector<std::unique_ptr<storage::BlobDataHandle>> handles2;
IndexedDBBackingStore::RecordIdentifier record2;
EXPECT_TRUE(test->backing_store()
->PutRecord(state->transaction2.get(), 1, 1,
- test->key1_, &test->value1_, &handles2,
- &record2)
+ test->key1_, &test->value1_, &record2)
.ok());
state->callback2 = base::MakeRefCounted<TestCallback>();
EXPECT_TRUE(
@@ -953,12 +982,10 @@ TEST_F(IndexedDBBackingStoreTestWithBlobs, LiveBlobJournal) {
std::make_unique<IndexedDBBackingStore::Transaction>(
test->backing_store());
state->transaction1->Begin();
- std::vector<std::unique_ptr<storage::BlobDataHandle>> handles;
IndexedDBBackingStore::RecordIdentifier record;
EXPECT_TRUE(test->backing_store()
->PutRecord(state->transaction1.get(), 1, 1,
- test->key3_, &test->value3_, &handles,
- &record)
+ test->key3_, &test->value3_, &record)
.ok());
state->callback1 = base::MakeRefCounted<TestCallback>();
EXPECT_TRUE(
@@ -1081,11 +1108,10 @@ TEST_F(IndexedDBBackingStoreTest, HighIds) {
{
IndexedDBBackingStore::Transaction transaction1(backing_store);
transaction1.Begin();
- std::vector<std::unique_ptr<storage::BlobDataHandle>> handles;
IndexedDBBackingStore::RecordIdentifier record;
leveldb::Status s = backing_store->PutRecord(
&transaction1, high_database_id, high_object_store_id, key1,
- &value1, &handles, &record);
+ &value1, &record);
EXPECT_TRUE(s.ok());
s = backing_store->PutIndexDataForRecord(
@@ -1158,21 +1184,19 @@ TEST_F(IndexedDBBackingStoreTest, InvalidIds) {
IndexedDBBackingStore::Transaction transaction1(backing_store);
transaction1.Begin();
- std::vector<std::unique_ptr<storage::BlobDataHandle>> handles;
IndexedDBBackingStore::RecordIdentifier record;
leveldb::Status s = backing_store->PutRecord(
&transaction1, database_id, KeyPrefix::kInvalidId, key, &value,
- &handles, &record);
+ &record);
EXPECT_FALSE(s.ok());
s = backing_store->PutRecord(&transaction1, database_id, 0, key,
- &value, &handles, &record);
+ &value, &record);
EXPECT_FALSE(s.ok());
s = backing_store->PutRecord(&transaction1, KeyPrefix::kInvalidId,
- object_store_id, key, &value, &handles,
- &record);
+ object_store_id, key, &value, &record);
EXPECT_FALSE(s.ok());
s = backing_store->PutRecord(&transaction1, 0, object_store_id, key,
- &value, &handles, &record);
+ &value, &record);
EXPECT_FALSE(s.ok());
s = backing_store->GetRecord(&transaction1, database_id,
@@ -1503,11 +1527,10 @@ TEST_F(IndexedDBBackingStoreTest, SchemaUpgradeWithoutBlobsSurvives) {
// Save a value.
IndexedDBBackingStore::Transaction transaction1(backing_store);
transaction1.Begin();
- std::vector<std::unique_ptr<storage::BlobDataHandle>> handles;
IndexedDBBackingStore::RecordIdentifier record;
leveldb::Status s = backing_store->PutRecord(
&transaction1, state->database_id, state->object_store_id, key,
- &value, &handles, &record);
+ &value, &record);
EXPECT_TRUE(s.ok());
scoped_refptr<TestCallback> callback(
base::MakeRefCounted<TestCallback>());
@@ -1648,13 +1671,12 @@ TEST_F(IndexedDBBackingStoreTestWithBlobs, SchemaUpgradeWithBlobsCorrupt) {
std::make_unique<IndexedDBBackingStore::Transaction>(
test->backing_store());
state->transaction1->Begin();
- std::vector<std::unique_ptr<storage::BlobDataHandle>> handles;
IndexedDBBackingStore::RecordIdentifier record;
EXPECT_TRUE(test->backing_store()
->PutRecord(state->transaction1.get(),
state->database_id,
state->object_store_id, test->key3_,
- &test->value3_, &handles, &record)
+ &test->value3_, &record)
.ok());
state->callback1 = base::MakeRefCounted<TestCallback>();
EXPECT_TRUE(
diff --git a/chromium/content/browser/indexed_db/indexed_db_blob_info.cc b/chromium/content/browser/indexed_db/indexed_db_blob_info.cc
index a2308c48f46..0e40f9c65fd 100644
--- a/chromium/content/browser/indexed_db/indexed_db_blob_info.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_blob_info.cc
@@ -14,11 +14,12 @@ IndexedDBBlobInfo::IndexedDBBlobInfo()
: is_file_(false), size_(-1), key_(DatabaseMetaDataKey::kInvalidBlobKey) {
}
-IndexedDBBlobInfo::IndexedDBBlobInfo(const std::string& uuid,
- const base::string16& type,
- int64_t size)
+IndexedDBBlobInfo::IndexedDBBlobInfo(
+ std::unique_ptr<storage::BlobDataHandle> blob_handle,
+ const base::string16& type,
+ int64_t size)
: is_file_(false),
- uuid_(uuid),
+ blob_handle_(*blob_handle),
type_(type),
size_(size),
key_(DatabaseMetaDataKey::kInvalidBlobKey) {}
@@ -28,18 +29,18 @@ IndexedDBBlobInfo::IndexedDBBlobInfo(const base::string16& type,
int64_t key)
: is_file_(false), type_(type), size_(size), key_(key) {}
-IndexedDBBlobInfo::IndexedDBBlobInfo(const std::string& uuid,
- const base::FilePath& file_path,
- const base::string16& file_name,
- const base::string16& type)
+IndexedDBBlobInfo::IndexedDBBlobInfo(
+ std::unique_ptr<storage::BlobDataHandle> blob_handle,
+ const base::FilePath& file_path,
+ const base::string16& file_name,
+ const base::string16& type)
: is_file_(true),
- uuid_(uuid),
+ blob_handle_(*blob_handle),
type_(type),
size_(-1),
file_name_(file_name),
file_path_(file_path),
- key_(DatabaseMetaDataKey::kInvalidBlobKey) {
-}
+ key_(DatabaseMetaDataKey::kInvalidBlobKey) {}
IndexedDBBlobInfo::IndexedDBBlobInfo(int64_t key,
const base::string16& type,
@@ -62,12 +63,6 @@ void IndexedDBBlobInfo::set_size(int64_t size) {
size_ = size;
}
-void IndexedDBBlobInfo::set_uuid(const std::string& uuid) {
- DCHECK(uuid_.empty());
- uuid_ = uuid;
- DCHECK(!uuid_.empty());
-}
-
void IndexedDBBlobInfo::set_file_path(const base::FilePath& file_path) {
DCHECK(file_path_.empty());
file_path_ = file_path;
diff --git a/chromium/content/browser/indexed_db/indexed_db_blob_info.h b/chromium/content/browser/indexed_db/indexed_db_blob_info.h
index 8b11194307a..2e36c081e48 100644
--- a/chromium/content/browser/indexed_db/indexed_db_blob_info.h
+++ b/chromium/content/browser/indexed_db/indexed_db_blob_info.h
@@ -11,8 +11,10 @@
#include "base/callback.h"
#include "base/files/file_path.h"
+#include "base/optional.h"
#include "base/time/time.h"
#include "content/common/content_export.h"
+#include "storage/browser/blob/blob_data_handle.h"
namespace content {
@@ -22,12 +24,12 @@ class CONTENT_EXPORT IndexedDBBlobInfo {
typedef base::RepeatingCallback<void(const base::FilePath&)> ReleaseCallback;
IndexedDBBlobInfo();
// These two are used for Blobs.
- IndexedDBBlobInfo(const std::string& uuid,
+ IndexedDBBlobInfo(std::unique_ptr<storage::BlobDataHandle> blob_handle,
const base::string16& type,
int64_t size);
IndexedDBBlobInfo(const base::string16& type, int64_t size, int64_t key);
// These two are used for Files.
- IndexedDBBlobInfo(const std::string& uuid,
+ IndexedDBBlobInfo(std::unique_ptr<storage::BlobDataHandle> blob_handle,
const base::FilePath& file_path,
const base::string16& file_name,
const base::string16& type);
@@ -40,7 +42,9 @@ class CONTENT_EXPORT IndexedDBBlobInfo {
IndexedDBBlobInfo& operator=(const IndexedDBBlobInfo& other);
bool is_file() const { return is_file_; }
- const std::string& uuid() const { return uuid_; }
+ const storage::BlobDataHandle* blob_handle() const {
+ return blob_handle_.has_value() ? &blob_handle_.value() : nullptr;
+ }
const base::string16& type() const { return type_; }
int64_t size() const { return size_; }
const base::string16& file_name() const { return file_name_; }
@@ -53,7 +57,6 @@ class CONTENT_EXPORT IndexedDBBlobInfo {
const ReleaseCallback& release_callback() const { return release_callback_; }
void set_size(int64_t size);
- void set_uuid(const std::string& uuid);
void set_file_path(const base::FilePath& file_path);
void set_last_modified(const base::Time& time);
void set_key(int64_t key);
@@ -62,7 +65,8 @@ class CONTENT_EXPORT IndexedDBBlobInfo {
private:
bool is_file_;
- std::string uuid_; // Always for Blob; sometimes for File.
+ base::Optional<storage::BlobDataHandle>
+ blob_handle_; // Always for Blob; sometimes for File.
base::string16 type_; // Mime type.
int64_t size_; // -1 if unknown for File.
base::string16 file_name_; // Only for File.
diff --git a/chromium/content/browser/indexed_db/indexed_db_browsertest.cc b/chromium/content/browser/indexed_db/indexed_db_browsertest.cc
index 860e36aee5b..e4f3274ff39 100644
--- a/chromium/content/browser/indexed_db/indexed_db_browsertest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_browsertest.cc
@@ -420,7 +420,7 @@ IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, LevelDBLogFileTest) {
base::FilePath log_file_path =
GetContext()->data_path().Append(leveldb_dir).Append(log_file);
{
- base::ThreadRestrictions::ScopedAllowIO allow_io_for_test_verification;
+ base::ScopedAllowBlockingForTesting allow_blocking;
int64_t size;
EXPECT_TRUE(base::GetFileSize(log_file_path, &size));
EXPECT_GT(size, 0);
diff --git a/chromium/content/browser/indexed_db/indexed_db_callbacks.cc b/chromium/content/browser/indexed_db/indexed_db_callbacks.cc
index 8e16c5dbeab..55fbe83dc93 100644
--- a/chromium/content/browser/indexed_db/indexed_db_callbacks.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_callbacks.cc
@@ -17,7 +17,6 @@
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/time/time.h"
#include "content/browser/child_process_security_policy_impl.h"
-#include "content/browser/fileapi/fileapi_message_filter.h"
#include "content/browser/indexed_db/cursor_impl.h"
#include "content/browser/indexed_db/database_impl.h"
#include "content/browser/indexed_db/indexed_db_connection.h"
@@ -28,8 +27,6 @@
#include "content/browser/indexed_db/indexed_db_tracing.h"
#include "content/browser/indexed_db/indexed_db_transaction.h"
#include "content/browser/indexed_db/indexed_db_value.h"
-#include "content/common/indexed_db/indexed_db_constants.h"
-#include "content/common/indexed_db/indexed_db_metadata.h"
#include "content/public/common/content_features.h"
#include "mojo/public/cpp/bindings/strong_associated_binding.h"
#include "storage/browser/blob/blob_data_builder.h"
@@ -37,8 +34,11 @@
#include "storage/browser/blob/blob_storage_context.h"
#include "storage/browser/blob/shareable_file_reference.h"
#include "storage/browser/quota/quota_manager.h"
+#include "third_party/blink/public/common/indexeddb/indexeddb_metadata.h"
-using indexed_db::mojom::CallbacksAssociatedPtrInfo;
+using blink::IndexedDBDatabaseMetadata;
+using blink::IndexedDBKey;
+using blink::mojom::IDBCallbacksAssociatedPtrInfo;
using std::swap;
using storage::ShareableFileReference;
@@ -93,17 +93,17 @@ class SafeIOThreadCursorWrapper {
void ConvertBlobInfo(
const std::vector<IndexedDBBlobInfo>& blob_info,
- std::vector<::indexed_db::mojom::BlobInfoPtr>* blob_or_file_info) {
+ std::vector<blink::mojom::IDBBlobInfoPtr>* blob_or_file_info) {
blob_or_file_info->reserve(blob_info.size());
for (const auto& iter : blob_info) {
if (!iter.mark_used_callback().is_null())
iter.mark_used_callback().Run();
- auto info = ::indexed_db::mojom::BlobInfo::New();
+ auto info = blink::mojom::IDBBlobInfo::New();
info->mime_type = iter.type();
info->size = iter.size();
if (iter.is_file()) {
- info->file = ::indexed_db::mojom::FileInfo::New();
+ info->file = blink::mojom::IDBFileInfo::New();
info->file->name = iter.file_name();
info->file->path = iter.file_path();
info->file->last_modified = iter.last_modified();
@@ -113,10 +113,10 @@ void ConvertBlobInfo(
}
// Destructively converts an IndexedDBReturnValue to a Mojo ReturnValue.
-::indexed_db::mojom::ReturnValuePtr ConvertReturnValue(
+blink::mojom::IDBReturnValuePtr ConvertReturnValue(
IndexedDBReturnValue* value) {
- auto mojo_value = ::indexed_db::mojom::ReturnValue::New();
- mojo_value->value = ::indexed_db::mojom::Value::New();
+ auto mojo_value = blink::mojom::IDBReturnValue::New();
+ mojo_value->value = blink::mojom::IDBValue::New();
if (value->primary_key.IsValid()) {
mojo_value->primary_key = value->primary_key;
mojo_value->key_path = value->key_path;
@@ -132,7 +132,7 @@ void ConvertBlobInfo(
// Expected to be created and called from IO thread.
class IndexedDBCallbacks::IOThreadHelper {
public:
- IOThreadHelper(CallbacksAssociatedPtrInfo callbacks_info,
+ IOThreadHelper(IDBCallbacksAssociatedPtrInfo callbacks_info,
base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host,
url::Origin origin,
scoped_refptr<base::SequencedTaskRunner> idb_runner);
@@ -145,28 +145,28 @@ class IndexedDBCallbacks::IOThreadHelper {
int64_t old_version,
blink::WebIDBDataLoss data_loss,
const std::string& data_loss_message,
- const content::IndexedDBDatabaseMetadata& metadata);
+ const IndexedDBDatabaseMetadata& metadata);
void SendSuccessDatabase(SafeIOThreadConnectionWrapper connection,
- const content::IndexedDBDatabaseMetadata& metadata);
+ const IndexedDBDatabaseMetadata& metadata);
void SendSuccessCursor(SafeIOThreadCursorWrapper cursor,
const IndexedDBKey& key,
const IndexedDBKey& primary_key,
- ::indexed_db::mojom::ValuePtr value,
+ blink::mojom::IDBValuePtr value,
const std::vector<IndexedDBBlobInfo>& blob_info);
- void SendSuccessValue(::indexed_db::mojom::ReturnValuePtr value,
+ void SendSuccessValue(blink::mojom::IDBReturnValuePtr value,
const std::vector<IndexedDBBlobInfo>& blob_info);
void SendSuccessCursorContinue(
const IndexedDBKey& key,
const IndexedDBKey& primary_key,
- ::indexed_db::mojom::ValuePtr value,
+ blink::mojom::IDBValuePtr value,
const std::vector<IndexedDBBlobInfo>& blob_info);
void SendSuccessCursorPrefetch(
const std::vector<IndexedDBKey>& keys,
const std::vector<IndexedDBKey>& primary_keys,
- std::vector<::indexed_db::mojom::ValuePtr> mojo_values,
+ std::vector<blink::mojom::IDBValuePtr> mojo_values,
const std::vector<IndexedDBValue>& values);
void SendSuccessArray(
- std::vector<::indexed_db::mojom::ReturnValuePtr> mojo_values,
+ std::vector<blink::mojom::IDBReturnValuePtr> mojo_values,
const std::vector<IndexedDBReturnValue>& values);
void SendSuccessKey(const IndexedDBKey& value);
void SendSuccessInteger(int64_t value);
@@ -176,12 +176,12 @@ class IndexedDBCallbacks::IOThreadHelper {
const IndexedDBBlobInfo& blob_info);
bool CreateAllBlobs(
const std::vector<IndexedDBBlobInfo>& blob_info,
- std::vector<::indexed_db::mojom::BlobInfoPtr>* blob_or_file_info);
+ std::vector<blink::mojom::IDBBlobInfoPtr>* blob_or_file_info);
void OnConnectionError();
private:
base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host_;
- ::indexed_db::mojom::CallbacksAssociatedPtr callbacks_;
+ blink::mojom::IDBCallbacksAssociatedPtr callbacks_;
url::Origin origin_;
scoped_refptr<base::SequencedTaskRunner> idb_runner_;
@@ -189,9 +189,9 @@ class IndexedDBCallbacks::IOThreadHelper {
};
// static
-::indexed_db::mojom::ValuePtr IndexedDBCallbacks::ConvertAndEraseValue(
+blink::mojom::IDBValuePtr IndexedDBCallbacks::ConvertAndEraseValue(
IndexedDBValue* value) {
- auto mojo_value = ::indexed_db::mojom::Value::New();
+ auto mojo_value = blink::mojom::IDBValue::New();
if (!value->empty())
swap(mojo_value->bits, value->bits);
ConvertBlobInfo(value->blob_info, &mojo_value->blob_or_file_info);
@@ -201,7 +201,7 @@ class IndexedDBCallbacks::IOThreadHelper {
IndexedDBCallbacks::IndexedDBCallbacks(
base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host,
const url::Origin& origin,
- ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks_info,
+ blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks_info,
scoped_refptr<base::SequencedTaskRunner> idb_runner)
: data_loss_(blink::kWebIDBDataLossNone),
io_helper_(new IOThreadHelper(std::move(callbacks_info),
@@ -341,7 +341,7 @@ void IndexedDBCallbacks::OnSuccess(std::unique_ptr<IndexedDBCursor> cursor,
DCHECK_EQ(blink::kWebIDBDataLossNone, data_loss_);
- ::indexed_db::mojom::ValuePtr mojo_value;
+ blink::mojom::IDBValuePtr mojo_value;
std::vector<IndexedDBBlobInfo> blob_info;
if (value) {
mojo_value = ConvertAndEraseValue(value);
@@ -368,7 +368,7 @@ void IndexedDBCallbacks::OnSuccess(const IndexedDBKey& key,
DCHECK_EQ(blink::kWebIDBDataLossNone, data_loss_);
- ::indexed_db::mojom::ValuePtr mojo_value;
+ blink::mojom::IDBValuePtr mojo_value;
std::vector<IndexedDBBlobInfo> blob_info;
if (value) {
mojo_value = ConvertAndEraseValue(value);
@@ -395,7 +395,7 @@ void IndexedDBCallbacks::OnSuccessWithPrefetch(
DCHECK_EQ(blink::kWebIDBDataLossNone, data_loss_);
- std::vector<::indexed_db::mojom::ValuePtr> mojo_values;
+ std::vector<blink::mojom::IDBValuePtr> mojo_values;
mojo_values.reserve(values->size());
for (size_t i = 0; i < values->size(); ++i)
mojo_values.push_back(ConvertAndEraseValue(&(*values)[i]));
@@ -414,7 +414,7 @@ void IndexedDBCallbacks::OnSuccess(IndexedDBReturnValue* value) {
DCHECK_EQ(blink::kWebIDBDataLossNone, data_loss_);
- ::indexed_db::mojom::ReturnValuePtr mojo_value;
+ blink::mojom::IDBReturnValuePtr mojo_value;
std::vector<IndexedDBBlobInfo> blob_info;
if (value) {
mojo_value = ConvertReturnValue(value);
@@ -437,7 +437,7 @@ void IndexedDBCallbacks::OnSuccessArray(
DCHECK_EQ(blink::kWebIDBDataLossNone, data_loss_);
- std::vector<::indexed_db::mojom::ReturnValuePtr> mojo_values;
+ 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(ConvertReturnValue(&(*values)[i]));
@@ -493,7 +493,7 @@ void IndexedDBCallbacks::SetConnectionOpenStartTime(
}
IndexedDBCallbacks::IOThreadHelper::IOThreadHelper(
- CallbacksAssociatedPtrInfo callbacks_info,
+ IDBCallbacksAssociatedPtrInfo callbacks_info,
base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host,
url::Origin origin,
scoped_refptr<base::SequencedTaskRunner> idb_runner)
@@ -551,7 +551,7 @@ void IndexedDBCallbacks::IOThreadHelper::SendUpgradeNeeded(
int64_t old_version,
blink::WebIDBDataLoss data_loss,
const std::string& data_loss_message,
- const content::IndexedDBDatabaseMetadata& metadata) {
+ const IndexedDBDatabaseMetadata& metadata) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!callbacks_)
return;
@@ -564,7 +564,7 @@ void IndexedDBCallbacks::IOThreadHelper::SendUpgradeNeeded(
std::move(connection_wrapper.connection_), origin_,
dispatcher_host_.get(), idb_runner_);
- ::indexed_db::mojom::DatabaseAssociatedPtrInfo ptr_info;
+ blink::mojom::IDBDatabaseAssociatedPtrInfo ptr_info;
auto request = mojo::MakeRequest(&ptr_info);
dispatcher_host_->AddDatabaseBinding(std::move(database), std::move(request));
@@ -574,7 +574,7 @@ void IndexedDBCallbacks::IOThreadHelper::SendUpgradeNeeded(
void IndexedDBCallbacks::IOThreadHelper::SendSuccessDatabase(
SafeIOThreadConnectionWrapper connection_wrapper,
- const content::IndexedDBDatabaseMetadata& metadata) {
+ const IndexedDBDatabaseMetadata& metadata) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!callbacks_)
return;
@@ -582,7 +582,7 @@ void IndexedDBCallbacks::IOThreadHelper::SendSuccessDatabase(
OnConnectionError();
return;
}
- ::indexed_db::mojom::DatabaseAssociatedPtrInfo ptr_info;
+ blink::mojom::IDBDatabaseAssociatedPtrInfo ptr_info;
if (connection_wrapper.connection_) {
auto database = std::make_unique<DatabaseImpl>(
std::move(connection_wrapper.connection_), origin_,
@@ -599,7 +599,7 @@ void IndexedDBCallbacks::IOThreadHelper::SendSuccessCursor(
SafeIOThreadCursorWrapper cursor,
const IndexedDBKey& key,
const IndexedDBKey& primary_key,
- ::indexed_db::mojom::ValuePtr value,
+ blink::mojom::IDBValuePtr value,
const std::vector<IndexedDBBlobInfo>& blob_info) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!callbacks_)
@@ -614,7 +614,7 @@ void IndexedDBCallbacks::IOThreadHelper::SendSuccessCursor(
if (value && !CreateAllBlobs(blob_info, &value->blob_or_file_info))
return;
- ::indexed_db::mojom::CursorAssociatedPtrInfo ptr_info;
+ blink::mojom::IDBCursorAssociatedPtrInfo ptr_info;
auto request = mojo::MakeRequest(&ptr_info);
dispatcher_host_->AddCursorBinding(std::move(cursor_impl),
std::move(request));
@@ -623,7 +623,7 @@ void IndexedDBCallbacks::IOThreadHelper::SendSuccessCursor(
}
void IndexedDBCallbacks::IOThreadHelper::SendSuccessValue(
- ::indexed_db::mojom::ReturnValuePtr value,
+ blink::mojom::IDBReturnValuePtr value,
const std::vector<IndexedDBBlobInfo>& blob_info) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!callbacks_)
@@ -638,7 +638,7 @@ void IndexedDBCallbacks::IOThreadHelper::SendSuccessValue(
}
void IndexedDBCallbacks::IOThreadHelper::SendSuccessArray(
- std::vector<::indexed_db::mojom::ReturnValuePtr> mojo_values,
+ std::vector<blink::mojom::IDBReturnValuePtr> mojo_values,
const std::vector<IndexedDBReturnValue>& values) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK_EQ(mojo_values.size(), values.size());
@@ -661,7 +661,7 @@ void IndexedDBCallbacks::IOThreadHelper::SendSuccessArray(
void IndexedDBCallbacks::IOThreadHelper::SendSuccessCursorContinue(
const IndexedDBKey& key,
const IndexedDBKey& primary_key,
- ::indexed_db::mojom::ValuePtr value,
+ blink::mojom::IDBValuePtr value,
const std::vector<IndexedDBBlobInfo>& blob_info) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!callbacks_)
@@ -678,7 +678,7 @@ void IndexedDBCallbacks::IOThreadHelper::SendSuccessCursorContinue(
void IndexedDBCallbacks::IOThreadHelper::SendSuccessCursorPrefetch(
const std::vector<IndexedDBKey>& keys,
const std::vector<IndexedDBKey>& primary_keys,
- std::vector<::indexed_db::mojom::ValuePtr> mojo_values,
+ std::vector<blink::mojom::IDBValuePtr> mojo_values,
const std::vector<IndexedDBValue>& values) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK_EQ(mojo_values.size(), values.size());
@@ -738,10 +738,9 @@ std::unique_ptr<storage::BlobDataHandle>
IndexedDBCallbacks::IOThreadHelper::CreateBlobData(
const IndexedDBBlobInfo& blob_info) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (!blob_info.uuid().empty()) {
+ if (blob_info.blob_handle()) {
// We're sending back a live blob, not a reference into our backing store.
- return dispatcher_host_->blob_storage_context()->GetBlobDataFromUUID(
- blob_info.uuid());
+ return std::make_unique<storage::BlobDataHandle>(*blob_info.blob_handle());
}
scoped_refptr<ShareableFileReference> shareable_file =
ShareableFileReference::Get(blob_info.file_path());
@@ -764,7 +763,7 @@ IndexedDBCallbacks::IOThreadHelper::CreateBlobData(
bool IndexedDBCallbacks::IOThreadHelper::CreateAllBlobs(
const std::vector<IndexedDBBlobInfo>& blob_info,
- std::vector<::indexed_db::mojom::BlobInfoPtr>* blob_or_file_info) {
+ std::vector<blink::mojom::IDBBlobInfoPtr>* blob_or_file_info) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!dispatcher_host_) {
OnConnectionError();
diff --git a/chromium/content/browser/indexed_db/indexed_db_callbacks.h b/chromium/content/browser/indexed_db/indexed_db_callbacks.h
index f654d0e144c..daada34ef53 100644
--- a/chromium/content/browser/indexed_db/indexed_db_callbacks.h
+++ b/chromium/content/browser/indexed_db/indexed_db_callbacks.h
@@ -18,22 +18,24 @@
#include "base/strings/string16.h"
#include "content/browser/indexed_db/indexed_db_database_error.h"
#include "content/browser/indexed_db/indexed_db_dispatcher_host.h"
-#include "content/common/indexed_db/indexed_db.mojom.h"
-#include "content/common/indexed_db/indexed_db_key.h"
-#include "content/common/indexed_db/indexed_db_key_path.h"
#include "content/public/browser/browser_thread.h"
+#include "third_party/blink/public/common/indexeddb/indexeddb_key.h"
+#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h"
#include "url/origin.h"
namespace base {
class SequencedTaskRunner;
}
+namespace blink {
+struct IndexedDBDatabaseMetadata;
+}
+
namespace content {
class IndexedDBConnection;
class IndexedDBCursor;
class IndexedDBDatabase;
struct IndexedDBDataLossInfo;
-struct IndexedDBDatabaseMetadata;
struct IndexedDBReturnValue;
struct IndexedDBValue;
@@ -42,14 +44,12 @@ class CONTENT_EXPORT IndexedDBCallbacks
: public base::RefCounted<IndexedDBCallbacks> {
public:
// Destructively converts an IndexedDBValue to a Mojo Value.
- static ::indexed_db::mojom::ValuePtr ConvertAndEraseValue(
- IndexedDBValue* value);
+ static blink::mojom::IDBValuePtr ConvertAndEraseValue(IndexedDBValue* value);
- IndexedDBCallbacks(
- base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host,
- const url::Origin& origin,
- ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks_info,
- scoped_refptr<base::SequencedTaskRunner> idb_runner);
+ IndexedDBCallbacks(base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host,
+ const url::Origin& origin,
+ blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks_info,
+ scoped_refptr<base::SequencedTaskRunner> idb_runner);
virtual void OnError(const IndexedDBDatabaseError& error);
@@ -60,29 +60,28 @@ class CONTENT_EXPORT IndexedDBCallbacks
virtual void OnBlocked(int64_t existing_version);
// IndexedDBFactory::Open
- virtual void OnUpgradeNeeded(
- int64_t old_version,
- std::unique_ptr<IndexedDBConnection> connection,
- const content::IndexedDBDatabaseMetadata& metadata,
- const IndexedDBDataLossInfo& data_loss_info);
+ virtual void OnUpgradeNeeded(int64_t old_version,
+ std::unique_ptr<IndexedDBConnection> connection,
+ const blink::IndexedDBDatabaseMetadata& metadata,
+ const IndexedDBDataLossInfo& data_loss_info);
virtual void OnSuccess(std::unique_ptr<IndexedDBConnection> connection,
- const content::IndexedDBDatabaseMetadata& metadata);
+ const blink::IndexedDBDatabaseMetadata& metadata);
// IndexedDBDatabase::OpenCursor
virtual void OnSuccess(std::unique_ptr<IndexedDBCursor> cursor,
- const IndexedDBKey& key,
- const IndexedDBKey& primary_key,
+ const blink::IndexedDBKey& key,
+ const blink::IndexedDBKey& primary_key,
IndexedDBValue* value);
// IndexedDBCursor::Continue / Advance
- virtual void OnSuccess(const IndexedDBKey& key,
- const IndexedDBKey& primary_key,
+ virtual void OnSuccess(const blink::IndexedDBKey& key,
+ const blink::IndexedDBKey& primary_key,
IndexedDBValue* value);
// IndexedDBCursor::PrefetchContinue
virtual void OnSuccessWithPrefetch(
- const std::vector<IndexedDBKey>& keys,
- const std::vector<IndexedDBKey>& primary_keys,
+ const std::vector<blink::IndexedDBKey>& keys,
+ const std::vector<blink::IndexedDBKey>& primary_keys,
std::vector<IndexedDBValue>* values);
// IndexedDBDatabase::Get
@@ -93,7 +92,7 @@ class CONTENT_EXPORT IndexedDBCallbacks
virtual void OnSuccessArray(std::vector<IndexedDBReturnValue>* values);
// IndexedDBDatabase::Put / IndexedDBCursor::Update
- virtual void OnSuccess(const IndexedDBKey& key);
+ virtual void OnSuccess(const blink::IndexedDBKey& key);
// IndexedDBDatabase::Count
// IndexedDBFactory::DeleteDatabase
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 21fc4381b64..a33b2f14049 100644
--- a/chromium/content/browser/indexed_db/indexed_db_class_factory.h
+++ b/chromium/content/browser/indexed_db/indexed_db_class_factory.h
@@ -15,7 +15,7 @@
#include "content/browser/indexed_db/indexed_db_backing_store.h"
#include "content/browser/indexed_db/indexed_db_database.h"
#include "content/common/content_export.h"
-#include "third_party/blink/public/platform/modules/indexeddb/web_idb_types.h"
+#include "third_party/blink/public/common/indexeddb/web_idb_types.h"
namespace leveldb {
class Iterator;
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 d582605c949..2bd6e7fc36e 100644
--- a/chromium/content/browser/indexed_db/indexed_db_context_impl.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_context_impl.cc
@@ -16,7 +16,7 @@
#include "base/sequenced_task_runner.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_restrictions.h"
#include "base/time/default_clock.h"
#include "base/time/time.h"
@@ -405,6 +405,17 @@ void IndexedDBContextImpl::ForceClose(const Origin origin,
DCHECK_EQ(0UL, GetConnectionCount(origin));
}
+void IndexedDBContextImpl::ForceSchemaDowngrade(const Origin& origin) {
+ DCHECK(TaskRunner()->RunsTasksInCurrentSequence());
+
+ if (data_path_.empty() || !HasOrigin(origin))
+ return;
+
+ if (factory_.get())
+ factory_->ForceSchemaDowngrade(origin);
+ DCHECK_EQ(0UL, GetConnectionCount(origin));
+}
+
size_t IndexedDBContextImpl::GetConnectionCount(const Origin& origin) {
DCHECK(TaskRunner()->RunsTasksInCurrentSequence());
if (!HasOrigin(origin))
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 12eecbed9f0..856f9e3e482 100644
--- a/chromium/content/browser/indexed_db/indexed_db_context_impl.h
+++ b/chromium/content/browser/indexed_db/indexed_db_context_impl.h
@@ -47,6 +47,7 @@ class CONTENT_EXPORT IndexedDBContextImpl : public IndexedDBContext {
FORCE_CLOSE_BACKING_STORE_FAILURE,
FORCE_CLOSE_INTERNALS_PAGE,
FORCE_CLOSE_COPY_ORIGIN,
+ FORCE_SCHEMA_DOWNGRADE_INTERNALS_PAGE,
// Append new values here and update IDBContextForcedCloseReason in
// enums.xml.
FORCE_CLOSE_REASON_MAX
@@ -122,6 +123,7 @@ class CONTENT_EXPORT IndexedDBContextImpl : public IndexedDBContext {
// ForceClose takes a value rather than a reference since it may release the
// owning object.
void ForceClose(const url::Origin origin, ForceCloseReason reason);
+ void ForceSchemaDowngrade(const url::Origin& origin);
// GetStoragePaths returns all paths owned by this database, in arbitrary
// order.
std::vector<base::FilePath> GetStoragePaths(const url::Origin& origin) const;
@@ -191,7 +193,7 @@ class CONTENT_EXPORT IndexedDBContextImpl : public IndexedDBContext {
scoped_refptr<base::SequencedTaskRunner> task_runner_;
std::unique_ptr<std::set<url::Origin>> origin_set_;
std::map<url::Origin, int64_t> origin_size_map_;
- base::ObserverList<Observer> observers_;
+ base::ObserverList<Observer>::Unchecked observers_;
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 bd12dd62086..6a940b17897 100644
--- a/chromium/content/browser/indexed_db/indexed_db_cursor.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_cursor.cc
@@ -17,6 +17,8 @@
#include "content/browser/indexed_db/indexed_db_value.h"
#include "third_party/blink/public/platform/modules/indexeddb/web_idb_database_exception.h"
+using blink::IndexedDBKey;
+
namespace content {
namespace {
// This should never be script visible: the cursor should either be closed when
diff --git a/chromium/content/browser/indexed_db/indexed_db_cursor.h b/chromium/content/browser/indexed_db/indexed_db_cursor.h
index d0cc7e74e37..60aad023c62 100644
--- a/chromium/content/browser/indexed_db/indexed_db_cursor.h
+++ b/chromium/content/browser/indexed_db/indexed_db_cursor.h
@@ -16,8 +16,7 @@
#include "content/browser/indexed_db/indexed_db_backing_store.h"
#include "content/browser/indexed_db/indexed_db_database.h"
#include "content/browser/indexed_db/indexed_db_transaction.h"
-#include "content/common/indexed_db/indexed_db_key_range.h"
-#include "third_party/blink/public/platform/modules/indexeddb/web_idb_types.h"
+#include "third_party/blink/public/common/indexeddb/web_idb_types.h"
namespace content {
@@ -30,15 +29,17 @@ class CONTENT_EXPORT IndexedDBCursor {
~IndexedDBCursor();
void Advance(uint32_t count, scoped_refptr<IndexedDBCallbacks> callbacks);
- void Continue(std::unique_ptr<IndexedDBKey> key,
- std::unique_ptr<IndexedDBKey> primary_key,
+ void Continue(std::unique_ptr<blink::IndexedDBKey> key,
+ std::unique_ptr<blink::IndexedDBKey> primary_key,
scoped_refptr<IndexedDBCallbacks> callbacks);
void PrefetchContinue(int number_to_fetch,
scoped_refptr<IndexedDBCallbacks> callbacks);
leveldb::Status PrefetchReset(int used_prefetches, int unused_prefetches);
- const IndexedDBKey& key() const { return cursor_->key(); }
- const IndexedDBKey& primary_key() const { return cursor_->primary_key(); }
+ const blink::IndexedDBKey& key() const { return cursor_->key(); }
+ const blink::IndexedDBKey& primary_key() const {
+ return cursor_->primary_key();
+ }
IndexedDBValue* Value() const {
return (cursor_type_ == indexed_db::CURSOR_KEY_ONLY) ? NULL
: cursor_->value();
@@ -47,8 +48,8 @@ class CONTENT_EXPORT IndexedDBCursor {
void Close();
leveldb::Status CursorIterationOperation(
- std::unique_ptr<IndexedDBKey> key,
- std::unique_ptr<IndexedDBKey> primary_key,
+ std::unique_ptr<blink::IndexedDBKey> key,
+ std::unique_ptr<blink::IndexedDBKey> primary_key,
scoped_refptr<IndexedDBCallbacks> callbacks,
IndexedDBTransaction* transaction);
leveldb::Status CursorAdvanceOperation(
diff --git a/chromium/content/browser/indexed_db/indexed_db_data_loss_info.h b/chromium/content/browser/indexed_db/indexed_db_data_loss_info.h
index 8c36dd38666..318f04e78e2 100644
--- a/chromium/content/browser/indexed_db/indexed_db_data_loss_info.h
+++ b/chromium/content/browser/indexed_db/indexed_db_data_loss_info.h
@@ -7,7 +7,7 @@
#include <string>
-#include "third_party/blink/public/platform/modules/indexeddb/web_idb_types.h"
+#include "third_party/blink/public/common/indexeddb/web_idb_types.h"
namespace content {
diff --git a/chromium/content/browser/indexed_db/indexed_db_database.cc b/chromium/content/browser/indexed_db/indexed_db_database.cc
index 3baba4f2ed7..62b40f652fb 100644
--- a/chromium/content/browser/indexed_db/indexed_db_database.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_database.cc
@@ -31,17 +31,25 @@
#include "content/browser/indexed_db/indexed_db_tracing.h"
#include "content/browser/indexed_db/indexed_db_transaction.h"
#include "content/browser/indexed_db/indexed_db_value.h"
-#include "content/common/indexed_db/indexed_db_constants.h"
-#include "content/common/indexed_db/indexed_db_key_path.h"
-#include "content/common/indexed_db/indexed_db_key_range.h"
#include "content/public/common/content_switches.h"
+#include "ipc/ipc_channel.h"
#include "storage/browser/blob/blob_data_handle.h"
+#include "third_party/blink/public/common/indexeddb/indexeddb_key_path.h"
+#include "third_party/blink/public/common/indexeddb/indexeddb_key_range.h"
+#include "third_party/blink/public/common/indexeddb/indexeddb_metadata.h"
#include "third_party/blink/public/platform/modules/indexeddb/web_idb_database_exception.h"
#include "third_party/leveldatabase/env_chromium.h"
#include "url/origin.h"
using base::ASCIIToUTF16;
using base::Int64ToString16;
+using blink::IndexedDBDatabaseMetadata;
+using blink::IndexedDBIndexKeys;
+using blink::IndexedDBIndexMetadata;
+using blink::IndexedDBKey;
+using blink::IndexedDBKeyPath;
+using blink::IndexedDBKeyRange;
+using blink::IndexedDBObjectStoreMetadata;
using blink::kWebIDBKeyTypeNumber;
using leveldb::Status;
@@ -469,8 +477,18 @@ IndexedDBDatabase::~IndexedDBDatabase() {
DCHECK(pending_requests_.empty());
}
-size_t IndexedDBDatabase::GetMaxMessageSizeInBytes() const {
- return kMaxIDBMessageSizeInBytes;
+// 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
+// value is always no bigger than the current kMaximumMessageSize value which
+// also ensures it is always no bigger than the current Mojo message size limit.
+static_assert(
+ blink::mojom::kIDBMaxMessageSize <= IPC::Channel::kMaximumMessageSize,
+ "kIDBMaxMessageSize is bigger than IPC::Channel::kMaximumMessageSize");
+
+size_t IndexedDBDatabase::GetUsableMessageSizeInBytes() const {
+ return blink::mojom::kIDBMaxMessageSize -
+ blink::mojom::kIDBMaxMessageOverhead;
}
std::unique_ptr<IndexedDBConnection> IndexedDBDatabase::CreateConnection(
@@ -816,7 +834,7 @@ void IndexedDBDatabase::FilterObservation(IndexedDBTransaction* transaction,
!observer->IsRecordingObjectStore(object_store_id))
continue;
if (!recorded) {
- auto observation = ::indexed_db::mojom::Observation::New();
+ auto observation = blink::mojom::IDBObservation::New();
observation->object_store_id = object_store_id;
observation->type = type;
if (type != blink::kWebIDBClear)
@@ -824,14 +842,14 @@ void IndexedDBDatabase::FilterObservation(IndexedDBTransaction* transaction,
transaction->AddObservation(connection->id(), std::move(observation));
recorded = true;
}
- ::indexed_db::mojom::ObserverChangesPtr& changes =
+ blink::mojom::IDBObserverChangesPtr& changes =
*transaction->GetPendingChangesForConnection(connection->id());
changes->observation_index_map[observer->id()].push_back(
changes->observations.size() - 1);
if (observer->include_transaction() &&
!base::ContainsKey(changes->transaction_map, observer->id())) {
- auto mojo_transaction = ::indexed_db::mojom::ObserverTransaction::New();
+ auto mojo_transaction = blink::mojom::IDBObserverTransaction::New();
mojo_transaction->id = connection->NewObserverTransactionId();
mojo_transaction->scope.insert(mojo_transaction->scope.end(),
observer->object_store_ids().begin(),
@@ -851,14 +869,14 @@ void IndexedDBDatabase::FilterObservation(IndexedDBTransaction* transaction,
}
void IndexedDBDatabase::SendObservations(
- std::map<int32_t, ::indexed_db::mojom::ObserverChangesPtr> changes_map) {
+ std::map<int32_t, blink::mojom::IDBObserverChangesPtr> changes_map) {
for (auto* conn : connections_) {
auto it = changes_map.find(conn->id());
if (it == changes_map.end())
continue;
// Start all of the transactions.
- ::indexed_db::mojom::ObserverChangesPtr& changes = it->second;
+ blink::mojom::IDBObserverChangesPtr& changes = it->second;
for (const auto& transaction_pair : changes->transaction_map) {
std::set<int64_t> scope(transaction_pair.second->scope.begin(),
transaction_pair.second->scope.end());
@@ -1047,6 +1065,11 @@ Status IndexedDBDatabase::GetOperation(
return s;
}
+static_assert(sizeof(size_t) >= sizeof(int32_t),
+ "Size of size_t is less than size of int32");
+static_assert(blink::mojom::kIDBMaxMessageOverhead <= INT32_MAX,
+ "kIDBMaxMessageOverhead is more than INT32_MAX");
+
Status IndexedDBDatabase::GetAllOperation(
int64_t object_store_id,
int64_t index_id,
@@ -1114,7 +1137,7 @@ Status IndexedDBDatabase::GetAllOperation(
bool generated_key = object_store_metadata.auto_increment &&
!object_store_metadata.key_path.IsNull();
- size_t response_size = kMaxIDBMessageOverhead;
+ size_t response_size = blink::mojom::kIDBMaxMessageOverhead;
int64_t num_found_items = 0;
while (num_found_items++ < max_count) {
bool cursor_valid;
@@ -1148,7 +1171,7 @@ Status IndexedDBDatabase::GetAllOperation(
response_size += return_key.size_estimate();
else
response_size += return_value.SizeEstimate();
- if (response_size > GetMaxMessageSizeInBytes()) {
+ if (response_size > GetUsableMessageSizeInBytes()) {
callbacks->OnError(
IndexedDBDatabaseError(blink::kWebIDBDatabaseExceptionUnknownError,
"Maximum IPC message size exceeded."));
@@ -1216,7 +1239,6 @@ struct IndexedDBDatabase::PutOperationParams {
PutOperationParams() {}
int64_t object_store_id;
IndexedDBValue value;
- std::vector<std::unique_ptr<storage::BlobDataHandle>> handles;
std::unique_ptr<IndexedDBKey> key;
blink::WebIDBPutMode put_mode;
scoped_refptr<IndexedDBCallbacks> callbacks;
@@ -1230,7 +1252,6 @@ void IndexedDBDatabase::Put(
IndexedDBTransaction* transaction,
int64_t object_store_id,
IndexedDBValue* value,
- std::vector<std::unique_ptr<storage::BlobDataHandle>>* handles,
std::unique_ptr<IndexedDBKey> key,
blink::WebIDBPutMode put_mode,
scoped_refptr<IndexedDBCallbacks> callbacks,
@@ -1248,7 +1269,6 @@ void IndexedDBDatabase::Put(
std::make_unique<PutOperationParams>());
params->object_store_id = object_store_id;
params->value.swap(*value);
- params->handles.swap(*handles);
params->key = std::move(key);
params->put_mode = put_mode;
params->callbacks = callbacks;
@@ -1336,7 +1356,7 @@ Status IndexedDBDatabase::PutOperation(
// transaction in case of error.
s = backing_store_->PutRecord(transaction->BackingStoreTransaction(), id(),
params->object_store_id, *key, &params->value,
- &params->handles, &record_identifier);
+ &record_identifier);
if (!s.ok())
return s;
diff --git a/chromium/content/browser/indexed_db/indexed_db_database.h b/chromium/content/browser/indexed_db/indexed_db_database.h
index 0fc4f636c2b..4ca1676c41a 100644
--- a/chromium/content/browser/indexed_db/indexed_db_database.h
+++ b/chromium/content/browser/indexed_db/indexed_db_database.h
@@ -28,8 +28,16 @@
#include "content/browser/indexed_db/indexed_db_transaction_coordinator.h"
#include "content/browser/indexed_db/list_set.h"
#include "content/common/content_export.h"
-#include "content/common/indexed_db/indexed_db_metadata.h"
-#include "third_party/blink/public/platform/modules/indexeddb/web_idb_types.h"
+#include "third_party/blink/public/common/indexeddb/indexeddb_key.h"
+#include "third_party/blink/public/common/indexeddb/web_idb_types.h"
+
+namespace blink {
+class IndexedDBKeyPath;
+class IndexedDBKeyRange;
+struct IndexedDBDatabaseMetadata;
+struct IndexedDBIndexMetadata;
+struct IndexedDBObjectStoreMetadata;
+} // namespace blink
namespace url {
class Origin;
@@ -40,9 +48,6 @@ namespace content {
class IndexedDBConnection;
class IndexedDBDatabaseCallbacks;
class IndexedDBFactory;
-class IndexedDBKey;
-class IndexedDBKeyPath;
-class IndexedDBKeyRange;
class IndexedDBMetadataCoding;
class IndexedDBTransaction;
struct IndexedDBValue;
@@ -70,23 +75,25 @@ class CONTENT_EXPORT IndexedDBDatabase
const base::string16& name() const { return metadata_.name; }
const url::Origin& origin() const { return identifier_.first; }
- void AddObjectStore(IndexedDBObjectStoreMetadata metadata,
+ void AddObjectStore(blink::IndexedDBObjectStoreMetadata metadata,
int64_t new_max_object_store_id);
- IndexedDBObjectStoreMetadata RemoveObjectStore(int64_t object_store_id);
+ blink::IndexedDBObjectStoreMetadata RemoveObjectStore(
+ int64_t object_store_id);
void AddIndex(int64_t object_store_id,
- IndexedDBIndexMetadata metadata,
+ blink::IndexedDBIndexMetadata metadata,
int64_t new_max_index_id);
- IndexedDBIndexMetadata RemoveIndex(int64_t object_store_id, int64_t index_id);
+ 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);
- const IndexedDBDatabaseMetadata& metadata() const { return metadata_; }
+ const blink::IndexedDBDatabaseMetadata& metadata() const { return metadata_; }
void CreateObjectStore(IndexedDBTransaction* transaction,
int64_t object_store_id,
const base::string16& name,
- const IndexedDBKeyPath& key_path,
+ const blink::IndexedDBKeyPath& key_path,
bool auto_increment);
void DeleteObjectStore(IndexedDBTransaction* transaction,
int64_t object_store_id);
@@ -115,7 +122,7 @@ class CONTENT_EXPORT IndexedDBDatabase
int64_t object_store_id,
int64_t index_id,
const base::string16& name,
- const IndexedDBKeyPath& key_path,
+ const blink::IndexedDBKeyPath& key_path,
bool unique,
bool multi_entry);
void DeleteIndex(IndexedDBTransaction* transaction,
@@ -146,43 +153,42 @@ class CONTENT_EXPORT IndexedDBDatabase
void FilterObservation(IndexedDBTransaction*,
int64_t object_store_id,
blink::WebIDBOperationType type,
- const IndexedDBKeyRange& key_range,
+ const blink::IndexedDBKeyRange& key_range,
const IndexedDBValue* value);
void SendObservations(
- std::map<int32_t, ::indexed_db::mojom::ObserverChangesPtr> change_map);
+ std::map<int32_t, blink::mojom::IDBObserverChangesPtr> change_map);
void Get(IndexedDBTransaction* transaction,
int64_t object_store_id,
int64_t index_id,
- std::unique_ptr<IndexedDBKeyRange> key_range,
+ std::unique_ptr<blink::IndexedDBKeyRange> key_range,
bool key_only,
scoped_refptr<IndexedDBCallbacks> callbacks);
void GetAll(IndexedDBTransaction* transaction,
int64_t object_store_id,
int64_t index_id,
- std::unique_ptr<IndexedDBKeyRange> key_range,
+ std::unique_ptr<blink::IndexedDBKeyRange> key_range,
bool key_only,
int64_t max_count,
scoped_refptr<IndexedDBCallbacks> callbacks);
void Put(IndexedDBTransaction* transaction,
int64_t object_store_id,
IndexedDBValue* value,
- std::vector<std::unique_ptr<storage::BlobDataHandle>>* handles,
- std::unique_ptr<IndexedDBKey> key,
+ std::unique_ptr<blink::IndexedDBKey> key,
blink::WebIDBPutMode mode,
scoped_refptr<IndexedDBCallbacks> callbacks,
- const std::vector<IndexedDBIndexKeys>& index_keys);
+ const std::vector<blink::IndexedDBIndexKeys>& index_keys);
void SetIndexKeys(IndexedDBTransaction* transaction,
int64_t object_store_id,
- std::unique_ptr<IndexedDBKey> primary_key,
- const std::vector<IndexedDBIndexKeys>& index_keys);
+ std::unique_ptr<blink::IndexedDBKey> primary_key,
+ const std::vector<blink::IndexedDBIndexKeys>& index_keys);
void SetIndexesReady(IndexedDBTransaction* transaction,
int64_t object_store_id,
const std::vector<int64_t>& index_ids);
void OpenCursor(IndexedDBTransaction* transaction,
int64_t object_store_id,
int64_t index_id,
- std::unique_ptr<IndexedDBKeyRange> key_range,
+ std::unique_ptr<blink::IndexedDBKeyRange> key_range,
blink::WebIDBCursorDirection,
bool key_only,
blink::WebIDBTaskType task_type,
@@ -190,11 +196,11 @@ class CONTENT_EXPORT IndexedDBDatabase
void Count(IndexedDBTransaction* transaction,
int64_t object_store_id,
int64_t index_id,
- std::unique_ptr<IndexedDBKeyRange> key_range,
+ std::unique_ptr<blink::IndexedDBKeyRange> key_range,
scoped_refptr<IndexedDBCallbacks> callbacks);
void DeleteRange(IndexedDBTransaction* transaction,
int64_t object_store_id,
- std::unique_ptr<IndexedDBKeyRange> key_range,
+ std::unique_ptr<blink::IndexedDBKeyRange> key_range,
scoped_refptr<IndexedDBCallbacks> callbacks);
void Clear(IndexedDBTransaction* transaction,
int64_t object_store_id,
@@ -215,7 +221,7 @@ class CONTENT_EXPORT IndexedDBDatabase
leveldb::Status DeleteObjectStoreOperation(int64_t object_store_id,
IndexedDBTransaction* transaction);
void DeleteObjectStoreAbortOperation(
- IndexedDBObjectStoreMetadata object_store_metadata);
+ blink::IndexedDBObjectStoreMetadata object_store_metadata);
void RenameObjectStoreAbortOperation(int64_t object_store_id,
base::string16 old_name);
leveldb::Status VersionChangeOperation(
@@ -228,23 +234,25 @@ class CONTENT_EXPORT IndexedDBDatabase
IndexedDBTransaction* transaction);
void CreateIndexAbortOperation(int64_t object_store_id, int64_t index_id);
void DeleteIndexAbortOperation(int64_t object_store_id,
- IndexedDBIndexMetadata index_metadata);
+ blink::IndexedDBIndexMetadata index_metadata);
void RenameIndexAbortOperation(int64_t object_store_id,
int64_t index_id,
base::string16 old_name);
- leveldb::Status GetOperation(int64_t object_store_id,
- int64_t index_id,
- std::unique_ptr<IndexedDBKeyRange> key_range,
- indexed_db::CursorType cursor_type,
- scoped_refptr<IndexedDBCallbacks> callbacks,
- IndexedDBTransaction* transaction);
- leveldb::Status GetAllOperation(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,
- IndexedDBTransaction* transaction);
+ leveldb::Status GetOperation(
+ int64_t object_store_id,
+ int64_t index_id,
+ std::unique_ptr<blink::IndexedDBKeyRange> key_range,
+ indexed_db::CursorType cursor_type,
+ scoped_refptr<IndexedDBCallbacks> callbacks,
+ IndexedDBTransaction* transaction);
+ leveldb::Status GetAllOperation(
+ 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,
+ IndexedDBTransaction* transaction);
struct PutOperationParams;
leveldb::Status PutOperation(std::unique_ptr<PutOperationParams> params,
IndexedDBTransaction* transaction);
@@ -254,14 +262,15 @@ class CONTENT_EXPORT IndexedDBDatabase
leveldb::Status OpenCursorOperation(
std::unique_ptr<OpenCursorOperationParams> params,
IndexedDBTransaction* transaction);
- leveldb::Status CountOperation(int64_t object_store_id,
- int64_t index_id,
- std::unique_ptr<IndexedDBKeyRange> key_range,
- scoped_refptr<IndexedDBCallbacks> callbacks,
- IndexedDBTransaction* transaction);
+ leveldb::Status CountOperation(
+ int64_t object_store_id,
+ int64_t index_id,
+ std::unique_ptr<blink::IndexedDBKeyRange> key_range,
+ scoped_refptr<IndexedDBCallbacks> callbacks,
+ IndexedDBTransaction* transaction);
leveldb::Status DeleteRangeOperation(
int64_t object_store_id,
- std::unique_ptr<IndexedDBKeyRange> key_range,
+ std::unique_ptr<blink::IndexedDBKeyRange> key_range,
scoped_refptr<IndexedDBCallbacks> callbacks,
IndexedDBTransaction* transaction);
leveldb::Status ClearOperation(int64_t object_store_id,
@@ -287,7 +296,7 @@ class CONTENT_EXPORT IndexedDBDatabase
virtual ~IndexedDBDatabase();
// May be overridden in tests.
- virtual size_t GetMaxMessageSizeInBytes() const;
+ virtual size_t GetUsableMessageSizeInBytes() const;
private:
friend class base::RefCounted<IndexedDBDatabase>;
@@ -328,7 +337,7 @@ class CONTENT_EXPORT IndexedDBDatabase
int64_t index_id) const;
scoped_refptr<IndexedDBBackingStore> backing_store_;
- IndexedDBDatabaseMetadata metadata_;
+ blink::IndexedDBDatabaseMetadata metadata_;
const Identifier identifier_;
scoped_refptr<IndexedDBFactory> factory_;
diff --git a/chromium/content/browser/indexed_db/indexed_db_database_callbacks.cc b/chromium/content/browser/indexed_db/indexed_db_database_callbacks.cc
index 0dcddfd12fc..2da4f50e3b4 100644
--- a/chromium/content/browser/indexed_db/indexed_db_database_callbacks.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_database_callbacks.cc
@@ -9,31 +9,31 @@
#include "content/browser/indexed_db/indexed_db_dispatcher_host.h"
#include "content/browser/indexed_db/indexed_db_transaction.h"
-using ::indexed_db::mojom::DatabaseCallbacksAssociatedPtrInfo;
+using blink::mojom::IDBDatabaseCallbacksAssociatedPtrInfo;
namespace content {
class IndexedDBDatabaseCallbacks::IOThreadHelper {
public:
- explicit IOThreadHelper(DatabaseCallbacksAssociatedPtrInfo callbacks_info);
+ explicit IOThreadHelper(IDBDatabaseCallbacksAssociatedPtrInfo callbacks_info);
~IOThreadHelper();
void SendForcedClose();
void SendVersionChange(int64_t old_version, int64_t new_version);
void SendAbort(int64_t transaction_id, const IndexedDBDatabaseError& error);
void SendComplete(int64_t transaction_id);
- void SendChanges(::indexed_db::mojom::ObserverChangesPtr changes);
+ void SendChanges(blink::mojom::IDBObserverChangesPtr changes);
void OnConnectionError();
private:
- ::indexed_db::mojom::DatabaseCallbacksAssociatedPtr callbacks_;
+ blink::mojom::IDBDatabaseCallbacksAssociatedPtr callbacks_;
DISALLOW_COPY_AND_ASSIGN(IOThreadHelper);
};
IndexedDBDatabaseCallbacks::IndexedDBDatabaseCallbacks(
scoped_refptr<IndexedDBContextImpl> context,
- DatabaseCallbacksAssociatedPtrInfo callbacks_info)
+ IDBDatabaseCallbacksAssociatedPtrInfo callbacks_info)
: indexed_db_context_(std::move(context)),
io_helper_(new IOThreadHelper(std::move(callbacks_info))) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -98,7 +98,7 @@ void IndexedDBDatabaseCallbacks::OnComplete(
}
void IndexedDBDatabaseCallbacks::OnDatabaseChange(
- ::indexed_db::mojom::ObserverChangesPtr changes) {
+ blink::mojom::IDBObserverChangesPtr changes) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(io_helper_);
BrowserThread::PostTask(
@@ -108,7 +108,7 @@ void IndexedDBDatabaseCallbacks::OnDatabaseChange(
}
IndexedDBDatabaseCallbacks::IOThreadHelper::IOThreadHelper(
- DatabaseCallbacksAssociatedPtrInfo callbacks_info) {
+ IDBDatabaseCallbacksAssociatedPtrInfo callbacks_info) {
if (!callbacks_info.is_valid())
return;
callbacks_.Bind(std::move(callbacks_info));
@@ -144,7 +144,7 @@ void IndexedDBDatabaseCallbacks::IOThreadHelper::SendComplete(
}
void IndexedDBDatabaseCallbacks::IOThreadHelper::SendChanges(
- ::indexed_db::mojom::ObserverChangesPtr changes) {
+ blink::mojom::IDBObserverChangesPtr changes) {
if (callbacks_)
callbacks_->Changes(std::move(changes));
}
diff --git a/chromium/content/browser/indexed_db/indexed_db_database_callbacks.h b/chromium/content/browser/indexed_db/indexed_db_database_callbacks.h
index 86160968999..282d7736f0d 100644
--- a/chromium/content/browser/indexed_db/indexed_db_database_callbacks.h
+++ b/chromium/content/browser/indexed_db/indexed_db_database_callbacks.h
@@ -11,8 +11,8 @@
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "content/common/content_export.h"
-#include "content/common/indexed_db/indexed_db.mojom.h"
#include "content/public/browser/browser_thread.h"
+#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h"
namespace content {
class IndexedDBContextImpl;
@@ -25,7 +25,7 @@ class CONTENT_EXPORT IndexedDBDatabaseCallbacks
public:
IndexedDBDatabaseCallbacks(
scoped_refptr<IndexedDBContextImpl> context,
- ::indexed_db::mojom::DatabaseCallbacksAssociatedPtrInfo callbacks_info);
+ blink::mojom::IDBDatabaseCallbacksAssociatedPtrInfo callbacks_info);
virtual void OnForcedClose();
virtual void OnVersionChange(int64_t old_version, int64_t new_version);
@@ -33,8 +33,7 @@ class CONTENT_EXPORT IndexedDBDatabaseCallbacks
virtual void OnAbort(const IndexedDBTransaction& transaction,
const IndexedDBDatabaseError& error);
virtual void OnComplete(const IndexedDBTransaction& transaction);
- virtual void OnDatabaseChange(
- ::indexed_db::mojom::ObserverChangesPtr changes);
+ virtual void OnDatabaseChange(blink::mojom::IDBObserverChangesPtr changes);
protected:
virtual ~IndexedDBDatabaseCallbacks();
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 fd5e26400ab..7a8db895399 100644
--- a/chromium/content/browser/indexed_db/indexed_db_database_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_database_unittest.cc
@@ -32,6 +32,10 @@
#include "testing/gtest/include/gtest/gtest.h"
using base::ASCIIToUTF16;
+using blink::IndexedDBDatabaseMetadata;
+using blink::IndexedDBIndexKeys;
+using blink::IndexedDBKey;
+using blink::IndexedDBKeyPath;
namespace {
const int kFakeChildProcessId = 0;
@@ -451,12 +455,11 @@ TEST_F(IndexedDBDatabaseOperationTest, CreatePutDelete) {
// Put is asynchronous
IndexedDBValue value("value1", std::vector<IndexedDBBlobInfo>());
- std::vector<std::unique_ptr<storage::BlobDataHandle>> handles;
std::unique_ptr<IndexedDBKey> key(std::make_unique<IndexedDBKey>("key"));
std::vector<IndexedDBIndexKeys> index_keys;
scoped_refptr<MockIndexedDBCallbacks> request(
new MockIndexedDBCallbacks(false));
- db_->Put(transaction_, store_id, &value, &handles, std::move(key),
+ db_->Put(transaction_, store_id, &value, std::move(key),
blink::kWebIDBPutModeAddOnly, request, index_keys);
// Deletion is asynchronous.
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 034a34e0465..e876744e8dc 100644
--- a/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.cc
@@ -32,19 +32,19 @@ bool IsValidOrigin(const url::Origin& origin) {
return !origin.unique();
}
-::indexed_db::mojom::Status GetIndexedDBStatus(leveldb::Status status) {
+blink::mojom::IDBStatus GetIndexedDBStatus(leveldb::Status status) {
if (status.ok())
- return ::indexed_db::mojom::Status::OK;
+ return blink::mojom::IDBStatus::OK;
else if (status.IsNotFound())
- return ::indexed_db::mojom::Status::NotFound;
+ return blink::mojom::IDBStatus::NotFound;
else if (status.IsCorruption())
- return ::indexed_db::mojom::Status::Corruption;
+ return blink::mojom::IDBStatus::Corruption;
else if (status.IsNotSupportedError())
- return ::indexed_db::mojom::Status::NotSupported;
+ return blink::mojom::IDBStatus::NotSupported;
else if (status.IsInvalidArgument())
- return ::indexed_db::mojom::Status::InvalidArgument;
+ return blink::mojom::IDBStatus::InvalidArgument;
else
- return ::indexed_db::mojom::Status::IOError;
+ return blink::mojom::IDBStatus::IOError;
}
void DoCallCompactionStatusCallback(
@@ -142,19 +142,19 @@ IndexedDBDispatcherHost::~IndexedDBDispatcherHost() {
}
void IndexedDBDispatcherHost::AddBinding(
- ::indexed_db::mojom::FactoryAssociatedRequest request) {
+ blink::mojom::IDBFactoryRequest request) {
bindings_.AddBinding(this, std::move(request));
}
void IndexedDBDispatcherHost::AddDatabaseBinding(
- std::unique_ptr<::indexed_db::mojom::Database> database,
- ::indexed_db::mojom::DatabaseAssociatedRequest request) {
+ std::unique_ptr<blink::mojom::IDBDatabase> database,
+ blink::mojom::IDBDatabaseAssociatedRequest request) {
database_bindings_.AddBinding(std::move(database), std::move(request));
}
void IndexedDBDispatcherHost::AddCursorBinding(
- std::unique_ptr<::indexed_db::mojom::Cursor> cursor,
- ::indexed_db::mojom::CursorAssociatedRequest request) {
+ std::unique_ptr<blink::mojom::IDBCursor> cursor,
+ blink::mojom::IDBCursorAssociatedRequest request) {
cursor_bindings_.AddBinding(std::move(cursor), std::move(request));
}
@@ -169,7 +169,7 @@ void IndexedDBDispatcherHost::RenderProcessExited(
}
void IndexedDBDispatcherHost::GetDatabaseNames(
- ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks_info,
+ blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks_info,
const url::Origin& origin) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -187,9 +187,8 @@ void IndexedDBDispatcherHost::GetDatabaseNames(
}
void IndexedDBDispatcherHost::Open(
- ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks_info,
- ::indexed_db::mojom::DatabaseCallbacksAssociatedPtrInfo
- database_callbacks_info,
+ blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks_info,
+ blink::mojom::IDBDatabaseCallbacksAssociatedPtrInfo database_callbacks_info,
const url::Origin& origin,
const base::string16& name,
int64_t version,
@@ -215,7 +214,7 @@ void IndexedDBDispatcherHost::Open(
}
void IndexedDBDispatcherHost::DeleteDatabase(
- ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks_info,
+ blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks_info,
const url::Origin& origin,
const base::string16& name,
bool force_close) {
diff --git a/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.h b/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.h
index dc177044771..099b0315498 100644
--- a/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.h
+++ b/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.h
@@ -17,12 +17,12 @@
#include "base/memory/ref_counted.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/common/content_export.h"
-#include "content/common/indexed_db/indexed_db.mojom.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host_observer.h"
#include "mojo/public/cpp/bindings/associated_binding_set.h"
#include "mojo/public/cpp/bindings/strong_associated_binding_set.h"
#include "net/url_request/url_request_context_getter.h"
+#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h"
namespace base {
class SequencedTaskRunner;
@@ -39,7 +39,7 @@ class IndexedDBContextImpl;
// Constructed on UI thread, expects all other calls (including destruction) on
// IO thread.
class CONTENT_EXPORT IndexedDBDispatcherHost
- : public ::indexed_db::mojom::Factory,
+ : public blink::mojom::IDBFactory,
public RenderProcessHostObserver {
public:
// Only call the constructor from the UI thread.
@@ -49,14 +49,13 @@ class CONTENT_EXPORT IndexedDBDispatcherHost
scoped_refptr<IndexedDBContextImpl> indexed_db_context,
scoped_refptr<ChromeBlobStorageContext> blob_storage_context);
- void AddBinding(::indexed_db::mojom::FactoryAssociatedRequest request);
+ void AddBinding(blink::mojom::IDBFactoryRequest request);
- void AddDatabaseBinding(
- std::unique_ptr<::indexed_db::mojom::Database> database,
- ::indexed_db::mojom::DatabaseAssociatedRequest request);
+ void AddDatabaseBinding(std::unique_ptr<blink::mojom::IDBDatabase> database,
+ blink::mojom::IDBDatabaseAssociatedRequest request);
- void AddCursorBinding(std::unique_ptr<::indexed_db::mojom::Cursor> cursor,
- ::indexed_db::mojom::CursorAssociatedRequest request);
+ void AddCursorBinding(std::unique_ptr<blink::mojom::IDBCursor> cursor,
+ blink::mojom::IDBCursorAssociatedRequest request);
// A shortcut for accessing our context.
IndexedDBContextImpl* context() const { return indexed_db_context_.get(); }
@@ -84,19 +83,19 @@ class CONTENT_EXPORT IndexedDBDispatcherHost
~IndexedDBDispatcherHost() override;
- // indexed_db::mojom::Factory implementation:
+ // blink::mojom::IDBFactory implementation:
void GetDatabaseNames(
- ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks_info,
+ blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks_info,
const url::Origin& origin) override;
- void Open(::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks_info,
- ::indexed_db::mojom::DatabaseCallbacksAssociatedPtrInfo
+ void Open(blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks_info,
+ blink::mojom::IDBDatabaseCallbacksAssociatedPtrInfo
database_callbacks_info,
const url::Origin& origin,
const base::string16& name,
int64_t version,
int64_t transaction_id) override;
void DeleteDatabase(
- ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks_info,
+ blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks_info,
const url::Origin& origin,
const base::string16& name,
bool force_close) override;
@@ -117,13 +116,12 @@ class CONTENT_EXPORT IndexedDBDispatcherHost
// Used to set file permissions for blob storage.
const int ipc_process_id_;
- mojo::AssociatedBindingSet<::indexed_db::mojom::Factory> bindings_;
+ mojo::BindingSet<blink::mojom::IDBFactory> bindings_;
- mojo::StrongAssociatedBindingSet<::indexed_db::mojom::Database>
+ mojo::StrongAssociatedBindingSet<blink::mojom::IDBDatabase>
database_bindings_;
- mojo::StrongAssociatedBindingSet<::indexed_db::mojom::Cursor>
- cursor_bindings_;
+ mojo::StrongAssociatedBindingSet<blink::mojom::IDBCursor> cursor_bindings_;
IDBSequenceHelper* idb_helper_;
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 ff718191b32..960febdf847 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
@@ -20,7 +20,6 @@
#include "content/browser/indexed_db/indexed_db_pending_connection.h"
#include "content/browser/indexed_db/mock_mojo_indexed_db_callbacks.h"
#include "content/browser/indexed_db/mock_mojo_indexed_db_database_callbacks.h"
-#include "content/common/indexed_db/indexed_db.mojom.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"
@@ -32,22 +31,24 @@
#include "storage/browser/test/mock_special_storage_policy.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h"
#include "third_party/blink/public/platform/modules/indexeddb/web_idb_database_exception.h"
#include "url/origin.h"
-using indexed_db::mojom::Callbacks;
-using indexed_db::mojom::CallbacksAssociatedPtrInfo;
-using indexed_db::mojom::DatabaseAssociatedPtr;
-using indexed_db::mojom::DatabaseAssociatedPtrInfo;
-using indexed_db::mojom::DatabaseAssociatedRequest;
-using indexed_db::mojom::DatabaseCallbacks;
-using indexed_db::mojom::DatabaseCallbacksAssociatedPtrInfo;
-using indexed_db::mojom::Factory;
-using indexed_db::mojom::FactoryAssociatedPtr;
-using indexed_db::mojom::FactoryAssociatedRequest;
-using indexed_db::mojom::KeyPath;
-using indexed_db::mojom::Value;
-using indexed_db::mojom::ValuePtr;
+using blink::mojom::IDBValue;
+using blink::mojom::IDBValuePtr;
+using blink::IndexedDBDatabaseMetadata;
+using blink::IndexedDBIndexKeys;
+using blink::IndexedDBKey;
+using blink::mojom::IDBCallbacks;
+using blink::mojom::IDBCallbacksAssociatedPtrInfo;
+using blink::mojom::IDBDatabaseAssociatedPtr;
+using blink::mojom::IDBDatabaseAssociatedPtrInfo;
+using blink::mojom::IDBDatabaseAssociatedRequest;
+using blink::mojom::IDBDatabaseCallbacks;
+using blink::mojom::IDBDatabaseCallbacksAssociatedPtrInfo;
+using blink::mojom::IDBFactory;
+using blink::mojom::IDBFactoryPtr;
using mojo::StrongAssociatedBindingPtr;
using testing::_;
using testing::StrictMock;
@@ -103,7 +104,7 @@ struct TestDatabaseConnection {
new StrictMock<MockMojoIndexedDBDatabaseCallbacks>()){};
~TestDatabaseConnection() {}
- void Open(Factory* factory) {
+ void Open(IDBFactory* factory) {
factory->Open(open_callbacks->CreateInterfacePtrAndBind(),
connection_callbacks->CreateInterfacePtrAndBind(), origin,
db_name, version, upgrade_txn_id);
@@ -114,7 +115,7 @@ struct TestDatabaseConnection {
int64_t version;
int64_t upgrade_txn_id;
- DatabaseAssociatedPtr database;
+ IDBDatabaseAssociatedPtr database;
std::unique_ptr<MockMojoIndexedDBCallbacks> open_callbacks;
std::unique_ptr<MockMojoIndexedDBDatabaseCallbacks> connection_callbacks;
@@ -124,8 +125,8 @@ struct TestDatabaseConnection {
};
void StatusCallback(const base::Closure& callback,
- ::indexed_db::mojom::Status* status_out,
- ::indexed_db::mojom::Status status) {
+ blink::mojom::IDBStatus* status_out,
+ blink::mojom::IDBStatus status) {
*status_out = status;
callback.Run();
}
@@ -184,9 +185,7 @@ class IndexedDBDispatcherHostTest : public testing::Test {
}
void SetUp() override {
- FactoryAssociatedRequest request =
- ::mojo::MakeRequestAssociatedWithDedicatedPipe(&idb_mojo_factory_);
- host_->AddBinding(std::move(request));
+ host_->AddBinding(::mojo::MakeRequest(&idb_mojo_factory_));
}
protected:
@@ -199,7 +198,7 @@ class IndexedDBDispatcherHostTest : public testing::Test {
scoped_refptr<IndexedDBContextImpl> context_impl_;
std::unique_ptr<IndexedDBDispatcherHost, BrowserThread::DeleteOnIOThread>
host_;
- FactoryAssociatedPtr idb_mojo_factory_;
+ IDBFactoryPtr idb_mojo_factory_;
DISALLOW_COPY_AND_ASSIGN(IndexedDBDispatcherHostTest);
};
@@ -212,7 +211,7 @@ TEST_F(IndexedDBDispatcherHostTest, CloseConnectionBeforeUpgrade) {
base::UTF8ToUTF16(kDatabaseName),
kDBVersion, kTransactionId);
IndexedDBDatabaseMetadata metadata;
- DatabaseAssociatedPtrInfo database_info;
+ IDBDatabaseAssociatedPtrInfo database_info;
base::RunLoop loop;
EXPECT_CALL(
*connection.open_callbacks,
@@ -243,7 +242,7 @@ TEST_F(IndexedDBDispatcherHostTest, CloseAfterUpgrade) {
kDBVersion, kTransactionId);
IndexedDBDatabaseMetadata metadata;
- DatabaseAssociatedPtrInfo database_info;
+ IDBDatabaseAssociatedPtrInfo database_info;
{
base::RunLoop loop;
EXPECT_CALL(
@@ -282,7 +281,7 @@ TEST_F(IndexedDBDispatcherHostTest, CloseAfterUpgrade) {
ASSERT_TRUE(connection.database.is_bound());
connection.database->CreateObjectStore(kTransactionId, kObjectStoreId,
base::UTF8ToUTF16(kObjectStoreName),
- content::IndexedDBKeyPath(), false);
+ blink::IndexedDBKeyPath(), false);
connection.database->Commit(kTransactionId);
loop.Run();
}
@@ -298,7 +297,7 @@ TEST_F(IndexedDBDispatcherHostTest, OpenNewConnectionWhileUpgrading) {
TestDatabaseConnection connection1(url::Origin::Create(GURL(kOrigin)),
base::UTF8ToUTF16(kDatabaseName),
kDBVersion, kTransactionId);
- DatabaseAssociatedPtrInfo database_info1;
+ IDBDatabaseAssociatedPtrInfo database_info1;
{
base::RunLoop loop;
IndexedDBDatabaseMetadata metadata;
@@ -318,7 +317,7 @@ TEST_F(IndexedDBDispatcherHostTest, OpenNewConnectionWhileUpgrading) {
connection1.database.Bind(std::move(database_info1));
// Open connection 2, but expect that we won't be called back.
- DatabaseAssociatedPtrInfo database_info2;
+ IDBDatabaseAssociatedPtrInfo database_info2;
IndexedDBDatabaseMetadata metadata2;
TestDatabaseConnection connection2(url::Origin::Create(GURL(kOrigin)),
base::UTF8ToUTF16(kDatabaseName),
@@ -350,7 +349,7 @@ TEST_F(IndexedDBDispatcherHostTest, OpenNewConnectionWhileUpgrading) {
ASSERT_TRUE(connection1.database.is_bound());
connection1.database->CreateObjectStore(kTransactionId, kObjectStoreId,
base::UTF8ToUTF16(kObjectStoreName),
- content::IndexedDBKeyPath(), false);
+ blink::IndexedDBKeyPath(), false);
connection1.database->Commit(kTransactionId);
loop.Run();
}
@@ -372,7 +371,7 @@ TEST_F(IndexedDBDispatcherHostTest, PutWithInvalidBlob) {
kDBVersion, kTransactionId);
IndexedDBDatabaseMetadata metadata;
- DatabaseAssociatedPtrInfo database_info;
+ IDBDatabaseAssociatedPtrInfo database_info;
{
base::RunLoop loop;
EXPECT_CALL(
@@ -422,19 +421,19 @@ TEST_F(IndexedDBDispatcherHostTest, PutWithInvalidBlob) {
ASSERT_TRUE(connection.database.is_bound());
connection.database->CreateObjectStore(kTransactionId, kObjectStoreId,
base::UTF8ToUTF16(kObjectStoreName),
- content::IndexedDBKeyPath(), false);
+ blink::IndexedDBKeyPath(), false);
// Call Put with an invalid blob.
- std::vector<::indexed_db::mojom::BlobInfoPtr> blobs;
+ std::vector<blink::mojom::IDBBlobInfoPtr> blobs;
blink::mojom::BlobPtrInfo blob;
// Ignore the result of MakeRequest, to end up with an invalid blob.
mojo::MakeRequest(&blob);
- blobs.push_back(::indexed_db::mojom::BlobInfo::New(
+ blobs.push_back(blink::mojom::IDBBlobInfo::New(
std::move(blob), "fakeUUID", base::string16(), 100, nullptr));
connection.database->Put(kTransactionId, kObjectStoreId,
- Value::New("hello", std::move(blobs)),
- content::IndexedDBKey(base::UTF8ToUTF16("hello")),
+ IDBValue::New("hello", std::move(blobs)),
+ IndexedDBKey(base::UTF8ToUTF16("hello")),
blink::kWebIDBPutModeAddOnly,
- std::vector<content::IndexedDBIndexKeys>(),
+ std::vector<IndexedDBIndexKeys>(),
put_callbacks->CreateInterfacePtrAndBind());
connection.database->Commit(kTransactionId);
loop.Run();
@@ -450,7 +449,7 @@ TEST_F(IndexedDBDispatcherHostTest, CompactDatabaseWithConnection) {
base::UTF8ToUTF16(kDatabaseName),
kDBVersion, kTransactionId);
IndexedDBDatabaseMetadata metadata;
- DatabaseAssociatedPtrInfo database_info;
+ IDBDatabaseAssociatedPtrInfo database_info;
{
base::RunLoop loop;
EXPECT_CALL(
@@ -473,8 +472,7 @@ TEST_F(IndexedDBDispatcherHostTest, CompactDatabaseWithConnection) {
connection.database.Bind(std::move(database_info));
- ::indexed_db::mojom::Status callback_result =
- ::indexed_db::mojom::Status::IOError;
+ blink::mojom::IDBStatus callback_result = blink::mojom::IDBStatus::IOError;
{
::testing::InSequence dummy;
base::RunLoop loop;
@@ -497,7 +495,7 @@ TEST_F(IndexedDBDispatcherHostTest, CompactDatabaseWithConnection) {
loop.Run();
}
- EXPECT_EQ(::indexed_db::mojom::Status::OK, callback_result);
+ EXPECT_EQ(blink::mojom::IDBStatus::OK, callback_result);
}
TEST_F(IndexedDBDispatcherHostTest, CompactDatabaseWhileDoingTransaction) {
@@ -511,7 +509,7 @@ TEST_F(IndexedDBDispatcherHostTest, CompactDatabaseWhileDoingTransaction) {
base::UTF8ToUTF16(kDatabaseName),
kDBVersion, kTransactionId);
IndexedDBDatabaseMetadata metadata;
- DatabaseAssociatedPtrInfo database_info;
+ IDBDatabaseAssociatedPtrInfo database_info;
{
base::RunLoop loop;
EXPECT_CALL(
@@ -534,8 +532,7 @@ TEST_F(IndexedDBDispatcherHostTest, CompactDatabaseWhileDoingTransaction) {
connection.database.Bind(std::move(database_info));
- ::indexed_db::mojom::Status callback_result =
- ::indexed_db::mojom::Status::IOError;
+ blink::mojom::IDBStatus callback_result = blink::mojom::IDBStatus::IOError;
{
::testing::InSequence dummy;
base::RunLoop loop;
@@ -558,14 +555,14 @@ TEST_F(IndexedDBDispatcherHostTest, CompactDatabaseWhileDoingTransaction) {
ASSERT_TRUE(connection.database.is_bound());
connection.database->CreateObjectStore(kTransactionId, kObjectStoreId,
base::UTF8ToUTF16(kObjectStoreName),
- content::IndexedDBKeyPath(), false);
+ blink::IndexedDBKeyPath(), false);
idb_mojo_factory_->AbortTransactionsAndCompactDatabase(
origin, base::BindOnce(&StatusCallback, std::move(quit_closure),
&callback_result));
loop.Run();
}
- EXPECT_EQ(::indexed_db::mojom::Status::OK, callback_result);
+ EXPECT_EQ(blink::mojom::IDBStatus::OK, callback_result);
}
TEST_F(IndexedDBDispatcherHostTest, CompactDatabaseWhileUpgrading) {
@@ -577,7 +574,7 @@ TEST_F(IndexedDBDispatcherHostTest, CompactDatabaseWhileUpgrading) {
base::UTF8ToUTF16(kDatabaseName),
kDBVersion, kTransactionId);
IndexedDBDatabaseMetadata metadata;
- DatabaseAssociatedPtrInfo database_info;
+ IDBDatabaseAssociatedPtrInfo database_info;
{
base::RunLoop loop;
EXPECT_CALL(
@@ -600,8 +597,7 @@ TEST_F(IndexedDBDispatcherHostTest, CompactDatabaseWhileUpgrading) {
connection.database.Bind(std::move(database_info));
- ::indexed_db::mojom::Status callback_result =
- ::indexed_db::mojom::Status::IOError;
+ blink::mojom::IDBStatus callback_result = blink::mojom::IDBStatus::IOError;
{
::testing::InSequence dummy;
base::RunLoop loop;
@@ -628,7 +624,7 @@ TEST_F(IndexedDBDispatcherHostTest, CompactDatabaseWhileUpgrading) {
loop.Run();
}
- EXPECT_EQ(::indexed_db::mojom::Status::OK, callback_result);
+ EXPECT_EQ(blink::mojom::IDBStatus::OK, callback_result);
}
TEST_F(IndexedDBDispatcherHostTest,
@@ -641,7 +637,7 @@ TEST_F(IndexedDBDispatcherHostTest,
base::UTF8ToUTF16(kDatabaseName),
kDBVersion, kTransactionId);
IndexedDBDatabaseMetadata metadata;
- DatabaseAssociatedPtrInfo database_info;
+ IDBDatabaseAssociatedPtrInfo database_info;
{
base::RunLoop loop;
EXPECT_CALL(
@@ -664,8 +660,7 @@ TEST_F(IndexedDBDispatcherHostTest,
connection.database.Bind(std::move(database_info));
- ::indexed_db::mojom::Status callback_result =
- ::indexed_db::mojom::Status::IOError;
+ blink::mojom::IDBStatus callback_result = blink::mojom::IDBStatus::IOError;
{
::testing::InSequence dummy;
base::RunLoop loop;
@@ -691,7 +686,7 @@ TEST_F(IndexedDBDispatcherHostTest,
loop.Run();
}
- EXPECT_EQ(::indexed_db::mojom::Status::OK, callback_result);
+ EXPECT_EQ(blink::mojom::IDBStatus::OK, callback_result);
}
TEST_F(IndexedDBDispatcherHostTest, AbortTransactionsWhileDoingTransaction) {
@@ -705,7 +700,7 @@ TEST_F(IndexedDBDispatcherHostTest, AbortTransactionsWhileDoingTransaction) {
base::UTF8ToUTF16(kDatabaseName),
kDBVersion, kTransactionId);
IndexedDBDatabaseMetadata metadata;
- DatabaseAssociatedPtrInfo database_info;
+ IDBDatabaseAssociatedPtrInfo database_info;
{
base::RunLoop loop;
EXPECT_CALL(
@@ -728,8 +723,7 @@ TEST_F(IndexedDBDispatcherHostTest, AbortTransactionsWhileDoingTransaction) {
connection.database.Bind(std::move(database_info));
- ::indexed_db::mojom::Status callback_result =
- ::indexed_db::mojom::Status::IOError;
+ blink::mojom::IDBStatus callback_result = blink::mojom::IDBStatus::IOError;
{
::testing::InSequence dummy;
base::RunLoop loop;
@@ -752,14 +746,14 @@ TEST_F(IndexedDBDispatcherHostTest, AbortTransactionsWhileDoingTransaction) {
ASSERT_TRUE(connection.database.is_bound());
connection.database->CreateObjectStore(kTransactionId, kObjectStoreId,
base::UTF8ToUTF16(kObjectStoreName),
- content::IndexedDBKeyPath(), false);
+ blink::IndexedDBKeyPath(), false);
idb_mojo_factory_->AbortTransactionsForDatabase(
origin, base::BindOnce(&StatusCallback, std::move(quit_closure),
&callback_result));
loop.Run();
}
- EXPECT_EQ(::indexed_db::mojom::Status::OK, callback_result);
+ EXPECT_EQ(blink::mojom::IDBStatus::OK, callback_result);
}
TEST_F(IndexedDBDispatcherHostTest, AbortTransactionsWhileUpgrading) {
@@ -771,7 +765,7 @@ TEST_F(IndexedDBDispatcherHostTest, AbortTransactionsWhileUpgrading) {
base::UTF8ToUTF16(kDatabaseName),
kDBVersion, kTransactionId);
IndexedDBDatabaseMetadata metadata;
- DatabaseAssociatedPtrInfo database_info;
+ IDBDatabaseAssociatedPtrInfo database_info;
{
base::RunLoop loop;
EXPECT_CALL(
@@ -794,8 +788,7 @@ TEST_F(IndexedDBDispatcherHostTest, AbortTransactionsWhileUpgrading) {
connection.database.Bind(std::move(database_info));
- ::indexed_db::mojom::Status callback_result =
- ::indexed_db::mojom::Status::IOError;
+ blink::mojom::IDBStatus callback_result = blink::mojom::IDBStatus::IOError;
{
::testing::InSequence dummy;
base::RunLoop loop;
@@ -822,7 +815,7 @@ TEST_F(IndexedDBDispatcherHostTest, AbortTransactionsWhileUpgrading) {
loop.Run();
}
- EXPECT_EQ(::indexed_db::mojom::Status::OK, callback_result);
+ EXPECT_EQ(blink::mojom::IDBStatus::OK, callback_result);
}
// Flaky: crbug.com/772067
@@ -846,7 +839,7 @@ TEST_F(IndexedDBDispatcherHostTest, DISABLED_NotifyIndexedDBListChanged) {
base::UTF8ToUTF16(kDatabaseName),
kDBVersion1, kTransactionId1);
IndexedDBDatabaseMetadata metadata1;
- DatabaseAssociatedPtrInfo database_info1;
+ IDBDatabaseAssociatedPtrInfo database_info1;
EXPECT_EQ(0, observer.notify_list_changed_count);
{
base::RunLoop loop;
@@ -886,11 +879,10 @@ TEST_F(IndexedDBDispatcherHostTest, DISABLED_NotifyIndexedDBListChanged) {
ASSERT_TRUE(connection1.database.is_bound());
connection1.database->CreateObjectStore(kTransactionId1, kObjectStoreId,
base::UTF8ToUTF16(kObjectStoreName),
- content::IndexedDBKeyPath(), false);
+ blink::IndexedDBKeyPath(), false);
connection1.database->CreateIndex(kTransactionId1, kObjectStoreId, kIndexId,
base::UTF8ToUTF16(kIndexName),
- content::IndexedDBKeyPath(), false,
- false);
+ blink::IndexedDBKeyPath(), false, false);
connection1.database->Commit(kTransactionId1);
loop.Run();
}
@@ -902,7 +894,7 @@ TEST_F(IndexedDBDispatcherHostTest, DISABLED_NotifyIndexedDBListChanged) {
base::UTF8ToUTF16(kDatabaseName),
kDBVersion2, kTransactionId2);
IndexedDBDatabaseMetadata metadata2;
- DatabaseAssociatedPtrInfo database_info2;
+ IDBDatabaseAssociatedPtrInfo database_info2;
{
::testing::InSequence dummy;
base::RunLoop loop;
@@ -952,7 +944,7 @@ TEST_F(IndexedDBDispatcherHostTest, DISABLED_NotifyIndexedDBListChanged) {
base::UTF8ToUTF16(kDatabaseName),
kDBVersion3, kTransactionId3);
IndexedDBDatabaseMetadata metadata3;
- DatabaseAssociatedPtrInfo database_info3;
+ IDBDatabaseAssociatedPtrInfo database_info3;
{
::testing::InSequence dummy;
base::RunLoop loop;
@@ -1014,7 +1006,7 @@ TEST_F(IndexedDBDispatcherHostTest, NotifyIndexedDBContentChanged) {
base::UTF8ToUTF16(kDatabaseName),
kDBVersion1, kTransactionId1);
IndexedDBDatabaseMetadata metadata1;
- DatabaseAssociatedPtrInfo database_info1;
+ IDBDatabaseAssociatedPtrInfo database_info1;
EXPECT_EQ(0, observer.notify_list_changed_count);
EXPECT_EQ(0, observer.notify_content_changed_count);
{
@@ -1061,14 +1053,13 @@ TEST_F(IndexedDBDispatcherHostTest, NotifyIndexedDBContentChanged) {
ASSERT_TRUE(connection1.database.is_bound());
connection1.database->CreateObjectStore(kTransactionId1, kObjectStoreId,
base::UTF8ToUTF16(kObjectStoreName),
- content::IndexedDBKeyPath(), false);
+ blink::IndexedDBKeyPath(), false);
connection1.database->Put(
kTransactionId1, kObjectStoreId,
- ::indexed_db::mojom::Value::New(
- "value", std::vector<::indexed_db::mojom::BlobInfoPtr>()),
- content::IndexedDBKey(base::UTF8ToUTF16("key")),
- blink::kWebIDBPutModeAddOnly,
- std::vector<content::IndexedDBIndexKeys>(),
+ blink::mojom::IDBValue::New(
+ "value", std::vector<blink::mojom::IDBBlobInfoPtr>()),
+ IndexedDBKey(base::UTF8ToUTF16("key")), blink::kWebIDBPutModeAddOnly,
+ std::vector<IndexedDBIndexKeys>(),
put_callbacks->CreateInterfacePtrAndBind());
connection1.database->Commit(kTransactionId1);
loop.Run();
@@ -1082,7 +1073,7 @@ TEST_F(IndexedDBDispatcherHostTest, NotifyIndexedDBContentChanged) {
base::UTF8ToUTF16(kDatabaseName),
kDBVersion2, kTransactionId2);
IndexedDBDatabaseMetadata metadata2;
- DatabaseAssociatedPtrInfo database_info2;
+ IDBDatabaseAssociatedPtrInfo database_info2;
{
::testing::InSequence dummy;
base::RunLoop loop;
diff --git a/chromium/content/browser/indexed_db/indexed_db_factory.h b/chromium/content/browser/indexed_db/indexed_db_factory.h
index c4edb3f5d3f..d4e62a6a9f7 100644
--- a/chromium/content/browser/indexed_db/indexed_db_factory.h
+++ b/chromium/content/browser/indexed_db/indexed_db_factory.h
@@ -79,6 +79,7 @@ class CONTENT_EXPORT IndexedDBFactory
const url::Origin& origin) const = 0;
virtual void ForceClose(const url::Origin& origin) = 0;
+ virtual void ForceSchemaDowngrade(const url::Origin& origin) = 0;
// Called by the IndexedDBContext destructor so the factory can do cleanup.
virtual void ContextDestroyed() = 0;
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 cd079aedd08..404b2556081 100644
--- a/chromium/content/browser/indexed_db/indexed_db_factory_impl.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_factory_impl.cc
@@ -191,7 +191,8 @@ void IndexedDBFactoryImpl::ReleaseBackingStore(const Origin& origin,
DCHECK(!backing_store_map_[origin]->close_timer()->IsRunning());
backing_store_map_[origin]->close_timer()->Start(
FROM_HERE, base::TimeDelta::FromSeconds(kBackingStoreGracePeriodSeconds),
- base::Bind(&IndexedDBFactoryImpl::MaybeStartPreCloseTasks, this, origin));
+ base::BindOnce(&IndexedDBFactoryImpl::MaybeStartPreCloseTasks, this,
+ origin));
}
void IndexedDBFactoryImpl::MaybeStartPreCloseTasks(const Origin& origin) {
@@ -337,6 +338,17 @@ void IndexedDBFactoryImpl::ForceClose(const Origin& origin) {
ReleaseBackingStore(origin, true /* immediate */);
}
+void IndexedDBFactoryImpl::ForceSchemaDowngrade(const Origin& origin) {
+ OriginDBs range = GetOpenDatabasesForOrigin(origin);
+
+ while (range.first != range.second) {
+ IndexedDBDatabase* db = range.first->second;
+ ++range.first;
+ leveldb::Status s = db->backing_store()->RevertSchemaToV2();
+ DLOG_IF(ERROR, !s.ok()) << "Unable to force downgrade: " << s.ToString();
+ }
+}
+
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
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 3935f9b319f..b78429e2e2c 100644
--- a/chromium/content/browser/indexed_db/indexed_db_factory_impl.h
+++ b/chromium/content/browser/indexed_db/indexed_db_factory_impl.h
@@ -87,6 +87,7 @@ class CONTENT_EXPORT IndexedDBFactoryImpl : public IndexedDBFactory {
OriginDBs GetOpenDatabasesForOrigin(const url::Origin& origin) const override;
void ForceClose(const url::Origin& origin) override;
+ void ForceSchemaDowngrade(const url::Origin& origin) override;
// Called by the IndexedDBContext destructor so the factory can do cleanup.
void ContextDestroyed() override;
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 0031ef8024b..849666e7be5 100644
--- a/chromium/content/browser/indexed_db/indexed_db_factory_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_factory_unittest.cc
@@ -27,12 +27,13 @@
#include "content/public/test/test_utils.h"
#include "storage/browser/test/mock_quota_manager_proxy.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/indexeddb/web_idb_types.h"
#include "third_party/blink/public/platform/modules/indexeddb/web_idb_database_exception.h"
-#include "third_party/blink/public/platform/modules/indexeddb/web_idb_types.h"
#include "url/gurl.h"
#include "url/origin.h"
using base::ASCIIToUTF16;
+using blink::IndexedDBDatabaseMetadata;
using url::Origin;
namespace content {
@@ -720,7 +721,7 @@ class UpgradeNeededCallbacks : public MockIndexedDBCallbacks {
void OnUpgradeNeeded(int64_t old_version,
std::unique_ptr<IndexedDBConnection> connection,
- const content::IndexedDBDatabaseMetadata& metadata,
+ const IndexedDBDatabaseMetadata& metadata,
const IndexedDBDataLossInfo& data_loss_info) override {
connection_ = std::move(connection);
}
@@ -854,7 +855,7 @@ class DataLossCallbacks final : public MockIndexedDBCallbacks {
}
void OnUpgradeNeeded(int64_t old_version,
std::unique_ptr<IndexedDBConnection> connection,
- const content::IndexedDBDatabaseMetadata& metadata,
+ const IndexedDBDatabaseMetadata& metadata,
const IndexedDBDataLossInfo& data_loss) final {
connection_ = std::move(connection);
data_loss_ = data_loss.status;
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 46b713fb53a..7477de76328 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
@@ -9,6 +9,12 @@
#include "net/url_request/url_request_context_getter.h"
namespace content {
+namespace {
+
+using blink::IndexedDBKey;
+using blink::IndexedDBKeyRange;
+
+} // namespace
IndexedDBFakeBackingStore::IndexedDBFakeBackingStore()
: IndexedDBBackingStore(nullptr /* indexed_db_factory */,
@@ -41,7 +47,6 @@ leveldb::Status IndexedDBFakeBackingStore::PutRecord(
int64_t object_store_id,
const IndexedDBKey& key,
IndexedDBValue* value,
- std::vector<std::unique_ptr<storage::BlobDataHandle>>* handles,
RecordIdentifier* record) {
return leveldb::Status::OK();
}
diff --git a/chromium/content/browser/indexed_db/indexed_db_fake_backing_store.h b/chromium/content/browser/indexed_db/indexed_db_fake_backing_store.h
index 42ab318bfd9..3f8337cfd6f 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
@@ -12,11 +12,16 @@
#include "base/macros.h"
#include "content/browser/indexed_db/indexed_db_backing_store.h"
+#include "third_party/blink/public/common/indexeddb/indexeddb_key.h"
namespace base {
class SequencedTaskRunner;
}
+namespace blink {
+class IndexedDBKeyRange;
+}
+
namespace content {
class IndexedDBFactory;
@@ -28,14 +33,12 @@ class IndexedDBFakeBackingStore : public IndexedDBBackingStore {
base::SequencedTaskRunner* task_runner);
leveldb::Status DeleteDatabase(const base::string16& name) override;
- leveldb::Status PutRecord(
- IndexedDBBackingStore::Transaction* transaction,
- int64_t database_id,
- int64_t object_store_id,
- const IndexedDBKey& key,
- IndexedDBValue* value,
- std::vector<std::unique_ptr<storage::BlobDataHandle>>* handles,
- RecordIdentifier* record) override;
+ leveldb::Status PutRecord(IndexedDBBackingStore::Transaction* transaction,
+ int64_t database_id,
+ int64_t object_store_id,
+ const blink::IndexedDBKey& key,
+ IndexedDBValue* value,
+ RecordIdentifier* record) override;
leveldb::Status ClearObjectStore(Transaction*,
int64_t database_id,
@@ -59,7 +62,7 @@ class IndexedDBFakeBackingStore : public IndexedDBBackingStore {
Transaction*,
int64_t database_id,
int64_t object_store_id,
- const IndexedDBKey&,
+ const blink::IndexedDBKey&,
RecordIdentifier* found_record_identifier,
bool* found) override;
@@ -71,37 +74,39 @@ class IndexedDBFakeBackingStore : public IndexedDBBackingStore {
int64_t database_id,
int64_t object_store_id,
int64_t index_id,
- const IndexedDBKey&,
+ const blink::IndexedDBKey&,
const RecordIdentifier&) override;
void ReportBlobUnused(int64_t database_id, int64_t blob_key) override;
std::unique_ptr<Cursor> OpenObjectStoreKeyCursor(
Transaction* transaction,
int64_t database_id,
int64_t object_store_id,
- const IndexedDBKeyRange& key_range,
+ const blink::IndexedDBKeyRange& key_range,
blink::WebIDBCursorDirection,
leveldb::Status*) override;
std::unique_ptr<Cursor> OpenObjectStoreCursor(
Transaction* transaction,
int64_t database_id,
int64_t object_store_id,
- const IndexedDBKeyRange& key_range,
+ const blink::IndexedDBKeyRange& key_range,
+ blink::WebIDBCursorDirection,
+ leveldb::Status*) override;
+ std::unique_ptr<Cursor> OpenIndexKeyCursor(
+ Transaction* transaction,
+ int64_t database_id,
+ int64_t object_store_id,
+ int64_t index_id,
+ const blink::IndexedDBKeyRange& key_range,
+ blink::WebIDBCursorDirection,
+ leveldb::Status*) override;
+ std::unique_ptr<Cursor> OpenIndexCursor(
+ Transaction* transaction,
+ int64_t database_id,
+ int64_t object_store_id,
+ int64_t index_id,
+ const blink::IndexedDBKeyRange& key_range,
blink::WebIDBCursorDirection,
leveldb::Status*) override;
- std::unique_ptr<Cursor> OpenIndexKeyCursor(Transaction* transaction,
- int64_t database_id,
- int64_t object_store_id,
- int64_t index_id,
- const IndexedDBKeyRange& key_range,
- blink::WebIDBCursorDirection,
- leveldb::Status*) override;
- std::unique_ptr<Cursor> OpenIndexCursor(Transaction* transaction,
- int64_t database_id,
- int64_t object_store_id,
- int64_t index_id,
- const IndexedDBKeyRange& key_range,
- blink::WebIDBCursorDirection,
- leveldb::Status*) override;
class FakeTransaction : public IndexedDBBackingStore::Transaction {
public:
diff --git a/chromium/content/browser/indexed_db/indexed_db_index_writer.cc b/chromium/content/browser/indexed_db/indexed_db_index_writer.cc
index f18444c36f8..597603919c5 100644
--- a/chromium/content/browser/indexed_db/indexed_db_index_writer.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_index_writer.cc
@@ -12,11 +12,13 @@
#include "content/browser/indexed_db/indexed_db_backing_store.h"
#include "content/browser/indexed_db/indexed_db_tracing.h"
#include "content/browser/indexed_db/indexed_db_transaction.h"
-#include "content/common/indexed_db/indexed_db_key.h"
-#include "content/common/indexed_db/indexed_db_key_path.h"
-#include "content/common/indexed_db/indexed_db_key_range.h"
+#include "third_party/blink/public/common/indexeddb/indexeddb_metadata.h"
using base::ASCIIToUTF16;
+using blink::IndexedDBIndexKeys;
+using blink::IndexedDBIndexMetadata;
+using blink::IndexedDBKey;
+using blink::IndexedDBObjectStoreMetadata;
namespace content {
diff --git a/chromium/content/browser/indexed_db/indexed_db_index_writer.h b/chromium/content/browser/indexed_db/indexed_db_index_writer.h
index bf9c4e88109..78bf722c92d 100644
--- a/chromium/content/browser/indexed_db/indexed_db_index_writer.h
+++ b/chromium/content/browser/indexed_db/indexed_db_index_writer.h
@@ -14,20 +14,22 @@
#include "base/macros.h"
#include "content/browser/indexed_db/indexed_db_backing_store.h"
#include "content/browser/indexed_db/indexed_db_database.h"
-#include "content/common/indexed_db/indexed_db_key_path.h"
-#include "content/common/indexed_db/indexed_db_metadata.h"
+#include "third_party/blink/public/common/indexeddb/indexeddb_key.h"
+
+namespace blink {
+struct IndexedDBObjectStoreMetadata;
+}
namespace content {
class IndexedDBTransaction;
-struct IndexedDBObjectStoreMetadata;
class IndexWriter {
public:
- explicit IndexWriter(const IndexedDBIndexMetadata& index_metadata);
+ explicit IndexWriter(const blink::IndexedDBIndexMetadata& index_metadata);
- IndexWriter(const IndexedDBIndexMetadata& index_metadata,
- const IndexedDBIndexKeys& index_keys);
+ IndexWriter(const blink::IndexedDBIndexMetadata& index_metadata,
+ const blink::IndexedDBIndexKeys& index_keys);
bool VerifyIndexKeys(IndexedDBBackingStore* store,
IndexedDBBackingStore::Transaction* transaction,
@@ -35,7 +37,7 @@ class IndexWriter {
int64_t object_store_id,
int64_t index_id,
bool* can_add_keys,
- const IndexedDBKey& primary_key,
+ const blink::IndexedDBKey& primary_key,
base::string16* error_message) const WARN_UNUSED_RESULT;
void WriteIndexKeys(const IndexedDBBackingStore::RecordIdentifier& record,
@@ -52,12 +54,12 @@ class IndexWriter {
int64_t database_id,
int64_t object_store_id,
int64_t index_id,
- const IndexedDBKey& index_key,
- const IndexedDBKey& primary_key,
+ const blink::IndexedDBKey& index_key,
+ const blink::IndexedDBKey& primary_key,
bool* allowed) const WARN_UNUSED_RESULT;
- const IndexedDBIndexMetadata index_metadata_;
- IndexedDBIndexKeys index_keys_;
+ const blink::IndexedDBIndexMetadata index_metadata_;
+ blink::IndexedDBIndexKeys index_keys_;
DISALLOW_COPY_AND_ASSIGN(IndexWriter);
};
@@ -65,10 +67,10 @@ class IndexWriter {
bool MakeIndexWriters(IndexedDBTransaction* transaction,
IndexedDBBackingStore* store,
int64_t database_id,
- const IndexedDBObjectStoreMetadata& metadata,
- const IndexedDBKey& primary_key,
+ const blink::IndexedDBObjectStoreMetadata& metadata,
+ const blink::IndexedDBKey& primary_key,
bool key_was_generated,
- const std::vector<IndexedDBIndexKeys>& index_keys,
+ const std::vector<blink::IndexedDBIndexKeys>& index_keys,
std::vector<std::unique_ptr<IndexWriter>>* index_writers,
base::string16* error_message,
bool* completed) WARN_UNUSED_RESULT;
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 b548e8953e4..cd8bc3bdb43 100644
--- a/chromium/content/browser/indexed_db/indexed_db_internals_ui.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_internals_ui.cc
@@ -12,7 +12,7 @@
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/macros.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "base/threading/platform_thread.h"
#include "base/values.h"
#include "content/browser/indexed_db/indexed_db_context_impl.h"
@@ -62,6 +62,10 @@ IndexedDBInternalsUI::IndexedDBInternalsUI(WebUI* web_ui)
web_ui->RegisterMessageCallback(
"forceClose", base::BindRepeating(&IndexedDBInternalsUI::ForceCloseOrigin,
base::Unretained(this)));
+ web_ui->RegisterMessageCallback(
+ "forceSchemaDowngrade",
+ base::BindRepeating(&IndexedDBInternalsUI::ForceSchemaDowngradeOrigin,
+ base::Unretained(this)));
WebUIDataSource* source =
WebUIDataSource::Create(kChromeUIIndexedDBInternalsHost);
@@ -210,6 +214,23 @@ void IndexedDBInternalsUI::ForceCloseOrigin(const base::ListValue* args) {
base::Unretained(this), partition_path, context, origin));
}
+void IndexedDBInternalsUI::ForceSchemaDowngradeOrigin(
+ const base::ListValue* args) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ base::FilePath partition_path;
+ Origin origin;
+ scoped_refptr<IndexedDBContextImpl> context;
+ if (!GetOriginData(args, &partition_path, &origin, &context))
+ return;
+
+ context->TaskRunner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &IndexedDBInternalsUI::ForceSchemaDowngradeOriginOnIndexedDBThread,
+ base::Unretained(this), partition_path, context, origin));
+}
+
void IndexedDBInternalsUI::DownloadOriginDataOnIndexedDBThread(
const base::FilePath& partition_path,
const scoped_refptr<IndexedDBContextImpl> context,
@@ -260,10 +281,33 @@ void IndexedDBInternalsUI::ForceCloseOriginOnIndexedDBThread(
context->ForceClose(origin, IndexedDBContextImpl::FORCE_CLOSE_INTERNALS_PAGE);
size_t connection_count = context->GetConnectionCount(origin);
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(&IndexedDBInternalsUI::OnForcedClose,
- base::Unretained(this), partition_path,
- origin, connection_count));
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&IndexedDBInternalsUI::OnForcedSchemaDowngrade,
+ base::Unretained(this), partition_path, origin,
+ connection_count));
+}
+
+void IndexedDBInternalsUI::ForceSchemaDowngradeOriginOnIndexedDBThread(
+ const base::FilePath& partition_path,
+ const scoped_refptr<IndexedDBContextImpl> context,
+ const Origin& origin) {
+ DCHECK(context->TaskRunner()->RunsTasksInCurrentSequence());
+
+ // Make sure the database hasn't been deleted since the page was loaded.
+ if (!context->HasOrigin(origin))
+ return;
+
+ context->ForceSchemaDowngrade(origin);
+ context->ForceClose(
+ origin, IndexedDBContextImpl::FORCE_SCHEMA_DOWNGRADE_INTERNALS_PAGE);
+ size_t connection_count = context->GetConnectionCount(origin);
+
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&IndexedDBInternalsUI::OnForcedSchemaDowngrade,
+ base::Unretained(this), partition_path, origin,
+ connection_count));
}
void IndexedDBInternalsUI::OnForcedClose(const base::FilePath& partition_path,
@@ -275,6 +319,16 @@ void IndexedDBInternalsUI::OnForcedClose(const base::FilePath& partition_path,
base::Value(static_cast<double>(connection_count)));
}
+void IndexedDBInternalsUI::OnForcedSchemaDowngrade(
+ const base::FilePath& partition_path,
+ const Origin& origin,
+ size_t connection_count) {
+ web_ui()->CallJavascriptFunctionUnsafe(
+ "indexeddb.onForcedSchemaDowngrade", base::Value(partition_path.value()),
+ base::Value(origin.Serialize()),
+ base::Value(static_cast<double>(connection_count)));
+}
+
void IndexedDBInternalsUI::OnDownloadDataReady(
const base::FilePath& partition_path,
const Origin& origin,
@@ -362,7 +416,7 @@ void FileDeleter::OnDownloadUpdated(download::DownloadItem* item) {
FileDeleter::~FileDeleter() {
base::PostTaskWithTraits(FROM_HERE,
- {base::MayBlock(), base::TaskPriority::BACKGROUND,
+ {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
base::BindOnce(base::IgnoreResult(&base::DeleteFile),
std::move(temp_dir_), true));
diff --git a/chromium/content/browser/indexed_db/indexed_db_internals_ui.h b/chromium/content/browser/indexed_db/indexed_db_internals_ui.h
index 1cce5203b66..1a8a154042e 100644
--- a/chromium/content/browser/indexed_db/indexed_db_internals_ui.h
+++ b/chromium/content/browser/indexed_db/indexed_db_internals_ui.h
@@ -73,6 +73,16 @@ class IndexedDBInternalsUI : public WebUIController {
void OnForcedClose(const base::FilePath& partition_path,
const url::Origin& origin,
size_t connection_count);
+
+ void ForceSchemaDowngradeOrigin(const base::ListValue* args);
+ void ForceSchemaDowngradeOriginOnIndexedDBThread(
+ const base::FilePath& partition_path,
+ const scoped_refptr<IndexedDBContextImpl> context,
+ const url::Origin& origin);
+ void OnForcedSchemaDowngrade(const base::FilePath& partition_path,
+ const url::Origin& origin,
+ size_t connection_count);
+
bool GetOriginContext(const base::FilePath& path,
const url::Origin& origin,
scoped_refptr<IndexedDBContextImpl>* context);
diff --git a/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.cc b/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.cc
index d407f6018cf..7a9a4f25ea0 100644
--- a/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.cc
@@ -11,13 +11,13 @@
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "base/sys_byteorder.h"
-#include "content/common/indexed_db/indexed_db_key.h"
-#include "content/common/indexed_db/indexed_db_key_path.h"
// See leveldb_coding_scheme.md for detailed documentation of the coding
// scheme implemented here.
using base::StringPiece;
+using blink::IndexedDBKey;
+using blink::IndexedDBKeyPath;
using blink::WebIDBKeyType;
using blink::kWebIDBKeyTypeArray;
using blink::kWebIDBKeyTypeBinary;
diff --git a/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.h b/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.h
index 739982f55d4..fdc46986ace 100644
--- a/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.h
+++ b/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.h
@@ -18,8 +18,9 @@
#include "base/memory/ref_counted.h"
#include "base/strings/string16.h"
#include "base/strings/string_piece.h"
-#include "content/common/indexed_db/indexed_db_key.h"
-#include "content/common/indexed_db/indexed_db_key_path.h"
+#include "content/common/content_export.h"
+#include "third_party/blink/public/common/indexeddb/indexeddb_key.h"
+#include "third_party/blink/public/common/indexeddb/indexeddb_key_path.h"
namespace content {
@@ -50,8 +51,9 @@ CONTENT_EXPORT void EncodeStringWithLength(const base::string16& value,
std::string* into);
CONTENT_EXPORT void EncodeBinary(const std::string& value, std::string* into);
CONTENT_EXPORT void EncodeDouble(double value, std::string* into);
-CONTENT_EXPORT void EncodeIDBKey(const IndexedDBKey& value, std::string* into);
-CONTENT_EXPORT void EncodeIDBKeyPath(const IndexedDBKeyPath& value,
+CONTENT_EXPORT void EncodeIDBKey(const blink::IndexedDBKey& value,
+ std::string* into);
+CONTENT_EXPORT void EncodeIDBKeyPath(const blink::IndexedDBKeyPath& value,
std::string* into);
CONTENT_EXPORT void EncodeBlobJournal(const BlobJournalType& journal,
std::string* into);
@@ -75,10 +77,10 @@ CONTENT_EXPORT WARN_UNUSED_RESULT bool DecodeDouble(base::StringPiece* slice,
double* value);
CONTENT_EXPORT WARN_UNUSED_RESULT bool DecodeIDBKey(
base::StringPiece* slice,
- std::unique_ptr<IndexedDBKey>* value);
+ std::unique_ptr<blink::IndexedDBKey>* value);
CONTENT_EXPORT WARN_UNUSED_RESULT bool DecodeIDBKeyPath(
base::StringPiece* slice,
- IndexedDBKeyPath* value);
+ blink::IndexedDBKeyPath* value);
CONTENT_EXPORT WARN_UNUSED_RESULT bool DecodeBlobJournal(
base::StringPiece* slice,
BlobJournalType* journal);
@@ -415,8 +417,8 @@ class ObjectStoreDataKey {
const std::string encoded_user_key);
static std::string Encode(int64_t database_id,
int64_t object_store_id,
- const IndexedDBKey& user_key);
- std::unique_ptr<IndexedDBKey> user_key() const;
+ const blink::IndexedDBKey& user_key);
+ std::unique_ptr<blink::IndexedDBKey> user_key() const;
private:
std::string encoded_user_key_;
@@ -433,8 +435,8 @@ class ExistsEntryKey {
const std::string& encoded_key);
static std::string Encode(int64_t database_id,
int64_t object_store_id,
- const IndexedDBKey& user_key);
- std::unique_ptr<IndexedDBKey> user_key() const;
+ const blink::IndexedDBKey& user_key);
+ std::unique_ptr<blink::IndexedDBKey> user_key() const;
private:
static const int64_t kSpecialIndexNumber;
@@ -456,7 +458,7 @@ class BlobEntryKey {
int64_t object_store_id);
static std::string Encode(int64_t database_id,
int64_t object_store_id,
- const IndexedDBKey& user_key);
+ const blink::IndexedDBKey& user_key);
std::string Encode() const;
int64_t database_id() const { return database_id_; }
int64_t object_store_id() const { return object_store_id_; }
@@ -490,13 +492,13 @@ class IndexDataKey {
static std::string Encode(int64_t database_id,
int64_t object_store_id,
int64_t index_id,
- const IndexedDBKey& user_key);
+ const blink::IndexedDBKey& user_key);
CONTENT_EXPORT static std::string Encode(
int64_t database_id,
int64_t object_store_id,
int64_t index_id,
- const IndexedDBKey& user_key,
- const IndexedDBKey& user_primary_key);
+ const blink::IndexedDBKey& user_key,
+ const blink::IndexedDBKey& user_primary_key);
CONTENT_EXPORT static std::string EncodeMinKey(int64_t database_id,
int64_t object_store_id,
int64_t index_id);
@@ -506,8 +508,8 @@ class IndexDataKey {
int64_t DatabaseId() const;
int64_t ObjectStoreId() const;
int64_t IndexId() const;
- std::unique_ptr<IndexedDBKey> user_key() const;
- std::unique_ptr<IndexedDBKey> primary_key() const;
+ std::unique_ptr<blink::IndexedDBKey> user_key() const;
+ std::unique_ptr<blink::IndexedDBKey> primary_key() const;
CONTENT_EXPORT std::string Encode() const;
diff --git a/chromium/content/browser/indexed_db/indexed_db_leveldb_coding_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_leveldb_coding_unittest.cc
index d2e4e8e775c..edea49ca768 100644
--- a/chromium/content/browser/indexed_db/indexed_db_leveldb_coding_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_leveldb_coding_unittest.cc
@@ -14,12 +14,12 @@
#include "base/strings/string16.h"
#include "base/strings/string_piece.h"
#include "base/strings/utf_string_conversions.h"
-#include "content/common/indexed_db/indexed_db_key.h"
-#include "content/common/indexed_db/indexed_db_key_path.h"
#include "testing/gtest/include/gtest/gtest.h"
using base::ASCIIToUTF16;
using base::StringPiece;
+using blink::IndexedDBKey;
+using blink::IndexedDBKeyPath;
using blink::kWebIDBKeyTypeDate;
using blink::kWebIDBKeyTypeNumber;
diff --git a/chromium/content/browser/indexed_db/indexed_db_leveldb_operations.cc b/chromium/content/browser/indexed_db/indexed_db_leveldb_operations.cc
index 0908595054e..1e981b9e563 100644
--- a/chromium/content/browser/indexed_db/indexed_db_leveldb_operations.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_leveldb_operations.cc
@@ -10,8 +10,9 @@
#include "content/browser/indexed_db/leveldb/leveldb_iterator.h"
#include "content/browser/indexed_db/leveldb/leveldb_transaction.h"
-using leveldb::Status;
using base::StringPiece;
+using blink::IndexedDBKeyPath;
+using leveldb::Status;
namespace content {
namespace indexed_db {
diff --git a/chromium/content/browser/indexed_db/indexed_db_leveldb_operations.h b/chromium/content/browser/indexed_db/indexed_db_leveldb_operations.h
index 1f75df341d9..fbbc9957457 100644
--- a/chromium/content/browser/indexed_db/indexed_db_leveldb_operations.h
+++ b/chromium/content/browser/indexed_db/indexed_db_leveldb_operations.h
@@ -11,7 +11,7 @@
#include "base/strings/string_piece.h"
#include "base/time/time.h"
#include "content/common/content_export.h"
-#include "content/common/indexed_db/indexed_db_key_path.h"
+#include "third_party/blink/public/common/indexeddb/indexeddb_key_path.h"
#include "third_party/leveldatabase/src/include/leveldb/status.h"
// Contains common operations for LevelDBTransactions and/or LevelDBDatabases.
@@ -69,7 +69,7 @@ void PutString(LevelDBTransaction* transaction,
void PutIDBKeyPath(LevelDBTransaction* transaction,
const base::StringPiece& key,
- const IndexedDBKeyPath& value);
+ const blink::IndexedDBKeyPath& value);
template <typename DBOrTransaction>
WARN_UNUSED_RESULT leveldb::Status GetMaxObjectStoreId(
diff --git a/chromium/content/browser/indexed_db/indexed_db_metadata_coding.cc b/chromium/content/browser/indexed_db/indexed_db_metadata_coding.cc
index dfb98770800..6ffb4bb256f 100644
--- a/chromium/content/browser/indexed_db/indexed_db_metadata_coding.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_metadata_coding.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "content/browser/indexed_db/indexed_db_metadata_coding.h"
+
#include "base/strings/string_piece.h"
#include "content/browser/indexed_db/indexed_db_class_factory.h"
#include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
@@ -11,9 +12,13 @@
#include "content/browser/indexed_db/indexed_db_tracing.h"
#include "content/browser/indexed_db/leveldb/leveldb_database.h"
#include "content/browser/indexed_db/leveldb/leveldb_transaction.h"
-#include "content/common/indexed_db/indexed_db_metadata.h"
+#include "third_party/blink/public/common/indexeddb/indexeddb_metadata.h"
using base::StringPiece;
+using blink::IndexedDBDatabaseMetadata;
+using blink::IndexedDBIndexMetadata;
+using blink::IndexedDBKeyPath;
+using blink::IndexedDBObjectStoreMetadata;
using leveldb::Status;
namespace content {
diff --git a/chromium/content/browser/indexed_db/indexed_db_metadata_coding.h b/chromium/content/browser/indexed_db/indexed_db_metadata_coding.h
index 3abf22a822b..e6b579ef3c2 100644
--- a/chromium/content/browser/indexed_db/indexed_db_metadata_coding.h
+++ b/chromium/content/browser/indexed_db/indexed_db_metadata_coding.h
@@ -12,15 +12,19 @@
#include "base/macros.h"
#include "base/strings/string16.h"
-#include "content/common/indexed_db/indexed_db_key_path.h"
+#include "content/common/content_export.h"
+#include "third_party/blink/public/common/indexeddb/indexeddb_key_path.h"
#include "third_party/leveldatabase/src/include/leveldb/status.h"
+namespace blink {
+struct IndexedDBDatabaseMetadata;
+struct IndexedDBIndexMetadata;
+struct IndexedDBObjectStoreMetadata;
+} // namespace blink
+
namespace content {
class LevelDBDatabase;
class LevelDBTransaction;
-struct IndexedDBDatabaseMetadata;
-struct IndexedDBObjectStoreMetadata;
-struct IndexedDBIndexMetadata;
// Creation, reading, and modification operations for IndexedDB metadata. All
// methods that write data to disk use the given |transaction| for writing (and
@@ -49,27 +53,28 @@ class CONTENT_EXPORT IndexedDBMetadataCoding {
LevelDBDatabase* db,
const std::string& origin_identifier,
const base::string16& name,
- IndexedDBDatabaseMetadata* metadata,
+ blink::IndexedDBDatabaseMetadata* metadata,
bool* found);
virtual leveldb::Status ReadMetadataForDatabaseName(
LevelDBTransaction* transaction,
const std::string& origin_identifier,
const base::string16& name,
- IndexedDBDatabaseMetadata* metadata,
+ blink::IndexedDBDatabaseMetadata* metadata,
bool* found);
// Creates a new database metadata entry and writes it to disk.
- virtual leveldb::Status CreateDatabase(LevelDBDatabase* database,
- const std::string& origin_identifier,
- const base::string16& name,
- int64_t version,
- IndexedDBDatabaseMetadata* metadata);
+ virtual leveldb::Status CreateDatabase(
+ LevelDBDatabase* database,
+ const std::string& origin_identifier,
+ const base::string16& name,
+ int64_t version,
+ blink::IndexedDBDatabaseMetadata* metadata);
// Changes the database version to |version|.
virtual void SetDatabaseVersion(LevelDBTransaction* transaction,
int64_t row_id,
int64_t version,
- IndexedDBDatabaseMetadata* metadata);
+ blink::IndexedDBDatabaseMetadata* metadata);
// Reads only the database id, if found.
virtual leveldb::Status FindDatabaseId(LevelDBDatabase* db,
@@ -84,16 +89,16 @@ class CONTENT_EXPORT IndexedDBMetadataCoding {
int64_t database_id,
int64_t object_store_id,
base::string16 name,
- IndexedDBKeyPath key_path,
+ blink::IndexedDBKeyPath key_path,
bool auto_increment,
- IndexedDBObjectStoreMetadata* metadata);
+ blink::IndexedDBObjectStoreMetadata* metadata);
// Deletes the given object store metadata on the transaction (but not any
// data entries or blobs in the object store).
virtual leveldb::Status DeleteObjectStore(
LevelDBTransaction* transaction,
int64_t database_id,
- const IndexedDBObjectStoreMetadata& object_store);
+ const blink::IndexedDBObjectStoreMetadata& object_store);
// Renames the given object store and writes it to the transaction.
virtual leveldb::Status RenameObjectStore(
@@ -101,7 +106,7 @@ class CONTENT_EXPORT IndexedDBMetadataCoding {
int64_t database_id,
base::string16 new_name,
base::string16* old_name,
- IndexedDBObjectStoreMetadata* metadata);
+ blink::IndexedDBObjectStoreMetadata* metadata);
// Creates a new index metadata and writes it to the transaction.
virtual leveldb::Status CreateIndex(LevelDBTransaction* transaction,
@@ -109,16 +114,17 @@ class CONTENT_EXPORT IndexedDBMetadataCoding {
int64_t object_store_id,
int64_t index_id,
base::string16 name,
- IndexedDBKeyPath key_path,
+ blink::IndexedDBKeyPath key_path,
bool is_unique,
bool is_multi_entry,
- IndexedDBIndexMetadata* metadata);
+ blink::IndexedDBIndexMetadata* metadata);
// Deletes the index metadata on the transaction (but not any index entries).
- virtual leveldb::Status DeleteIndex(LevelDBTransaction* transaction,
- int64_t database_id,
- int64_t object_store_id,
- const IndexedDBIndexMetadata& metadata);
+ virtual leveldb::Status DeleteIndex(
+ LevelDBTransaction* transaction,
+ int64_t database_id,
+ int64_t object_store_id,
+ const blink::IndexedDBIndexMetadata& metadata);
// Renames the given index and writes it to the transaction.
virtual leveldb::Status RenameIndex(LevelDBTransaction* transaction,
@@ -126,7 +132,7 @@ class CONTENT_EXPORT IndexedDBMetadataCoding {
int64_t object_store_id,
base::string16 new_name,
base::string16* old_name,
- IndexedDBIndexMetadata* metadata);
+ blink::IndexedDBIndexMetadata* metadata);
private:
DISALLOW_COPY_AND_ASSIGN(IndexedDBMetadataCoding);
diff --git a/chromium/content/browser/indexed_db/indexed_db_observer.h b/chromium/content/browser/indexed_db/indexed_db_observer.h
index c648455a75e..5b5ae2d3be9 100644
--- a/chromium/content/browser/indexed_db/indexed_db_observer.h
+++ b/chromium/content/browser/indexed_db/indexed_db_observer.h
@@ -14,7 +14,7 @@
#include "base/macros.h"
#include "base/stl_util.h"
#include "content/common/content_export.h"
-#include "third_party/blink/public/platform/modules/indexeddb/web_idb_types.h"
+#include "third_party/blink/public/common/indexeddb/web_idb_types.h"
namespace content {
diff --git a/chromium/content/browser/indexed_db/indexed_db_pre_close_task_queue.cc b/chromium/content/browser/indexed_db/indexed_db_pre_close_task_queue.cc
index 0be77f326e1..ec0ebcf5169 100644
--- a/chromium/content/browser/indexed_db/indexed_db_pre_close_task_queue.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_pre_close_task_queue.cc
@@ -6,8 +6,11 @@
#include "base/metrics/histogram_macros.h"
#include "base/threading/sequenced_task_runner_handle.h"
+#include "third_party/blink/public/common/indexeddb/indexeddb_metadata.h"
#include "third_party/leveldatabase/env_chromium.h"
+using blink::IndexedDBDatabaseMetadata;
+
namespace content {
IndexedDBPreCloseTaskQueue::PreCloseTask::~PreCloseTask() {}
@@ -45,9 +48,10 @@ void IndexedDBPreCloseTaskQueue::Start(
OnComplete();
return;
}
- timeout_timer_->Start(FROM_HERE, timeout_time_,
- base::Bind(&IndexedDBPreCloseTaskQueue::StopForTimout,
- ptr_factory_.GetWeakPtr()));
+ timeout_timer_->Start(
+ FROM_HERE, timeout_time_,
+ base::BindOnce(&IndexedDBPreCloseTaskQueue::StopForTimout,
+ ptr_factory_.GetWeakPtr()));
leveldb::Status status = std::move(metadata_fetcher).Run(&metadata_);
if (!status.ok()) {
StopForMetadataError(status);
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 7e2aa847c55..988a941e596 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
@@ -14,9 +14,13 @@
#include "base/memory/ref_counted.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
-#include "content/common/indexed_db/indexed_db_metadata.h"
+#include "content/common/content_export.h"
#include "third_party/leveldatabase/src/include/leveldb/status.h"
+namespace blink {
+struct IndexedDBDatabaseMetadata;
+}
+
namespace content {
// Holds a queue of PreCloseTask's to be run after an IndexedDBBackingStore no
@@ -48,7 +52,7 @@ class CONTENT_EXPORT IndexedDBPreCloseTaskQueue {
// Called before RunRound. |metadata| is guaranteed to outlive this task.
virtual void SetMetadata(
- std::vector<IndexedDBDatabaseMetadata> const* metadata) = 0;
+ std::vector<blink::IndexedDBDatabaseMetadata> const* metadata) = 0;
// Tells the task to stop before completion. It will be destroyed after this
// call. Can be called at any time.
@@ -77,8 +81,9 @@ class CONTENT_EXPORT IndexedDBPreCloseTaskQueue {
void StopForNewConnection();
// Starts running tasks. Can only be called once.
- void Start(base::OnceCallback<leveldb::Status(
- std::vector<IndexedDBDatabaseMetadata>*)> metadata_fetcher);
+ void Start(
+ base::OnceCallback<leveldb::Status(
+ std::vector<blink::IndexedDBDatabaseMetadata>*)> metadata_fetcher);
private:
void OnComplete();
@@ -88,7 +93,7 @@ class CONTENT_EXPORT IndexedDBPreCloseTaskQueue {
void RunLoop();
- std::vector<IndexedDBDatabaseMetadata> metadata_;
+ std::vector<blink::IndexedDBDatabaseMetadata> metadata_;
bool started_ = false;
bool done_ = false;
diff --git a/chromium/content/browser/indexed_db/indexed_db_pre_close_task_queue_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_pre_close_task_queue_unittest.cc
index 48bf2edc32f..18bfa258969 100644
--- a/chromium/content/browser/indexed_db/indexed_db_pre_close_task_queue_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_pre_close_task_queue_unittest.cc
@@ -14,9 +14,11 @@
#include "base/time/time.h"
#include "base/timer/mock_timer.h"
#include "base/timer/timer.h"
-#include "content/common/indexed_db/indexed_db_metadata.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/indexeddb/indexeddb_metadata.h"
+
+using blink::IndexedDBDatabaseMetadata;
namespace content {
diff --git a/chromium/content/browser/indexed_db/indexed_db_reporting.h b/chromium/content/browser/indexed_db/indexed_db_reporting.h
index 353e436e053..ef82e103ea2 100644
--- a/chromium/content/browser/indexed_db/indexed_db_reporting.h
+++ b/chromium/content/browser/indexed_db/indexed_db_reporting.h
@@ -47,6 +47,7 @@ enum IndexedDBBackingStoreErrorSource {
GET_BLOB_KEY_GENERATOR_CURRENT_NUMBER = 28,
GET_BLOB_INFO_FOR_RECORD = 29,
UPGRADING_SCHEMA_CORRUPTED_BLOBS = 30,
+ REVERT_SCHEMA_TO_V2 = 31,
INTERNAL_ERROR_MAX,
};
diff --git a/chromium/content/browser/indexed_db/indexed_db_return_value.h b/chromium/content/browser/indexed_db/indexed_db_return_value.h
index 6a50a26165f..a52851908f6 100644
--- a/chromium/content/browser/indexed_db/indexed_db_return_value.h
+++ b/chromium/content/browser/indexed_db/indexed_db_return_value.h
@@ -7,8 +7,8 @@
#include "content/browser/indexed_db/indexed_db_value.h"
#include "content/common/content_export.h"
-#include "content/common/indexed_db/indexed_db_key.h"
-#include "content/common/indexed_db/indexed_db_key_path.h"
+#include "third_party/blink/public/common/indexeddb/indexeddb_key.h"
+#include "third_party/blink/public/common/indexeddb/indexeddb_key_path.h"
namespace content {
@@ -18,8 +18,9 @@ namespace content {
// database, so they are kept separately, and sent back with the original data
// so that the render process can amend the returned object.
struct CONTENT_EXPORT IndexedDBReturnValue : public IndexedDBValue {
- IndexedDBKey primary_key; // primary key (only when using key generator)
- IndexedDBKeyPath key_path;
+ blink::IndexedDBKey
+ primary_key; // primary key (only when using key generator)
+ blink::IndexedDBKeyPath key_path;
};
} // namespace content
diff --git a/chromium/content/browser/indexed_db/indexed_db_tombstone_sweeper.cc b/chromium/content/browser/indexed_db/indexed_db_tombstone_sweeper.cc
index e3d35567d14..37db1001464 100644
--- a/chromium/content/browser/indexed_db/indexed_db_tombstone_sweeper.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_tombstone_sweeper.cc
@@ -11,6 +11,8 @@
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/time/tick_clock.h"
#include "content/browser/indexed_db/indexed_db_backing_store.h"
+#include "third_party/blink/public/common/indexeddb/indexeddb_key.h"
+#include "third_party/blink/public/common/indexeddb/indexeddb_metadata.h"
#include "third_party/leveldatabase/env_chromium.h"
#include "third_party/leveldatabase/src/include/leveldb/db.h"
#include "third_party/leveldatabase/src/include/leveldb/iterator.h"
@@ -19,6 +21,10 @@ namespace content {
namespace {
using StopReason = IndexedDBPreCloseTaskQueue::StopReason;
+using blink::IndexedDBDatabaseMetadata;
+using blink::IndexedDBIndexMetadata;
+using blink::IndexedDBKey;
+using blink::IndexedDBObjectStoreMetadata;
} // namespace
diff --git a/chromium/content/browser/indexed_db/indexed_db_tombstone_sweeper.h b/chromium/content/browser/indexed_db/indexed_db_tombstone_sweeper.h
index ef335a71440..9ab45a69dee 100644
--- a/chromium/content/browser/indexed_db/indexed_db_tombstone_sweeper.h
+++ b/chromium/content/browser/indexed_db/indexed_db_tombstone_sweeper.h
@@ -18,7 +18,6 @@
#include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
#include "content/browser/indexed_db/indexed_db_pre_close_task_queue.h"
#include "content/common/content_export.h"
-#include "content/common/indexed_db/indexed_db_metadata.h"
#include "third_party/leveldatabase/src/include/leveldb/status.h"
#include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
@@ -26,6 +25,12 @@ namespace base {
class TickClock;
}
+namespace blink {
+struct IndexedDBDatabaseMetadata;
+struct IndexedDBIndexMetadata;
+struct IndexedDBObjectStoreMetadata;
+} // namespace blink
+
namespace leveldb {
class DB;
class Iterator;
@@ -86,17 +91,17 @@ class CONTENT_EXPORT IndexedDBTombstoneSweeper
~IndexedDBTombstoneSweeper() override;
void SetMetadata(
- std::vector<IndexedDBDatabaseMetadata> const* metadata) override;
+ std::vector<blink::IndexedDBDatabaseMetadata> const* metadata) override;
void Stop(IndexedDBPreCloseTaskQueue::StopReason reason) override;
bool RunRound() override;
private:
- using DatabaseMetadataVector = std::vector<IndexedDBDatabaseMetadata>;
+ using DatabaseMetadataVector = std::vector<blink::IndexedDBDatabaseMetadata>;
using ObjectStoreMetadataMap =
- std::map<int64_t, IndexedDBObjectStoreMetadata>;
- using IndexMetadataMap = std::map<int64_t, IndexedDBIndexMetadata>;
+ std::map<int64_t, blink::IndexedDBObjectStoreMetadata>;
+ using IndexMetadataMap = std::map<int64_t, blink::IndexedDBIndexMetadata>;
friend class indexed_db_tombstone_sweeper_unittest::
IndexedDBTombstoneSweeperTest;
@@ -163,7 +168,7 @@ class CONTENT_EXPORT IndexedDBTombstoneSweeper
// Returns true if sweeper can continue iterating.
bool IterateIndex(int64_t database_id,
int64_t object_store_id,
- const IndexedDBIndexMetadata& index,
+ const blink::IndexedDBIndexMetadata& index,
Status* sweep_status,
leveldb::Status* leveldb_status,
int* round_iterations);
@@ -185,7 +190,8 @@ class CONTENT_EXPORT IndexedDBTombstoneSweeper
leveldb::WriteBatch round_deletion_batch_;
base::TimeDelta total_deletion_time_;
- std::vector<IndexedDBDatabaseMetadata> const* database_metadata_ = nullptr;
+ std::vector<blink::IndexedDBDatabaseMetadata> const* database_metadata_ =
+ nullptr;
std::unique_ptr<leveldb::Iterator> iterator_;
SweepState sweep_state_;
diff --git a/chromium/content/browser/indexed_db/indexed_db_tombstone_sweeper_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_tombstone_sweeper_unittest.cc
index 2793b7449b7..4d8e872d43f 100644
--- a/chromium/content/browser/indexed_db/indexed_db_tombstone_sweeper_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_tombstone_sweeper_unittest.cc
@@ -14,15 +14,23 @@
#include "content/browser/indexed_db/leveldb/leveldb_comparator.h"
#include "content/browser/indexed_db/leveldb/leveldb_database.h"
#include "content/browser/indexed_db/leveldb/mock_level_db.h"
-#include "content/common/indexed_db/indexed_db_metadata.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/indexeddb/indexeddb_key.h"
+#include "third_party/blink/public/common/indexeddb/indexeddb_key_path.h"
+#include "third_party/blink/public/common/indexeddb/indexeddb_metadata.h"
#include "third_party/leveldatabase/env_chromium.h"
#include "third_party/leveldatabase/src/include/leveldb/db.h"
#include "third_party/leveldatabase/src/include/leveldb/filter_policy.h"
#include "third_party/leveldatabase/src/include/leveldb/slice.h"
+using blink::IndexedDBDatabaseMetadata;
+using blink::IndexedDBIndexMetadata;
+using blink::IndexedDBKey;
+using blink::IndexedDBKeyPath;
+using blink::IndexedDBObjectStoreMetadata;
+
namespace content {
class BrowserContext;
diff --git a/chromium/content/browser/indexed_db/indexed_db_transaction.cc b/chromium/content/browser/indexed_db/indexed_db_transaction.cc
index 78ac2ba3600..7e2eff576ca 100644
--- a/chromium/content/browser/indexed_db/indexed_db_transaction.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_transaction.cc
@@ -526,9 +526,9 @@ void IndexedDBTransaction::ProcessTaskQueue() {
// never requests further activity. Read-only transactions don't
// block other transactions, so don't time those out.
if (mode_ != blink::kWebIDBTransactionModeReadOnly) {
- timeout_timer_.Start(
- FROM_HERE, GetInactivityTimeout(),
- base::Bind(&IndexedDBTransaction::Timeout, ptr_factory_.GetWeakPtr()));
+ timeout_timer_.Start(FROM_HERE, GetInactivityTimeout(),
+ base::BindOnce(&IndexedDBTransaction::Timeout,
+ ptr_factory_.GetWeakPtr()));
}
processing_event_queue_ = false;
}
@@ -571,18 +571,18 @@ void IndexedDBTransaction::RemovePendingObservers(
void IndexedDBTransaction::AddObservation(
int32_t connection_id,
- ::indexed_db::mojom::ObservationPtr observation) {
+ blink::mojom::IDBObservationPtr observation) {
auto it = connection_changes_map_.find(connection_id);
if (it == connection_changes_map_.end()) {
it = connection_changes_map_
- .insert(std::make_pair(
- connection_id, ::indexed_db::mojom::ObserverChanges::New()))
+ .insert(std::make_pair(connection_id,
+ blink::mojom::IDBObserverChanges::New()))
.first;
}
it->second->observations.push_back(std::move(observation));
}
-::indexed_db::mojom::ObserverChangesPtr*
+blink::mojom::IDBObserverChangesPtr*
IndexedDBTransaction::GetPendingChangesForConnection(int32_t connection_id) {
auto it = connection_changes_map_.find(connection_id);
if (it != connection_changes_map_.end())
diff --git a/chromium/content/browser/indexed_db/indexed_db_transaction.h b/chromium/content/browser/indexed_db/indexed_db_transaction.h
index fd690bcc345..f7bc5f07a14 100644
--- a/chromium/content/browser/indexed_db/indexed_db_transaction.h
+++ b/chromium/content/browser/indexed_db/indexed_db_transaction.h
@@ -23,8 +23,8 @@
#include "content/browser/indexed_db/indexed_db_database.h"
#include "content/browser/indexed_db/indexed_db_database_error.h"
#include "content/browser/indexed_db/indexed_db_observer.h"
-#include "content/common/indexed_db/indexed_db.mojom.h"
-#include "third_party/blink/public/platform/modules/indexeddb/web_idb_types.h"
+#include "third_party/blink/public/common/indexeddb/web_idb_types.h"
+#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h"
namespace content {
@@ -95,9 +95,9 @@ class CONTENT_EXPORT IndexedDBTransaction {
// Adds observation for the connection.
void AddObservation(int32_t connection_id,
- ::indexed_db::mojom::ObservationPtr observation);
+ blink::mojom::IDBObservationPtr observation);
- ::indexed_db::mojom::ObserverChangesPtr* GetPendingChangesForConnection(
+ blink::mojom::IDBObserverChangesPtr* GetPendingChangesForConnection(
int32_t connection_id);
IndexedDBBackingStore::Transaction* BackingStoreTransaction() {
@@ -195,7 +195,7 @@ class CONTENT_EXPORT IndexedDBTransaction {
// Observers in pending queue do not listen to changes until activated.
std::vector<std::unique_ptr<IndexedDBObserver>> pending_observers_;
- std::map<int32_t, ::indexed_db::mojom::ObserverChangesPtr>
+ std::map<int32_t, blink::mojom::IDBObserverChangesPtr>
connection_changes_map_;
// Metrics for quota.
diff --git a/chromium/content/browser/indexed_db/indexed_db_transaction_coordinator.cc b/chromium/content/browser/indexed_db/indexed_db_transaction_coordinator.cc
index eb714dde14d..91dd95712ad 100644
--- a/chromium/content/browser/indexed_db/indexed_db_transaction_coordinator.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_transaction_coordinator.cc
@@ -7,7 +7,7 @@
#include "base/logging.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_types.h"
+#include "third_party/blink/public/common/indexeddb/web_idb_types.h"
namespace content {
namespace {
diff --git a/chromium/content/browser/indexed_db/indexed_db_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_unittest.cc
index 705a2ed309c..4763c2f5eaf 100644
--- a/chromium/content/browser/indexed_db/indexed_db_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_unittest.cc
@@ -26,6 +26,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "url/origin.h"
+using blink::IndexedDBDatabaseMetadata;
using url::Origin;
namespace content {
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 266205bdb14..742de2e5732 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
@@ -64,7 +64,7 @@ class IndexedDBTestDatabase : public IndexedDBDatabase {
protected:
~IndexedDBTestDatabase() override {}
- size_t GetMaxMessageSizeInBytes() const override {
+ size_t GetUsableMessageSizeInBytes() const override {
return 10 * 1024 * 1024; // 10MB
}
};
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 0c520868636..64e9ce487f1 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
@@ -14,7 +14,7 @@
#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_database.h"
-#include "third_party/blink/public/platform/modules/indexeddb/web_idb_types.h"
+#include "third_party/blink/public/common/indexeddb/web_idb_types.h"
namespace content {
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 fe8a6a12c9c..eb7a20405b1 100644
--- a/chromium/content/browser/indexed_db/mock_indexed_db_callbacks.cc
+++ b/chromium/content/browser/indexed_db/mock_indexed_db_callbacks.cc
@@ -8,6 +8,9 @@
#include "testing/gtest/include/gtest/gtest.h"
+using blink::IndexedDBDatabaseMetadata;
+using blink::IndexedDBKey;
+
namespace content {
MockIndexedDBCallbacks::MockIndexedDBCallbacks()
@@ -41,7 +44,7 @@ void MockIndexedDBCallbacks::OnSuccess(
void MockIndexedDBCallbacks::OnUpgradeNeeded(
int64_t old_version,
std::unique_ptr<IndexedDBConnection> connection,
- const content::IndexedDBDatabaseMetadata& metadata,
+ const IndexedDBDatabaseMetadata& metadata,
const IndexedDBDataLossInfo& data_loss_info) {
connection_ = std::move(connection);
upgrade_called_ = true;
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 10fa56e204e..bc67121a9cd 100644
--- a/chromium/content/browser/indexed_db/mock_indexed_db_callbacks.h
+++ b/chromium/content/browser/indexed_db/mock_indexed_db_callbacks.h
@@ -12,6 +12,11 @@
#include "base/macros.h"
#include "content/browser/indexed_db/indexed_db_callbacks.h"
#include "content/browser/indexed_db/indexed_db_connection.h"
+#include "third_party/blink/public/common/indexeddb/indexeddb_key.h"
+
+namespace blink {
+struct IndexedDBDatabaseMetadata;
+}
namespace content {
@@ -25,14 +30,14 @@ class MockIndexedDBCallbacks : public IndexedDBCallbacks {
void OnSuccess() override;
void OnSuccess(int64_t result) override;
void OnSuccess(const std::vector<base::string16>& result) override;
- void OnSuccess(const IndexedDBKey& key) override;
+ void OnSuccess(const blink::IndexedDBKey& key) override;
void OnSuccess(std::unique_ptr<IndexedDBConnection> connection,
- const IndexedDBDatabaseMetadata& metadata) override;
+ const blink::IndexedDBDatabaseMetadata& metadata) override;
IndexedDBConnection* connection() { return connection_.get(); }
void OnUpgradeNeeded(int64_t old_version,
std::unique_ptr<IndexedDBConnection> connection,
- const content::IndexedDBDatabaseMetadata& metadata,
+ const blink::IndexedDBDatabaseMetadata& metadata,
const IndexedDBDataLossInfo& data_loss_info) override;
bool error_called() { return error_called_; }
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 6a3022197a0..b2747857a84 100644
--- a/chromium/content/browser/indexed_db/mock_indexed_db_factory.h
+++ b/chromium/content/browser/indexed_db/mock_indexed_db_factory.h
@@ -78,6 +78,7 @@ class MockIndexedDBFactory : public IndexedDBFactory {
// deal with std::pair's. This means we can't use GoogleMock for this method
OriginDBs GetOpenDatabasesForOrigin(const url::Origin& origin) const override;
MOCK_METHOD1(ForceClose, void(const url::Origin& origin));
+ MOCK_METHOD1(ForceSchemaDowngrade, void(const url::Origin& origin));
MOCK_METHOD0(ContextDestroyed, void());
MOCK_METHOD1(DatabaseDeleted,
void(const IndexedDBDatabase::Identifier& identifier));
diff --git a/chromium/content/browser/indexed_db/mock_mojo_indexed_db_callbacks.cc b/chromium/content/browser/indexed_db/mock_mojo_indexed_db_callbacks.cc
index 7f0f9bdb43d..358a6703e9a 100644
--- a/chromium/content/browser/indexed_db/mock_mojo_indexed_db_callbacks.cc
+++ b/chromium/content/browser/indexed_db/mock_mojo_indexed_db_callbacks.cc
@@ -9,9 +9,9 @@ namespace content {
MockMojoIndexedDBCallbacks::MockMojoIndexedDBCallbacks() : binding_(this) {}
MockMojoIndexedDBCallbacks::~MockMojoIndexedDBCallbacks() {}
-::indexed_db::mojom::CallbacksAssociatedPtrInfo
+blink::mojom::IDBCallbacksAssociatedPtrInfo
MockMojoIndexedDBCallbacks::CreateInterfacePtrAndBind() {
- ::indexed_db::mojom::CallbacksAssociatedPtrInfo ptr_info;
+ blink::mojom::IDBCallbacksAssociatedPtrInfo ptr_info;
binding_.Bind(::mojo::MakeRequest(&ptr_info));
return ptr_info;
}
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 ca8fb743097..ee92e16a517 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
@@ -9,18 +9,23 @@
#include <string>
#include "base/macros.h"
-#include "content/common/indexed_db/indexed_db.mojom.h"
#include "mojo/public/cpp/bindings/associated_binding.h"
#include "testing/gmock/include/gmock/gmock.h"
+#include "third_party/blink/public/common/indexeddb/indexeddb_key.h"
+#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h"
+
+namespace blink {
+struct IndexedDBDatabaseMetadata;
+}
namespace content {
-class MockMojoIndexedDBCallbacks : public ::indexed_db::mojom::Callbacks {
+class MockMojoIndexedDBCallbacks : public blink::mojom::IDBCallbacks {
public:
explicit MockMojoIndexedDBCallbacks();
~MockMojoIndexedDBCallbacks() override;
- ::indexed_db::mojom::CallbacksAssociatedPtrInfo CreateInterfacePtrAndBind();
+ blink::mojom::IDBCallbacksAssociatedPtrInfo CreateInterfacePtrAndBind();
MOCK_METHOD2(Error, void(int32_t code, const base::string16& message));
@@ -29,89 +34,87 @@ class MockMojoIndexedDBCallbacks : public ::indexed_db::mojom::Callbacks {
MOCK_METHOD1(Blocked, void(int64_t existing_version));
- MOCK_METHOD5(
- MockedUpgradeNeeded,
- void(::indexed_db::mojom::DatabaseAssociatedPtrInfo* database_info,
- int64_t old_version,
- blink::WebIDBDataLoss data_loss,
- const std::string& data_loss_message,
- const content::IndexedDBDatabaseMetadata& metadata));
+ MOCK_METHOD5(MockedUpgradeNeeded,
+ void(blink::mojom::IDBDatabaseAssociatedPtrInfo* database_info,
+ int64_t old_version,
+ blink::WebIDBDataLoss data_loss,
+ const std::string& data_loss_message,
+ const blink::IndexedDBDatabaseMetadata& metadata));
// Move-only types not supported by mock methods.
void UpgradeNeeded(
- ::indexed_db::mojom::DatabaseAssociatedPtrInfo database_info,
+ blink::mojom::IDBDatabaseAssociatedPtrInfo database_info,
int64_t old_version,
blink::WebIDBDataLoss data_loss,
const std::string& data_loss_message,
- const content::IndexedDBDatabaseMetadata& metadata) override {
+ const blink::IndexedDBDatabaseMetadata& metadata) override {
MockedUpgradeNeeded(&database_info, old_version, data_loss,
data_loss_message, metadata);
}
- MOCK_METHOD2(
- MockedSuccessDatabase,
- void(::indexed_db::mojom::DatabaseAssociatedPtrInfo* database_info,
- const content::IndexedDBDatabaseMetadata& metadata));
+ MOCK_METHOD2(MockedSuccessDatabase,
+ void(blink::mojom::IDBDatabaseAssociatedPtrInfo* database_info,
+ const blink::IndexedDBDatabaseMetadata& metadata));
void SuccessDatabase(
- ::indexed_db::mojom::DatabaseAssociatedPtrInfo database_info,
- const content::IndexedDBDatabaseMetadata& metadata) override {
+ blink::mojom::IDBDatabaseAssociatedPtrInfo database_info,
+ const blink::IndexedDBDatabaseMetadata& metadata) override {
MockedSuccessDatabase(&database_info, metadata);
}
MOCK_METHOD4(MockedSuccessCursor,
- void(::indexed_db::mojom::CursorAssociatedPtrInfo* cursor,
- const IndexedDBKey& key,
- const IndexedDBKey& primary_key,
- ::indexed_db::mojom::ValuePtr* value));
- void SuccessCursor(::indexed_db::mojom::CursorAssociatedPtrInfo cursor,
- const IndexedDBKey& key,
- const IndexedDBKey& primary_key,
- ::indexed_db::mojom::ValuePtr value) override {
+ void(blink::mojom::IDBCursorAssociatedPtrInfo* cursor,
+ const blink::IndexedDBKey& key,
+ const blink::IndexedDBKey& primary_key,
+ blink::mojom::IDBValuePtr* value));
+ void SuccessCursor(blink::mojom::IDBCursorAssociatedPtrInfo cursor,
+ const blink::IndexedDBKey& key,
+ const blink::IndexedDBKey& primary_key,
+ blink::mojom::IDBValuePtr value) override {
MockedSuccessCursor(&cursor, key, primary_key, &value);
}
MOCK_METHOD1(MockedSuccessValue,
- void(::indexed_db::mojom::ReturnValuePtr* value));
- void SuccessValue(::indexed_db::mojom::ReturnValuePtr value) override {
+ void(blink::mojom::IDBReturnValuePtr* value));
+ void SuccessValue(blink::mojom::IDBReturnValuePtr value) override {
MockedSuccessValue(&value);
}
MOCK_METHOD3(MockedSuccessCursorContinue,
- void(const IndexedDBKey& key,
- const IndexedDBKey& primary_key,
- ::indexed_db::mojom::ValuePtr* value));
+ void(const blink::IndexedDBKey& key,
+ const blink::IndexedDBKey& primary_key,
+ blink::mojom::IDBValuePtr* value));
- void SuccessCursorContinue(const IndexedDBKey& key,
- const IndexedDBKey& primary_key,
- ::indexed_db::mojom::ValuePtr value) override {
+ void SuccessCursorContinue(const blink::IndexedDBKey& key,
+ const blink::IndexedDBKey& primary_key,
+ blink::mojom::IDBValuePtr value) override {
MockedSuccessCursorContinue(key, primary_key, &value);
}
MOCK_METHOD3(MockedSuccessCursorPrefetch,
- void(const std::vector<IndexedDBKey>& keys,
- const std::vector<IndexedDBKey>& primary_keys,
- std::vector<::indexed_db::mojom::ValuePtr>* values));
+ void(const std::vector<blink::IndexedDBKey>& keys,
+ const std::vector<blink::IndexedDBKey>& primary_keys,
+ std::vector<blink::mojom::IDBValuePtr>* values));
void SuccessCursorPrefetch(
- const std::vector<IndexedDBKey>& keys,
- const std::vector<IndexedDBKey>& primary_keys,
- std::vector<::indexed_db::mojom::ValuePtr> values) override {
+ const std::vector<blink::IndexedDBKey>& keys,
+ const std::vector<blink::IndexedDBKey>& primary_keys,
+ std::vector<blink::mojom::IDBValuePtr> values) override {
MockedSuccessCursorPrefetch(keys, primary_keys, &values);
}
MOCK_METHOD1(MockedSuccessArray,
- void(std::vector<::indexed_db::mojom::ReturnValuePtr>* values));
+ void(std::vector<blink::mojom::IDBReturnValuePtr>* values));
void SuccessArray(
- std::vector<::indexed_db::mojom::ReturnValuePtr> values) override {
+ std::vector<blink::mojom::IDBReturnValuePtr> values) override {
MockedSuccessArray(&values);
}
- MOCK_METHOD1(SuccessKey, void(const IndexedDBKey& key));
+ MOCK_METHOD1(SuccessKey, void(const blink::IndexedDBKey& key));
MOCK_METHOD1(SuccessInteger, void(int64_t value));
MOCK_METHOD0(Success, void());
private:
- mojo::AssociatedBinding<::indexed_db::mojom::Callbacks> binding_;
+ mojo::AssociatedBinding<blink::mojom::IDBCallbacks> binding_;
DISALLOW_COPY_AND_ASSIGN(MockMojoIndexedDBCallbacks);
};
diff --git a/chromium/content/browser/indexed_db/mock_mojo_indexed_db_database_callbacks.cc b/chromium/content/browser/indexed_db/mock_mojo_indexed_db_database_callbacks.cc
index db53b3f7550..b53faf06cb3 100644
--- a/chromium/content/browser/indexed_db/mock_mojo_indexed_db_database_callbacks.cc
+++ b/chromium/content/browser/indexed_db/mock_mojo_indexed_db_database_callbacks.cc
@@ -10,9 +10,9 @@ MockMojoIndexedDBDatabaseCallbacks::MockMojoIndexedDBDatabaseCallbacks()
: binding_(this) {}
MockMojoIndexedDBDatabaseCallbacks::~MockMojoIndexedDBDatabaseCallbacks() {}
-::indexed_db::mojom::DatabaseCallbacksAssociatedPtrInfo
+blink::mojom::IDBDatabaseCallbacksAssociatedPtrInfo
MockMojoIndexedDBDatabaseCallbacks::CreateInterfacePtrAndBind() {
- ::indexed_db::mojom::DatabaseCallbacksAssociatedPtrInfo ptr_info;
+ blink::mojom::IDBDatabaseCallbacksAssociatedPtrInfo ptr_info;
binding_.Bind(::mojo::MakeRequest(&ptr_info));
return ptr_info;
}
diff --git a/chromium/content/browser/indexed_db/mock_mojo_indexed_db_database_callbacks.h b/chromium/content/browser/indexed_db/mock_mojo_indexed_db_database_callbacks.h
index cff98884f15..b19047754e9 100644
--- a/chromium/content/browser/indexed_db/mock_mojo_indexed_db_database_callbacks.h
+++ b/chromium/content/browser/indexed_db/mock_mojo_indexed_db_database_callbacks.h
@@ -8,19 +8,19 @@
#include <stdint.h>
#include "base/macros.h"
-#include "content/common/indexed_db/indexed_db.mojom.h"
#include "mojo/public/cpp/bindings/associated_binding.h"
#include "testing/gmock/include/gmock/gmock.h"
+#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h"
namespace content {
class MockMojoIndexedDBDatabaseCallbacks
- : public ::indexed_db::mojom::DatabaseCallbacks {
+ : public blink::mojom::IDBDatabaseCallbacks {
public:
MockMojoIndexedDBDatabaseCallbacks();
~MockMojoIndexedDBDatabaseCallbacks() override;
- ::indexed_db::mojom::DatabaseCallbacksAssociatedPtrInfo
+ blink::mojom::IDBDatabaseCallbacksAssociatedPtrInfo
CreateInterfacePtrAndBind();
MOCK_METHOD0(ForcedClose, void());
@@ -32,13 +32,13 @@ class MockMojoIndexedDBDatabaseCallbacks
MOCK_METHOD1(Complete, void(int64_t transaction_id));
MOCK_METHOD1(MockedChanges,
- void(::indexed_db::mojom::ObserverChangesPtr* changes));
- void Changes(::indexed_db::mojom::ObserverChangesPtr changes) override {
+ void(blink::mojom::IDBObserverChangesPtr* changes));
+ void Changes(blink::mojom::IDBObserverChangesPtr changes) override {
MockedChanges(&changes);
}
private:
- mojo::AssociatedBinding<::indexed_db::mojom::DatabaseCallbacks> binding_;
+ mojo::AssociatedBinding<blink::mojom::IDBDatabaseCallbacks> binding_;
DISALLOW_COPY_AND_ASSIGN(MockMojoIndexedDBDatabaseCallbacks);
};
diff --git a/chromium/content/browser/indexed_db/scopes/README.md b/chromium/content/browser/indexed_db/scopes/README.md
new file mode 100644
index 00000000000..75982fe42f1
--- /dev/null
+++ b/chromium/content/browser/indexed_db/scopes/README.md
@@ -0,0 +1,184 @@
+# LevelDB Scopes Implementation Design
+
+This document is the implementation plan and design for LevelDB Scopes. It serves to both document the current state and the future plans for implementing LevelDB Scopes.
+
+See LevelDB Scopes general design doc [here](https://docs.google.com/document/d/16_igCI15Gfzb6UYqeuJTmJPrzEtawz6Y1tVOKNtYgiU/edit).
+
+# Status / Current State
+
+The only thing implemented so far is the lock manager interface & descrete implementation.
+
+# Vocabulary
+
+**Scope**
+
+A scope encompases 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.
+
+**Undo Log**
+
+Each scope saves an undo log, which has all the information needed to undo all changes performed in the scope.
+
+**Scope Number (scope#)**
+
+Each scope has an identifier unique to the backing store that is auto-incrementing. During recovery, it is set to the minimum unused scope (see more in the recovery section).
+
+**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
+
+**Commit Point**
+
+This signifies that a scope has been committed. It also means that a specific sequence number was written for a scope.
+
+**Key Range**
+
+Represents a range of LevelDB keys. Every operation has a key or a key range associated with it. Sometimes key ranges are expected to be re-used or modified again by subsequent operations, and sometimes key ranges are known to be never used again.
+
+**Lock**
+
+To prevent reading uncommitted data, IndexedDB 'locks' objects stores when there are (readwrite) transactions operating on them.
+
+## New LevelDB Table Data
+
+|Purpose|Key |Final 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\> |
+
+
+### Key Format
+
+* Allow the 'user' of the scopes system to choose the key prefix (`prefix`).
+* Scope # is a varint
+* Sequence # is a Fixed64
+
+### Value Format
+
+All values will be protobufs
+
+# Operation Flows
+
+## Creating & Using a Scope
+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.
+* 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
+ * See the [Undo Operation Generation](#undo-operations) section below
+* 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 metadatais 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 #.
+* Output - Scope is committed, and lock is released.
+
+## Reverting a Scope
+**Cleanup & Revert Sequence**
+
+* Input - revert a given scope number.
+* Opens a cursor to 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.
+* 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
+ * 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
+* Signals IndexedDB that it can start accepting operations (IndexedDB can now start running)
+* For every undo-scopes- metadata that is empty
+ * 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).
+ * 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.
+* Output - nothing
+
+# Lock Manager
+
+The scopes feature needs a fairly generic lock manager. This lock manager needs two levels, because versionchange transactions need to lock a whole database, where other transactions will lock smaller ranges within the level one range.
+
+### API Methods
+
+#### AcquireLock
+
+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.
+
+### Internal Data Structure
+
+The lock manager basically holds ranges, and needs to know if a new range intersects any old ranges. A good data structure for this is an Interval Tree.
+
+# Undo Operations
+
+## Types
+
+* `Put(key, value)`
+* `Delete(key)`
+* `DeleteRange(key_range)`
+
+## Generation
+
+### Normal Cases
+
+Note - all cases where "old_value" is used requires reading the current value from the database.
+
+**`Put(key, value)`**
+
+* `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
+
+**`Add(key, value)`**
+
+* Delete(key), trusting the client that there wasn't a value here before.
+
+**`Delete(key)`**
+
+* `Put(key, old_value)` if the old_value exists, or
+* Nothing if no old_value exists.
+
+**`DeleteRange(key_range)`**
+
+* `Put(key, old_value)` for every entry in that key range. This requires iterating the database using the key_range to find all entries.
+
+### Special Case - Empty Unique Key Range
+
+#### Creation - key range is empty initially
+
+If the values being created are in a key range that is initially empty (we trust the API caller here - there is no verification), and if the key range will never be reused if it is reverted, then the undo log can consist of a single:
+
+`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.
+
+#### 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 commited, with the key ranges never-to-be-used-again will be the value of the commit point record.
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
new file mode 100644
index 00000000000..19daa4f0a43
--- /dev/null
+++ b/chromium/content/browser/indexed_db/scopes/disjoint_range_lock_manager.cc
@@ -0,0 +1,166 @@
+// 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/disjoint_range_lock_manager.h"
+
+namespace content {
+
+DisjointRangeLockManager::LockRequest::LockRequest() = default;
+DisjointRangeLockManager::LockRequest::LockRequest(LockType type,
+ LockAquiredCallback callback)
+ : requested_type(type), callback(std::move(callback)) {}
+DisjointRangeLockManager::LockRequest::LockRequest(LockRequest&&) noexcept =
+ default;
+DisjointRangeLockManager::LockRequest::~LockRequest() = default;
+DisjointRangeLockManager::Lock::Lock() = default;
+DisjointRangeLockManager::Lock::Lock(Lock&&) noexcept = default;
+DisjointRangeLockManager::Lock::~Lock() = default;
+DisjointRangeLockManager::Lock& DisjointRangeLockManager::Lock::operator=(
+ DisjointRangeLockManager::Lock&&) noexcept = default;
+
+DisjointRangeLockManager::DisjointRangeLockManager(
+ int level_count,
+ const leveldb::Comparator* comparator,
+ scoped_refptr<base::SequencedTaskRunner> task_runner)
+ : comparator_(comparator), task_runner_(task_runner), weak_factory_(this) {
+ for (int level = 0; level < level_count; ++level) {
+ locks_.emplace_back(RangeLessThan(comparator));
+ }
+}
+
+DisjointRangeLockManager::~DisjointRangeLockManager() = default;
+
+int64_t DisjointRangeLockManager::LocksHeldForTesting() const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ int64_t locks = 0;
+ for (const LockLevelMap& map : locks_) {
+ for (const auto& pair : map) {
+ locks += pair.second.acquired_count;
+ }
+ }
+ return locks;
+}
+int64_t DisjointRangeLockManager::RequestsWaitingForTesting() const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ int64_t requests = 0;
+ for (const LockLevelMap& map : locks_) {
+ for (const auto& pair : map) {
+ requests += pair.second.queue.size();
+ }
+ }
+ return requests;
+}
+
+void DisjointRangeLockManager::AcquireLock(int level,
+ const LockRange& range,
+ LockType type,
+ LockAquiredCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK_LT(level, static_cast<int>(locks_.size()));
+ DCHECK_LT(comparator_->Compare(leveldb::Slice(range.begin),
+ leveldb::Slice(range.end)),
+ 0)
+ << "Range is invalid: " << range;
+
+ auto& level_locks = locks_[level];
+
+ auto it = level_locks.find(range);
+ if (it == level_locks.end()) {
+ it = level_locks
+ .emplace(std::piecewise_construct, std::forward_as_tuple(range),
+ std::forward_as_tuple())
+ .first;
+ }
+
+ DCHECK_EQ(it->first, range)
+ << range << " does not match what is in the lock map " << it->first;
+#if DCHECK_IS_ON()
+ DCHECK(IsRangeDisjointFromNeighbors(level_locks, range, comparator_))
+ << "Range not discrete: " << range;
+#endif
+ Lock& lock = it->second;
+
+ if (lock.CanBeAcquired(type)) {
+ ++lock.acquired_count;
+ lock.lock_mode = type;
+ std::move(callback).Run(
+ ScopeLock(range, level,
+ base::BindOnce(&DisjointRangeLockManager::LockReleased,
+ weak_factory_.GetWeakPtr(), level, range)));
+ } else {
+ lock.queue.emplace_back(type, std::move(callback));
+ }
+}
+
+void DisjointRangeLockManager::RemoveLockRange(int level,
+ const LockRange& range) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK_LT(level, static_cast<int>(locks_.size()));
+ auto& level_locks = locks_[level];
+ auto it = level_locks.find(range);
+ if (it != level_locks.end()) {
+ DCHECK_EQ(0, it->second.acquired_count);
+ level_locks.erase(it);
+ }
+}
+
+void DisjointRangeLockManager::LockReleased(int level, LockRange range) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK_LT(level, static_cast<int>(locks_.size()));
+ auto& level_locks = locks_[level];
+ auto it = level_locks.find(range);
+ DCHECK(it != level_locks.end());
+ Lock& lock = it->second;
+
+ DCHECK_GT(lock.acquired_count, 0);
+ --(lock.acquired_count);
+ if (lock.acquired_count == 0) {
+ // Either the lock isn't acquired yet or more shared locks can be granted.
+ while (!lock.queue.empty() &&
+ (lock.acquired_count == 0 ||
+ lock.queue.front().requested_type == LockType::kShared)) {
+ LockRequest requester = std::move(lock.queue.front());
+ lock.queue.pop_front();
+ ++lock.acquired_count;
+ lock.lock_mode = requester.requested_type;
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ std::move(requester.callback),
+ ScopeLock(range, level,
+ base::BindOnce(&DisjointRangeLockManager::LockReleased,
+ weak_factory_.GetWeakPtr(), level,
+ std::move(range)))));
+ // This can only happen if acquired_count was 0.
+ if (requester.requested_type == LockType::kExclusive)
+ return;
+ }
+ }
+}
+
+#if DCHECK_IS_ON()
+// static
+bool DisjointRangeLockManager::IsRangeDisjointFromNeighbors(
+ const LockLevelMap& map,
+ const LockRange& range,
+ const leveldb::Comparator* const comparator) {
+ DCHECK_EQ(map.count(range), 1ull);
+ auto it = map.find(range);
+ auto next_it = it;
+ ++next_it;
+ if (next_it != map.end()) {
+ return comparator->Compare(leveldb::Slice(range.end),
+ leveldb::Slice(next_it->first.begin)) <= 0;
+ }
+ auto last_it = it;
+ if (last_it != map.begin()) {
+ --last_it;
+ return comparator->Compare(leveldb::Slice(last_it->first.end),
+ leveldb::Slice(range.begin)) <= 0;
+ }
+ return true;
+}
+#endif
+
+} // namespace content
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
new file mode 100644
index 00000000000..f01a5abf161
--- /dev/null
+++ b/chromium/content/browser/indexed_db/scopes/disjoint_range_lock_manager.h
@@ -0,0 +1,127 @@
+// 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_DISJOINT_RANGE_LOCK_MANAGER_H_
+#define CONTENT_BROWSER_INDEXED_DB_SCOPES_DISJOINT_RANGE_LOCK_MANAGER_H_
+
+#include <list>
+#include <vector>
+
+#include "base/containers/flat_map.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/optional.h"
+#include "base/sequence_checker.h"
+#include "base/sequenced_task_runner.h"
+#include "content/browser/indexed_db/scopes/scopes_lock_manager.h"
+#include "content/common/content_export.h"
+#include "third_party/leveldatabase/src/include/leveldb/comparator.h"
+#include "third_party/leveldatabase/src/include/leveldb/slice.h"
+
+namespace content {
+
+// Holds locks of the scopes system. To be performant without an Interval Tree,
+// this implementation has the following invariants:
+// * All lock range requests at a level must be disjoint - they cannot overlap.
+// * Lock ranges are remembered for future performance - remove them using
+// RemoveLockRange.
+// * All calls must happen from the same sequenced task runner.
+class CONTENT_EXPORT DisjointRangeLockManager : public ScopesLockManager {
+ public:
+ // Creates a lock manager with the given number of levels, the comparator for
+ // leveldb keys, and the current task runner that we are running on. The task
+ // runner will be used for the lock acquisition callbacks.
+ DisjointRangeLockManager(
+ int level_count,
+ const leveldb::Comparator* comparator,
+ scoped_refptr<base::SequencedTaskRunner> task_runner);
+ ~DisjointRangeLockManager() override;
+
+ int64_t LocksHeldForTesting() const override;
+ int64_t RequestsWaitingForTesting() const override;
+
+ void AcquireLock(int level,
+ const LockRange& range,
+ LockType type,
+ LockAquiredCallback callback) override;
+
+ // Remove the given lock range at the given level. The lock range must not be
+ // in use. Use this if the lock will never be used again.
+ void RemoveLockRange(int level, const LockRange& range);
+
+ private:
+ struct LockRequest {
+ public:
+ LockRequest();
+ LockRequest(LockRequest&&) noexcept;
+ LockRequest(LockType type, LockAquiredCallback callback);
+ ~LockRequest();
+
+ LockType requested_type = LockType::kShared;
+ LockAquiredCallback callback;
+ };
+
+ // Represents a lock, which has a range and a level. To support shared access,
+ // there can be multiple acquisitions of this lock, represented in
+ // |acquired_count|. Also holds the pending requests for this lock.
+ struct Lock {
+ public:
+ Lock();
+ Lock(Lock&&) noexcept;
+ ~Lock();
+ Lock& operator=(Lock&&) noexcept;
+
+ bool CanBeAcquired(LockType lock_type) {
+ return acquired_count == 0 ||
+ (queue.empty() && this->lock_mode == LockType::kShared &&
+ lock_type == LockType::kShared);
+ }
+
+ int acquired_count = 0;
+ LockType lock_mode = LockType::kShared;
+ std::list<LockRequest> queue;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Lock);
+ };
+
+ // This is a proxy between a LevelDB Comparator and the interface expected by
+ // std::map. It sorts using the |begin| entry of the ranges.
+ class RangeLessThan {
+ public:
+ explicit RangeLessThan(const leveldb::Comparator* comparator)
+ : comparator_(comparator) {}
+ bool operator()(const LockRange& a, const LockRange& b) const {
+ return comparator_->Compare(leveldb::Slice(a.begin),
+ leveldb::Slice(b.begin)) < 0;
+ }
+
+ private:
+ const leveldb::Comparator* const comparator_;
+ };
+
+ using LockLevelMap = base::flat_map<LockRange, Lock, RangeLessThan>;
+
+ void LockReleased(int level, LockRange range);
+
+#if DCHECK_IS_ON()
+ static bool IsRangeDisjointFromNeighbors(
+ const LockLevelMap& map,
+ const LockRange& range,
+ const leveldb::Comparator* const comparator_);
+#endif
+
+ const leveldb::Comparator* const comparator_;
+ const scoped_refptr<base::SequencedTaskRunner> task_runner_;
+ // This vector should never be modified after construction.
+ std::vector<LockLevelMap> locks_;
+
+ SEQUENCE_CHECKER(sequence_checker_);
+ base::WeakPtrFactory<DisjointRangeLockManager> weak_factory_;
+ DISALLOW_COPY_AND_ASSIGN(DisjointRangeLockManager);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_INDEXED_DB_SCOPES_DISJOINT_RANGE_LOCK_MANAGER_H_
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
new file mode 100644
index 00000000000..1e952f51e2e
--- /dev/null
+++ b/chromium/content/browser/indexed_db/scopes/disjoint_range_lock_manager_unittest.cc
@@ -0,0 +1,221 @@
+// 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/disjoint_range_lock_manager.h>
+#include <content/test/barrier_builder.h>
+
+#include "base/barrier_closure.h"
+#include "base/bind_helpers.h"
+#include "base/run_loop.h"
+#include "base/strings/stringprintf.h"
+#include "base/test/bind_test_util.h"
+#include "base/test/scoped_task_environment.h"
+#include "base/threading/sequenced_task_runner_handle.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+namespace {
+using ScopeLock = ScopesLockManager::ScopeLock;
+using LockRange = ScopesLockManager::LockRange;
+
+template <typename T>
+void SetValue(T* out, T value) {
+ *out = value;
+}
+
+std::string IntegerKey(size_t num) {
+ return base::StringPrintf("%010zd", num);
+}
+
+void StoreLock(ScopeLock* lock_out, base::OnceClosure done, ScopeLock lock) {
+ (*lock_out) = std::move(lock);
+ std::move(done).Run();
+}
+
+class DisjointRangeLockManagerTest : public testing::Test {
+ public:
+ DisjointRangeLockManagerTest() = default;
+ ~DisjointRangeLockManagerTest() override = default;
+
+ private:
+ base::test::ScopedTaskEnvironment task_env_;
+};
+
+TEST_F(DisjointRangeLockManagerTest, BasicAcquisition) {
+ const size_t kTotalLocks = 1000;
+ DisjointRangeLockManager lock_manager(1, leveldb::BytewiseComparator(),
+ base::SequencedTaskRunnerHandle::Get());
+
+ EXPECT_EQ(0ll, lock_manager.LocksHeldForTesting());
+ EXPECT_EQ(0ll, lock_manager.RequestsWaitingForTesting());
+
+ base::RunLoop loop;
+ std::vector<ScopeLock> locks;
+ locks.resize(kTotalLocks);
+ {
+ BarrierBuilder barrier(loop.QuitClosure());
+
+ for (size_t i = 0; i < kTotalLocks / 2; ++i) {
+ LockRange range = {IntegerKey(i), IntegerKey(i + 1)};
+ lock_manager.AcquireLock(
+ 0, range, ScopesLockManager::LockType::kExclusive,
+ base::BindOnce(&StoreLock, &locks[i], barrier.AddClosure()));
+ }
+
+ for (size_t i = kTotalLocks - 1; i >= kTotalLocks / 2; --i) {
+ LockRange range = {IntegerKey(i), IntegerKey(i + 1)};
+ lock_manager.AcquireLock(
+ 0, range, ScopesLockManager::LockType::kExclusive,
+ base::BindOnce(&StoreLock, &locks[i], 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 : locks) {
+ EXPECT_TRUE(lock.is_locked());
+ }
+
+ locks.clear();
+ EXPECT_EQ(0ll, lock_manager.LocksHeldForTesting());
+}
+
+TEST_F(DisjointRangeLockManagerTest, Shared) {
+ DisjointRangeLockManager lock_manager(1, leveldb::BytewiseComparator(),
+ base::SequencedTaskRunnerHandle::Get());
+ EXPECT_EQ(0ll, lock_manager.LocksHeldForTesting());
+ EXPECT_EQ(0ll, lock_manager.RequestsWaitingForTesting());
+
+ LockRange range = {IntegerKey(0), IntegerKey(1)};
+
+ ScopeLock lock1;
+ ScopeLock lock2;
+ base::RunLoop loop;
+ {
+ BarrierBuilder barrier(loop.QuitClosure());
+ lock_manager.AcquireLock(
+ 0, range, ScopesLockManager::LockType::kShared,
+ base::BindOnce(&StoreLock, &lock1, barrier.AddClosure()));
+ lock_manager.AcquireLock(
+ 0, range, ScopesLockManager::LockType::kShared,
+ base::BindOnce(&StoreLock, &lock2, barrier.AddClosure()));
+ }
+ loop.Run();
+ EXPECT_EQ(2ll, lock_manager.LocksHeldForTesting());
+
+ EXPECT_TRUE(lock1.is_locked());
+ EXPECT_TRUE(lock2.is_locked());
+}
+
+TEST_F(DisjointRangeLockManagerTest, SharedAndExclusiveQueuing) {
+ DisjointRangeLockManager lock_manager(1, leveldb::BytewiseComparator(),
+ base::SequencedTaskRunnerHandle::Get());
+ EXPECT_EQ(0ll, lock_manager.LocksHeldForTesting());
+ EXPECT_EQ(0ll, lock_manager.RequestsWaitingForTesting());
+
+ LockRange range = {IntegerKey(0), IntegerKey(1)};
+
+ ScopeLock shared_lock1;
+ ScopeLock shared_lock2;
+ ScopeLock exclusive_lock3;
+ ScopeLock shared_lock4;
+
+ {
+ base::RunLoop loop;
+ base::RepeatingClosure barrier =
+ base::BarrierClosure(2, loop.QuitClosure());
+ lock_manager.AcquireLock(
+ 0, range, ScopesLockManager::LockType::kShared,
+ base::BindOnce(&StoreLock, &shared_lock1, barrier));
+ lock_manager.AcquireLock(
+ 0, range, ScopesLockManager::LockType::kShared,
+ base::BindOnce(&StoreLock, &shared_lock2, barrier));
+ loop.Run();
+ }
+
+ // Both of the following locks should be queued - the exclusive is next in
+ // line, then the shared lock will come after it.
+ lock_manager.AcquireLock(
+ 0, range, ScopesLockManager::LockType::kExclusive,
+ base::BindOnce(&StoreLock, &exclusive_lock3, base::DoNothing::Once()));
+ lock_manager.AcquireLock(
+ 0, range, ScopesLockManager::LockType::kShared,
+ base::BindOnce(&StoreLock, &shared_lock4, base::DoNothing::Once()));
+ // Flush the task queue.
+ {
+ base::RunLoop loop;
+ base::SequencedTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ loop.QuitClosure());
+ loop.Run();
+ }
+ EXPECT_FALSE(exclusive_lock3.is_locked());
+ EXPECT_FALSE(shared_lock4.is_locked());
+ EXPECT_EQ(2ll, lock_manager.LocksHeldForTesting());
+ EXPECT_EQ(2ll, lock_manager.RequestsWaitingForTesting());
+
+ // Release the shared locks.
+ shared_lock1.Release();
+ shared_lock2.Release();
+ EXPECT_FALSE(shared_lock1.is_locked());
+ EXPECT_FALSE(shared_lock2.is_locked());
+
+ // Flush the task queue to propagate the lock releases and grant the exclusive
+ // lock.
+ {
+ base::RunLoop loop;
+ base::SequencedTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ loop.QuitClosure());
+ loop.Run();
+ }
+ EXPECT_TRUE(exclusive_lock3.is_locked());
+ EXPECT_FALSE(shared_lock4.is_locked());
+ EXPECT_EQ(1ll, lock_manager.LocksHeldForTesting());
+ EXPECT_EQ(1ll, lock_manager.RequestsWaitingForTesting());
+
+ exclusive_lock3.Release();
+ EXPECT_FALSE(exclusive_lock3.is_locked());
+
+ // Flush the task queue to propagate the lock releases and grant the exclusive
+ // lock.
+ {
+ base::RunLoop loop;
+ base::SequencedTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ loop.QuitClosure());
+ loop.Run();
+ }
+ EXPECT_TRUE(shared_lock4.is_locked());
+ EXPECT_EQ(1ll, lock_manager.LocksHeldForTesting());
+ EXPECT_EQ(0ll, lock_manager.RequestsWaitingForTesting());
+}
+
+TEST_F(DisjointRangeLockManagerTest, LevelsOperateSeparately) {
+ DisjointRangeLockManager lock_manager(2, leveldb::BytewiseComparator(),
+ base::SequencedTaskRunnerHandle::Get());
+ base::RunLoop loop;
+ ScopeLock l0_lock;
+ ScopeLock l1_lock;
+ {
+ BarrierBuilder barrier(loop.QuitClosure());
+ LockRange range = {IntegerKey(0), IntegerKey(1)};
+ lock_manager.AcquireLock(
+ 0, range, ScopesLockManager::LockType::kExclusive,
+ base::BindOnce(&StoreLock, &l0_lock, barrier.AddClosure()));
+ lock_manager.AcquireLock(
+ 1, range, ScopesLockManager::LockType::kExclusive,
+ base::BindOnce(&StoreLock, &l1_lock, barrier.AddClosure()));
+ }
+ loop.Run();
+ EXPECT_TRUE(l0_lock.is_locked());
+ EXPECT_TRUE(l1_lock.is_locked());
+ EXPECT_EQ(2ll, lock_manager.LocksHeldForTesting());
+ EXPECT_EQ(0ll, lock_manager.RequestsWaitingForTesting());
+ l0_lock.Release();
+ l1_lock.Release();
+ EXPECT_EQ(0ll, lock_manager.LocksHeldForTesting());
+}
+
+} // 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
new file mode 100644
index 00000000000..1b687396daf
--- /dev/null
+++ b/chromium/content/browser/indexed_db/scopes/scopes_lock_manager.cc
@@ -0,0 +1,61 @@
+// 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/scopes_lock_manager.h"
+
+#include <ostream>
+
+namespace content {
+
+ScopesLockManager::LockRange::LockRange(std::string begin, std::string end)
+ : begin(std::move(begin)), end(std::move(end)) {}
+
+ScopesLockManager::ScopeLock::ScopeLock() = default;
+ScopesLockManager::ScopeLock::ScopeLock(ScopeLock&& other) noexcept {
+ DCHECK(!this->is_locked_) << "Cannot move a lock onto an active lock.";
+ this->is_locked_ = other.is_locked_;
+ this->range_ = std::move(other.range_);
+ this->level_ = other.level_;
+ this->closure_runner_ = std::move(other.closure_runner_);
+ other.is_locked_ = false;
+}
+ScopesLockManager::ScopeLock::ScopeLock(LockRange range,
+ int level,
+ base::OnceClosure closure)
+ : is_locked_(!closure.is_null()),
+ range_(std::move(range)),
+ level_(level),
+ closure_runner_(std::move(closure)) {}
+
+ScopesLockManager::ScopeLock& ScopesLockManager::ScopeLock::operator=(
+ ScopesLockManager::ScopeLock&& other) noexcept {
+ DCHECK(!this->is_locked_);
+ this->is_locked_ = other.is_locked_;
+ this->range_ = std::move(other.range_);
+ this->level_ = other.level_;
+ this->closure_runner_ = std::move(other.closure_runner_);
+ other.is_locked_ = false;
+ return *this;
+};
+
+void ScopesLockManager::ScopeLock::Release() {
+ is_locked_ = false;
+ closure_runner_.RunAndReset();
+}
+
+std::ostream& operator<<(std::ostream& out,
+ const ScopesLockManager::LockRange& range) {
+ return out << "<ScopesLockManager::ScopeLock>{begin: " << range.begin
+ << ", end: " << range.end << "}";
+}
+
+bool operator==(const ScopesLockManager::LockRange& x,
+ const ScopesLockManager::LockRange& y) {
+ return x.begin == y.begin && x.end == y.end;
+}
+bool operator!=(const ScopesLockManager::LockRange& x,
+ const ScopesLockManager::LockRange& y) {
+ return !(x == y);
+}
+} // namespace content
diff --git a/chromium/content/browser/indexed_db/scopes/scopes_lock_manager.h b/chromium/content/browser/indexed_db/scopes/scopes_lock_manager.h
new file mode 100644
index 00000000000..075da81bd22
--- /dev/null
+++ b/chromium/content/browser/indexed_db/scopes/scopes_lock_manager.h
@@ -0,0 +1,103 @@
+// 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_SCOPES_LOCK_MANAGER_H_
+#define CONTENT_BROWSER_INDEXED_DB_SCOPES_SCOPES_LOCK_MANAGER_H_
+
+#include <iosfwd>
+#include <string>
+
+#include "base/callback.h"
+#include "base/callback_helpers.h"
+#include "base/logging.h"
+#include "base/macros.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+// Generic two-level lock management system based on ranges. Granted locks are
+// represented by the |ScopeLock| class.
+class CONTENT_EXPORT ScopesLockManager {
+ public:
+ // Shared locks can share access to a lock range, while exclusive locks
+ // require that they are the only lock for their range.
+ enum class LockType { kShared, kExclusive };
+
+ // The range is [begin, end).
+ struct CONTENT_EXPORT LockRange {
+ LockRange(std::string begin, std::string end);
+ LockRange() = default;
+ ~LockRange() = default;
+ std::string begin;
+ std::string end;
+ };
+
+ // Represents a granted lock in the ScopesLockManager. When this object is
+ // destroyed, the lock is released. Since default construction is supported,
+ // |is_locked()| can be used to inquire locked status. Also, |Release()| can
+ // be called to manually release the lock, which appropriately updates the
+ // |is_locked()| result.
+ class CONTENT_EXPORT ScopeLock {
+ public:
+ ScopeLock();
+ ScopeLock(ScopeLock&&) noexcept;
+ // The |closure| is called when the lock is released, either by destruction
+ // of this object or by the |Released()| call. It will be called
+ // synchronously on the sequence runner this lock is released on.
+ ScopeLock(LockRange range, int level, base::OnceClosure closure);
+ ~ScopeLock() = default;
+ // This does NOT release the lock if one is being held.
+ ScopeLock& operator=(ScopeLock&&) noexcept;
+
+ // Returns true if this object is holding a lock.
+ bool is_locked() const { return is_locked_; }
+
+ // Releases this lock.
+ void Release();
+
+ int level() const { return level_; }
+ const LockRange& range() const { return range_; }
+
+ private:
+ bool is_locked_ = false;
+ LockRange range_;
+ int level_ = 0;
+ base::ScopedClosureRunner closure_runner_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopeLock);
+ };
+
+ using LockAquiredCallback = base::OnceCallback<void(ScopeLock)>;
+
+ ScopesLockManager() = default;
+
+ virtual ~ScopesLockManager() = default;
+
+ virtual int64_t LocksHeldForTesting() const = 0;
+ virtual int64_t RequestsWaitingForTesting() const = 0;
+
+ // Acquires a lock for a given lock level. Lock levels are treated as
+ // completely independent domains. The lock levels start at zero.
+ virtual void AcquireLock(int level,
+ const LockRange& range,
+ LockType type,
+ LockAquiredCallback callback) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ScopesLockManager);
+};
+
+// Stream operator so lock range can be used in log statements.
+CONTENT_EXPORT std::ostream& operator<<(
+ std::ostream& out,
+ const ScopesLockManager::LockRange& range);
+
+CONTENT_EXPORT bool operator==(const ScopesLockManager::LockRange& x,
+ const ScopesLockManager::LockRange& y);
+CONTENT_EXPORT bool operator!=(const ScopesLockManager::LockRange& x,
+ const ScopesLockManager::LockRange& y);
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_INDEXED_DB_SCOPES_SCOPES_LOCK_MANAGER_H_
diff --git a/chromium/content/browser/indexed_db/scopes/scopes_lock_manager_unittest.cc b/chromium/content/browser/indexed_db/scopes/scopes_lock_manager_unittest.cc
new file mode 100644
index 00000000000..a4240c660f8
--- /dev/null
+++ b/chromium/content/browser/indexed_db/scopes/scopes_lock_manager_unittest.cc
@@ -0,0 +1,17 @@
+// 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/scopes_lock_manager.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+TEST(ScopesLockManager, TestRangePopulation) {
+ ScopesLockManager::LockRange range("a", "b");
+ EXPECT_EQ("a", range.begin);
+ EXPECT_EQ("b", range.end);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/isolated_origin_browsertest.cc b/chromium/content/browser/isolated_origin_browsertest.cc
index 365f03302cb..7c0f014d404 100644
--- a/chromium/content/browser/isolated_origin_browsertest.cc
+++ b/chromium/content/browser/isolated_origin_browsertest.cc
@@ -568,10 +568,12 @@ IN_PROC_BROWSER_TEST_F(IsolatedOriginTest, ProcessLimit) {
// Sanity-check IsSuitableHost values for the current processes.
BrowserContext* browser_context = web_contents()->GetBrowserContext();
auto is_suitable_host = [browser_context](RenderProcessHost* process,
- GURL url) {
- return RenderProcessHostImpl::IsSuitableHost(
- process, browser_context,
- SiteInstance::GetSiteForURL(browser_context, url));
+ const GURL& url) {
+ GURL site_url(SiteInstance::GetSiteForURL(browser_context, url));
+ GURL lock_url(
+ SiteInstanceImpl::DetermineProcessLockURL(browser_context, url));
+ return RenderProcessHostImpl::IsSuitableHost(process, browser_context,
+ site_url, lock_url);
};
EXPECT_TRUE(is_suitable_host(foo_process, foo_url));
EXPECT_FALSE(is_suitable_host(foo_process, isolated_foo_url));
@@ -1102,10 +1104,14 @@ class IsolatedOriginFieldTrialTest : public ContentBrowserTest {
};
IN_PROC_BROWSER_TEST_F(IsolatedOriginFieldTrialTest, Test) {
+ bool expected_to_isolate = !base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableSiteIsolationTrials);
+
auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
- EXPECT_TRUE(policy->IsIsolatedOrigin(
- url::Origin::Create(GURL("https://field.trial.com/"))));
- EXPECT_TRUE(
+ EXPECT_EQ(expected_to_isolate, policy->IsIsolatedOrigin(url::Origin::Create(
+ GURL("https://field.trial.com/"))));
+ EXPECT_EQ(
+ expected_to_isolate,
policy->IsIsolatedOrigin(url::Origin::Create(GURL("https://bar.com/"))));
}
diff --git a/chromium/content/browser/keyboard_lock/keyboard_lock_service_impl.cc b/chromium/content/browser/keyboard_lock/keyboard_lock_service_impl.cc
index f783d5356c8..b0aa16010bb 100644
--- a/chromium/content/browser/keyboard_lock/keyboard_lock_service_impl.cc
+++ b/chromium/content/browser/keyboard_lock/keyboard_lock_service_impl.cc
@@ -38,20 +38,22 @@ void LogKeyboardLockMethodCalled(KeyboardLockMethods method) {
} // namespace
KeyboardLockServiceImpl::KeyboardLockServiceImpl(
- RenderFrameHost* render_frame_host)
- : render_frame_host_(static_cast<RenderFrameHostImpl*>(render_frame_host)) {
+ RenderFrameHost* render_frame_host,
+ blink::mojom::KeyboardLockServiceRequest request)
+ : FrameServiceBase(render_frame_host, std::move(request)),
+ render_frame_host_(static_cast<RenderFrameHostImpl*>(render_frame_host)) {
DCHECK(render_frame_host_);
}
-KeyboardLockServiceImpl::~KeyboardLockServiceImpl() = default;
-
// static
void KeyboardLockServiceImpl::CreateMojoService(
RenderFrameHost* render_frame_host,
blink::mojom::KeyboardLockServiceRequest request) {
- mojo::MakeStrongBinding(
- std::make_unique<KeyboardLockServiceImpl>(render_frame_host),
- std::move(request));
+ DCHECK(render_frame_host);
+
+ // The object is bound to the lifetime of |render_frame_host| and the mojo
+ // connection. See FrameServiceBase for details.
+ new KeyboardLockServiceImpl(render_frame_host, std::move(request));
}
void KeyboardLockServiceImpl::RequestKeyboardLock(
@@ -131,4 +133,6 @@ void KeyboardLockServiceImpl::GetKeyboardLayoutMap(
std::move(callback).Run(std::move(response));
}
+KeyboardLockServiceImpl::~KeyboardLockServiceImpl() = default;
+
} // namespace content
diff --git a/chromium/content/browser/keyboard_lock/keyboard_lock_service_impl.h b/chromium/content/browser/keyboard_lock/keyboard_lock_service_impl.h
index 19c2f994758..eecefd26e44 100644
--- a/chromium/content/browser/keyboard_lock/keyboard_lock_service_impl.h
+++ b/chromium/content/browser/keyboard_lock/keyboard_lock_service_impl.h
@@ -9,6 +9,7 @@
#include <vector>
#include "content/common/content_export.h"
+#include "content/public/browser/frame_service_base.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "third_party/blink/public/platform/modules/keyboard_lock/keyboard_lock.mojom.h"
@@ -17,11 +18,11 @@ namespace content {
class RenderFrameHost;
class RenderFrameHostImpl;
-class CONTENT_EXPORT KeyboardLockServiceImpl
- : public blink::mojom::KeyboardLockService {
+class CONTENT_EXPORT KeyboardLockServiceImpl final
+ : public FrameServiceBase<blink::mojom::KeyboardLockService> {
public:
- explicit KeyboardLockServiceImpl(RenderFrameHost* render_frame_host);
- ~KeyboardLockServiceImpl() override;
+ KeyboardLockServiceImpl(RenderFrameHost* render_frame_host,
+ blink::mojom::KeyboardLockServiceRequest request);
static void CreateMojoService(
RenderFrameHost* render_frame_host,
@@ -34,6 +35,9 @@ class CONTENT_EXPORT KeyboardLockServiceImpl
void GetKeyboardLayoutMap(GetKeyboardLayoutMapCallback callback) override;
private:
+ // |this| can only be destroyed by FrameServiceBase.
+ ~KeyboardLockServiceImpl() override;
+
RenderFrameHostImpl* const render_frame_host_;
};
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 321ab2c8e87..fa11009de25 100644
--- a/chromium/content/browser/loader/cross_site_document_blocking_browsertest.cc
+++ b/chromium/content/browser/loader/cross_site_document_blocking_browsertest.cc
@@ -89,7 +89,7 @@ void InspectHistograms(const base::HistogramTester& histograms,
const std::string& resource_name,
ResourceType resource_type) {
// //services/network doesn't have access to content::ResourceType and
- // therefore cannot log some XSDB UMAs.
+ // therefore cannot log some CORB UMAs.
bool is_restricted_uma_expected = false;
if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
is_restricted_uma_expected = true;
@@ -613,38 +613,21 @@ IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTest, BlockHeaders) {
ASSERT_EQ(net::OK, interceptor.completion_status().error_code);
ASSERT_TRUE(interceptor.completion_status().should_report_corb_blocking);
- // Verify that safelisted headers have not been removed by XSDB.
- // See https://fetch.spec.whatwg.org/#cors-safelisted-response-header-name.
+ // Verify that most response headers have been removed by CORB.
const std::string& headers =
interceptor.response_head().headers->raw_headers();
- EXPECT_THAT(headers,
- HasSubstr("Cache-Control: no-cache, no-store, must-revalidate"));
- EXPECT_THAT(headers, HasSubstr("Content-Language: TestLanguage"));
- EXPECT_THAT(headers,
- HasSubstr("Content-Type: application/json; charset=utf-8"));
- EXPECT_THAT(headers, HasSubstr("Expires: Wed, 21 Oct 2199 07:28:00 GMT"));
- EXPECT_THAT(headers,
- HasSubstr("Last-Modified: Wed, 07 Feb 2018 13:55:00 PST"));
- EXPECT_THAT(headers, HasSubstr("Pragma: TestPragma"));
-
- // Make sure the test covers all the safelisted headers known to the product
- // code.
- for (const std::string& safelisted_header :
- network::CrossOriginReadBlocking::GetCorsSafelistedHeadersForTesting()) {
- EXPECT_TRUE(
- interceptor.response_head().headers->HasHeader(safelisted_header));
-
- std::string value;
- interceptor.response_head().headers->EnumerateHeader(
- nullptr, safelisted_header, &value);
- EXPECT_FALSE(value.empty());
- }
-
- // Verify that other response headers have been removed by XSDB.
+ EXPECT_THAT(headers, HasSubstr("Access-Control-Allow-Origin: https://other"));
+ EXPECT_THAT(headers, Not(HasSubstr("Cache-Control")));
+ EXPECT_THAT(headers, Not(HasSubstr("Content-Language")));
EXPECT_THAT(headers, Not(HasSubstr("Content-Length")));
- EXPECT_THAT(headers, Not(HasSubstr("X-My-Secret-Header")));
+ EXPECT_THAT(headers, Not(HasSubstr("Content-Type")));
+ EXPECT_THAT(headers, Not(HasSubstr("Expires")));
+ EXPECT_THAT(headers, Not(HasSubstr("Last-Modified")));
EXPECT_THAT(headers, Not(HasSubstr("MySecretCookieKey")));
EXPECT_THAT(headers, Not(HasSubstr("MySecretCookieValue")));
+ EXPECT_THAT(headers, Not(HasSubstr("Pragma")));
+ EXPECT_THAT(headers, Not(HasSubstr("X-Content-Type-Options")));
+ EXPECT_THAT(headers, Not(HasSubstr("X-My-Secret-Header")));
// Verify that the body is empty.
EXPECT_EQ("", interceptor.response_body());
@@ -899,7 +882,7 @@ IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingServiceWorkerTest, NoNetwork) {
}); )";
EXPECT_TRUE(ExecuteScriptAndExtractString(shell(), script, &response));
- // Verify that XSDB didn't block the response (since it was "faked" within the
+ // Verify that CORB didn't block the response (since it was "faked" within the
// service worker and didn't cross any security boundaries).
EXPECT_EQ("Response created by service worker", response);
InspectHistograms(histograms, kShouldBeAllowedWithoutSniffing, "blah.html",
@@ -938,13 +921,13 @@ IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingServiceWorkerTest,
std::string response;
EXPECT_TRUE(ExecuteScriptAndExtractString(shell(), script, &response));
- // Verify that XSDB blocked the response from the network (from
+ // Verify that CORB blocked the response from the network (from
// |cross_origin_https_server_|) to the service worker.
InspectHistograms(histograms, kShouldBeBlockedWithoutSniffing, "network.txt",
RESOURCE_TYPE_XHR);
// Verify that the service worker replied with an expected error.
- // Replying with an error means that XSDB is only active once (for the
+ // Replying with an error means that CORB is only active once (for the
// initial, real network request) and therefore the test doesn't get
// confused (second successful response would have added noise to the
// histograms captured by the test).
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 90792270128..585868689f6 100644
--- a/chromium/content/browser/loader/cross_site_document_resource_handler.cc
+++ b/chromium/content/browser/loader/cross_site_document_resource_handler.cc
@@ -221,6 +221,16 @@ void CrossSiteDocumentResourceHandler::OnResponseStarted(
std::unique_ptr<ResourceController> controller) {
has_response_started_ = true;
+ if (request()->initiator().has_value()) {
+ const char* initiator_scheme_exception =
+ GetContentClient()
+ ->browser()
+ ->GetInitiatorSchemeBypassingDocumentBlocking();
+ is_initiator_scheme_excluded_ =
+ initiator_scheme_exception &&
+ request()->initiator().value().scheme() == initiator_scheme_exception;
+ }
+
network::CrossOriginReadBlocking::LogAction(
network::CrossOriginReadBlocking::Action::kResponseStarted);
@@ -358,6 +368,12 @@ void CrossSiteDocumentResourceHandler::OnReadCompleted(
return;
}
+ // If |next_handler_->OnReadCompleted(...)| was not called above, then the
+ // response bytes are being accumulated in the local buffer we've allocated in
+ // ResumeOnWillRead.
+ const size_t new_data_offset = local_buffer_bytes_read_;
+ local_buffer_bytes_read_ += bytes_read;
+
// If we intended to block the response and haven't sniffed yet, try to
// confirm that we should block it. If sniffing is needed, look at the local
// buffer and either report that zero bytes were read (to indicate the
@@ -377,8 +393,6 @@ void CrossSiteDocumentResourceHandler::OnReadCompleted(
// JSONP, or another allowable data type and we should let it through.
// Record how many bytes were read to see how often it's too small. (This
// will typically be under 100,000.)
- const size_t new_data_offset = local_buffer_bytes_read_;
- local_buffer_bytes_read_ += bytes_read;
DCHECK_LE(local_buffer_bytes_read_, next_handler_buffer_size_);
const bool more_data_possible =
bytes_read != 0 && local_buffer_bytes_read_ < net::kMaxBytesToSniff &&
@@ -406,6 +420,16 @@ void CrossSiteDocumentResourceHandler::OnReadCompleted(
}
}
+ // At this point the block-vs-allow decision was made, but might be still
+ // suppressed because of |is_initiator_scheme_excluded_|. We perform the
+ // suppression at such a late point, because we want to ensure we only call
+ // LogInitiatorSchemeBypassingDocumentBlocking for cases that actuall matter
+ // in practice.
+ if (confirmed_blockable && is_initiator_scheme_excluded_) {
+ initiator_scheme_prevented_blocking_ = true;
+ confirmed_blockable = false;
+ }
+
// At this point we have already made a block-vs-allow decision and we know
// that we can wake the |next_handler_| and let it catch-up with our
// processing of the response. The first step will always be calling
@@ -532,10 +556,22 @@ void CrossSiteDocumentResourceHandler::OnResponseCompleted(
next_handler_->OnResponseCompleted(net::URLRequestStatus(),
std::move(controller));
} else {
- // Only report XSDB status for successful (i.e. non-aborted,
+ // Only report CORB status for successful (i.e. non-aborted,
// non-errored-out) requests.
- if (status.is_success())
+ if (status.is_success()) {
analyzer_->LogAllowedResponse();
+ if (initiator_scheme_prevented_blocking_ &&
+ analyzer_->ShouldReportBlockedResponse() && GetRequestInfo()) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&ContentBrowserClient::
+ LogInitiatorSchemeBypassingDocumentBlocking,
+ base::Unretained(GetContentClient()->browser()),
+ request()->initiator().value(),
+ GetRequestInfo()->GetChildID(),
+ GetRequestInfo()->GetResourceType()));
+ }
+ }
next_handler_->OnResponseCompleted(status, std::move(controller));
}
@@ -543,16 +579,12 @@ void CrossSiteDocumentResourceHandler::OnResponseCompleted(
bool CrossSiteDocumentResourceHandler::ShouldBlockBasedOnHeaders(
const network::ResourceResponse& response) {
- // Give embedder a chance to skip document blocking for this response.
- const char* initiator_scheme_exception =
- GetContentClient()
- ->browser()
- ->GetInitatorSchemeBypassingDocumentBlocking();
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
// Delegate most decisions to CrossOriginReadBlocking::ResponseAnalyzer.
analyzer_ =
std::make_unique<network::CrossOriginReadBlocking::ResponseAnalyzer>(
- *request(), response, initiator_scheme_exception);
+ *request(), response);
if (analyzer_->ShouldAllow())
return false;
@@ -582,14 +614,22 @@ bool CrossSiteDocumentResourceHandler::ShouldBlockBasedOnHeaders(
if (!info || info->GetChildID() == -1)
return false;
- // Don't block plugin requests.
- // TODO(lukasza): Only disable CORB for plugins with universal access (see
- // PepperURLLoaderHost::has_universal_access_), because only such plugins may
- // have their own CORS-like mechanisms - e.g. crossdomain.xml in Flash). We
- // should still enforce CORB for other kinds of plugins (i.e. ones without
- // universal access).
+ // Don't block some plugin requests.
+ //
+ // Note that in practice this exception only only matters to Flash and test
+ // plugins (both can issue requests without CORS and both will be covered by
+ // CORB::ShouldAllowForPlugin below).
+ //
+ // This exception is not needed for:
+ // - PNaCl (which always issues CORS requests)
+ // - PDF (which is already covered by the exception for chrome-extension://...
+ // initiators and therefore doesn't need another exception here;
+ // additionally PDF doesn't _really_ make *cross*-origin requests - it just
+ // seems that way because of the usage of the Chrome extension).
if (info->GetResourceType() == RESOURCE_TYPE_PLUGIN_RESOURCE &&
- is_nocors_plugin_request_) {
+ is_nocors_plugin_request_ &&
+ network::CrossOriginReadBlocking::ShouldAllowForPlugin(
+ info->GetChildID())) {
return false;
}
diff --git a/chromium/content/browser/loader/cross_site_document_resource_handler.h b/chromium/content/browser/loader/cross_site_document_resource_handler.h
index 1598fb024bd..5f11dc707ce 100644
--- a/chromium/content/browser/loader/cross_site_document_resource_handler.h
+++ b/chromium/content/browser/loader/cross_site_document_resource_handler.h
@@ -164,6 +164,14 @@ class CONTENT_EXPORT CrossSiteDocumentResourceHandler
// completed, and thus it is safe to cancel or detach on the next read.
bool blocked_read_completed_ = false;
+ // Whether the request should be allowed because of
+ // ContentBrowserClient::GetInitatorSchemeBypassingDocumentBlocking
+ bool is_initiator_scheme_excluded_ = false;
+
+ // Whether |is_initiator_scheme_excluded_| actually prevented blocking from
+ // happening.
+ bool initiator_scheme_prevented_blocking_ = false;
+
base::WeakPtrFactory<CrossSiteDocumentResourceHandler> weak_this_;
DISALLOW_COPY_AND_ASSIGN(CrossSiteDocumentResourceHandler);
diff --git a/chromium/content/browser/loader/cross_site_document_resource_handler_unittest.cc b/chromium/content/browser/loader/cross_site_document_resource_handler_unittest.cc
index 99405d1b48e..e09e9a1b602 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
@@ -345,7 +345,13 @@ const TestScenario kScenarios[] = {
kVerdictPacketForHeadersBasedVerdict, // verdict_packet
},
{
- "Allowed: Cross-site fetch HTML from Flash without CORS",
+ // Blocked, because the unit test doesn't make a call to
+ // CrossOriginReadBlocking::AddExceptionForFlash (simulating a behavior
+ // of a compromised renderer that only pretends to be hosting Flash).
+ //
+ // The regular scenario is covered by integration tests:
+ // OutOfProcessPPAPITest.URLLoaderTrusted.
+ "Blocked: Cross-site fetch HTML from Flash without CORS",
__LINE__,
"http://www.b.com/plugin.html", // target_url
RESOURCE_TYPE_PLUGIN_RESOURCE, // resource_type
@@ -357,7 +363,7 @@ const TestScenario kScenarios[] = {
false, // simulate_range_response
AccessControlAllowOriginHeader::kOmit, // cors_response
{"<html><head>this should sniff as HTML"}, // packets
- Verdict::kAllow, // verdict
+ Verdict::kBlock, // verdict
kVerdictPacketForHeadersBasedVerdict, // verdict_packet
},
{
diff --git a/chromium/content/browser/loader/loader_browsertest.cc b/chromium/content/browser/loader/loader_browsertest.cc
index 024fadee921..927f2af62d3 100644
--- a/chromium/content/browser/loader/loader_browsertest.cc
+++ b/chromium/content/browser/loader/loader_browsertest.cc
@@ -25,6 +25,7 @@
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/resource_dispatcher_host_delegate.h"
#include "content/public/browser/resource_request_info.h"
+#include "content/public/browser/site_isolation_policy.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/previews_state.h"
@@ -627,6 +628,100 @@ IN_PROC_BROWSER_TEST_F(LoaderBrowserTest, PageTransitionClientRedirect) {
EXPECT_TRUE(delegate.page_transition() & ui::PAGE_TRANSITION_CLIENT_REDIRECT);
}
+IN_PROC_BROWSER_TEST_F(LoaderBrowserTest, SubresourceRedirectToDataURLBlocked) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ EXPECT_TRUE(NavigateToURL(shell(), embedded_test_server()->GetURL("/echo")));
+
+ GURL subresource_url = embedded_test_server()->GetURL(
+ "/server-redirect?data:text/plain,redirected1");
+ std::string script = R"((url => {
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', url, true);
+ xhr.onload = () => domAutomationController.send("ALLOWED");
+ xhr.onerror = () => domAutomationController.send("BLOCKED");
+ xhr.send();
+ }))";
+ std::string result;
+ ASSERT_TRUE(ExecuteScriptAndExtractString(
+ shell(), script + "('" + subresource_url.spec() + "')", &result));
+
+ EXPECT_EQ("BLOCKED", result);
+}
+
+IN_PROC_BROWSER_TEST_F(LoaderBrowserTest, RedirectToDataURLBlocked) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+ EXPECT_FALSE(NavigateToURL(
+ shell(), embedded_test_server()->GetURL(
+ "/server-redirect?data:text/plain,redirected1")));
+}
+
+IN_PROC_BROWSER_TEST_F(LoaderBrowserTest, RedirectToAboutURLBlocked) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+ EXPECT_FALSE(NavigateToURL(
+ shell(), embedded_test_server()->GetURL(
+ "/server-redirect?" + std::string(url::kAboutBlankURL))));
+}
+
+namespace {
+
+// Creates a valid filesystem URL.
+GURL CreateFileSystemURL(Shell* window) {
+ std::string filesystem_url_string;
+ EXPECT_TRUE(
+ ExecuteScriptAndExtractString(window, R"(
+ var blob = new Blob(['<html><body>hello</body></html>'],
+ {type: 'text/html'});
+ window.webkitRequestFileSystem(TEMPORARY, blob.size, fs => {
+ fs.root.getFile('foo.html', {create: true}, file => {
+ file.createWriter(writer => {
+ writer.write(blob);
+ writer.onwriteend = () => {
+ domAutomationController.send(file.toURL());
+ }
+ });
+ });
+ });)", &filesystem_url_string));
+ GURL filesystem_url(filesystem_url_string);
+ EXPECT_TRUE(filesystem_url.is_valid());
+ EXPECT_TRUE(filesystem_url.SchemeIsFileSystem());
+ return filesystem_url;
+}
+
+} // namespace
+
+IN_PROC_BROWSER_TEST_F(LoaderBrowserTest,
+ SubresourceRedirectToFileSystemURLBlocked) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ EXPECT_TRUE(NavigateToURL(shell(), embedded_test_server()->GetURL("/echo")));
+
+ GURL subresource_url = embedded_test_server()->GetURL(
+ "/server-redirect?" + CreateFileSystemURL(shell()).spec());
+ std::string script = R"((url => {
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', url, true);
+ xhr.onload = () => domAutomationController.send("ALLOWED");
+ xhr.onerror = () => domAutomationController.send("BLOCKED");
+ xhr.send();
+ }))";
+ std::string result;
+ ASSERT_TRUE(ExecuteScriptAndExtractString(
+ shell(), script + "('" + subresource_url.spec() + "')", &result));
+
+ EXPECT_EQ("BLOCKED", result);
+}
+
+IN_PROC_BROWSER_TEST_F(LoaderBrowserTest, RedirectToFileSystemURLBlocked) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+ // Need to navigate to a URL first so the filesystem can be created.
+ EXPECT_TRUE(NavigateToURL(shell(), embedded_test_server()->GetURL("/echo")));
+
+ EXPECT_FALSE(NavigateToURL(
+ shell(), embedded_test_server()->GetURL(
+ "/server-redirect?" + CreateFileSystemURL(shell()).spec())));
+}
+
namespace {
// Checks whether the given urls are requested, and that GetPreviewsState()
@@ -1172,6 +1267,11 @@ IN_PROC_BROWSER_TEST_F(RequestDataBrowserTest, CrossOriginNested) {
// bypass cookies SameSite=Strict protections by navigating a new window twice.
IN_PROC_BROWSER_TEST_F(LoaderBrowserTest,
CookieSameSiteStrictOpenNewNamedWindowTwice) {
+ // TODO(lukasza): https://crbug.com/417518: Get tests working with
+ // --site-per-process.
+ if (SiteIsolationPolicy::UseDedicatedProcessesForAllSites())
+ return;
+
ASSERT_TRUE(embedded_test_server()->Start());
// 1) Add cookies for 'a.com', one of them with the "SameSite=Strict" option.
diff --git a/chromium/content/browser/loader/loader_io_thread_notifier.cc b/chromium/content/browser/loader/loader_io_thread_notifier.cc
index 47efe2831fe..215e2f95fac 100644
--- a/chromium/content/browser/loader/loader_io_thread_notifier.cc
+++ b/chromium/content/browser/loader/loader_io_thread_notifier.cc
@@ -5,9 +5,9 @@
#include "content/browser/loader/loader_io_thread_notifier.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
-#include "content/browser/loader/global_routing_id.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/global_routing_id.h"
namespace content {
diff --git a/chromium/content/browser/loader/merkle_integrity_source_stream.cc b/chromium/content/browser/loader/merkle_integrity_source_stream.cc
index 94c532f18e2..77497667434 100644
--- a/chromium/content/browser/loader/merkle_integrity_source_stream.cc
+++ b/chromium/content/browser/loader/merkle_integrity_source_stream.cc
@@ -6,7 +6,7 @@
#include <string.h>
-#include "base/base64url.h"
+#include "base/base64.h"
#include "base/big_endian.h"
#include "base/numerics/safe_conversions.h"
#include "net/base/io_buffer.h"
@@ -19,7 +19,7 @@ namespace {
// maximum record size in TLS and the default maximum frame size in HTTP/2.
constexpr uint64_t kMaxRecordSize = 16 * 1024;
-constexpr char kMiSha256Header[] = "mi-sha256-draft2=";
+constexpr char kMiSha256Header[] = "mi-sha256-03=";
constexpr size_t kMiSha256HeaderLength = sizeof(kMiSha256Header) - 1;
// Copies as many bytes from |input| as will fit in |output| and advances both.
@@ -34,16 +34,14 @@ size_t CopyClamped(base::span<const char>* input, base::span<char>* output) {
} // namespace
MerkleIntegritySourceStream::MerkleIntegritySourceStream(
- base::StringPiece mi_header_value,
+ base::StringPiece digest_header_value,
std::unique_ptr<SourceStream> upstream)
// TODO(ksakamoto): Use appropriate SourceType.
: net::FilterSourceStream(SourceStream::TYPE_NONE, std::move(upstream)) {
- // TODO(ksakamoto): Support quoted parameter value.
std::string next_proof;
- if (!mi_header_value.starts_with(kMiSha256Header) ||
- !base::Base64UrlDecode(mi_header_value.substr(kMiSha256HeaderLength),
- base::Base64UrlDecodePolicy::DISALLOW_PADDING,
- &next_proof) ||
+ if (!digest_header_value.starts_with(kMiSha256Header) ||
+ !base::Base64Decode(digest_header_value.substr(kMiSha256HeaderLength),
+ &next_proof) ||
next_proof.size() != SHA256_DIGEST_LENGTH) {
failed_ = true;
} else {
@@ -91,7 +89,17 @@ bool MerkleIntegritySourceStream::FilterDataImpl(base::span<char>* output,
if (record_size_ == 0) {
base::span<const char> bytes;
if (!ConsumeBytes(input, 8, &bytes, &storage)) {
- return !upstream_eof_reached;
+ if (!upstream_eof_reached) {
+ return true; // Wait for more data later.
+ }
+ if (partial_input_.empty()) {
+ // As a special case, the encoding of an empty payload is itself an
+ // empty message (i.e. it omits the initial record size), and its
+ // integrity proof is SHA-256("\0").
+ final_record_done_ = true;
+ return ProcessRecord({}, final_record_done_, output);
+ }
+ return false;
}
uint64_t record_size;
base::ReadBigEndian(bytes.data(), &record_size);
@@ -124,14 +132,8 @@ bool MerkleIntegritySourceStream::FilterDataImpl(base::span<char>* output,
}
// The final record is shorter and does not contain a hash. Process all
- // remaining input the final record.
- //
- // TODO(davidben): This matches the previous implementation in that it
- // allows empty final records, but this does not match the specification
- // and means some inputs have two valid encodings. However, the
- // specification's version cannot represent the empty string. Update this
- // when https://github.com/martinthomson/http-mice/issues/3 is resolved.
- if (partial_input_.size() > record_size_) {
+ // remaining input as the final record.
+ if (partial_input_.empty() || partial_input_.size() > record_size_) {
return false;
}
record = partial_input_;
diff --git a/chromium/content/browser/loader/merkle_integrity_source_stream.h b/chromium/content/browser/loader/merkle_integrity_source_stream.h
index d2554372a48..7fe7e4f18b6 100644
--- a/chromium/content/browser/loader/merkle_integrity_source_stream.h
+++ b/chromium/content/browser/loader/merkle_integrity_source_stream.h
@@ -19,12 +19,12 @@ namespace content {
// MerkleIntegritySourceStream decodes and validates content encoded with the
// "mi-sha256" content encoding
-// (https://tools.ietf.org/html/draft-thomson-http-mice-02).
+// (https://tools.ietf.org/html/draft-thomson-http-mice-03).
// TODO(ksakamoto): This class should eventually live in src/net/filter/.
class CONTENT_EXPORT MerkleIntegritySourceStream
: public net::FilterSourceStream {
public:
- MerkleIntegritySourceStream(base::StringPiece mi_header_value,
+ MerkleIntegritySourceStream(base::StringPiece digest_header_value,
std::unique_ptr<SourceStream> upstream);
~MerkleIntegritySourceStream() override;
diff --git a/chromium/content/browser/loader/merkle_integrity_source_stream_unittest.cc b/chromium/content/browser/loader/merkle_integrity_source_stream_unittest.cc
index 61c61692ec5..8765b844ae8 100644
--- a/chromium/content/browser/loader/merkle_integrity_source_stream_unittest.cc
+++ b/chromium/content/browser/loader/merkle_integrity_source_stream_unittest.cc
@@ -3,7 +3,7 @@
// found in the LICENSE file.
#include "content/browser/loader/merkle_integrity_source_stream.h"
-#include "base/base64url.h"
+#include "base/base64.h"
#include "net/base/io_buffer.h"
#include "net/base/test_completion_callback.h"
#include "net/filter/mock_source_stream.h"
@@ -17,13 +17,13 @@ const int kBigBufferSize = 4096;
const int kSmallBufferSize = 1;
const char kMIEmptyBody[] =
- "mi-sha256-draft2=bjQLnP-zepicpUTmu3gKLHiQHT-zNzh2hRGjBhevoB0";
+ "mi-sha256-03=bjQLnP+zepicpUTmu3gKLHiQHT+zNzh2hRGjBhevoB0=";
const char kMISingleRecord[] =
- "mi-sha256-draft2=dcRDgR2GM35DluAV13PzgnG6-pvQwPywfFvAu1UeFrs";
+ "mi-sha256-03=dcRDgR2GM35DluAV13PzgnG6+pvQwPywfFvAu1UeFrs=";
const char kMIMultipleRecords[] =
- "mi-sha256-draft2=IVa9shfs0nyKEhHqtB3WVNANJ2Njm5KjQLjRtnbkYJ4";
+ "mi-sha256-03=IVa9shfs0nyKEhHqtB3WVNANJ2Njm5KjQLjRtnbkYJ4=";
const char kMIWholeNumberOfRecords[] =
- "mi-sha256-draft2=L2vdwBplKvIr0ZPkcuskWZfEVDgVdHa6aD363UpKuZs";
+ "mi-sha256-03=L2vdwBplKvIr0ZPkcuskWZfEVDgVdHa6aD363UpKuZs=";
enum class ReadResultType {
// Each call to AddReadResult is a separate read from the lower layer
@@ -112,8 +112,7 @@ class MerkleIntegritySourceStreamTest
std::string Base64Decode(const char* hash) {
std::string out;
- EXPECT_TRUE(base::Base64UrlDecode(
- hash, base::Base64UrlDecodePolicy::DISALLOW_PADDING, &out));
+ EXPECT_TRUE(base::Base64Decode(hash, &out));
EXPECT_EQ(32u, out.size());
return out;
}
@@ -160,6 +159,14 @@ TEST_P(MerkleIntegritySourceStreamTest, EmptyStream) {
source()->AddReadResult(nullptr, 0, net::OK, GetParam().mode);
std::string actual_output;
int result = ReadStream(&actual_output);
+ EXPECT_EQ(net::OK, result);
+}
+
+TEST_P(MerkleIntegritySourceStreamTest, EmptyStreamWrongHash) {
+ Init(kMISingleRecord);
+ source()->AddReadResult(nullptr, 0, net::OK, GetParam().mode);
+ std::string actual_output;
+ int result = ReadStream(&actual_output);
EXPECT_EQ(net::ERR_CONTENT_DECODING_FAILED, result);
}
@@ -180,7 +187,7 @@ TEST_P(MerkleIntegritySourceStreamTest, MalformedMIHeader) {
}
TEST_P(MerkleIntegritySourceStreamTest, WrongMIAttributeName) {
- Init("mi-sha256-draft1=bjQLnP-zepicpUTmu3gKLHiQHT-zNzh2hRGjBhevoB0");
+ Init("mi-sha256-01=bjQLnP+zepicpUTmu3gKLHiQHT+zNzh2hRGjBhevoB0=");
source()->AddReadResult(nullptr, 0, net::OK, GetParam().mode);
std::string actual_output;
int result = ReadStream(&actual_output);
@@ -188,7 +195,7 @@ TEST_P(MerkleIntegritySourceStreamTest, WrongMIAttributeName) {
}
TEST_P(MerkleIntegritySourceStreamTest, HashTooShort) {
- Init("mi-sha256-draft2=bjQLnP-zepicpUTmu3gKLHiQHT-zNzh2hRGjBhevoA");
+ Init("mi-sha256-03=bjQLnP+zepicpUTmu3gKLHiQHT+zNzh2hRGjBhevoA==");
source()->AddReadResult(nullptr, 0, net::OK, GetParam().mode);
std::string actual_output;
int result = ReadStream(&actual_output);
@@ -196,7 +203,7 @@ TEST_P(MerkleIntegritySourceStreamTest, HashTooShort) {
}
TEST_P(MerkleIntegritySourceStreamTest, HashTooLong) {
- Init("mi-sha256-draft2=bjQLnP-zepicpUTmu3gKLHiQHT-zNzh2hRGjBhevoB0A");
+ Init("mi-sha256-03=bjQLnP+zepicpUTmu3gKLHiQHT+zNzh2hRGjBhevoB0A");
source()->AddReadResult(nullptr, 0, net::OK, GetParam().mode);
std::string actual_output;
int result = ReadStream(&actual_output);
@@ -211,7 +218,7 @@ TEST_P(MerkleIntegritySourceStreamTest, RecordSizeOnly) {
source()->AddReadResult(nullptr, 0, net::OK, GetParam().mode);
std::string actual_output;
int result = ReadStream(&actual_output);
- EXPECT_EQ(net::OK, result);
+ EXPECT_EQ(net::ERR_CONTENT_DECODING_FAILED, result);
}
TEST_P(MerkleIntegritySourceStreamTest, TruncatedRecordSize) {
@@ -329,11 +336,11 @@ TEST_P(MerkleIntegritySourceStreamTest, MultipleRecords) {
sizeof(kRecordSize), net::OK, GetParam().mode);
source()->AddReadResult(kMessage.data(), 16, net::OK, GetParam().mode);
std::string hash1 =
- Base64Decode("OElbplJlPK-Rv6JNK6p5_515IaoPoZo-2elWL7OQ60A");
+ Base64Decode("OElbplJlPK+Rv6JNK6p5/515IaoPoZo+2elWL7OQ60A=");
source()->AddReadResult(hash1.data(), 32, net::OK, GetParam().mode);
source()->AddReadResult(kMessage.data() + 16, 16, net::OK, GetParam().mode);
std::string hash2 =
- Base64Decode("iPMpmgExHPrbEX3_RvwP4d16fWlK4l--p75PUu_KyN0");
+ Base64Decode("iPMpmgExHPrbEX3/RvwP4d16fWlK4l++p75PUu/KyN0=");
source()->AddReadResult(hash2.data(), 32, net::OK, GetParam().mode);
source()->AddReadResult(kMessage.data() + 32, kMessage.size() - 32, net::OK,
GetParam().mode);
@@ -353,9 +360,9 @@ TEST_P(MerkleIntegritySourceStreamTest, MultipleRecordsAllAtOnce) {
std::string body(reinterpret_cast<const char*>(kRecordSize),
sizeof(kRecordSize));
body += kMessage.substr(0, 16);
- body += Base64Decode("OElbplJlPK-Rv6JNK6p5_515IaoPoZo-2elWL7OQ60A");
+ body += Base64Decode("OElbplJlPK+Rv6JNK6p5/515IaoPoZo+2elWL7OQ60A=");
body += kMessage.substr(16, 16);
- body += Base64Decode("iPMpmgExHPrbEX3_RvwP4d16fWlK4l--p75PUu_KyN0");
+ body += Base64Decode("iPMpmgExHPrbEX3/RvwP4d16fWlK4l++p75PUu/KyN0=");
body += kMessage.substr(32);
source()->AddReadResult(body.data(), body.size(), net::OK, GetParam().mode);
@@ -375,11 +382,11 @@ TEST_P(MerkleIntegritySourceStreamTest, MultipleRecordsWrongLastRecordHash) {
sizeof(kRecordSize), net::OK, GetParam().mode);
source()->AddReadResult(kMessage.data(), 16, net::OK, GetParam().mode);
std::string hash1 =
- Base64Decode("OElbplJlPK-Rv6JNK6p5_515IaoPoZo-2elWL7OQ60A");
+ Base64Decode("OElbplJlPK+Rv6JNK6p5/515IaoPoZo+2elWL7OQ60A=");
source()->AddReadResult(hash1.data(), 32, net::OK, GetParam().mode);
source()->AddReadResult(kMessage.data() + 16, 16, net::OK, GetParam().mode);
std::string hash2 =
- Base64Decode("iPMpmgExHPrbEX3_RvwP4d16fWlK4l--p75PUu_KyN0");
+ Base64Decode("iPMpmgExHPrbEX3/RvwP4d16fWlK4l++p75PUu/KyN0=");
source()->AddReadResult(hash2.data(), 32, net::OK, GetParam().mode);
source()->AddReadResult(kMessage.data() + 32, kMessage.size() - 32, net::OK,
GetParam().mode);
@@ -400,7 +407,7 @@ TEST_P(MerkleIntegritySourceStreamTest, MultipleRecordsWrongFirstRecordHash) {
sizeof(kRecordSize), net::OK, GetParam().mode);
source()->AddReadResult(kMessage.data(), 16, net::OK, GetParam().mode);
std::string hash1 =
- Base64Decode("OElbplJlPK-Rv6JNK6p5_515IaoPoZo-2elWL7OQ60A");
+ Base64Decode("OElbplJlPK+Rv6JNK6p5/515IaoPoZo+2elWL7OQ60A=");
source()->AddReadResult(hash1.data(), 32, net::OK, GetParam().mode);
std::string actual_output;
@@ -418,11 +425,11 @@ TEST_P(MerkleIntegritySourceStreamTest, TrailingNetError) {
sizeof(kRecordSize), net::OK, GetParam().mode);
source()->AddReadResult(kMessage.data(), 16, net::OK, GetParam().mode);
std::string hash1 =
- Base64Decode("OElbplJlPK-Rv6JNK6p5_515IaoPoZo-2elWL7OQ60A");
+ Base64Decode("OElbplJlPK+Rv6JNK6p5/515IaoPoZo+2elWL7OQ60A=");
source()->AddReadResult(hash1.data(), 32, net::OK, GetParam().mode);
source()->AddReadResult(kMessage.data() + 16, 16, net::OK, GetParam().mode);
std::string hash2 =
- Base64Decode("iPMpmgExHPrbEX3_RvwP4d16fWlK4l--p75PUu_KyN0");
+ Base64Decode("iPMpmgExHPrbEX3/RvwP4d16fWlK4l++p75PUu/KyN0=");
source()->AddReadResult(hash2.data(), 32, net::OK, GetParam().mode);
source()->AddReadResult(kMessage.data() + 32, kMessage.size() - 32, net::OK,
GetParam().mode);
@@ -447,11 +454,11 @@ TEST_P(MerkleIntegritySourceStreamTest, Truncated) {
sizeof(kRecordSize), net::OK, GetParam().mode);
source()->AddReadResult(kMessage.data(), 16, net::OK, GetParam().mode);
std::string hash1 =
- Base64Decode("OElbplJlPK-Rv6JNK6p5_515IaoPoZo-2elWL7OQ60A");
+ Base64Decode("OElbplJlPK+Rv6JNK6p5/515IaoPoZo+2elWL7OQ60A=");
source()->AddReadResult(hash1.data(), 32, net::OK, GetParam().mode);
source()->AddReadResult(kMessage.data() + 16, 16, net::OK, GetParam().mode);
std::string hash2 =
- Base64Decode("iPMpmgExHPrbEX3_RvwP4d16fWlK4l--p75PUu_KyN0");
+ Base64Decode("iPMpmgExHPrbEX3/RvwP4d16fWlK4l++p75PUu/KyN0=");
source()->AddReadResult(hash2.data(), 32, net::OK, GetParam().mode);
// |hash2| is the hash of "atermelon", but this stream ends early. Decoding
// thus should fail.
@@ -463,14 +470,9 @@ TEST_P(MerkleIntegritySourceStreamTest, Truncated) {
EXPECT_EQ(kMessage, actual_output);
}
-// Test that the final record is allowed to be empty.
-//
-// TODO(davidben): This does not match the specification and means some inputs
-// have two valid encodings. However, the specification's version cannot
-// represent the empty string. Update the code and possibly this test depending
-// on how https://github.com/martinthomson/http-mice/issues/3 is resolved.
+// Test that the final record is not allowed to be empty.
TEST_P(MerkleIntegritySourceStreamTest, EmptyFinalRecord) {
- Init("mi-sha256-draft2=JJnIuaOEc2247K9V88VQAQy1GJuQ6ylaVM7mG69QkE4");
+ Init("mi-sha256-03=JJnIuaOEc2247K9V88VQAQy1GJuQ6ylaVM7mG69QkE4=");
const uint8_t kRecordSize[] = {0, 0, 0, 0, 0, 0, 0, 16};
const std::string kMessage(
"When I grow up, I want to be a watermelon!! \xf0\x9f\x8d\x89");
@@ -479,21 +481,21 @@ TEST_P(MerkleIntegritySourceStreamTest, EmptyFinalRecord) {
sizeof(kRecordSize), net::OK, GetParam().mode);
source()->AddReadResult(kMessage.data(), 16, net::OK, GetParam().mode);
std::string hash1 =
- Base64Decode("hhJEKpkbuZoWUjzBPAZxMUN2DXdJ6epkS0McZh77IXo");
+ Base64Decode("hhJEKpkbuZoWUjzBPAZxMUN2DXdJ6epkS0McZh77IXo=");
source()->AddReadResult(hash1.data(), 32, net::OK, GetParam().mode);
source()->AddReadResult(kMessage.data() + 16, 16, net::OK, GetParam().mode);
std::string hash2 =
- Base64Decode("RKTTVSMiH3bkxUQKreVATPL1KUd5eqRdmDgRQcZq_80");
+ Base64Decode("RKTTVSMiH3bkxUQKreVATPL1KUd5eqRdmDgRQcZq/80=");
source()->AddReadResult(hash2.data(), 32, net::OK, GetParam().mode);
source()->AddReadResult(kMessage.data() + 32, 16, net::OK, GetParam().mode);
std::string hash3 =
- Base64Decode("bjQLnP-zepicpUTmu3gKLHiQHT-zNzh2hRGjBhevoB0");
+ Base64Decode("bjQLnP+zepicpUTmu3gKLHiQHT+zNzh2hRGjBhevoB0=");
source()->AddReadResult(hash3.data(), 32, net::OK, GetParam().mode);
source()->AddReadResult(nullptr, 0, net::OK, GetParam().mode);
std::string actual_output;
int rv = ReadStream(&actual_output);
- EXPECT_EQ(static_cast<int>(kMessage.size()), rv);
+ EXPECT_EQ(net::ERR_CONTENT_DECODING_FAILED, rv);
EXPECT_EQ(kMessage, actual_output);
}
@@ -507,11 +509,11 @@ TEST_P(MerkleIntegritySourceStreamTest, WholeNumberOfRecords) {
sizeof(kRecordSize), net::OK, GetParam().mode);
source()->AddReadResult(kMessage.data(), 16, net::OK, GetParam().mode);
std::string hash1 =
- Base64Decode("2s-MNG6NrTt556s__HYnQTjG3WOktEcXZ61O8mzG9f4");
+ Base64Decode("2s+MNG6NrTt556s//HYnQTjG3WOktEcXZ61O8mzG9f4=");
source()->AddReadResult(hash1.data(), 32, net::OK, GetParam().mode);
source()->AddReadResult(kMessage.data() + 16, 16, net::OK, GetParam().mode);
std::string hash2 =
- Base64Decode("qa_cQSMjFyZsm0cnYG4H6LqwOM_hzMSclK6I8iVoZYQ");
+ Base64Decode("qa/cQSMjFyZsm0cnYG4H6LqwOM/hzMSclK6I8iVoZYQ=");
source()->AddReadResult(hash2.data(), 32, net::OK, GetParam().mode);
source()->AddReadResult(kMessage.data() + 32, 16, net::OK, GetParam().mode);
@@ -530,9 +532,9 @@ TEST_P(MerkleIntegritySourceStreamTest, WholeNumberOfRecordsAllAtOnce) {
std::string body(reinterpret_cast<const char*>(kRecordSize),
sizeof(kRecordSize));
body += kMessage.substr(0, 16);
- body += Base64Decode("2s-MNG6NrTt556s__HYnQTjG3WOktEcXZ61O8mzG9f4");
+ body += Base64Decode("2s+MNG6NrTt556s//HYnQTjG3WOktEcXZ61O8mzG9f4=");
body += kMessage.substr(16, 16);
- body += Base64Decode("qa_cQSMjFyZsm0cnYG4H6LqwOM_hzMSclK6I8iVoZYQ");
+ body += Base64Decode("qa/cQSMjFyZsm0cnYG4H6LqwOM/hzMSclK6I8iVoZYQ=");
body += kMessage.substr(32, 16);
source()->AddReadResult(body.data(), body.size(), net::OK, GetParam().mode);
diff --git a/chromium/content/browser/loader/mime_sniffing_resource_handler.cc b/chromium/content/browser/loader/mime_sniffing_resource_handler.cc
index 89e2c5351c4..74707ef3128 100644
--- a/chromium/content/browser/loader/mime_sniffing_resource_handler.cc
+++ b/chromium/content/browser/loader/mime_sniffing_resource_handler.cc
@@ -250,6 +250,7 @@ void MimeSniffingResourceHandler::OnReadCompleted(
// the mime type. However, even if it returns false, it returns a new type
// that is probably better than the current one.
response_->head.mime_type.assign(new_type);
+ response_->head.did_mime_sniff = true;
if (!made_final_decision && (bytes_read > 0)) {
controller->Resume();
diff --git a/chromium/content/browser/loader/mime_sniffing_resource_handler_unittest.cc b/chromium/content/browser/loader/mime_sniffing_resource_handler_unittest.cc
index 6ac35383ea9..6d23266622c 100644
--- a/chromium/content/browser/loader/mime_sniffing_resource_handler_unittest.cc
+++ b/chromium/content/browser/loader/mime_sniffing_resource_handler_unittest.cc
@@ -473,6 +473,8 @@ void MimeSniffingResourceHandlerTest::TestHandlerSniffing(
EXPECT_EQ(1, test_handler->on_will_read_called());
EXPECT_EQ(1, test_handler->on_read_completed_called());
+ EXPECT_TRUE(test_handler->resource_response()->head.did_mime_sniff);
+
// Process all messages to ensure proper test teardown.
content::RunAllPendingInMessageLoop();
}
@@ -601,6 +603,8 @@ void MimeSniffingResourceHandlerTest::TestHandlerNoSniffing(
EXPECT_EQ(1, test_handler->on_will_read_called());
EXPECT_EQ(1, test_handler->on_read_completed_called());
+ EXPECT_FALSE(test_handler->resource_response()->head.did_mime_sniff);
+
if (!read_completed) {
EXPECT_EQ(MockResourceLoader::Status::CANCELED, mock_loader.status());
EXPECT_EQ(net::ERR_ABORTED, mock_loader.error_code());
diff --git a/chromium/content/browser/loader/mojo_async_resource_handler.cc b/chromium/content/browser/loader/mojo_async_resource_handler.cc
index 4910201a2d1..de7d58c0a73 100644
--- a/chromium/content/browser/loader/mojo_async_resource_handler.cc
+++ b/chromium/content/browser/loader/mojo_async_resource_handler.cc
@@ -13,6 +13,7 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/time/time.h"
+#include "base/timer/timer.h"
#include "content/browser/loader/resource_controller.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader/resource_request_info_impl.h"
@@ -115,6 +116,7 @@ MojoAsyncResourceHandler::MojoAsyncResourceHandler(
mojo::SimpleWatcher::ArmingPolicy::MANUAL,
base::SequencedTaskRunnerHandle::Get()),
url_loader_client_(std::move(url_loader_client)),
+ report_transfer_size_async_timer_(std::make_unique<base::OneShotTimer>()),
weak_factory_(this) {
DCHECK(IsResourceTypeFrame(resource_type) ||
resource_type == RESOURCE_TYPE_SERVICE_WORKER ||
@@ -304,6 +306,37 @@ void MojoAsyncResourceHandler::OnWillRead(
controller->Resume();
}
+void MojoAsyncResourceHandler::set_report_transfer_size_async_timer_for_testing(
+ std::unique_ptr<base::OneShotTimer> timer) {
+ report_transfer_size_async_timer_ = std::move(timer);
+}
+
+void MojoAsyncResourceHandler::SendTransferSizeUpdate() {
+ int64_t transfer_size_diff = CalculateRecentlyReceivedBytes();
+ if (transfer_size_diff > 0) {
+ url_loader_client_->OnTransferSizeUpdated(transfer_size_diff);
+ }
+}
+
+void MojoAsyncResourceHandler::EnsureTransferSizeUpdate() {
+ auto current_time = base::TimeTicks::Now();
+ if (earliest_time_next_transfer_size_report_.is_null() ||
+ earliest_time_next_transfer_size_report_ <= current_time) {
+ report_transfer_size_async_timer_->Stop();
+ SendTransferSizeUpdate();
+ earliest_time_next_transfer_size_report_ =
+ current_time + kTransferSizeReportInterval;
+ } else {
+ // Ensure that a single transfer update will eventually occur even if reads
+ // stop. Unretained is safe here because the callback will only live as long
+ // as |report_transfer_size_async_timer_|.
+ report_transfer_size_async_timer_->Start(
+ FROM_HERE, kTransferSizeReportInterval,
+ base::BindOnce(&MojoAsyncResourceHandler::SendTransferSizeUpdate,
+ base::Unretained(this)));
+ }
+}
+
void MojoAsyncResourceHandler::OnReadCompleted(
int bytes_read,
std::unique_ptr<ResourceController> controller) {
@@ -318,15 +351,8 @@ void MojoAsyncResourceHandler::OnReadCompleted(
return;
}
- if (ShouldReportTransferSize(GetRequestInfo()) &&
- (time_transfer_size_next_report_.is_null() ||
- time_transfer_size_next_report_ <= base::TimeTicks::Now())) {
- auto transfer_size_diff = CalculateRecentlyReceivedBytes();
- if (transfer_size_diff > 0) {
- url_loader_client_->OnTransferSizeUpdated(transfer_size_diff);
- time_transfer_size_next_report_ =
- base::TimeTicks::Now() + kTransferSizeReportInterval;
- }
+ if (ShouldReportTransferSize(GetRequestInfo())) {
+ EnsureTransferSizeUpdate();
}
if (response_body_consumer_handle_.is_valid()) {
@@ -507,9 +533,9 @@ void MojoAsyncResourceHandler::OnResponseCompleted(
}
if (ShouldReportTransferSize(GetRequestInfo())) {
- auto transfer_size_diff = CalculateRecentlyReceivedBytes();
- if (transfer_size_diff > 0)
- url_loader_client_->OnTransferSizeUpdated(transfer_size_diff);
+ // All received bytes will be reported.
+ report_transfer_size_async_timer_->Stop();
+ SendTransferSizeUpdate();
}
url_loader_client_->OnComplete(loader_status);
diff --git a/chromium/content/browser/loader/mojo_async_resource_handler.h b/chromium/content/browser/loader/mojo_async_resource_handler.h
index ad87065771e..73ae262665c 100644
--- a/chromium/content/browser/loader/mojo_async_resource_handler.h
+++ b/chromium/content/browser/loader/mojo_async_resource_handler.h
@@ -28,6 +28,7 @@ class GURL;
namespace base {
class Location;
+class OneShotTimer;
}
namespace net {
@@ -93,6 +94,8 @@ class CONTENT_EXPORT MojoAsyncResourceHandler
void PauseReadingBodyFromNet() override;
void ResumeReadingBodyFromNet() override;
+ void set_report_transfer_size_async_timer_for_testing(
+ std::unique_ptr<base::OneShotTimer> timer);
void OnWritableForTesting();
static void SetAllocationSizeForTesting(size_t size);
static constexpr size_t kDefaultAllocationSize = 512 * 1024;
@@ -123,6 +126,8 @@ class CONTENT_EXPORT MojoAsyncResourceHandler
// |reported_total_received_bytes_|, returns it, and updates
// |reported_total_received_bytes_|.
int64_t CalculateRecentlyReceivedBytes();
+ void SendTransferSizeUpdate();
+ void EnsureTransferSizeUpdate();
// These functions can be overriden only for tests.
virtual void ReportBadMessage(const std::string& error);
@@ -150,9 +155,6 @@ class CONTENT_EXPORT MojoAsyncResourceHandler
bool did_defer_on_redirect_ = false;
bool did_defer_on_response_started_ = false;
- // The time transfer size should be reported next.
- base::TimeTicks time_transfer_size_next_report_;
- int64_t reported_total_received_bytes_ = 0;
int64_t total_written_bytes_ = 0;
// Pointer to parent's information about the read buffer. Only non-null while
@@ -171,6 +173,14 @@ class CONTENT_EXPORT MojoAsyncResourceHandler
std::unique_ptr<network::UploadProgressTracker> upload_progress_tracker_;
+ // Timer to report transfer size after a read is completed but not reported.
+ // Gurantees that all received bytes will be reported eventually, regardless
+ // of read rate or completion, as long as the client is alive.
+ std::unique_ptr<base::OneShotTimer> report_transfer_size_async_timer_;
+ // The time transfer size should be reported next.
+ base::TimeTicks earliest_time_next_transfer_size_report_;
+ int64_t reported_total_received_bytes_ = 0;
+
base::WeakPtrFactory<MojoAsyncResourceHandler> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(MojoAsyncResourceHandler);
};
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 a4170df9f58..68e6a784850 100644
--- a/chromium/content/browser/loader/mojo_async_resource_handler_unittest.cc
+++ b/chromium/content/browser/loader/mojo_async_resource_handler_unittest.cc
@@ -19,6 +19,7 @@
#include "base/run_loop.h"
#include "base/test/gtest_util.h"
#include "base/test/test_simple_task_runner.h"
+#include "base/timer/mock_timer.h"
#include "content/browser/loader/mock_resource_loader.h"
#include "content/browser/loader/resource_controller.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
@@ -1523,6 +1524,62 @@ TEST_F(MojoAsyncResourceHandlerTest,
EXPECT_LT(0, request_->GetTotalReceivedBytes());
}
+TEST_F(MojoAsyncResourceHandlerTest,
+ TransferSizeUpdateCalledWithoutResponseComplete) {
+ const char kResponseHeaders[] = "response headers";
+ const char kResponseData[] = "response data";
+ // Create a mock timer to control when the final transfersizeupdate is sent.
+ auto timer = std::make_unique<base::MockOneShotTimer>();
+ auto* raw_timer = timer.get();
+ handler_->set_report_transfer_size_async_timer_for_testing(std::move(timer));
+
+ // Create a test job so the underlying URLRequest will receive bytes.
+ net::URLRequestJobFactoryImpl test_job_factory_;
+ auto test_job = std::make_unique<net::URLRequestTestJob>(
+ request_.get(), request_context_->network_delegate(), kResponseHeaders,
+ kResponseData, true);
+ auto test_job_interceptor = std::make_unique<net::TestJobInterceptor>();
+ net::TestJobInterceptor* raw_test_job_interceptor =
+ test_job_interceptor.get();
+ EXPECT_TRUE(test_job_factory_.SetProtocolHandler(
+ url::kHttpScheme, std::move(test_job_interceptor)));
+ request_context_->set_job_factory(&test_job_factory_);
+ raw_test_job_interceptor->set_main_intercept_job(std::move(test_job));
+ request_->Start();
+
+ // Prepare for loader read complete.
+ ASSERT_TRUE(CallOnWillStartAndOnResponseStarted());
+ EXPECT_EQ(MockResourceLoader::Status::IDLE,
+ mock_loader_->OnWillStart(request_->url()));
+ EXPECT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
+ // Only headers are read by the time the response is started.
+ mock_loader_->OnReadCompleted(kResponseHeaders);
+
+ // Make the loader process another read of the rest of the URLTestJob data.
+ EXPECT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
+ mock_loader_->OnReadCompleted(kResponseData);
+
+ // Process the entire URL request.
+ url_request_delegate_.RunUntilComplete();
+
+ // All data received by the request.
+ EXPECT_EQ(
+ request_->GetTotalReceivedBytes(),
+ static_cast<int64_t>(strlen(kResponseHeaders) + strlen(kResponseData)));
+
+ // Wait for a transfer size update to be received.
+ url_loader_client_.RunUntilTransferSizeUpdated();
+ // Only the first read caused a transfer size update.
+ EXPECT_EQ(static_cast<int64_t>(strlen(kResponseHeaders)),
+ url_loader_client_.body_transfer_size());
+ // Firing the timer will cause the rest of the bytes to be reported.
+ // Without timer fire no transfer size updates would be received.
+ raw_timer->Fire();
+ url_loader_client_.RunUntilTransferSizeUpdated();
+ EXPECT_EQ(request_->GetTotalReceivedBytes(),
+ url_loader_client_.body_transfer_size());
+}
+
INSTANTIATE_TEST_CASE_P(MojoAsyncResourceHandlerWithAllocationSizeTest,
MojoAsyncResourceHandlerWithAllocationSizeTest,
::testing::Values(8, 32 * 2014));
diff --git a/chromium/content/browser/loader/navigation_loader_interceptor.h b/chromium/content/browser/loader/navigation_loader_interceptor.h
index 2f4ad19e0ba..ca2f3ad6d5f 100644
--- a/chromium/content/browser/loader/navigation_loader_interceptor.h
+++ b/chromium/content/browser/loader/navigation_loader_interceptor.h
@@ -35,23 +35,49 @@ class CONTENT_EXPORT NavigationLoaderInterceptor {
using LoaderCallback =
base::OnceCallback<void(SingleRequestURLLoaderFactory::RequestHandler)>;
+ using FallbackCallback =
+ base::OnceCallback<void(bool /* reset_subresource_loader_params */)>;
// Asks this handler to handle this resource load request.
// The handler must invoke |callback| eventually with either a non-null
// RequestHandler indicating its willingness to handle the request, or a null
// RequestHandler to indicate that someone else should handle the request.
+ //
+ // The |tentative_resource_request| passed to this function and the resource
+ // request later passed to the RequestHandler given to |callback| may not be
+ // exactly the same, because URLLoaderThrottles may rewrite the request
+ // between the two calls. However the URL must remain constant between the
+ // two, as any modifications on the URL done by URLLoaderThrottles must result
+ // in an (internal) redirect, which must restart the request with a new
+ // MaybeCreateLoader().
+ //
+ // This handler might initially elect to handle the request, but later decide
+ // to fall back to the default behavior. In that case, it can invoke
+ // |fallback_callback| to do so. An example of this is when a service worker
+ // decides to handle the request because it is in-scope, but the service
+ // worker JavaScript execution does not result in a response provided, so
+ // fallback to network is required.
+ //
+ // If |fallback_callback| is called, it must be called prior to the
+ // RequestHandler making any URLLoaderClient calls. The
+ // |reset_subresource_loader_params| parameter to |fallback_callback|
+ // indicates whether to discard the subresource loader params previously
+ // returned by MaybeCreateSubresourceLoaderParams().
virtual void MaybeCreateLoader(
- const network::ResourceRequest& resource_request,
+ const network::ResourceRequest& tentative_resource_request,
ResourceContext* resource_context,
- LoaderCallback callback) = 0;
+ LoaderCallback callback,
+ FallbackCallback fallback_callback) = 0;
// Returns a SubresourceLoaderParams if any to be used for subsequent URL
// requests going forward. Subclasses who want to set-up custom loader for
// subresource requests may want to override this.
+ //
// Note that the handler can return a null callback to MaybeCreateLoader(),
// and at the same time can return non-null SubresourceLoaderParams here if it
// does NOT want to handle the specific request given to MaybeCreateLoader()
- // but wants to handle the subsequent resource requests.
+ // but wants to handle the subsequent resource requests or ensure other
+ // interceptors are skipped.
virtual base::Optional<SubresourceLoaderParams>
MaybeCreateSubresourceLoaderParams();
diff --git a/chromium/content/browser/loader/navigation_url_loader_delegate.h b/chromium/content/browser/loader/navigation_url_loader_delegate.h
index c7d238283e1..c1f56144194 100644
--- a/chromium/content/browser/loader/navigation_url_loader_delegate.h
+++ b/chromium/content/browser/loader/navigation_url_loader_delegate.h
@@ -11,6 +11,7 @@
#include "base/memory/ref_counted.h"
#include "base/optional.h"
#include "content/common/content_export.h"
+#include "content/public/common/previews_state.h"
#include "services/network/public/mojom/url_loader.mojom.h"
namespace net {
@@ -45,6 +46,7 @@ class CONTENT_EXPORT NavigationURLLoaderDelegate {
// necessary info to create a custom subresource loader in the renderer
// process if the navigated context is controlled by a request interceptor
// like AppCache or ServiceWorker.
+ // |previews_state| is updated in common params.
virtual void OnResponseStarted(
const scoped_refptr<network::ResourceResponse>& response,
network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
@@ -52,6 +54,7 @@ class CONTENT_EXPORT NavigationURLLoaderDelegate {
const GlobalRequestID& request_id,
bool is_download,
bool is_stream,
+ PreviewsState previews_state,
base::Optional<SubresourceLoaderParams> subresource_loader_params) = 0;
// Called if the request fails before receving a response. Specific
diff --git a/chromium/content/browser/loader/navigation_url_loader_impl.cc b/chromium/content/browser/loader/navigation_url_loader_impl.cc
index 0fb15c7c1be..f14b46b86a8 100644
--- a/chromium/content/browser/loader/navigation_url_loader_impl.cc
+++ b/chromium/content/browser/loader/navigation_url_loader_impl.cc
@@ -10,11 +10,13 @@
#include "base/bind_helpers.h"
#include "base/feature_list.h"
#include "base/metrics/histogram_macros.h"
+#include "base/optional.h"
#include "base/stl_util.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "base/trace_event/trace_event.h"
#include "components/download/public/common/download_stats.h"
#include "content/browser/appcache/appcache_navigation_handle.h"
+#include "content/browser/appcache/appcache_navigation_handle_core.h"
#include "content/browser/appcache/appcache_request_handler.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/browser/devtools/render_frame_devtools_agent_host.h"
@@ -39,6 +41,7 @@
#include "content/browser/web_package/signed_exchange_utils.h"
#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"
@@ -59,8 +62,11 @@
#include "content/public/common/url_utils.h"
#include "content/public/common/webplugininfo.h"
#include "net/base/load_flags.h"
+#include "net/cert/sct_status_flags.h"
+#include "net/cert/signed_certificate_timestamp_and_status.h"
#include "net/http/http_content_disposition.h"
#include "net/http/http_request_headers.h"
+#include "net/ssl/ssl_info.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/url_request/redirect_util.h"
#include "net/url_request/url_request.h"
@@ -90,11 +96,13 @@ class NavigationLoaderInterceptorBrowserContainer
~NavigationLoaderInterceptorBrowserContainer() override = default;
- void MaybeCreateLoader(const network::ResourceRequest& resource_request,
- ResourceContext* resource_context,
- LoaderCallback callback) override {
- browser_interceptor_->MaybeCreateLoader(resource_request, resource_context,
- std::move(callback));
+ void MaybeCreateLoader(
+ const network::ResourceRequest& tentative_resource_request,
+ ResourceContext* resource_context,
+ LoaderCallback callback,
+ FallbackCallback fallback_callback) override {
+ browser_interceptor_->MaybeCreateLoader(
+ tentative_resource_request, resource_context, std::move(callback));
}
private:
@@ -290,13 +298,62 @@ std::unique_ptr<NavigationRequestInfo> CreateNavigationRequestInfoForRedirect(
}
// Called for requests that we don't have a URLLoaderFactory for.
-void UnknownSchemeCallback(bool handled_externally,
- network::mojom::URLLoaderRequest request,
- network::mojom::URLLoaderClientPtr client) {
+void UnknownSchemeCallback(
+ bool handled_externally,
+ const network::ResourceRequest& /* resource_request */,
+ network::mojom::URLLoaderRequest request,
+ network::mojom::URLLoaderClientPtr client) {
client->OnComplete(network::URLLoaderCompletionStatus(
handled_externally ? net::ERR_ABORTED : net::ERR_UNKNOWN_URL_SCHEME));
}
+// Returns whether this URL can be handled by the default network service
+// URLLoader.
+bool IsURLHandledByDefaultLoader(const GURL& url) {
+ // Data URLs are only handled by the network service if
+ // |enable_data_url_support| is set in NetworkContextParams. This is set to
+ // true for the context used by NavigationURLLoaderImpl, so in addition to
+ // checking whether the URL is handled by the network service, we also need to
+ // check for the data scheme.
+ return IsURLHandledByNetworkService(url) || url.SchemeIs(url::kDataScheme);
+}
+
+// Determines whether it is safe to redirect from |from_url| to |to_url|.
+bool IsRedirectSafe(const GURL& from_url,
+ const GURL& to_url,
+ ResourceContext* resource_context) {
+ return IsSafeRedirectTarget(from_url, to_url) &&
+ GetContentClient()->browser()->IsSafeRedirectTarget(to_url,
+ resource_context);
+}
+
+// URLLoaderFactory for handling about: URLs. This treats everything as
+// about:blank since no other about: features should be available to web
+// content.
+class AboutURLLoaderFactory : public network::mojom::URLLoaderFactory {
+ private:
+ // network::mojom::URLLoaderFactory:
+ 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 {
+ network::ResourceResponseHead response;
+ response.mime_type = "text/html";
+ client->OnReceiveResponse(response);
+ client->OnComplete(network::URLLoaderCompletionStatus(net::OK));
+ }
+
+ void Clone(network::mojom::URLLoaderFactoryRequest loader) override {
+ bindings_.AddBinding(this, std::move(loader));
+ }
+
+ mojo::BindingSet<network::mojom::URLLoaderFactory> bindings_;
+};
+
} // namespace
// Kept around during the lifetime of the navigation request, and is
@@ -315,19 +372,23 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
std::unique_ptr<network::ResourceRequest> resource_request,
ResourceContext* resource_context,
const GURL& url,
+ bool is_main_frame,
network::mojom::URLLoaderFactoryRequest proxied_factory_request,
network::mojom::URLLoaderFactoryPtrInfo proxied_factory_info,
std::set<std::string> known_schemes,
+ bool bypass_redirect_checks,
const base::WeakPtr<NavigationURLLoaderImpl>& owner)
: interceptors_(std::move(initial_interceptors)),
resource_request_(std::move(resource_request)),
resource_context_(resource_context),
url_(url),
+ is_main_frame_(is_main_frame),
owner_(owner),
response_loader_binding_(this),
proxied_factory_request_(std::move(proxied_factory_request)),
proxied_factory_info_(std::move(proxied_factory_info)),
known_schemes_(std::move(known_schemes)),
+ bypass_redirect_checks_(bypass_redirect_checks),
weak_factory_(this) {}
~URLLoaderRequestController() override {
@@ -347,13 +408,19 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
}
static uint32_t GetURLLoaderOptions(bool is_main_frame) {
- uint32_t options = network::mojom::kURLLoadOptionSendSSLInfoWithResponse;
- if (is_main_frame)
+ uint32_t options = network::mojom::kURLLoadOptionNone;
+
+ // Ensure that Mime sniffing works.
+ options |= network::mojom::kURLLoadOptionSniffMimeType;
+
+ if (is_main_frame) {
+ // SSLInfo is not needed on subframe responses because users can inspect
+ // only the certificate for the main frame when using the info bubble.
+ options |= network::mojom::kURLLoadOptionSendSSLInfoWithResponse;
options |= network::mojom::kURLLoadOptionSendSSLInfoForCertificateError;
+ }
- if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
- options |= network::mojom::kURLLoadOptionSniffMimeType;
- } else {
+ if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
// TODO(arthursonzogni): This is a temporary option. Remove this as soon
// as the InterceptingResourceHandler is removed.
// See https://crbug.com/791049.
@@ -400,14 +467,22 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
std::unique_ptr<NavigationRequestInfo> request_info,
ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core,
AppCacheNavigationHandleCore* appcache_handle_core,
+ const network::ResourceRequest& /* resource_request */,
network::mojom::URLLoaderRequest url_loader,
network::mojom::URLLoaderClientPtr url_loader_client) {
+ // |resource_request| is unused here. Its info may not be the same as
+ // |request_info|, because URLLoaderThrottles may have rewritten it. We
+ // don't propagate the fields to |request_info| here because the request
+ // will usually go to ResourceDispatcherHost which does its own request
+ // modification independent of URLLoaderThrottles.
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
DCHECK(started_);
default_loader_used_ = true;
if (signed_exchange_utils::IsSignedExchangeHandlingEnabled()) {
+ // TODO(falken): Understand and add a comment about why
+ // SignedExchangeRequestHandler is the only interceptor being added here.
DCHECK(!network_loader_factory_);
// It is safe to pass the callback of CreateURLLoaderThrottles with the
// unretained |this|, because the passed callback will be used by a
@@ -426,8 +501,7 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
resource_context_, url_request_context_getter),
base::BindRepeating(
&URLLoaderRequestController::CreateURLLoaderThrottles,
- base::Unretained(this)),
- url_request_context_getter));
+ base::Unretained(this))));
}
uint32_t options = GetURLLoaderOptions(request_info->is_main_frame);
@@ -549,7 +623,6 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
}
void Start(
- net::URLRequestContextGetter* url_request_context_getter,
std::unique_ptr<network::SharedURLLoaderFactoryInfo>
network_loader_factory_info,
ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core,
@@ -615,8 +688,8 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
if (appcache_handle_core) {
std::unique_ptr<NavigationLoaderInterceptor> appcache_interceptor =
- AppCacheRequestHandler::InitializeForNavigationNetworkService(
- *resource_request_, appcache_handle_core,
+ AppCacheRequestHandler::InitializeForMainResourceNetworkService(
+ *resource_request_, appcache_handle_core->host()->GetWeakPtr(),
network_loader_factory_);
if (appcache_interceptor)
interceptors_.push_back(std::move(appcache_interceptor));
@@ -642,8 +715,7 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
request_info->begin_params->load_flags, network_loader_factory_,
base::BindRepeating(
&URLLoaderRequestController::CreateURLLoaderThrottles,
- base::Unretained(this)),
- url_request_context_getter));
+ base::Unretained(this))));
}
std::vector<std::unique_ptr<URLLoaderRequestInterceptor>>
@@ -670,9 +742,15 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
// the restarted request to use a new loader, instead of, e.g., reusing the
// AppCache or service worker loader. For an optimization, we keep and reuse
// the default url loader if the all |interceptors_| doesn't handle the
- // redirected request.
- if (!default_loader_used_)
+ // redirected request. If the network service is enabled, only certain
+ // schemes are handled by the default URL loader. We need to make sure the
+ // redirected URL is a handled scheme, otherwise reset the loader so the
+ // correct non-network service loader can be used.
+ if (!default_loader_used_ ||
+ (base::FeatureList::IsEnabled(network::features::kNetworkService) &&
+ !IsURLHandledByDefaultLoader(resource_request_->url))) {
url_loader_.reset();
+ }
interceptor_index_ = 0;
received_response_ = false;
MaybeStartLoader(nullptr /* interceptor */,
@@ -694,11 +772,19 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
// |interceptor| wants to handle the request with
// |single_request_handler|.
DCHECK(interceptor);
+
+ std::vector<std::unique_ptr<URLLoaderThrottle>> throttles =
+ CreateURLLoaderThrottles();
+ // Intercepted requests need MimeSniffingThrottle to do mime sniffing.
+ // Non-intercepted requests usually go through the regular network
+ // URLLoader, which does mime sniffing.
+ throttles.push_back(std::make_unique<MimeSniffingThrottle>());
+
default_loader_used_ = false;
url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
base::MakeRefCounted<SingleRequestURLLoaderFactory>(
std::move(single_request_handler)),
- CreateURLLoaderThrottles(), frame_tree_node_id_,
+ std::move(throttles), frame_tree_node_id_,
global_request_id_.request_id, network::mojom::kURLLoadOptionNone,
resource_request_.get(), this, kNavigationUrlLoaderTrafficAnnotation,
base::ThreadTaskRunnerHandle::Get());
@@ -714,9 +800,9 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
// that case we will just fall back to the default loader (i.e. won't go on
// to the next interceptors) but send the subresource_loader_params to the
// child process. This is necessary for correctness in the cases where, e.g.
- // there's a controlling ServiceWorker that doesn't handle main resource
- // loading, but may still want to control the page and/or handle subresource
- // loading. In that case we want to skip AppCache.
+ // there's a controlling service worker that doesn't have a fetch event
+ // handler so it doesn't intercept requests. In that case we still want to
+ // skip AppCache.
if (interceptor) {
subresource_loader_params_ =
interceptor->MaybeCreateSubresourceLoaderParams();
@@ -733,13 +819,16 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
next_interceptor->MaybeCreateLoader(
*resource_request_, resource_context_,
base::BindOnce(&URLLoaderRequestController::MaybeStartLoader,
- base::Unretained(this), next_interceptor));
+ base::Unretained(this), next_interceptor),
+ base::BindOnce(
+ &URLLoaderRequestController::FallbackToNonInterceptedRequest,
+ base::Unretained(this)));
return;
}
- // If we already have the default |url_loader_| we must come here after
- // a redirect. No interceptors wanted to intercept the redirected request,
- // so let it just follow the redirect.
+ // If we already have the default |url_loader_| we must come here after a
+ // redirect. No interceptors wanted to intercept the redirected request, so
+ // let the loader just follow the redirect.
if (url_loader_) {
DCHECK(!redirect_info_.new_url.is_empty());
url_loader_->FollowRedirect(
@@ -747,48 +836,87 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
return;
}
- // TODO(https://crbug.com/796425): We temporarily wrap raw
- // mojom::URLLoaderFactory pointers into SharedURLLoaderFactory. Need to
- // further refactor the factory getters to avoid this.
- scoped_refptr<network::SharedURLLoaderFactory> factory;
- DCHECK_EQ(interceptors_.size(), interceptor_index_);
+ // No interceptors wanted to handle this request.
+ uint32_t options = network::mojom::kURLLoadOptionNone;
+ scoped_refptr<network::SharedURLLoaderFactory> factory =
+ PrepareForNonInterceptedRequest(&options);
+ url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
+ std::move(factory), CreateURLLoaderThrottles(), frame_tree_node_id_,
+ global_request_id_.request_id, options, resource_request_.get(),
+ this /* client */, kNavigationUrlLoaderTrafficAnnotation,
+ base::ThreadTaskRunnerHandle::Get());
+ }
+ // This is the |fallback_callback| passed to
+ // NavigationLoaderInterceptor::MaybeCreateLoader. It allows an interceptor
+ // to initially elect to handle a request, and later decide to fallback to
+ // the default behavior. This is needed for service worker network fallback.
+ void FallbackToNonInterceptedRequest(bool reset_subresource_loader_params) {
+ if (reset_subresource_loader_params)
+ subresource_loader_params_.reset();
+
+ // Non-NetworkService:
+ // Cancel state on ResourceDispatcherHostImpl so it doesn't complain about
+ // reusing the request_id after redirects. Otherwise the following sequence
+ // can happen:
+ // RDHI Start(request_id) -> Redirect -> SW interception -> SW fallback to
+ // network -> RDHI Start(request_id).
+ if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ DCHECK(ResourceDispatcherHostImpl::Get());
+ ResourceDispatcherHostImpl::Get()->CancelRequest(
+ global_request_id_.child_id, global_request_id_.request_id);
+ }
+
+ // |url_loader_| is using the factory for the interceptor that decided to
+ // fallback, so restart it with the non-interceptor factory.
+ DCHECK(url_loader_);
+ uint32_t options = network::mojom::kURLLoadOptionNone;
+ scoped_refptr<network::SharedURLLoaderFactory> factory =
+ PrepareForNonInterceptedRequest(&options);
+ url_loader_->RestartWithFactory(std::move(factory), options);
+ }
+
+ scoped_refptr<network::SharedURLLoaderFactory>
+ PrepareForNonInterceptedRequest(uint32_t* out_options) {
// If NetworkService is not enabled (which means we come here because one of
// the loader interceptors is enabled), use the default request handler
// instead of going through the NetworkService path.
if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
DCHECK(!interceptors_.empty());
DCHECK(default_request_handler_factory_);
- // The only way to come here is to enable ServiceWorkerServicification
- // without NetworkService. We know that the service worker's request
- // interceptor has already intercepted and decided not to handle the
+ // The only way to come here is to enable ServiceWorkerServicification or
+ // SignedExchange without NetworkService. We know that their request
+ // interceptors have already intercepted and decided not to handle the
// request.
- DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled());
+ DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled() ||
+ signed_exchange_utils::IsSignedExchangeHandlingEnabled());
default_loader_used_ = true;
// Update |request_info_| when following a redirect.
if (url_chain_.size() > 0) {
request_info_ = CreateNavigationRequestInfoForRedirect(
*request_info_, *resource_request_);
}
+
// When |subresource_loader_params_| has its value, the request should not
// be intercepted by any other interceptors since it means that a request
// interceptor already intercepted the request and it attached its info to
// the request.
- url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
- base::MakeRefCounted<SingleRequestURLLoaderFactory>(
- default_request_handler_factory_.Run(
- subresource_loader_params_.has_value()
- /* was_request_intercepted */)),
- CreateURLLoaderThrottles(), frame_tree_node_id_,
- global_request_id_.request_id, network::mojom::kURLLoadOptionNone,
- resource_request_.get(), this /* client */,
- kNavigationUrlLoaderTrafficAnnotation,
- base::ThreadTaskRunnerHandle::Get());
- return;
+ bool was_request_intercepted = subresource_loader_params_.has_value();
+
+ // TODO(falken): Determine whether GetURLLoaderOptions() can be called
+ // here like below. It looks like |default_request_handler_factory_| just
+ // calls that.
+ *out_options = network::mojom::kURLLoadOptionNone;
+ return base::MakeRefCounted<SingleRequestURLLoaderFactory>(
+ default_request_handler_factory_.Run(was_request_intercepted));
}
- if (!IsURLHandledByNetworkService(resource_request_->url) &&
- !resource_request_->url.SchemeIs(url::kDataScheme)) {
+ // TODO(https://crbug.com/796425): We temporarily wrap raw
+ // mojom::URLLoaderFactory pointers into SharedURLLoaderFactory. Need to
+ // further refactor the factory getters to avoid this.
+ scoped_refptr<network::SharedURLLoaderFactory> factory;
+
+ if (!IsURLHandledByDefaultLoader(resource_request_->url)) {
if (known_schemes_.find(resource_request_->url.scheme()) ==
known_schemes_.end()) {
bool handled = GetContentClient()->browser()->HandleExternalProtocol(
@@ -836,13 +964,9 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
}
}
url_chain_.push_back(resource_request_->url);
- uint32_t options = GetURLLoaderOptions(resource_request_->resource_type ==
- RESOURCE_TYPE_MAIN_FRAME);
- url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
- factory, CreateURLLoaderThrottles(), frame_tree_node_id_,
- global_request_id_.request_id, options, resource_request_.get(), this,
- kNavigationUrlLoaderTrafficAnnotation,
- base::ThreadTaskRunnerHandle::Get());
+ *out_options = GetURLLoaderOptions(resource_request_->resource_type ==
+ RESOURCE_TYPE_MAIN_FRAME);
+ return factory;
}
void FollowRedirect(
@@ -897,6 +1021,11 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
private:
// network::mojom::URLLoaderClient implementation:
void OnReceiveResponse(const network::ResourceResponseHead& head) override {
+ // Record the SCT histogram before checking if anything wants to intercept
+ // the response, so interceptors like AppCache and extensions can't hide
+ // values from the histograms.
+ RecordSCTHistogramIfNeeded(head.ssl_info);
+
received_response_ = true;
// If the default loader (network) was used to handle the URL load request
@@ -922,86 +1051,105 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
bool is_download;
bool is_stream;
+ // If there is not an explicit PreviewsState set on the request, turn
+ // Previews off.
+ PreviewsState previews_state = PREVIEWS_OFF;
std::unique_ptr<NavigationData> cloned_navigation_data;
+
if (IsLoaderInterceptionEnabled()) {
bool must_download = download_utils::MustDownload(
url_, head.headers.get(), head.mime_type);
bool known_mime_type = blink::IsSupportedMimeType(head.mime_type);
+ bool is_download_if_not_handled_by_plugin =
+ !response_intercepted && (must_download || !known_mime_type);
+
#if BUILDFLAG(ENABLE_PLUGINS)
if (!response_intercepted && !must_download && !known_mime_type) {
CheckPluginAndContinueOnReceiveResponse(
head, std::move(url_loader_client_endpoints),
- std::vector<WebPluginInfo>());
+ is_download_if_not_handled_by_plugin, std::vector<WebPluginInfo>());
return;
}
#endif
- is_download =
- !response_intercepted && (must_download || !known_mime_type);
+ is_download = is_download_if_not_handled_by_plugin;
is_stream = false;
- } else {
- ResourceDispatcherHostImpl* rdh = ResourceDispatcherHostImpl::Get();
- net::URLRequest* url_request = rdh->GetURLRequest(global_request_id_);
-
- // The |url_request| maybe have been removed from the resource dispatcher
- // host during the time it took for OnReceiveResponse() to be received.
- if (url_request) {
- ResourceRequestInfoImpl* info =
- ResourceRequestInfoImpl::ForRequest(url_request);
- is_download = !response_intercepted && info->IsDownload();
- is_stream = info->is_stream();
- if (rdh->delegate()) {
- NavigationData* navigation_data =
- rdh->delegate()->GetNavigationData(url_request);
-
- // Clone the embedder's NavigationData before moving it to the UI
- // thread.
- if (navigation_data)
- cloned_navigation_data = navigation_data->Clone();
- }
- // This is similar to what is done in
- // ServiceWorkerControlleeHandler::MaybeCreateSubresourceLoaderParams().
- // It takes the matching ControllerServiceWorkerInfo (if any) associated
- // with the request. It will be sent to the renderer process and used to
- // intercept requests.
- // TODO(arthursonzogni): This is needed only for the
- // non-S13nServiceWorker case. The S13nServiceWorker case is still not
- // supported without the NetworkService. This block needs to be updated
- // once support for it will be added.
- ServiceWorkerProviderHost* sw_provider_host =
- ServiceWorkerRequestHandler::GetProviderHost(url_request);
- if (sw_provider_host && sw_provider_host->controller()) {
- subresource_loader_params_ = SubresourceLoaderParams();
- subresource_loader_params_->controller_service_worker_info =
- mojom::ControllerServiceWorkerInfo::New();
- subresource_loader_params_->controller_service_worker_info->mode =
- sw_provider_host->GetControllerMode();
- base::WeakPtr<ServiceWorkerObjectHost> sw_object_host =
- sw_provider_host->GetOrCreateServiceWorkerObjectHost(
- sw_provider_host->controller());
- if (sw_object_host) {
- subresource_loader_params_->controller_service_worker_object_host =
- sw_object_host;
- subresource_loader_params_->controller_service_worker_info
- ->object_info = sw_object_host->CreateIncompleteObjectInfo();
- }
+ // If NetworkService is on, or an interceptor handled the request, the
+ // request doesn't use ResourceDispatcherHost so
+ // CallOnReceivedResponse and return here.
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService) ||
+ !default_loader_used_) {
+ CallOnReceivedResponse(head, std::move(url_loader_client_endpoints),
+ std::move(cloned_navigation_data), is_download,
+ is_stream, previews_state);
+ return;
+ }
+ }
+
+ // NetworkService is off and an interceptor didn't handle the request,
+ // so it went to ResourceDispatcherHost.
+ ResourceDispatcherHostImpl* rdh = ResourceDispatcherHostImpl::Get();
+ net::URLRequest* url_request = rdh->GetURLRequest(global_request_id_);
+
+ // The |url_request| maybe have been removed from the resource dispatcher
+ // host during the time it took for OnReceiveResponse() to be received.
+ if (url_request) {
+ ResourceRequestInfoImpl* info =
+ ResourceRequestInfoImpl::ForRequest(url_request);
+ is_download = !response_intercepted && info->IsDownload();
+ is_stream = info->is_stream();
+ previews_state = info->GetPreviewsState();
+ if (rdh->delegate()) {
+ NavigationData* navigation_data =
+ rdh->delegate()->GetNavigationData(url_request);
+
+ // Clone the embedder's NavigationData before moving it to the UI
+ // thread.
+ if (navigation_data)
+ cloned_navigation_data = navigation_data->Clone();
+ }
+
+ // non-S13nServiceWorker:
+ // This is similar to what is done in
+ // ServiceWorkerControlleeHandler::MaybeCreateSubresourceLoaderParams()
+ // (which is used when S13nServiceWorker is on). It takes the matching
+ // ControllerServiceWorkerInfo (if any) associated with the request. It
+ // will be sent to the renderer process and used to intercept requests.
+ ServiceWorkerProviderHost* sw_provider_host =
+ ServiceWorkerRequestHandler::GetProviderHost(url_request);
+ if (sw_provider_host && sw_provider_host->controller()) {
+ DCHECK(!blink::ServiceWorkerUtils::IsServicificationEnabled());
+ subresource_loader_params_ = SubresourceLoaderParams();
+ subresource_loader_params_->controller_service_worker_info =
+ mojom::ControllerServiceWorkerInfo::New();
+ subresource_loader_params_->controller_service_worker_info->mode =
+ sw_provider_host->GetControllerMode();
+ base::WeakPtr<ServiceWorkerObjectHost> sw_object_host =
+ sw_provider_host->GetOrCreateServiceWorkerObjectHost(
+ sw_provider_host->controller());
+ if (sw_object_host) {
+ subresource_loader_params_->controller_service_worker_object_host =
+ sw_object_host;
+ subresource_loader_params_->controller_service_worker_info
+ ->object_info = sw_object_host->CreateIncompleteObjectInfo();
}
- } else {
- is_download = is_stream = false;
}
+ } else {
+ is_download = is_stream = false;
}
CallOnReceivedResponse(head, std::move(url_loader_client_endpoints),
std::move(cloned_navigation_data), is_download,
- is_stream);
+ is_stream, previews_state);
}
#if BUILDFLAG(ENABLE_PLUGINS)
void CheckPluginAndContinueOnReceiveResponse(
const network::ResourceResponseHead& head,
network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
+ bool is_download_if_not_handled_by_plugin,
const std::vector<WebPluginInfo>& plugins) {
bool stale;
WebPluginInfo plugin;
@@ -1020,16 +1168,16 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
PluginService::GetInstance()->GetPlugins(base::BindOnce(
&URLLoaderRequestController::CheckPluginAndContinueOnReceiveResponse,
weak_factory_.GetWeakPtr(), head,
- std::move(url_loader_client_endpoints)));
+ std::move(url_loader_client_endpoints),
+ is_download_if_not_handled_by_plugin));
return;
}
- bool is_download =
- !has_plugin &&
- (!head.headers || head.headers->response_code() / 100 == 2);
+ bool is_download = !has_plugin && is_download_if_not_handled_by_plugin;
CallOnReceivedResponse(head, std::move(url_loader_client_endpoints),
- nullptr, is_download, false /* is_stream */);
+ nullptr, is_download, false /* is_stream */,
+ PREVIEWS_OFF /* previews_state */);
}
#endif
@@ -1038,7 +1186,8 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
std::unique_ptr<NavigationData> cloned_navigation_data,
bool is_download,
- bool is_stream) {
+ bool is_stream,
+ PreviewsState previews_state) {
scoped_refptr<network::ResourceResponse> response(
new network::ResourceResponse());
response->head = head;
@@ -1055,11 +1204,18 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
response->DeepCopy(),
std::move(url_loader_client_endpoints),
std::move(cloned_navigation_data), global_request_id_,
- is_download, is_stream));
+ is_download, is_stream, previews_state));
}
void OnReceiveRedirect(const net::RedirectInfo& redirect_info,
const network::ResourceResponseHead& head) override {
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService) &&
+ !bypass_redirect_checks_ &&
+ !IsRedirectSafe(url_, redirect_info.new_url, resource_context_)) {
+ OnComplete(network::URLLoaderCompletionStatus(net::ERR_UNSAFE_REDIRECT));
+ return;
+ }
+
if (--redirect_limit_ == 0) {
OnComplete(
network::URLLoaderCompletionStatus(net::ERR_TOO_MANY_REDIRECTS));
@@ -1100,6 +1256,8 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
}
void OnComplete(const network::URLLoaderCompletionStatus& status) override {
+ RecordSCTHistogramIfNeeded(status.ssl_info);
+
UMA_HISTOGRAM_BOOLEAN(
"Navigation.URLLoaderNetworkService.OnCompleteHasSSLInfo",
status.ssl_info.has_value());
@@ -1138,6 +1296,8 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
if (interceptor->MaybeCreateLoaderForResponse(
response, &response_url_loader_, &response_client_request,
url_loader_.get())) {
+ if (response_loader_binding_.is_bound())
+ response_loader_binding_.Close();
response_loader_binding_.Bind(std::move(response_client_request));
default_loader_used_ = false;
url_loader_.reset();
@@ -1147,8 +1307,7 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
return false;
}
- std::vector<std::unique_ptr<content::URLLoaderThrottle>>
- CreateURLLoaderThrottles() {
+ std::vector<std::unique_ptr<URLLoaderThrottle>> CreateURLLoaderThrottles() {
return GetContentClient()->browser()->CreateURLLoaderThrottles(
*resource_request_, resource_context_, web_contents_getter_,
navigation_ui_data_.get(), frame_tree_node_id_);
@@ -1168,7 +1327,7 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
storage::BlobStorageContext* blob_storage_context = GetBlobStorageContext(
GetChromeBlobStorageContextForResourceContext(resource_context_));
return ServiceWorkerRequestHandler::InitializeForNavigationNetworkService(
- *resource_request_, resource_context_,
+ resource_request_->url, resource_context_,
service_worker_navigation_handle_core, blob_storage_context,
request_info.begin_params->skip_service_worker, resource_type,
request_info.begin_params->request_context_type, frame_type,
@@ -1176,6 +1335,21 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
web_contents_getter_);
}
+ void RecordSCTHistogramIfNeeded(
+ const base::Optional<net::SSLInfo>& ssl_info) {
+ if (is_main_frame_ && url_.SchemeIsCryptographic() &&
+ ssl_info.has_value()) {
+ int num_valid_scts = 0;
+ for (const auto& signed_certificate_timestamps :
+ ssl_info->signed_certificate_timestamps) {
+ if (signed_certificate_timestamps.status == net::ct::SCT_STATUS_OK)
+ ++num_valid_scts;
+ }
+ UMA_HISTOGRAM_COUNTS_100(
+ "Net.CertificateTransparency.MainFrameValidSCTCount", num_valid_scts);
+ }
+ }
+
std::vector<std::unique_ptr<NavigationLoaderInterceptor>> interceptors_;
size_t interceptor_index_ = 0;
@@ -1204,6 +1378,8 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
// Current URL that is being navigated, updated after redirection.
GURL url_;
+ const bool is_main_frame_;
+
// Currently used by the AppCache loader to pass its factory to the
// renderer which enables it to handle subresources.
base::Optional<SubresourceLoaderParams> subresource_loader_params_;
@@ -1266,6 +1442,9 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
// protocol handlers.
std::set<std::string> known_schemes_;
+ // If true, redirect checks will be handled in a proxy, and not here.
+ bool bypass_redirect_checks_;
+
mutable base::WeakPtrFactory<URLLoaderRequestController> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(URLLoaderRequestController);
@@ -1312,10 +1491,10 @@ NavigationURLLoaderImpl::NavigationURLLoaderImpl(
/* initial_interceptors = */
std::vector<std::unique_ptr<NavigationLoaderInterceptor>>(),
std::move(new_request), resource_context,
- request_info->common_params.url,
+ request_info->common_params.url, request_info->is_main_frame,
/* proxied_url_loader_factory_request */ nullptr,
/* proxied_url_loader_factory_info */ nullptr, std::set<std::string>(),
- weak_factory_.GetWeakPtr());
+ /* bypass_redirect_checks */ false, weak_factory_.GetWeakPtr());
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
@@ -1344,6 +1523,7 @@ NavigationURLLoaderImpl::NavigationURLLoaderImpl(
network::mojom::URLLoaderFactoryPtrInfo proxied_factory_info;
network::mojom::URLLoaderFactoryRequest proxied_factory_request;
+ bool bypass_redirect_checks = false;
auto* partition = static_cast<StoragePartitionImpl*>(storage_partition);
if (frame_tree_node) {
// |frame_tree_node| may be null in some unit test environments.
@@ -1360,7 +1540,8 @@ NavigationURLLoaderImpl::NavigationURLLoaderImpl(
auto factory_request = mojo::MakeRequest(&factory_info);
bool use_proxy = GetContentClient()->browser()->WillCreateURLLoaderFactory(
partition->browser_context(), frame_tree_node->current_frame_host(),
- true /* is_navigation */, &factory_request);
+ true /* is_navigation */, new_request->url, &factory_request);
+ bypass_redirect_checks = use_proxy;
if (RenderFrameDevToolsAgentHost::WillCreateURLLoaderFactory(
frame_tree_node->current_frame_host(), true, false,
&factory_request)) {
@@ -1379,11 +1560,14 @@ NavigationURLLoaderImpl::NavigationURLLoaderImpl(
storage_domain);
}
+ non_network_url_loader_factories_[url::kAboutScheme] =
+ std::make_unique<AboutURLLoaderFactory>();
+
non_network_url_loader_factories_[url::kFileScheme] =
std::make_unique<FileURLLoaderFactory>(
partition->browser_context()->GetPath(),
base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BACKGROUND,
+ {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}));
std::set<std::string> known_schemes;
for (auto& iter : non_network_url_loader_factories_)
@@ -1392,15 +1576,15 @@ NavigationURLLoaderImpl::NavigationURLLoaderImpl(
DCHECK(!request_controller_);
request_controller_ = std::make_unique<URLLoaderRequestController>(
std::move(initial_interceptors), std::move(new_request), resource_context,
- request_info->common_params.url, std::move(proxied_factory_request),
- std::move(proxied_factory_info), std::move(known_schemes),
+ request_info->common_params.url, request_info->is_main_frame,
+ std::move(proxied_factory_request), std::move(proxied_factory_info),
+ std::move(known_schemes), bypass_redirect_checks,
weak_factory_.GetWeakPtr());
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(
&URLLoaderRequestController::Start,
base::Unretained(request_controller_.get()),
- base::RetainedRef(storage_partition->GetURLRequestContext()),
partition->url_loader_factory_getter()->GetNetworkFactoryInfo(),
service_worker_navigation_handle_core, appcache_handle_core,
std::move(request_info), std::move(navigation_ui_data),
@@ -1432,7 +1616,8 @@ void NavigationURLLoaderImpl::OnReceiveResponse(
std::unique_ptr<NavigationData> navigation_data,
const GlobalRequestID& global_request_id,
bool is_download,
- bool is_stream) {
+ bool is_stream,
+ PreviewsState previews_state) {
TRACE_EVENT_ASYNC_END2("navigation", "Navigation timeToResponseStarted", this,
"&NavigationURLLoaderImpl", this, "success", true);
@@ -1442,7 +1627,7 @@ void NavigationURLLoaderImpl::OnReceiveResponse(
delegate_->OnResponseStarted(
std::move(response), std::move(url_loader_client_endpoints),
std::move(navigation_data), global_request_id,
- allow_download_ && is_download, is_stream,
+ allow_download_ && is_download, is_stream, previews_state,
request_controller_->TakeSubresourceLoaderParams());
}
@@ -1491,7 +1676,7 @@ void NavigationURLLoaderImpl::BindNonNetworkURLLoaderFactoryRequest(
auto* frame = frame_tree_node->current_frame_host();
GetContentClient()->browser()->WillCreateURLLoaderFactory(
frame->GetSiteInstance()->GetBrowserContext(), frame,
- true /* is_navigation */, &factory);
+ true /* is_navigation */, url, &factory);
it->second->Clone(std::move(factory));
}
diff --git a/chromium/content/browser/loader/navigation_url_loader_impl.h b/chromium/content/browser/loader/navigation_url_loader_impl.h
index ac5e384a04d..1bcc9efb46d 100644
--- a/chromium/content/browser/loader/navigation_url_loader_impl.h
+++ b/chromium/content/browser/loader/navigation_url_loader_impl.h
@@ -12,6 +12,7 @@
#include "content/browser/loader/navigation_url_loader.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/ssl_status.h"
+#include "content/public/common/previews_state.h"
#include "services/network/public/mojom/url_loader.mojom.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
@@ -22,9 +23,9 @@ struct RedirectInfo;
namespace content {
class NavigationData;
+class NavigationLoaderInterceptor;
class ResourceContext;
class StoragePartition;
-class NavigationLoaderInterceptor;
struct GlobalRequestID;
class CONTENT_EXPORT NavigationURLLoaderImpl : public NavigationURLLoader {
@@ -56,7 +57,8 @@ class CONTENT_EXPORT NavigationURLLoaderImpl : public NavigationURLLoader {
std::unique_ptr<NavigationData> navigation_data,
const GlobalRequestID& global_request_id,
bool is_download,
- bool is_stream);
+ bool is_stream,
+ PreviewsState previews_state);
void OnReceiveRedirect(const net::RedirectInfo& redirect_info,
scoped_refptr<network::ResourceResponse> response);
void OnComplete(const network::URLLoaderCompletionStatus& status);
diff --git a/chromium/content/browser/loader/navigation_url_loader_impl_unittest.cc b/chromium/content/browser/loader/navigation_url_loader_impl_unittest.cc
index 538274d42a9..37cf04dda21 100644
--- a/chromium/content/browser/loader/navigation_url_loader_impl_unittest.cc
+++ b/chromium/content/browser/loader/navigation_url_loader_impl_unittest.cc
@@ -71,13 +71,13 @@ class TestNavigationLoaderInterceptor : public NavigationLoaderInterceptor {
void MaybeCreateLoader(const network::ResourceRequest& resource_request,
ResourceContext* resource_context,
- LoaderCallback callback) override {
- std::move(callback).Run(
- base::BindOnce(&TestNavigationLoaderInterceptor::StartLoader,
- base::Unretained(this), resource_request));
+ LoaderCallback callback,
+ FallbackCallback fallback_callback) override {
+ std::move(callback).Run(base::BindOnce(
+ &TestNavigationLoaderInterceptor::StartLoader, base::Unretained(this)));
}
- void StartLoader(network::ResourceRequest resource_request,
+ void StartLoader(const network::ResourceRequest& resource_request,
network::mojom::URLLoaderRequest request,
network::mojom::URLLoaderClientPtr client) {
*most_recent_resource_request_ = resource_request;
@@ -145,6 +145,10 @@ class NavigationURLLoaderImplTest : public testing::Test {
}
~NavigationURLLoaderImplTest() override {
+ // The context needs to be deleted before ServiceManagerConnection is
+ // destroyed, so the storage partition in the context does not try to
+ // reconnect to the network service after ServiceManagerConnection is dead.
+ browser_context_.reset();
ServiceManagerConnection::DestroyForProcess();
}
diff --git a/chromium/content/browser/loader/prefetch_browsertest.cc b/chromium/content/browser/loader/prefetch_browsertest.cc
index fb0726ef37c..b3776b2bac6 100644
--- a/chromium/content/browser/loader/prefetch_browsertest.cc
+++ b/chromium/content/browser/loader/prefetch_browsertest.cc
@@ -29,11 +29,8 @@
namespace content {
struct PrefetchBrowserTestParam {
- PrefetchBrowserTestParam(bool network_service_enabled,
- bool signed_exchange_enabled)
- : network_service_enabled(network_service_enabled),
- signed_exchange_enabled(signed_exchange_enabled) {}
- const bool network_service_enabled;
+ PrefetchBrowserTestParam(bool signed_exchange_enabled)
+ : signed_exchange_enabled(signed_exchange_enabled) {}
const bool signed_exchange_enabled;
};
@@ -69,8 +66,6 @@ class PrefetchBrowserTest
void SetUp() override {
std::vector<base::Feature> enable_features;
- if (GetParam().network_service_enabled)
- enable_features.push_back(network::features::kNetworkService);
if (GetParam().signed_exchange_enabled)
enable_features.push_back(features::kSignedHTTPExchange);
feature_list_.InitWithFeatures(enable_features, {});
@@ -110,12 +105,16 @@ class PrefetchBrowserTest
return nullptr;
}
- void WatchURLAndRunClosure(const std::string& relative_url,
- int* visit_count,
- base::OnceClosure closure,
- const net::test_server::HttpRequest& request) {
+ void WatchURLAndRunClosure(
+ const std::string& relative_url,
+ int* visit_count,
+ net::test_server::HttpRequest::HeaderMap* out_headers,
+ base::OnceClosure closure,
+ const net::test_server::HttpRequest& request) {
if (request.relative_url == relative_url) {
(*visit_count)++;
+ if (out_headers)
+ *out_headers = request.headers;
if (closure)
std::move(closure).Run();
}
@@ -124,8 +123,7 @@ class PrefetchBrowserTest
void OnPrefetchURLLoaderCalled() { prefetch_url_loader_called_++; }
bool CheckPrefetchURLLoaderCountIfSupported(int expected) const {
- if (!base::FeatureList::IsEnabled(features::kSignedHTTPExchange) &&
- !base::FeatureList::IsEnabled(network::features::kNetworkService))
+ if (!base::FeatureList::IsEnabled(features::kSignedHTTPExchange))
return true;
return prefetch_url_loader_called_ == expected;
}
@@ -153,7 +151,7 @@ IN_PROC_BROWSER_TEST_P(PrefetchBrowserTest, Simple) {
base::RunLoop prefetch_waiter;
embedded_test_server()->RegisterRequestMonitor(base::BindRepeating(
&PrefetchBrowserTest::WatchURLAndRunClosure, base::Unretained(this),
- target_url, &target_fetch_count, prefetch_waiter.QuitClosure()));
+ target_url, &target_fetch_count, nullptr, prefetch_waiter.QuitClosure()));
embedded_test_server()->RegisterRequestHandler(base::BindRepeating(
&PrefetchBrowserTest::ServeResponses, base::Unretained(this)));
ASSERT_TRUE(embedded_test_server()->Start());
@@ -191,7 +189,7 @@ IN_PROC_BROWSER_TEST_P(PrefetchBrowserTest, DoublePrefetch) {
base::RunLoop prefetch_waiter;
embedded_test_server()->RegisterRequestMonitor(base::BindRepeating(
&PrefetchBrowserTest::WatchURLAndRunClosure, base::Unretained(this),
- target_url, &target_fetch_count, prefetch_waiter.QuitClosure()));
+ target_url, &target_fetch_count, nullptr, prefetch_waiter.QuitClosure()));
embedded_test_server()->RegisterRequestHandler(base::BindRepeating(
&PrefetchBrowserTest::ServeResponses, base::Unretained(this)));
ASSERT_TRUE(embedded_test_server()->Start());
@@ -238,10 +236,12 @@ IN_PROC_BROWSER_TEST_P(PrefetchBrowserTest, NoCacheAndNoStore) {
base::RunLoop nostore_waiter;
embedded_test_server()->RegisterRequestMonitor(base::BindRepeating(
&PrefetchBrowserTest::WatchURLAndRunClosure, base::Unretained(this),
- nocache_url, &nocache_fetch_count, nocache_waiter.QuitClosure()));
+ nocache_url, &nocache_fetch_count, nullptr,
+ nocache_waiter.QuitClosure()));
embedded_test_server()->RegisterRequestMonitor(base::BindRepeating(
&PrefetchBrowserTest::WatchURLAndRunClosure, base::Unretained(this),
- nostore_url, &nostore_fetch_count, nostore_waiter.QuitClosure()));
+ nostore_url, &nostore_fetch_count, nullptr,
+ nostore_waiter.QuitClosure()));
embedded_test_server()->RegisterRequestHandler(base::BindRepeating(
&PrefetchBrowserTest::ServeResponses, base::Unretained(this)));
ASSERT_TRUE(embedded_test_server()->Start());
@@ -298,10 +298,11 @@ IN_PROC_BROWSER_TEST_P(PrefetchBrowserTest, WithPreload) {
base::RunLoop preload_waiter;
embedded_test_server()->RegisterRequestMonitor(base::BindRepeating(
&PrefetchBrowserTest::WatchURLAndRunClosure, base::Unretained(this),
- target_url, &target_fetch_count, base::RepeatingClosure()));
+ target_url, &target_fetch_count, nullptr, base::RepeatingClosure()));
embedded_test_server()->RegisterRequestMonitor(base::BindRepeating(
&PrefetchBrowserTest::WatchURLAndRunClosure, base::Unretained(this),
- preload_url, &preload_fetch_count, preload_waiter.QuitClosure()));
+ preload_url, &preload_fetch_count, nullptr,
+ preload_waiter.QuitClosure()));
embedded_test_server()->RegisterRequestHandler(base::BindRepeating(
&PrefetchBrowserTest::ServeResponses, base::Unretained(this)));
ASSERT_TRUE(embedded_test_server()->Start());
@@ -344,27 +345,30 @@ IN_PROC_BROWSER_TEST_P(PrefetchBrowserTest, WebPackageWithPreload) {
RegisterResponse(
target_sxg,
// We mock the SignedExchangeHandler, so just return a HTML content
- // as "application/signed-exchange;v=b0".
+ // as "application/signed-exchange;v=b2".
ResponseEntry("<head><title>Prefetch Target (SXG)</title></head>",
- "application/signed-exchange;v=b0"));
+ "application/signed-exchange;v=b2"));
RegisterResponse(preload_url_in_sxg,
ResponseEntry("function foo() {}", "text/javascript"));
base::RunLoop preload_waiter;
base::RunLoop prefetch_waiter;
+ net::test_server::HttpRequest::HeaderMap prefetch_headers;
embedded_test_server()->RegisterRequestMonitor(base::BindRepeating(
&PrefetchBrowserTest::WatchURLAndRunClosure, base::Unretained(this),
- target_sxg, &target_fetch_count, prefetch_waiter.QuitClosure()));
+ target_sxg, &target_fetch_count, &prefetch_headers,
+ prefetch_waiter.QuitClosure()));
embedded_test_server()->RegisterRequestMonitor(base::BindRepeating(
&PrefetchBrowserTest::WatchURLAndRunClosure, base::Unretained(this),
- preload_url_in_sxg, &preload_fetch_count, preload_waiter.QuitClosure()));
+ preload_url_in_sxg, &preload_fetch_count, nullptr,
+ preload_waiter.QuitClosure()));
embedded_test_server()->RegisterRequestHandler(base::BindRepeating(
&PrefetchBrowserTest::ServeResponses, base::Unretained(this)));
ASSERT_TRUE(embedded_test_server()->Start());
EXPECT_TRUE(CheckPrefetchURLLoaderCountIfSupported(0));
MockSignedExchangeHandlerFactory factory(
- net::OK, GURL(target_url), "text/html",
+ net::OK, GURL(embedded_test_server()->GetURL(target_url)), "text/html",
{base::StringPrintf(
"Link: <%s>;rel=\"preload\";as=\"script\"",
embedded_test_server()->GetURL(preload_url_in_sxg).spec().c_str())});
@@ -376,13 +380,14 @@ IN_PROC_BROWSER_TEST_P(PrefetchBrowserTest, WebPackageWithPreload) {
prefetch_waiter.Run();
EXPECT_EQ(1, target_fetch_count);
EXPECT_TRUE(CheckPrefetchURLLoaderCountIfSupported(1));
-
- // Test after this point requires SignedHTTPExchange support, which is now
- // disabled when Network Service is enabled.
- // TODO(https://crbug.com/849935): Remove the second condition once we
- // re-enable Signed Exchange with Network Service.
- if (!base::FeatureList::IsEnabled(features::kSignedHTTPExchange) ||
- base::FeatureList::IsEnabled(network::features::kNetworkService))
+ if (base::FeatureList::IsEnabled(features::kSignedHTTPExchange))
+ EXPECT_EQ(prefetch_headers["Accept"],
+ "application/signed-exchange;v=b2;q=0.9,*/*;q=0.8");
+ else
+ EXPECT_EQ(prefetch_headers["Accept"], "*/*");
+
+ // Test after this point requires SignedHTTPExchange support
+ if (!base::FeatureList::IsEnabled(features::kSignedHTTPExchange))
return;
// If the header in the .sxg file is correctly extracted, we should
@@ -393,10 +398,7 @@ IN_PROC_BROWSER_TEST_P(PrefetchBrowserTest, WebPackageWithPreload) {
INSTANTIATE_TEST_CASE_P(PrefetchBrowserTest,
PrefetchBrowserTest,
- testing::Values(PrefetchBrowserTestParam(true, true),
- PrefetchBrowserTestParam(true, false),
- PrefetchBrowserTestParam(false, true),
- PrefetchBrowserTestParam(false,
- false)));
+ testing::Values(PrefetchBrowserTestParam(true),
+ PrefetchBrowserTestParam(false)));
} // namespace content
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_impl.cc b/chromium/content/browser/loader/resource_dispatcher_host_impl.cc
index 061ad189c46..2ed617dbab8 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_impl.cc
+++ b/chromium/content/browser/loader/resource_dispatcher_host_impl.cc
@@ -28,8 +28,8 @@
#include "base/metrics/histogram_macros.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
-#include "base/task_scheduler/post_task.h"
-#include "base/task_scheduler/task_traits.h"
+#include "base/task/post_task.h"
+#include "base/task/task_traits.h"
#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/timer/timer.h"
@@ -91,7 +91,6 @@
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "net/base/upload_data_stream.h"
#include "net/base/url_util.h"
-#include "net/cert/cert_status_flags.h"
#include "net/cookies/cookie_monster.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_response_headers.h"
@@ -169,11 +168,6 @@ void AbortRequestBeforeItStarts(
url_loader_client->OnComplete(status);
}
-bool IsValidatedSCT(
- const net::SignedCertificateTimestampAndStatus& sct_status) {
- return sct_status.status == net::ct::SCT_STATUS_OK;
-}
-
// Returns the PreviewsState for enabled previews after requesting it from
// the delegate. The PreviewsState is a bitmask of potentially several
// Previews optimizations that are initially enabled for a navigation.
@@ -605,18 +599,6 @@ void ResourceDispatcherHostImpl::DidReceiveResponse(
void ResourceDispatcherHostImpl::DidFinishLoading(ResourceLoader* loader) {
ResourceRequestInfoImpl* info = loader->GetRequestInfo();
- // Record final result of all resource loads.
- if (info->GetResourceType() == RESOURCE_TYPE_MAIN_FRAME) {
- if (loader->request()->url().SchemeIsCryptographic()) {
- int num_valid_scts = std::count_if(
- loader->request()->ssl_info().signed_certificate_timestamps.begin(),
- loader->request()->ssl_info().signed_certificate_timestamps.end(),
- IsValidatedSCT);
- UMA_HISTOGRAM_COUNTS_100(
- "Net.CertificateTransparency.MainFrameValidSCTCount", num_valid_scts);
- }
- }
-
if (delegate_)
delegate_->RequestComplete(loader->request());
@@ -1078,11 +1060,11 @@ ResourceDispatcherHostImpl::CreateResourceHandler(
requester_info->IsNavigationPreload() ||
requester_info->IsCertificateFetcherForSignedExchange());
// Construct the IPC resource handler.
- std::unique_ptr<ResourceHandler> handler;
- handler = CreateBaseResourceHandler(
- request, url_loader_options, std::move(mojo_request),
- std::move(url_loader_client),
- static_cast<ResourceType>(request_data.resource_type));
+ std::unique_ptr<ResourceHandler> handler =
+ std::make_unique<MojoAsyncResourceHandler>(
+ request, this, std::move(mojo_request), std::move(url_loader_client),
+ static_cast<ResourceType>(request_data.resource_type),
+ url_loader_options);
// Prefetches outlive their child process.
if (request_data.resource_type == RESOURCE_TYPE_PREFETCH) {
@@ -1097,22 +1079,8 @@ ResourceDispatcherHostImpl::CreateResourceHandler(
request, static_cast<ResourceType>(request_data.resource_type),
resource_context, request_data.fetch_request_mode,
static_cast<RequestContextType>(request_data.fetch_request_context_type),
- requester_info->appcache_service(), child_id, route_id,
- std::move(handler));
-}
-
-std::unique_ptr<ResourceHandler>
-ResourceDispatcherHostImpl::CreateBaseResourceHandler(
- net::URLRequest* request,
- uint32_t url_loader_options,
- network::mojom::URLLoaderRequest mojo_request,
- network::mojom::URLLoaderClientPtr url_loader_client,
- ResourceType resource_type) {
- std::unique_ptr<ResourceHandler> handler;
- handler.reset(new MojoAsyncResourceHandler(
- request, this, std::move(mojo_request), std::move(url_loader_client),
- resource_type, url_loader_options));
- return handler;
+ url_loader_options, requester_info->appcache_service(), child_id,
+ route_id, std::move(handler));
}
std::unique_ptr<ResourceHandler>
@@ -1122,6 +1090,7 @@ ResourceDispatcherHostImpl::AddStandardHandlers(
ResourceContext* resource_context,
network::mojom::FetchRequestMode fetch_request_mode,
RequestContextType fetch_request_context_type,
+ uint32_t url_loader_options,
AppCacheService* appcache_service,
int child_id,
int route_id,
@@ -1190,9 +1159,11 @@ ResourceDispatcherHostImpl::AddStandardHandlers(
// Note: all ResourceHandler following the MimeSniffingResourceHandler
// should expect OnWillRead to be called *before* OnResponseStarted as
// part of the mime sniffing process.
- handler.reset(new MimeSniffingResourceHandler(
- std::move(handler), this, plugin_service, intercepting_handler, request,
- fetch_request_context_type));
+ if (url_loader_options & network::mojom::kURLLoadOptionSniffMimeType) {
+ handler.reset(new MimeSniffingResourceHandler(
+ std::move(handler), this, plugin_service, intercepting_handler, request,
+ fetch_request_context_type));
+ }
// Add the pre mime sniffing throttles.
handler.reset(new ThrottlingResourceHandler(
@@ -1644,7 +1615,7 @@ void ResourceDispatcherHostImpl::BeginNavigationRequest(
handler = AddStandardHandlers(
new_request.get(), resource_type, resource_context,
network::mojom::FetchRequestMode::kNoCORS,
- info.begin_params->request_context_type,
+ info.begin_params->request_context_type, url_loader_options,
appcache_handle_core ? appcache_handle_core->GetAppCacheService()
: nullptr,
-1, // child_id
@@ -1927,6 +1898,7 @@ net::URLRequest* ResourceDispatcherHostImpl::GetURLRequest(
}
// static
+// This is duplicated in services/network/network_service.cc.
bool ResourceDispatcherHostImpl::LoadInfoIsMoreInteresting(const LoadInfo& a,
const LoadInfo& b) {
// Set |*_uploading_size| to be the size of the corresponding upload body if
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_impl.h b/chromium/content/browser/loader/resource_dispatcher_host_impl.h
index b8a81809fff..ec89329e361 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_impl.h
+++ b/chromium/content/browser/loader/resource_dispatcher_host_impl.h
@@ -29,10 +29,10 @@
#include "base/single_thread_task_runner.h"
#include "base/time/time.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
-#include "content/browser/loader/global_routing_id.h"
#include "content/browser/loader/resource_loader_delegate.h"
#include "content/common/content_export.h"
#include "content/public/browser/global_request_id.h"
+#include "content/public/browser/global_routing_id.h"
#include "content/public/browser/resource_dispatcher_host.h"
#include "content/public/browser/resource_request_info.h"
#include "content/public/browser/stream_handle.h"
@@ -330,6 +330,7 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
private:
class ScheduledResourceRequestAdapter;
+ friend class NetworkServiceClient;
friend class ResourceDispatcherHostTest;
FRIEND_TEST_ALL_PREFIXES(ResourceDispatcherHostTest,
@@ -587,14 +588,6 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
network::mojom::URLLoaderRequest mojo_request,
network::mojom::URLLoaderClientPtr url_loader_client);
- // Creates either MojoAsyncResourceHandler or AsyncResourceHandler.
- std::unique_ptr<ResourceHandler> CreateBaseResourceHandler(
- net::URLRequest* request,
- uint32_t url_loader_options,
- network::mojom::URLLoaderRequest mojo_request,
- network::mojom::URLLoaderClientPtr url_loader_client,
- ResourceType resource_type);
-
// Wraps |handler| in the standard resource handlers for normal resource
// loading and navigation requests. This adds MimeTypeResourceHandler and
// ResourceThrottles.
@@ -604,6 +597,7 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
ResourceContext* resource_context,
network::mojom::FetchRequestMode fetch_request_mode,
RequestContextType fetch_request_context_type,
+ uint32_t url_loader_options,
AppCacheService* appcache_service,
int child_id,
int route_id,
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc b/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc
index d8d744e64ff..38053a77162 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc
+++ b/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc
@@ -17,8 +17,8 @@
#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
-#include "base/task_scheduler/post_task.h"
-#include "base/task_scheduler/task_traits.h"
+#include "base/task/post_task.h"
+#include "base/task/task_traits.h"
#include "base/test/scoped_feature_list.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/unguessable_token.h"
@@ -59,6 +59,7 @@
#include "content/test/test_navigation_url_loader_delegate.h"
#include "mojo/public/cpp/system/data_pipe_utils.h"
#include "net/base/chunked_upload_data_stream.h"
+#include "net/base/completion_once_callback.h"
#include "net/base/elements_upload_data_stream.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
@@ -106,6 +107,7 @@ static network::ResourceRequest CreateResourceRequest(const char* method,
request.resource_type = type;
request.appcache_host_id = kAppCacheNoHostId;
request.should_reset_appcache = false;
+ request.render_frame_id = 0;
request.is_main_frame = true;
request.transition_type = ui::PAGE_TRANSITION_LINK;
request.allow_download = true;
@@ -311,7 +313,7 @@ class URLRequestBigJob : public net::URLRequestSimpleJob {
int GetData(std::string* mime_type,
std::string* charset,
std::string* data,
- const net::CompletionCallback& callback) const override {
+ net::CompletionOnceCallback callback) const override {
*mime_type = "text/plain";
*charset = "UTF-8";
@@ -897,7 +899,7 @@ void ResourceDispatcherHostTest::MakeTestRequestWithRenderFrame(
request.render_frame_id = render_frame_id;
filter_->CreateLoaderAndStart(
std::move(loader_request), render_view_id, request_id,
- network::mojom::kURLLoadOptionNone, request, std::move(client),
+ network::mojom::kURLLoadOptionSniffMimeType, request, std::move(client),
net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
}
@@ -912,7 +914,7 @@ void ResourceDispatcherHostTest::MakeTestRequestWithResourceType(
network::ResourceRequest request = CreateResourceRequest("GET", type, url);
filter->CreateLoaderAndStart(
std::move(loader_request), render_view_id, request_id,
- network::mojom::kURLLoadOptionNone, request, std::move(client),
+ network::mojom::kURLLoadOptionSniffMimeType, request, std::move(client),
net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
}
@@ -1551,9 +1553,9 @@ TEST_F(ResourceDispatcherHostTest, TestProcessCancelDetachedTimesOut) {
// messages.
base::RunLoop run_loop;
base::OneShotTimer timer;
- timer.Start(
- FROM_HERE, base::TimeDelta::FromMilliseconds(210),
- base::Bind(&base::RunLoop::QuitWhenIdle, base::Unretained(&run_loop)));
+ timer.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(210),
+ base::BindOnce(&base::RunLoop::QuitWhenIdle,
+ base::Unretained(&run_loop)));
run_loop.Run();
// The prefetch should be cancelled by now.
@@ -2010,6 +2012,7 @@ TEST_F(ResourceDispatcherHostTest, MimeSniffed) {
client.RunUntilResponseReceived();
EXPECT_EQ("text/html", client.response_head().mime_type);
+ EXPECT_TRUE(client.response_head().did_mime_sniff);
}
// Tests that we don't sniff the mime type when the server provides one.
@@ -2031,6 +2034,7 @@ TEST_F(ResourceDispatcherHostTest, MimeNotSniffed) {
client.RunUntilResponseReceived();
EXPECT_EQ("image/jpeg", client.response_head().mime_type);
+ EXPECT_FALSE(client.response_head().did_mime_sniff);
}
// Tests that we don't sniff the mime type when there is no message body.
diff --git a/chromium/content/browser/loader/resource_hints_impl.cc b/chromium/content/browser/loader/resource_hints_impl.cc
index 3ebe0570196..bdb06548a3a 100644
--- a/chromium/content/browser/loader/resource_hints_impl.cc
+++ b/chromium/content/browser/loader/resource_hints_impl.cc
@@ -102,7 +102,7 @@ int PreresolveUrl(net::URLRequestContextGetter* getter,
resolve_info.set_is_speculative(true);
return resolver->Resolve(
resolve_info, net::IDLE, raw_addresses,
- base::Bind(&OnResolveComplete, base::Passed(&addresses), callback),
+ base::BindOnce(&OnResolveComplete, std::move(addresses), callback),
out_request, net::NetLogWithSource());
}
diff --git a/chromium/content/browser/loader/resource_loader.cc b/chromium/content/browser/loader/resource_loader.cc
index 2435233851b..ff351ba64cf 100644
--- a/chromium/content/browser/loader/resource_loader.cc
+++ b/chromium/content/browser/loader/resource_loader.cc
@@ -87,12 +87,6 @@ void PopulateResourceResponse(
response->head.network_accessed = response_info.network_accessed;
response->head.async_revalidation_requested =
response_info.async_revalidation_requested;
- const content::ResourceRequestInfo* request_info =
- content::ResourceRequestInfo::ForRequest(request);
- if (request_info) {
- response->head.previews_state =
- static_cast<int>(request_info->GetPreviewsState());
- }
if (info->ShouldReportRawHeaders()) {
response->head.raw_request_response_info =
network::BuildRawRequestResponseInfo(*request, raw_request_headers,
diff --git a/chromium/content/browser/loader/resource_request_info_impl.cc b/chromium/content/browser/loader/resource_request_info_impl.cc
index 3db8fd33813..7fe59fe5542 100644
--- a/chromium/content/browser/loader/resource_request_info_impl.cc
+++ b/chromium/content/browser/loader/resource_request_info_impl.cc
@@ -5,13 +5,13 @@
#include "content/browser/loader/resource_request_info_impl.h"
#include "content/browser/frame_host/frame_tree_node.h"
-#include "content/browser/loader/global_routing_id.h"
#include "content/browser/loader/resource_message_filter.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/net/url_request_service_worker_data.h"
#include "content/common/net/url_request_user_data.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/global_request_id.h"
+#include "content/public/browser/global_routing_id.h"
#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/process_type.h"
#include "net/url_request/url_request.h"
@@ -314,6 +314,10 @@ PreviewsState ResourceRequestInfoImpl::GetPreviewsState() const {
return previews_state_;
}
+void ResourceRequestInfoImpl::SetPreviewsState(PreviewsState previews_state) {
+ previews_state_ = previews_state;
+}
+
NavigationUIData* ResourceRequestInfoImpl::GetNavigationUIData() const {
return navigation_ui_data_.get();
}
diff --git a/chromium/content/browser/loader/resource_request_info_impl.h b/chromium/content/browser/loader/resource_request_info_impl.h
index 0bc8ea93804..ec89c14e24b 100644
--- a/chromium/content/browser/loader/resource_request_info_impl.h
+++ b/chromium/content/browser/loader/resource_request_info_impl.h
@@ -96,6 +96,7 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
bool IsDownload() const override;
// Returns a bitmask of potentially several Previews optimizations.
PreviewsState GetPreviewsState() const override;
+ void SetPreviewsState(PreviewsState previews_state) override;
NavigationUIData* GetNavigationUIData() const override;
DevToolsStatus GetDevToolsStatus() const override;
void SetResourceRequestBlockedReason(
diff --git a/chromium/content/browser/loader/resource_requester_info.cc b/chromium/content/browser/loader/resource_requester_info.cc
index 862ff7ff379..f692a6fa920 100644
--- a/chromium/content/browser/loader/resource_requester_info.cc
+++ b/chromium/content/browser/loader/resource_requester_info.cc
@@ -4,6 +4,8 @@
#include "content/browser/loader/resource_requester_info.h"
+#include <utility>
+
#include "base/feature_list.h"
#include "base/logging.h"
#include "content/browser/appcache/chrome_appcache_service.h"
@@ -105,23 +107,16 @@ ResourceRequesterInfo::CreateForDownloadOrPageSave(int child_id) {
scoped_refptr<ResourceRequesterInfo>
ResourceRequesterInfo::CreateForNavigationPreload(
ResourceRequesterInfo* original_request_info) {
- GetContextsCallback get_contexts_callback =
- original_request_info->get_contexts_callback_;
- if (IsBrowserSideNavigationEnabled()) {
- DCHECK(original_request_info->IsBrowserSideNavigation());
- DCHECK(!get_contexts_callback);
- DCHECK(original_request_info->service_worker_context());
- // 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 form ServiceWorkerContext.
- get_contexts_callback =
- base::Bind(&GetContextsCallbackForNavigationPreload,
- scoped_refptr<ServiceWorkerContextWrapper>(
- original_request_info->service_worker_context()));
- } else {
- DCHECK(original_request_info->IsRenderer());
- DCHECK(get_contexts_callback);
- }
+ 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()));
return scoped_refptr<ResourceRequesterInfo>(new ResourceRequesterInfo(
RequesterType::NAVIGATION_PRELOAD, ChildProcessHost::kInvalidUniqueID,
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 9385955b5c5..168eed74072 100644
--- a/chromium/content/browser/loader/url_loader_factory_impl_unittest.cc
+++ b/chromium/content/browser/loader/url_loader_factory_impl_unittest.cc
@@ -149,7 +149,8 @@ TEST_P(URLLoaderFactoryImplTest, GetResponse) {
request.request_initiator = url::Origin::Create(request.url);
factory_->CreateLoaderAndStart(
mojo::MakeRequest(&loader), kRoutingId, kRequestId,
- network::mojom::kURLLoadOptionNone, request, client.CreateInterfacePtr(),
+ network::mojom::kURLLoadOptionSniffMimeType, request,
+ client.CreateInterfacePtr(),
net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
ASSERT_FALSE(client.has_received_response());
@@ -224,8 +225,9 @@ TEST_P(URLLoaderFactoryImplTest, GetFailedResponse) {
// Need to set same-site |request_initiator| for non main frame type request.
request.request_initiator = url::Origin::Create(request.url);
factory_->CreateLoaderAndStart(
- mojo::MakeRequest(&loader), 2, 1, network::mojom::kURLLoadOptionNone,
- request, client.CreateInterfacePtr(),
+ mojo::MakeRequest(&loader), 2, 1,
+ network::mojom::kURLLoadOptionSniffMimeType, request,
+ client.CreateInterfacePtr(),
net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
client.RunUntilComplete();
@@ -253,8 +255,9 @@ TEST_P(URLLoaderFactoryImplTest, GetFailedResponse2) {
// Need to set same-site |request_initiator| for non main frame type request.
request.request_initiator = url::Origin::Create(request.url);
factory_->CreateLoaderAndStart(
- mojo::MakeRequest(&loader), 2, 1, network::mojom::kURLLoadOptionNone,
- request, client.CreateInterfacePtr(),
+ mojo::MakeRequest(&loader), 2, 1,
+ network::mojom::kURLLoadOptionSniffMimeType, request,
+ client.CreateInterfacePtr(),
net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
client.RunUntilComplete();
@@ -281,8 +284,9 @@ TEST_P(URLLoaderFactoryImplTest, InvalidURL) {
request.request_initiator = url::Origin::Create(request.url);
ASSERT_FALSE(request.url.is_valid());
factory_->CreateLoaderAndStart(
- mojo::MakeRequest(&loader), 2, 1, network::mojom::kURLLoadOptionNone,
- request, client.CreateInterfacePtr(),
+ mojo::MakeRequest(&loader), 2, 1,
+ network::mojom::kURLLoadOptionSniffMimeType, request,
+ client.CreateInterfacePtr(),
net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
client.RunUntilComplete();
@@ -310,8 +314,9 @@ TEST_P(URLLoaderFactoryImplTest, ShouldNotRequestURL) {
// Need to set same-site |request_initiator| for non main frame type request.
request.request_initiator = url::Origin::Create(request.url);
factory_->CreateLoaderAndStart(
- mojo::MakeRequest(&loader), 2, 1, network::mojom::kURLLoadOptionNone,
- request, client.CreateInterfacePtr(),
+ mojo::MakeRequest(&loader), 2, 1,
+ network::mojom::kURLLoadOptionSniffMimeType, request,
+ client.CreateInterfacePtr(),
net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
client.RunUntilComplete();
@@ -343,7 +348,8 @@ TEST_P(URLLoaderFactoryImplTest, OnTransferSizeUpdated) {
request.report_raw_headers = true;
factory_->CreateLoaderAndStart(
mojo::MakeRequest(&loader), kRoutingId, kRequestId,
- network::mojom::kURLLoadOptionNone, request, client.CreateInterfacePtr(),
+ network::mojom::kURLLoadOptionSniffMimeType, request,
+ client.CreateInterfacePtr(),
net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
client.RunUntilComplete();
@@ -403,7 +409,8 @@ TEST_P(URLLoaderFactoryImplTest, CancelFromRenderer) {
request.request_initiator = url::Origin::Create(request.url);
factory_->CreateLoaderAndStart(
mojo::MakeRequest(&loader), kRoutingId, kRequestId,
- network::mojom::kURLLoadOptionNone, request, client.CreateInterfacePtr(),
+ network::mojom::kURLLoadOptionSniffMimeType, request,
+ client.CreateInterfacePtr(),
net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
base::RunLoop().RunUntilIdle();
diff --git a/chromium/content/browser/locks/lock_manager.cc b/chromium/content/browser/locks/lock_manager.cc
index a7768d01d7b..dc5384dbf53 100644
--- a/chromium/content/browser/locks/lock_manager.cc
+++ b/chromium/content/browser/locks/lock_manager.cc
@@ -287,7 +287,7 @@ void LockManager::RequestLock(const std::string& name,
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (wait == WaitMode::PREEMPT && mode != LockMode::EXCLUSIVE) {
- mojo::ReportBadMessage("Invalid option combinaton");
+ mojo::ReportBadMessage("Invalid option combination");
return;
}
diff --git a/chromium/content/browser/mach_broker_mac.mm b/chromium/content/browser/mach_broker_mac.mm
index 9b0da7da02f..21d1a5caf2f 100644
--- a/chromium/content/browser/mach_broker_mac.mm
+++ b/chromium/content/browser/mach_broker_mac.mm
@@ -8,6 +8,7 @@
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/logging.h"
+#include "content/common/content_constants_internal.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_data.h"
#include "content/public/browser/render_process_host.h"
@@ -15,15 +16,6 @@
namespace content {
-namespace {
-const char kBootstrapName[] = "rohitfork";
-}
-
-// static
-bool MachBroker::ChildSendTaskPortToParent() {
- return base::MachPortBroker::ChildSendTaskPortToParent(kBootstrapName);
-}
-
MachBroker* MachBroker::GetInstance() {
return base::Singleton<MachBroker,
base::LeakySingletonTraits<MachBroker>>::get();
@@ -88,10 +80,10 @@ std::string MachBroker::GetMachPortName() {
const base::CommandLine* command_line =
base::CommandLine::ForCurrentProcess();
const bool is_child = command_line->HasSwitch(switches::kProcessType);
- return base::MachPortBroker::GetMachPortName(kBootstrapName, is_child);
+ return base::MachPortBroker::GetMachPortName(kMachBootstrapName, is_child);
}
-MachBroker::MachBroker() : initialized_(false), broker_(kBootstrapName) {
+MachBroker::MachBroker() : initialized_(false), broker_(kMachBootstrapName) {
broker_.AddObserver(this);
}
diff --git a/chromium/content/browser/mach_broker_mac_unittest.cc b/chromium/content/browser/mach_broker_mac_unittest.cc
index 261f500a563..329ae496ff4 100644
--- a/chromium/content/browser/mach_broker_mac_unittest.cc
+++ b/chromium/content/browser/mach_broker_mac_unittest.cc
@@ -5,10 +5,12 @@
#include "content/browser/mach_broker_mac.h"
#include "base/command_line.h"
+#include "base/mac/mach_port_broker.h"
#include "base/synchronization/lock.h"
#include "base/synchronization/waitable_event.h"
#include "base/test/multiprocess_test.h"
#include "base/test/test_timeouts.h"
+#include "content/common/content_constants_internal.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/multiprocess_func_list.h"
@@ -77,7 +79,7 @@ class MachBrokerTest : public testing::Test,
};
MULTIPROCESS_TEST_MAIN(MachBrokerTestChild) {
- CHECK(MachBroker::ChildSendTaskPortToParent());
+ CHECK(base::MachPortBroker::ChildSendTaskPortToParent(kMachBootstrapName));
return 0;
}
diff --git a/chromium/content/browser/media/android/browser_media_player_manager.h b/chromium/content/browser/media/android/browser_media_player_manager.h
index aaaf4ccb74f..f942adc545b 100644
--- a/chromium/content/browser/media/android/browser_media_player_manager.h
+++ b/chromium/content/browser/media/android/browser_media_player_manager.h
@@ -24,9 +24,6 @@
struct MediaPlayerHostMsg_Initialize_Params;
namespace content {
-#if !defined(USE_AURA)
-class ContentViewCore;
-#endif
class RenderFrameHost;
class WebContents;
@@ -50,10 +47,6 @@ class CONTENT_EXPORT BrowserMediaPlayerManager
// Returns nullptr if no factory was registered.
static BrowserMediaPlayerManager* Create(RenderFrameHost* rfh);
-#if !defined(USE_AURA)
- ContentViewCore* GetContentViewCore() const;
-#endif
-
~BrowserMediaPlayerManager() override;
// Called when browser player wants the renderer media element to seek.
@@ -164,12 +157,6 @@ class CONTENT_EXPORT BrowserMediaPlayerManager
// will release its resources later.
ActivePlayerMap active_players_;
- // Player ID of the fullscreen media player.
- int fullscreen_player_id_;
-
- // Whether the fullscreen player has been Release()-d.
- bool fullscreen_player_is_released_;
-
WebContents* const web_contents_;
// Object for retrieving resources media players.
diff --git a/chromium/content/browser/media/android/media_player_renderer_web_contents_observer.cc b/chromium/content/browser/media/android/media_player_renderer_web_contents_observer.cc
index e5199578da9..82bd10ea55f 100644
--- a/chromium/content/browser/media/android/media_player_renderer_web_contents_observer.cc
+++ b/chromium/content/browser/media/android/media_player_renderer_web_contents_observer.cc
@@ -6,9 +6,6 @@
#include "content/browser/media/android/media_player_renderer.h"
-DEFINE_WEB_CONTENTS_USER_DATA_KEY(
- content::MediaPlayerRendererWebContentsObserver);
-
namespace content {
MediaPlayerRendererWebContentsObserver::MediaPlayerRendererWebContentsObserver(
diff --git a/chromium/content/browser/media/android/media_resource_getter_impl.cc b/chromium/content/browser/media/android/media_resource_getter_impl.cc
index 2633945e003..74a94dfa97d 100644
--- a/chromium/content/browser/media/android/media_resource_getter_impl.cc
+++ b/chromium/content/browser/media/android/media_resource_getter_impl.cc
@@ -8,7 +8,7 @@
#include "base/macros.h"
#include "base/path_service.h"
#include "base/single_thread_task_runner.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/fileapi/browser_file_system_helper.h"
#include "content/browser/resource_context_impl.h"
diff --git a/chromium/content/browser/media/audio_input_stream_broker.cc b/chromium/content/browser/media/audio_input_stream_broker.cc
index b8cc22b65e5..a93d2ca90f1 100644
--- a/chromium/content/browser/media/audio_input_stream_broker.cc
+++ b/chromium/content/browser/media/audio_input_stream_broker.cc
@@ -35,6 +35,7 @@ AudioInputStreamBroker::AudioInputStreamBroker(
const media::AudioParameters& params,
uint32_t shared_memory_count,
bool enable_agc,
+ audio::mojom::AudioProcessingConfigPtr processing_config,
AudioStreamBroker::DeleterCallback deleter,
mojom::RendererAudioInputStreamFactoryClientPtr renderer_factory_client)
: AudioStreamBroker(render_process_id, render_frame_id),
@@ -43,6 +44,7 @@ AudioInputStreamBroker::AudioInputStreamBroker(
shared_memory_count_(shared_memory_count),
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) {
@@ -159,6 +161,7 @@ void AudioInputStreamBroker::CreateStream(
log_component_id, render_process_id(), render_frame_id()),
device_id_, params_, shared_memory_count_, enable_agc_,
mojo::WrapReadOnlySharedMemoryRegion(std::move(key_press_count_buffer)),
+ std::move(processing_config_),
base::BindOnce(&AudioInputStreamBroker::StreamCreated,
weak_ptr_factory_.GetWeakPtr(), std::move(stream)));
}
diff --git a/chromium/content/browser/media/audio_input_stream_broker.h b/chromium/content/browser/media/audio_input_stream_broker.h
index 910453c4977..0ed31a6ee2f 100644
--- a/chromium/content/browser/media/audio_input_stream_broker.h
+++ b/chromium/content/browser/media/audio_input_stream_broker.h
@@ -15,6 +15,7 @@
#include "media/base/audio_parameters.h"
#include "media/mojo/interfaces/audio_input_stream.mojom.h"
#include "mojo/public/cpp/bindings/binding.h"
+#include "services/audio/public/mojom/audio_processing.mojom.h"
#include "services/audio/public/mojom/stream_factory.mojom.h"
namespace media {
@@ -36,6 +37,7 @@ class CONTENT_EXPORT AudioInputStreamBroker final
const media::AudioParameters& params,
uint32_t shared_memory_count,
bool enable_agc,
+ audio::mojom::AudioProcessingConfigPtr processing_config,
AudioStreamBroker::DeleterCallback deleter,
mojom::RendererAudioInputStreamFactoryClientPtr renderer_factory_client);
@@ -68,6 +70,7 @@ 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_;
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 4adcdff9b3c..b68713ab8fc 100644
--- a/chromium/content/browser/media/audio_input_stream_broker_unittest.cc
+++ b/chromium/content/browser/media/audio_input_stream_broker_unittest.cc
@@ -105,16 +105,18 @@ 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,
- const std::string& device_id,
- const media::AudioParameters& params,
- uint32_t shared_memory_count,
- bool enable_agc,
- mojo::ScopedSharedBufferHandle key_press_count_buffer,
- CreateInputStreamCallback created_callback) final {
+ void CreateInputStream(
+ media::mojom::AudioInputStreamRequest stream_request,
+ media::mojom::AudioInputStreamClientPtr client,
+ media::mojom::AudioInputStreamObserverPtr observer,
+ media::mojom::AudioLogPtr 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 {
// 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);
@@ -144,6 +146,7 @@ struct TestEnvironment {
TestParams(),
kShMemCount,
kEnableAgc,
+ nullptr,
deleter.Get(),
renderer_factory_client.MakePtr())) {}
@@ -166,7 +169,7 @@ TEST(AudioInputStreamBrokerTest, StoresProcessAndFrameId) {
AudioInputStreamBroker broker(
kRenderProcessId, kRenderFrameId, kDeviceId, TestParams(), kShMemCount,
- kEnableAgc, deleter.Get(), renderer_factory_client.MakePtr());
+ kEnableAgc, nullptr, deleter.Get(), renderer_factory_client.MakePtr());
EXPECT_EQ(kRenderProcessId, broker.render_process_id());
EXPECT_EQ(kRenderFrameId, broker.render_frame_id());
diff --git a/chromium/content/browser/media/audio_output_stream_broker.cc b/chromium/content/browser/media/audio_output_stream_broker.cc
index 0d2f3deafe2..1ddd0ad978d 100644
--- a/chromium/content/browser/media/audio_output_stream_broker.cc
+++ b/chromium/content/browser/media/audio_output_stream_broker.cc
@@ -23,12 +23,14 @@ AudioOutputStreamBroker::AudioOutputStreamBroker(
const std::string& output_device_id,
const media::AudioParameters& params,
const base::UnguessableToken& group_id,
+ const base::Optional<base::UnguessableToken>& processing_id,
DeleterCallback deleter,
media::mojom::AudioOutputStreamProviderClientPtr client)
: AudioStreamBroker(render_process_id, render_frame_id),
output_device_id_(output_device_id),
params_(params),
group_id_(group_id),
+ processing_id_(processing_id),
deleter_(std::move(deleter)),
client_(std::move(client)),
observer_(render_process_id, render_frame_id, stream_id),
@@ -94,7 +96,7 @@ void AudioOutputStreamBroker::CreateStream(
MediaInternals::GetInstance()->CreateMojoAudioLog(
media::AudioLogFactory::AudioComponent::AUDIO_OUTPUT_CONTROLLER,
log_component_id, render_process_id(), render_frame_id()),
- output_device_id_, params_, group_id_,
+ output_device_id_, params_, group_id_, processing_id_,
base::BindOnce(&AudioOutputStreamBroker::StreamCreated,
weak_ptr_factory_.GetWeakPtr(), std::move(stream)));
}
diff --git a/chromium/content/browser/media/audio_output_stream_broker.h b/chromium/content/browser/media/audio_output_stream_broker.h
index f2480aa0140..0f044081998 100644
--- a/chromium/content/browser/media/audio_output_stream_broker.h
+++ b/chromium/content/browser/media/audio_output_stream_broker.h
@@ -34,6 +34,7 @@ class CONTENT_EXPORT AudioOutputStreamBroker final : public AudioStreamBroker {
const std::string& output_device_id,
const media::AudioParameters& params,
const base::UnguessableToken& group_id,
+ const base::Optional<base::UnguessableToken>& processing_id,
DeleterCallback deleter,
media::mojom::AudioOutputStreamProviderClientPtr client);
@@ -54,6 +55,7 @@ class CONTENT_EXPORT AudioOutputStreamBroker final : public AudioStreamBroker {
const std::string output_device_id_;
const media::AudioParameters params_;
const base::UnguessableToken group_id_;
+ const base::Optional<base::UnguessableToken> processing_id_;
// Indicates that CreateStream has been called, but not StreamCreated.
bool awaiting_created_ = false;
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 7a9d488e322..0d5ea4b4572 100644
--- a/chromium/content/browser/media/audio_output_stream_broker_unittest.cc
+++ b/chromium/content/browser/media/audio_output_stream_broker_unittest.cc
@@ -115,6 +115,7 @@ class MockStreamFactory : public audio::FakeStreamFactory {
const std::string& output_device_id,
const media::AudioParameters& params,
const base::UnguessableToken& group_id,
+ const base::Optional<base::UnguessableToken>& processing_id,
CreateOutputStreamCallback created_callback) final {
// No way to cleanly exit the test here in case of failure, so use CHECK.
CHECK(stream_request_data_);
@@ -143,6 +144,7 @@ struct TestEnvironment {
kDeviceId,
TestParams(),
group,
+ base::nullopt,
deleter.Get(),
provider_client.MakePtr())) {}
@@ -164,10 +166,10 @@ TEST(AudioOutputStreamBrokerTest, StoresProcessAndFrameId) {
MockDeleterCallback deleter;
StrictMock<MockAudioOutputStreamProviderClient> provider_client;
- AudioOutputStreamBroker broker(kRenderProcessId, kRenderFrameId, kStreamId,
- kDeviceId, TestParams(),
- base::UnguessableToken::Create(),
- deleter.Get(), provider_client.MakePtr());
+ AudioOutputStreamBroker broker(
+ kRenderProcessId, kRenderFrameId, kStreamId, kDeviceId, TestParams(),
+ base::UnguessableToken::Create(), base::nullopt, deleter.Get(),
+ provider_client.MakePtr());
EXPECT_EQ(kRenderProcessId, broker.render_process_id());
EXPECT_EQ(kRenderFrameId, broker.render_frame_id());
diff --git a/chromium/content/browser/media/audio_stream_broker.cc b/chromium/content/browser/media/audio_stream_broker.cc
index 6ff668c3b9e..9894ff13d7c 100644
--- a/chromium/content/browser/media/audio_stream_broker.cc
+++ b/chromium/content/browser/media/audio_stream_broker.cc
@@ -26,13 +26,14 @@ class AudioStreamBrokerFactoryImpl final : public AudioStreamBrokerFactory {
const media::AudioParameters& params,
uint32_t shared_memory_count,
bool enable_agc,
+ audio::mojom::AudioProcessingConfigPtr processing_config,
AudioStreamBroker::DeleterCallback deleter,
mojom::RendererAudioInputStreamFactoryClientPtr renderer_factory_client)
final {
return std::make_unique<AudioInputStreamBroker>(
render_process_id, render_frame_id, device_id, params,
- shared_memory_count, enable_agc, std::move(deleter),
- std::move(renderer_factory_client));
+ shared_memory_count, enable_agc, std::move(processing_config),
+ std::move(deleter), std::move(renderer_factory_client));
}
std::unique_ptr<AudioStreamBroker> CreateAudioLoopbackStreamBroker(
@@ -58,11 +59,12 @@ class AudioStreamBrokerFactoryImpl final : public AudioStreamBrokerFactory {
const std::string& output_device_id,
const media::AudioParameters& params,
const base::UnguessableToken& group_id,
+ const base::Optional<base::UnguessableToken>& processing_id,
AudioStreamBroker::DeleterCallback deleter,
media::mojom::AudioOutputStreamProviderClientPtr client) final {
return std::make_unique<AudioOutputStreamBroker>(
render_process_id, render_frame_id, stream_id, output_device_id, params,
- group_id, std::move(deleter), std::move(client));
+ group_id, processing_id, std::move(deleter), std::move(client));
}
};
diff --git a/chromium/content/browser/media/audio_stream_broker.h b/chromium/content/browser/media/audio_stream_broker.h
index 40af0eac01b..e8deaa11bae 100644
--- a/chromium/content/browser/media/audio_stream_broker.h
+++ b/chromium/content/browser/media/audio_stream_broker.h
@@ -7,6 +7,7 @@
#include <memory>
#include <string>
+#include <utility>
#include "base/callback.h"
#include "base/macros.h"
@@ -15,6 +16,7 @@
#include "content/public/browser/web_contents_observer.h"
#include "media/mojo/interfaces/audio_input_stream.mojom.h"
#include "media/mojo/interfaces/audio_output_stream.mojom.h"
+#include "services/audio/public/mojom/audio_processing.mojom.h"
namespace audio {
namespace mojom {
@@ -103,6 +105,7 @@ class CONTENT_EXPORT AudioStreamBrokerFactory {
const media::AudioParameters& params,
uint32_t shared_memory_count,
bool enable_agc,
+ audio::mojom::AudioProcessingConfigPtr processing_config,
AudioStreamBroker::DeleterCallback deleter,
mojom::RendererAudioInputStreamFactoryClientPtr
renderer_factory_client) = 0;
@@ -125,6 +128,7 @@ class CONTENT_EXPORT AudioStreamBrokerFactory {
const std::string& output_device_id,
const media::AudioParameters& params,
const base::UnguessableToken& group_id,
+ const base::Optional<base::UnguessableToken>& processing_id,
AudioStreamBroker::DeleterCallback deleter,
media::mojom::AudioOutputStreamProviderClientPtr client) = 0;
diff --git a/chromium/content/browser/media/audio_stream_monitor.cc b/chromium/content/browser/media/audio_stream_monitor.cc
index 324f3105a21..17b5cb761c6 100644
--- a/chromium/content/browser/media/audio_stream_monitor.cc
+++ b/chromium/content/browser/media/audio_stream_monitor.cc
@@ -212,10 +212,9 @@ void AudioStreamMonitor::MaybeToggle() {
if (should_stop_timer) {
off_timer_.Stop();
} else if (!off_timer_.IsRunning()) {
- off_timer_.Start(
- FROM_HERE,
- off_time - now,
- base::Bind(&AudioStreamMonitor::MaybeToggle, base::Unretained(this)));
+ off_timer_.Start(FROM_HERE, off_time - now,
+ base::BindOnce(&AudioStreamMonitor::MaybeToggle,
+ base::Unretained(this)));
}
}
diff --git a/chromium/content/browser/media/capture/OWNERS b/chromium/content/browser/media/capture/OWNERS
index 31e7db3290b..e909a05d072 100644
--- a/chromium/content/browser/media/capture/OWNERS
+++ b/chromium/content/browser/media/capture/OWNERS
@@ -3,8 +3,8 @@ sergeyu@chromium.org
wez@chromium.org
# For WebRTC desktop capturer
-per-file desktop_capture_device.*=zijiehe@chromium.org
-per-file desktop_capture_device_unittest.cc=zijiehe@chromium.org
+per-file desktop*=braveyao@chromium.org
+per-file screen_capture*=braveyao@chromium.org
per-file image_capture*=mcasas@chromium.org
diff --git a/chromium/content/browser/media/capture/audio_mirroring_manager.cc b/chromium/content/browser/media/capture/audio_mirroring_manager.cc
index 1daaf6bf4d3..32544941366 100644
--- a/chromium/content/browser/media/capture/audio_mirroring_manager.cc
+++ b/chromium/content/browser/media/capture/audio_mirroring_manager.cc
@@ -36,12 +36,11 @@ void AudioMirroringManager::AddDiverter(
}
#endif
routes_.push_back(StreamRoutingState(
- SourceFrameRef(render_process_id, render_frame_id),
- diverter));
+ GlobalFrameRoutingId(render_process_id, render_frame_id), diverter));
// Query existing destinations to see whether to immediately start diverting
// the stream.
- std::set<SourceFrameRef> candidates;
+ std::set<GlobalFrameRoutingId> candidates;
candidates.insert(routes_.back().source_render_frame);
InitiateQueriesToFindNewDestination(nullptr, candidates);
}
@@ -79,7 +78,7 @@ void AudioMirroringManager::StartMirroring(MirroringDestination* destination) {
sessions_.push_back(destination);
}
- std::set<SourceFrameRef> candidates;
+ std::set<GlobalFrameRoutingId> candidates;
// Query the MirroringDestination to see which of the audio streams should be
// diverted.
@@ -103,7 +102,7 @@ void AudioMirroringManager::StopMirroring(MirroringDestination* destination) {
// Stop diverting each audio stream in the mirroring session being stopped.
// Each stopped stream becomes a candidate to be diverted to another
// destination.
- std::set<SourceFrameRef> redivert_candidates;
+ std::set<GlobalFrameRoutingId> redivert_candidates;
for (StreamRoutes::iterator it = routes_.begin(); it != routes_.end(); ++it) {
if (it->destination == destination) {
RouteDivertedFlow(&(*it), nullptr);
@@ -158,7 +157,7 @@ base::UnguessableToken AudioMirroringManager::ToGroupId(int render_process_id,
void AudioMirroringManager::InitiateQueriesToFindNewDestination(
MirroringDestination* old_destination,
- const std::set<SourceFrameRef>& candidates) {
+ const std::set<GlobalFrameRoutingId>& candidates) {
lock_.AssertAcquired();
for (Destinations::const_iterator it = sessions_.begin();
@@ -176,7 +175,7 @@ void AudioMirroringManager::InitiateQueriesToFindNewDestination(
void AudioMirroringManager::UpdateRoutesToDestination(
MirroringDestination* destination,
bool add_only,
- const std::set<SourceFrameRef>& matches,
+ const std::set<GlobalFrameRoutingId>& matches,
bool is_duplicate) {
base::AutoLock scoped_lock(lock_);
@@ -189,7 +188,7 @@ void AudioMirroringManager::UpdateRoutesToDestination(
void AudioMirroringManager::UpdateRoutesToDivertDestination(
MirroringDestination* destination,
bool add_only,
- const std::set<SourceFrameRef>& matches) {
+ const std::set<GlobalFrameRoutingId>& matches) {
lock_.AssertAcquired();
if (std::find(sessions_.begin(), sessions_.end(), destination) ==
@@ -202,7 +201,7 @@ void AudioMirroringManager::UpdateRoutesToDivertDestination(
// Start/stop diverting based on |matches|. Any stopped stream becomes a
// candidate to be diverted to another destination.
- std::set<SourceFrameRef> redivert_candidates;
+ std::set<GlobalFrameRoutingId> redivert_candidates;
for (StreamRoutes::iterator it = routes_.begin(); it != routes_.end(); ++it) {
if (matches.find(it->source_render_frame) != matches.end()) {
// Only change the route if the stream is not already being diverted.
@@ -223,7 +222,7 @@ void AudioMirroringManager::UpdateRoutesToDivertDestination(
void AudioMirroringManager::UpdateRoutesToDuplicateDestination(
MirroringDestination* destination,
bool add_only,
- const std::set<SourceFrameRef>& matches) {
+ const std::set<GlobalFrameRoutingId>& matches) {
lock_.AssertAcquired();
if (std::find(sessions_.begin(), sessions_.end(), destination) ==
@@ -267,18 +266,18 @@ void AudioMirroringManager::RouteDivertedFlow(
if (route->destination) {
DVLOG(1) << "Stop diverting render_process_id:render_frame_id="
- << route->source_render_frame.first << ':'
- << route->source_render_frame.second
+ << route->source_render_frame.child_id << ':'
+ << route->source_render_frame.frame_routing_id
<< " --> MirroringDestination@" << route->destination;
route->diverter->StopDiverting();
route->destination = nullptr;
}
if (new_destination) {
- DVLOG(1) << "Start diverting of render_process_id:render_frame_id="
- << route->source_render_frame.first << ':'
- << route->source_render_frame.second
- << " --> MirroringDestination@" << new_destination;
+ DVLOG(1) << "Start diverting of render_process_id:render_frame_id="
+ << route->source_render_frame.child_id << ':'
+ << route->source_render_frame.frame_routing_id
+ << " --> MirroringDestination@" << new_destination;
route->diverter->StartDiverting(
new_destination->AddInput(route->diverter->GetAudioParameters()));
route->destination = new_destination;
@@ -286,7 +285,7 @@ void AudioMirroringManager::RouteDivertedFlow(
}
AudioMirroringManager::StreamRoutingState::StreamRoutingState(
- const SourceFrameRef& source_frame,
+ const GlobalFrameRoutingId& source_frame,
Diverter* stream_diverter)
: source_render_frame(source_frame),
diverter(stream_diverter),
diff --git a/chromium/content/browser/media/capture/audio_mirroring_manager.h b/chromium/content/browser/media/capture/audio_mirroring_manager.h
index 67ee6fbdc3c..f2c7739a401 100644
--- a/chromium/content/browser/media/capture/audio_mirroring_manager.h
+++ b/chromium/content/browser/media/capture/audio_mirroring_manager.h
@@ -41,6 +41,7 @@
#include "base/synchronization/lock.h"
#include "base/unguessable_token.h"
#include "content/common/content_export.h"
+#include "content/public/browser/global_routing_id.h"
#include "media/audio/audio_source_diverter.h"
namespace media {
@@ -54,10 +55,6 @@ class CONTENT_EXPORT AudioMirroringManager {
// Interface for diverting audio data to an alternative AudioOutputStream.
typedef media::AudioSourceDiverter Diverter;
- // A SourceFrameRef is a RenderFrameHost identified by a <render_process_id,
- // render_frame_id> pair.
- typedef std::pair<int, int> SourceFrameRef;
-
// Interface to be implemented by audio mirroring destinations. See comments
// for StartMirroring() and StopMirroring() below.
class MirroringDestination {
@@ -70,11 +67,12 @@ class CONTENT_EXPORT AudioMirroringManager {
// access to a diverted audio flow versus 2) a duplicate copy of the audio
// flow. |results_callback| must be run on the same thread as the one that
// called QueryForMatches().
- typedef base::Callback<void(const std::set<SourceFrameRef>&, bool)>
+ typedef base::OnceCallback<void(const std::set<GlobalFrameRoutingId>&,
+ bool)>
MatchesCallback;
virtual void QueryForMatches(
- const std::set<SourceFrameRef>& candidates,
- const MatchesCallback& results_callback) = 0;
+ const std::set<GlobalFrameRoutingId>& candidates,
+ MatchesCallback results_callback) = 0;
// Create a consumer of audio data in the format specified by |params|, and
// connect it as an input to mirroring. This is used to provide
@@ -138,7 +136,7 @@ class CONTENT_EXPORT AudioMirroringManager {
struct StreamRoutingState {
// The source render frame associated with the audio stream.
- SourceFrameRef source_render_frame;
+ GlobalFrameRoutingId source_render_frame;
// The diverter for re-routing the audio stream.
Diverter* diverter;
@@ -152,7 +150,7 @@ class CONTENT_EXPORT AudioMirroringManager {
// StopDuplicating() is called to release them.
std::map<MirroringDestination*, media::AudioPushSink*> duplications;
- StreamRoutingState(const SourceFrameRef& source_frame,
+ StreamRoutingState(const GlobalFrameRoutingId& source_frame,
Diverter* stream_diverter);
StreamRoutingState(const StreamRoutingState& other);
~StreamRoutingState();
@@ -165,7 +163,7 @@ class CONTENT_EXPORT AudioMirroringManager {
// |candidates| to be diverted to.
void InitiateQueriesToFindNewDestination(
MirroringDestination* old_destination,
- const std::set<SourceFrameRef>& candidates);
+ const std::set<GlobalFrameRoutingId>& candidates);
// MirroringDestination query callback. |matches| contains all RenderFrame
// sources that will be diverted or duplicated to |destination|.
@@ -175,15 +173,16 @@ class CONTENT_EXPORT AudioMirroringManager {
// destination instead of diverted.
void UpdateRoutesToDestination(MirroringDestination* destination,
bool add_only,
- const std::set<SourceFrameRef>& matches,
+ const std::set<GlobalFrameRoutingId>& matches,
bool is_duplicate);
// |matches| contains all RenderFrame sources that will be diverted to
// |destination|. If |add_only| is false, then any Diverters currently routed
// to |destination| but not found in |matches| will be stopped.
- void UpdateRoutesToDivertDestination(MirroringDestination* destination,
- bool add_only,
- const std::set<SourceFrameRef>& matches);
+ void UpdateRoutesToDivertDestination(
+ MirroringDestination* destination,
+ bool add_only,
+ const std::set<GlobalFrameRoutingId>& matches);
// |matches| contains all RenderFrame sources that will be duplicated to
// |destination|. If |add_only| is false, then any Diverters currently
@@ -191,7 +190,7 @@ class CONTENT_EXPORT AudioMirroringManager {
void UpdateRoutesToDuplicateDestination(
MirroringDestination* destination,
bool add_only,
- const std::set<SourceFrameRef>& matches);
+ const std::set<GlobalFrameRoutingId>& matches);
// Starts diverting audio to the |new_destination|, if not NULL. Otherwise,
// stops diverting audio.
diff --git a/chromium/content/browser/media/capture/audio_mirroring_manager_unittest.cc b/chromium/content/browser/media/capture/audio_mirroring_manager_unittest.cc
index a485e46bf68..d128405139c 100644
--- a/chromium/content/browser/media/capture/audio_mirroring_manager_unittest.cc
+++ b/chromium/content/browser/media/capture/audio_mirroring_manager_unittest.cc
@@ -5,6 +5,7 @@
#include "content/browser/media/capture/audio_mirroring_manager.h"
#include <map>
+#include <memory>
#include <utility>
#include "base/bind.h"
@@ -44,8 +45,6 @@ class MockDiverter : public AudioMirroringManager::Diverter {
class MockMirroringDestination
: public AudioMirroringManager::MirroringDestination {
public:
- typedef AudioMirroringManager::SourceFrameRef SourceFrameRef;
-
MockMirroringDestination(int render_process_id,
int render_frame_id,
bool is_duplication)
@@ -54,27 +53,34 @@ class MockMirroringDestination
query_count_(0),
is_duplication_(is_duplication) {}
- MOCK_METHOD2(QueryForMatches,
- void(const std::set<SourceFrameRef>& candidates,
- const MatchesCallback& results_callback));
+ void QueryForMatches(const std::set<GlobalFrameRoutingId>& candidates,
+ MatchesCallback results_callback) override {
+ // The indirection is needed, because gmock has trouble with move-only
+ // parameters (like |results_callback|).
+ MockedQueryForMatches(candidates, &results_callback);
+ }
+ MOCK_METHOD2(MockedQueryForMatches,
+ void(const std::set<GlobalFrameRoutingId>& candidates,
+ MatchesCallback* results_callback));
+
MOCK_METHOD1(AddInput,
media::AudioOutputStream*(const media::AudioParameters& params));
MOCK_METHOD1(AddPushInput,
media::AudioPushSink*(const media::AudioParameters& params));
- void SimulateQuery(const std::set<SourceFrameRef>& candidates,
- const MatchesCallback& results_callback) {
+ void SimulateQuery(const std::set<GlobalFrameRoutingId>& candidates,
+ MatchesCallback* results_callback) {
++query_count_;
- std::set<SourceFrameRef> result;
- if (candidates.find(SourceFrameRef(render_process_id_, render_frame_id_)) !=
- candidates.end()) {
- result.insert(SourceFrameRef(render_process_id_, render_frame_id_));
+ std::set<GlobalFrameRoutingId> result;
+ if (candidates.find(GlobalFrameRoutingId(
+ render_process_id_, render_frame_id_)) != candidates.end()) {
+ result.insert(GlobalFrameRoutingId(render_process_id_, render_frame_id_));
}
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(results_callback, std::move(result), is_duplication_));
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::BindOnce(std::move(*results_callback),
+ std::move(result), is_duplication_));
}
media::AudioOutputStream* SimulateAddInput(
@@ -157,9 +163,9 @@ class AudioMirroringManagerTest : public testing::Test {
void StartMirroringTo(const std::unique_ptr<MockMirroringDestination>& dest,
int expected_inputs_added,
int expected_push_inputs_added) {
- EXPECT_CALL(*dest, QueryForMatches(_, _))
- .WillRepeatedly(Invoke(dest.get(),
- &MockMirroringDestination::SimulateQuery));
+ EXPECT_CALL(*dest, MockedQueryForMatches(_, _))
+ .WillRepeatedly(
+ Invoke(dest.get(), &MockMirroringDestination::SimulateQuery));
if (expected_inputs_added > 0) {
EXPECT_CALL(*dest, AddInput(Ref(params_)))
.Times(expected_inputs_added)
diff --git a/chromium/content/browser/media/capture/aura_window_video_capture_device.cc b/chromium/content/browser/media/capture/aura_window_video_capture_device.cc
index 93160c08dcf..72b973e16a8 100644
--- a/chromium/content/browser/media/capture/aura_window_video_capture_device.cc
+++ b/chromium/content/browser/media/capture/aura_window_video_capture_device.cc
@@ -4,12 +4,15 @@
#include "content/browser/media/capture/aura_window_video_capture_device.h"
+#include <utility>
+
#include "base/bind.h"
#include "base/location.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "content/browser/media/capture/mouse_cursor_overlay_controller.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/desktop_media_id.h"
#include "media/base/bind_to_current_loop.h"
@@ -31,14 +34,14 @@ class AuraWindowVideoCaptureDevice::WindowTracker
AuraWindowVideoCaptureDevice::WindowTracker> {
public:
WindowTracker(base::WeakPtr<AuraWindowVideoCaptureDevice> device,
- CursorRenderer* cursor_renderer,
+ MouseCursorOverlayController* cursor_controller,
const DesktopMediaID& source_id)
: device_(std::move(device)),
device_task_runner_(base::ThreadTaskRunnerHandle::Get()),
- cursor_renderer_(cursor_renderer),
+ cursor_controller_(cursor_controller),
target_type_(source_id.type) {
DCHECK(device_task_runner_);
- DCHECK(cursor_renderer_);
+ DCHECK(cursor_controller_);
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
@@ -86,10 +89,11 @@ class AuraWindowVideoCaptureDevice::WindowTracker
FROM_HERE,
base::BindOnce(&FrameSinkVideoCaptureDevice::OnTargetChanged, device_,
target_window_->GetFrameSinkId()));
- // Note: CursorRenderer runs on the UI thread. It's also important that
- // SetTargetView() be called in the current stack while |target_window_|
- // is known to be a valid pointer. http://crbug.com/818679
- cursor_renderer_->SetTargetView(target_window_);
+ // Note: The MouseCursorOverlayController runs on the UI thread. It's also
+ // important that SetTargetView() be called in the current stack while
+ // |target_window_| is known to be a valid pointer.
+ // http://crbug.com/818679
+ cursor_controller_->SetTargetView(target_window_);
} else {
device_task_runner_->PostTask(
FROM_HERE,
@@ -110,7 +114,7 @@ class AuraWindowVideoCaptureDevice::WindowTracker
FROM_HERE,
base::BindOnce(&FrameSinkVideoCaptureDevice::OnTargetPermanentlyLost,
device_));
- cursor_renderer_->SetTargetView(nullptr);
+ cursor_controller_->SetTargetView(gfx::NativeView());
}
private:
@@ -120,8 +124,8 @@ class AuraWindowVideoCaptureDevice::WindowTracker
// Owned by FrameSinkVideoCaptureDevice. This will be valid for the life of
// WindowTracker because the WindowTracker deleter task will be posted to the
- // UI thread before the CursorRenderer deleter task.
- CursorRenderer* const cursor_renderer_;
+ // UI thread before the MouseCursorOverlayController deleter task.
+ MouseCursorOverlayController* const cursor_controller_;
const DesktopMediaID::Type target_type_;
@@ -132,7 +136,8 @@ class AuraWindowVideoCaptureDevice::WindowTracker
AuraWindowVideoCaptureDevice::AuraWindowVideoCaptureDevice(
const DesktopMediaID& source_id)
- : tracker_(new WindowTracker(AsWeakPtr(), cursor_renderer(), source_id)) {}
+ : tracker_(new WindowTracker(AsWeakPtr(), cursor_controller(), source_id)) {
+}
AuraWindowVideoCaptureDevice::~AuraWindowVideoCaptureDevice() = default;
diff --git a/chromium/content/browser/media/capture/cursor_renderer.cc b/chromium/content/browser/media/capture/cursor_renderer.cc
deleted file mode 100644
index 6434a15a422..00000000000
--- a/chromium/content/browser/media/capture/cursor_renderer.cc
+++ /dev/null
@@ -1,353 +0,0 @@
-// Copyright (c) 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/media/capture/cursor_renderer.h"
-
-#include <algorithm>
-#include <cmath>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/logging.h"
-#include "base/numerics/safe_conversions.h"
-#include "skia/ext/image_operations.h"
-#include "ui/gfx/geometry/rect.h"
-
-namespace content {
-
-namespace {
-
-inline int clip_byte(int x) {
- return std::max(0, std::min(x, 255));
-}
-
-inline int alpha_blend(int alpha, int src, int dst) {
- return (src * alpha + dst * (255 - alpha)) / 255;
-}
-
-} // namespace
-
-CursorRenderer::CursorRenderer(CursorDisplaySetting cursor_display_setting)
- : cursor_display_setting_(cursor_display_setting),
- cursor_(gfx::NativeCursor()),
- update_scaled_cursor_bitmap_(false),
- mouse_move_behavior_atomic_(NOT_MOVING),
- weak_factory_(this) {
- // CursorRenderer can be constructed on any thread, but thereafter must be
- // used according to class-level comments.
- DETACH_FROM_SEQUENCE(ui_sequence_checker_);
- DETACH_FROM_SEQUENCE(render_sequence_checker_);
-}
-
-CursorRenderer::~CursorRenderer() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(ui_sequence_checker_);
-}
-
-base::WeakPtr<CursorRenderer> CursorRenderer::GetWeakPtr() {
- return weak_factory_.GetWeakPtr();
-}
-
-void CursorRenderer::SnapshotCursorState() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(ui_sequence_checker_);
-
- base::AutoLock auto_lock(lock_);
-
- // In CURSOR_DISPLAYED_ON_MOUSE_MOVEMENT mode, if the user hasn't recently
- // moved nor clicked the mouse, do not render the mouse cursor.
- if (cursor_display_setting_ == CURSOR_DISPLAYED_ON_MOUSE_MOVEMENT &&
- mouse_move_behavior() != RECENTLY_MOVED_OR_CLICKED) {
- view_size_ = gfx::Size();
- return;
- }
-
- // Do not render the mouse cursor if the view is not in the foreground window
- // on the user's desktop.
- if (!IsCapturedViewActive()) {
- view_size_ = gfx::Size();
- return;
- }
-
- // Collect current view size and mouse cursor state.
- view_size_ = GetCapturedViewSize();
- if (view_size_.IsEmpty()) {
- return;
- }
- cursor_position_ = GetCursorPositionInView();
- if (!gfx::Rect(view_size_).Contains(cursor_position_)) {
- view_size_ = gfx::Size();
- return;
- }
- const gfx::NativeCursor cursor = GetLastKnownCursor();
- if (cursor != cursor_ || !cursor_image_.readyToDraw()) {
- cursor_ = cursor;
- cursor_image_ = GetLastKnownCursorImage(&cursor_hot_point_);
- // Force RenderOnVideoFrame() to re-generate its scaled cursor bitmap.
- update_scaled_cursor_bitmap_ = true;
- }
-}
-
-bool CursorRenderer::RenderOnVideoFrame(media::VideoFrame* frame,
- const gfx::Rect& region_in_frame,
- CursorRendererUndoer* undoer) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(render_sequence_checker_);
- DCHECK(frame);
-
- // Grab the |lock_| to read from shared mouse cursor state, and maybe
- // re-render the scaled cursor bitmap.
- gfx::Size view_size;
- gfx::Point cursor_position;
- {
- base::AutoLock auto_lock(lock_);
-
- if (view_size_.IsEmpty() || !cursor_image_.readyToDraw()) {
- return false;
- }
-
- view_size = view_size_;
-
- cursor_position = cursor_position_;
- cursor_position.Offset(-cursor_hot_point_.x(), -cursor_hot_point_.y());
- // |cursor_position| is further modified, below; but the |lock_| need not be
- // held for that.
-
- const int scaled_width =
- base::saturated_cast<int>((static_cast<int64_t>(cursor_image_.width()) *
- region_in_frame.width()) /
- view_size.width());
- const int scaled_height = base::saturated_cast<int>(
- (static_cast<int64_t>(cursor_image_.height()) *
- region_in_frame.height()) /
- view_size.height());
- if (scaled_width <= 0 || scaled_height <= 0) {
- return false;
- }
- if (update_scaled_cursor_bitmap_) {
- scaled_cursor_bitmap_ = SkBitmap();
- update_scaled_cursor_bitmap_ = false;
- }
- if (!scaled_cursor_bitmap_.readyToDraw() ||
- scaled_width != scaled_cursor_bitmap_.width() ||
- scaled_height != scaled_cursor_bitmap_.height()) {
- scaled_cursor_bitmap_ = skia::ImageOperations::Resize(
- cursor_image_, skia::ImageOperations::RESIZE_BEST, scaled_width,
- scaled_height);
- }
- }
-
- // Translate cursor position from view coordinates to video frame content
- // coordinates.
- cursor_position.set_x(base::saturated_cast<int>(
- region_in_frame.x() +
- (static_cast<int64_t>(cursor_position.x()) * region_in_frame.width()) /
- view_size.width()));
- cursor_position.set_y(base::saturated_cast<int>(
- region_in_frame.y() +
- (static_cast<int64_t>(cursor_position.y()) * region_in_frame.height()) /
- view_size.height()));
-
- // Determine the region of the video frame to be modified.
- gfx::Rect rect = gfx::IntersectRects(
- gfx::Rect(cursor_position, gfx::Size(scaled_cursor_bitmap_.width(),
- scaled_cursor_bitmap_.height())),
- frame->visible_rect());
- if (rect.IsEmpty())
- return false;
-
- if (undoer)
- undoer->TakeSnapshot(*frame, rect);
-
- // Render the cursor in the video frame. This loop also performs a simple
- // RGB→YUV color space conversion, with alpha-blended compositing.
- for (int y = rect.y(); y < rect.bottom(); ++y) {
- int cursor_y = y - cursor_position.y();
- uint8_t* yplane = frame->visible_data(media::VideoFrame::kYPlane) +
- y * frame->stride(media::VideoFrame::kYPlane);
- uint8_t* uplane = frame->visible_data(media::VideoFrame::kUPlane) +
- (y / 2) * frame->stride(media::VideoFrame::kUPlane);
- uint8_t* vplane = frame->visible_data(media::VideoFrame::kVPlane) +
- (y / 2) * frame->stride(media::VideoFrame::kVPlane);
- for (int x = rect.x(); x < rect.right(); ++x) {
- int cursor_x = x - cursor_position.x();
- SkColor color = scaled_cursor_bitmap_.getColor(cursor_x, cursor_y);
- int alpha = SkColorGetA(color);
- int color_r = SkColorGetR(color);
- int color_g = SkColorGetG(color);
- int color_b = SkColorGetB(color);
- int color_y = clip_byte(
- ((color_r * 66 + color_g * 129 + color_b * 25 + 128) >> 8) + 16);
- yplane[x] = alpha_blend(alpha, color_y, yplane[x]);
-
- // Only sample U and V at even coordinates.
- // TODO(miu): This isn't right. We should be blending four cursor pixels
- // into each U or V output pixel.
- if ((x % 2 == 0) && (y % 2 == 0)) {
- int color_u = clip_byte(
- ((color_r * -38 + color_g * -74 + color_b * 112 + 128) >> 8) + 128);
- int color_v = clip_byte(
- ((color_r * 112 + color_g * -94 + color_b * -18 + 128) >> 8) + 128);
- uplane[x / 2] = alpha_blend(alpha, color_u, uplane[x / 2]);
- vplane[x / 2] = alpha_blend(alpha, color_v, vplane[x / 2]);
- }
- }
- }
-
- return true;
-}
-
-void CursorRenderer::SetNeedsRedrawCallback(base::RepeatingClosure callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(ui_sequence_checker_);
-
- needs_redraw_callback_ = std::move(callback);
-}
-
-bool CursorRenderer::IsUserInteractingWithView() const {
- return mouse_move_behavior() == RECENTLY_MOVED_OR_CLICKED;
-}
-
-void CursorRenderer::OnMouseMoved(const gfx::Point& location) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(ui_sequence_checker_);
-
- switch (mouse_move_behavior()) {
- case NOT_MOVING:
- set_mouse_move_behavior(STARTING_TO_MOVE);
- mouse_move_start_location_ = location;
- mouse_activity_ended_timer_.Start(
- FROM_HERE, base::TimeDelta::FromSeconds(IDLE_TIMEOUT_SECONDS),
- base::BindRepeating(&CursorRenderer::OnMouseHasGoneIdle,
- base::Unretained(this)));
- break;
- case STARTING_TO_MOVE:
- if (std::abs(location.x() - mouse_move_start_location_.x()) >
- MIN_MOVEMENT_PIXELS ||
- std::abs(location.y() - mouse_move_start_location_.y()) >
- MIN_MOVEMENT_PIXELS) {
- set_mouse_move_behavior(RECENTLY_MOVED_OR_CLICKED);
- mouse_activity_ended_timer_.Reset();
- }
- break;
- case RECENTLY_MOVED_OR_CLICKED:
- mouse_activity_ended_timer_.Reset();
- break;
- }
-
- // If there is sufficient mouse activity, or the cursor should always be
- // displayed, snapshot the cursor state and run the redraw callback to show it
- // at its new location in the video.
- if (mouse_move_behavior() == RECENTLY_MOVED_OR_CLICKED ||
- cursor_display_setting_ == CURSOR_DISPLAYED_ALWAYS) {
- SnapshotCursorState();
- if (!needs_redraw_callback_.is_null()) {
- needs_redraw_callback_.Run();
- }
- }
-}
-
-void CursorRenderer::OnMouseClicked(const gfx::Point& location) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(ui_sequence_checker_);
-
- if (mouse_activity_ended_timer_.IsRunning()) {
- mouse_activity_ended_timer_.Reset();
- } else {
- mouse_activity_ended_timer_.Start(
- FROM_HERE, base::TimeDelta::FromSeconds(IDLE_TIMEOUT_SECONDS),
- base::BindRepeating(&CursorRenderer::OnMouseHasGoneIdle,
- base::Unretained(this)));
- }
- set_mouse_move_behavior(RECENTLY_MOVED_OR_CLICKED);
-
- // Regardless of the |cursor_display_setting_|, snapshot the cursor and run
- // the redraw callback to show it at its current location in the video.
- SnapshotCursorState();
- if (!needs_redraw_callback_.is_null()) {
- needs_redraw_callback_.Run();
- }
-}
-
-void CursorRenderer::OnMouseHasGoneIdle() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(ui_sequence_checker_);
-
- set_mouse_move_behavior(NOT_MOVING);
-
- // The timer has fired to indicate no further mouse activity. It's a good idea
- // to snapshot the cursor and run the redraw callback to ensure it is being
- // presented in the video correctly, whether showing its final location or to
- // remove it from the video.
- SnapshotCursorState();
- if (!needs_redraw_callback_.is_null()) {
- needs_redraw_callback_.Run();
- }
-}
-
-CursorRendererUndoer::CursorRendererUndoer() = default;
-
-CursorRendererUndoer::~CursorRendererUndoer() = default;
-
-CursorRendererUndoer::CursorRendererUndoer(
- CursorRendererUndoer&& other) noexcept = default;
-
-CursorRendererUndoer& CursorRendererUndoer::operator=(
- CursorRendererUndoer&& other) noexcept = default;
-
-namespace {
-
-// Returns the rect of pixels in a Chroma plane affected by the given |rect| in
-// the Luma plane.
-gfx::Rect ToEncompassingChromaRect(const gfx::Rect& rect) {
- const int left = rect.x() / 2;
- const int top = rect.y() / 2;
- const int right = (rect.right() + 1) / 2;
- const int bottom = (rect.bottom() + 1) / 2;
- return gfx::Rect(left, top, right - left, bottom - top);
-}
-
-constexpr size_t kYuvPlanes[] = {media::VideoFrame::kYPlane,
- media::VideoFrame::kUPlane,
- media::VideoFrame::kVPlane};
-
-} // namespace
-
-void CursorRendererUndoer::TakeSnapshot(const media::VideoFrame& frame,
- const gfx::Rect& rect) {
- DCHECK(frame.visible_rect().Contains(rect));
-
- rect_ = rect;
- const gfx::Rect chroma_rect = ToEncompassingChromaRect(rect_);
- snapshot_.resize(rect_.size().GetArea() + 2 * chroma_rect.size().GetArea());
-
- uint8_t* dst = snapshot_.data();
- for (auto plane : kYuvPlanes) {
- const gfx::Rect& plane_rect =
- (plane == media::VideoFrame::kYPlane) ? rect_ : chroma_rect;
- const int stride = frame.stride(plane);
- const uint8_t* src =
- frame.visible_data(plane) + plane_rect.y() * stride + plane_rect.x();
- for (int row = 0; row < plane_rect.height(); ++row) {
- memcpy(dst, src, plane_rect.width());
- src += stride;
- dst += plane_rect.width();
- }
- }
-}
-
-void CursorRendererUndoer::Undo(media::VideoFrame* frame) const {
- DCHECK(frame->visible_rect().Contains(rect_));
-
- const gfx::Rect chroma_rect = ToEncompassingChromaRect(rect_);
-
- const uint8_t* src = snapshot_.data();
- for (auto plane : kYuvPlanes) {
- const gfx::Rect& plane_rect =
- (plane == media::VideoFrame::kYPlane) ? rect_ : chroma_rect;
- const int stride = frame->stride(plane);
- uint8_t* dst =
- frame->visible_data(plane) + plane_rect.y() * stride + plane_rect.x();
- for (int row = 0; row < plane_rect.height(); ++row) {
- memcpy(dst, src, plane_rect.width());
- src += plane_rect.width();
- dst += stride;
- }
- }
-}
-
-} // namespace content
diff --git a/chromium/content/browser/media/capture/cursor_renderer.h b/chromium/content/browser/media/capture/cursor_renderer.h
deleted file mode 100644
index 64409bd5b01..00000000000
--- a/chromium/content/browser/media/capture/cursor_renderer.h
+++ /dev/null
@@ -1,204 +0,0 @@
-// Copyright (c) 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_MEDIA_CAPTURE_CURSOR_RENDERER_H_
-#define CONTENT_BROWSER_MEDIA_CAPTURE_CURSOR_RENDERER_H_
-
-#include <atomic>
-
-#include "base/callback.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/sequence_checker.h"
-#include "base/synchronization/lock.h"
-#include "base/timer/timer.h"
-#include "content/common/content_export.h"
-#include "media/base/video_frame.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-#include "ui/base/cursor/cursor.h"
-#include "ui/gfx/geometry/point.h"
-#include "ui/gfx/geometry/size.h"
-#include "ui/gfx/native_widget_types.h"
-
-namespace content {
-
-class CursorRendererUndoer;
-
-// CursorRenderer is an abstract base class that handles all the
-// non-platform-specific common cursor rendering functionality. In order to
-// track the cursor, the platform-specific implementation will listen to
-// mouse events and this base class will process them.
-//
-// All parts of this class are meant to run on the UI BrowserThread, except for
-// RenderOnVideoFrame() and IsUserInteractingWithView(), which may be called
-// from any thread. It is up to the client code to ensure the CursorRenderer's
-// lifetime while in use across multiple threads.
-class CONTENT_EXPORT CursorRenderer {
- public:
- // Setting to control cursor display based on either mouse movement or always
- // forced to be enabled.
- enum CursorDisplaySetting {
- CURSOR_DISPLAYED_ALWAYS,
- CURSOR_DISPLAYED_ON_MOUSE_MOVEMENT,
- };
-
- static std::unique_ptr<CursorRenderer> Create(CursorDisplaySetting display);
-
- virtual ~CursorRenderer();
-
- // Sets a new target view to monitor for mouse cursor updates.
- virtual void SetTargetView(gfx::NativeView view) = 0;
-
- // Renders cursor on the given video frame within the content region,
- // returning true if |frame| was modified. |undoer| is optional: If provided,
- // it will be updated with state necessary for later undoing the cursor
- // rendering.
- bool RenderOnVideoFrame(media::VideoFrame* frame,
- const gfx::Rect& region_in_frame,
- CursorRendererUndoer* undoer);
-
- // Sets a callback that will be run whenever RenderOnVideoFrame() should be
- // called soon, to update the mouse cursor location or image in the video.
- void SetNeedsRedrawCallback(base::RepeatingClosure callback);
-
- // Returns true if the user has recently interacted with the view.
- bool IsUserInteractingWithView() const;
-
- // Returns a weak pointer.
- base::WeakPtr<CursorRenderer> GetWeakPtr();
-
- protected:
- enum {
- // Minium movement before cursor has been considered intentionally moved by
- // the user.
- MIN_MOVEMENT_PIXELS = 15,
- // Amount of time to elapse with no mouse activity before the cursor should
- // stop showing in the video. Does not apply to CURSOR_DISPLAYED_ALWAYS
- // mode, of course.
- IDLE_TIMEOUT_SECONDS = 2
- };
-
- explicit CursorRenderer(CursorDisplaySetting display);
-
- // Returns true if the captured view is a part of an active application
- // window.
- virtual bool IsCapturedViewActive() = 0;
-
- // Returns the size of the captured view (view coordinates).
- virtual gfx::Size GetCapturedViewSize() = 0;
-
- // Returns the cursor's position within the captured view (view coordinates).
- virtual gfx::Point GetCursorPositionInView() = 0;
-
- // Returns the last-known mouse cursor.
- virtual gfx::NativeCursor GetLastKnownCursor() = 0;
-
- // Returns the image of the last-known mouse cursor and its hotspot.
- virtual SkBitmap GetLastKnownCursorImage(gfx::Point* hot_point) = 0;
-
- // Called by subclasses to report mouse events within the captured view.
- void OnMouseMoved(const gfx::Point& location);
- void OnMouseClicked(const gfx::Point& location);
-
- // Called by the |mouse_activity_ended_timer_| once no mouse events have
- // occurred for IDLE_TIMEOUT_SECONDS. Also, called by subclasses when changing
- // the target view.
- void OnMouseHasGoneIdle();
-
- private:
- friend class CursorRendererAuraTest;
- friend class CursorRendererMacTest;
-
- enum MouseMoveBehavior {
- NOT_MOVING, // Mouse has not moved recently.
- STARTING_TO_MOVE, // Mouse has moved, but not significantly.
- RECENTLY_MOVED_OR_CLICKED, // Sufficient mouse activity present.
- };
-
- // Accessors for |mouse_move_behavior_atomic_|. See comments below.
- MouseMoveBehavior mouse_move_behavior() const {
- return mouse_move_behavior_atomic_.load(std::memory_order_relaxed);
- }
- void set_mouse_move_behavior(MouseMoveBehavior behavior) {
- mouse_move_behavior_atomic_.store(behavior, std::memory_order_relaxed);
- }
-
- // Takes a snapshot of the current mouse cursor state, for use by
- // RenderOnVideoFrame().
- void SnapshotCursorState();
-
- // Controls whether cursor is displayed based on active mouse movement.
- const CursorDisplaySetting cursor_display_setting_;
-
- // Protects members shared by RenderOnVideoFrame() and the rest of the class.
- base::Lock lock_;
-
- // These are updated by SnapshotCursorState(), then later read within
- // RenderOnVideoFrame(). Access is protected by |lock_|.
- gfx::Size view_size_; // Empty means "do not show mouse cursor."
- gfx::Point cursor_position_;
- gfx::NativeCursor cursor_;
- gfx::Point cursor_hot_point_;
- SkBitmap cursor_image_;
- // Flag set to invalidate |scaled_cursor_bitmap_|.
- bool update_scaled_cursor_bitmap_;
-
- // A cache of the current scaled cursor bitmap. This is only accessed by the
- // thread calling RenderOnVideoFrame().
- SkBitmap scaled_cursor_bitmap_;
-
- // Updated in the mouse event handlers and used to decide whether the user is
- // interacting with the view and whether to run the |needs_redraw_callback_|.
- // These do not need to be protected by |lock_| since they are only accessed
- // on the UI BrowserThread.
- gfx::Point mouse_move_start_location_;
- base::OneShotTimer mouse_activity_ended_timer_;
-
- // Updated in the mouse event handlers (on the UI BrowserThread) and read from
- // by IsUserInteractingWithView() (on any thread). This is not protected by
- // |lock_| since strict memory ordering semantics are not necessary, just
- // atomicity between threads. All code should use the accessors to read or set
- // this value.
- std::atomic<MouseMoveBehavior> mouse_move_behavior_atomic_;
-
- // Run whenever the mouse cursor would be rendered differently than when it
- // was rendered in the last video frame.
- base::RepeatingClosure needs_redraw_callback_;
-
- // Everything except the constructor and RenderOnVideoFrame() must be called
- // on the UI BrowserThread.
- SEQUENCE_CHECKER(ui_sequence_checker_);
-
- // RenderOnVideoFrame() must be called on the same thread each time.
- SEQUENCE_CHECKER(render_sequence_checker_);
-
- base::WeakPtrFactory<CursorRenderer> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(CursorRenderer);
-};
-
-// Restores the original content of a VideoFrame, to the point before cursor
-// rendering modified it. See CursorRenderer::RenderOnVideoFrame().
-class CONTENT_EXPORT CursorRendererUndoer {
- public:
- CursorRendererUndoer();
- ~CursorRendererUndoer();
-
- CursorRendererUndoer(CursorRendererUndoer&& other) noexcept;
- CursorRendererUndoer& operator=(CursorRendererUndoer&& other) noexcept;
-
- void TakeSnapshot(const media::VideoFrame& frame, const gfx::Rect& rect);
-
- // Restores the frame content to the point where TakeSnapshot() was last
- // called.
- void Undo(media::VideoFrame* frame) const;
-
- private:
- gfx::Rect rect_;
- std::vector<uint8_t> snapshot_;
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_MEDIA_CAPTURE_CURSOR_RENDERER_H_
diff --git a/chromium/content/browser/media/capture/cursor_renderer_aura.cc b/chromium/content/browser/media/capture/cursor_renderer_aura.cc
deleted file mode 100644
index ec13d0da468..00000000000
--- a/chromium/content/browser/media/capture/cursor_renderer_aura.cc
+++ /dev/null
@@ -1,142 +0,0 @@
-// Copyright (c) 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/media/capture/cursor_renderer_aura.h"
-
-#include "ui/aura/client/screen_position_client.h"
-#include "ui/aura/env.h"
-#include "ui/aura/window.h"
-#include "ui/aura/window_tree_host.h"
-#include "ui/base/cursor/cursors_aura.h"
-#include "ui/events/event_utils.h"
-#include "ui/wm/public/activation_client.h"
-
-namespace content {
-
-// static
-std::unique_ptr<CursorRenderer> CursorRenderer::Create(
- CursorRenderer::CursorDisplaySetting display) {
- return std::make_unique<CursorRendererAura>(display);
-}
-
-CursorRendererAura::CursorRendererAura(CursorDisplaySetting display)
- : CursorRenderer(display) {}
-
-CursorRendererAura::~CursorRendererAura() {
- SetTargetView(nullptr);
-}
-
-void CursorRendererAura::SetTargetView(aura::Window* window) {
- if (window_) {
- window_->RemoveObserver(this);
- window_->RemovePreTargetHandler(this);
- }
- window_ = window;
- OnMouseHasGoneIdle();
- if (window_) {
- window_->AddObserver(this);
- window_->AddPreTargetHandler(this);
- }
-}
-
-bool CursorRendererAura::IsCapturedViewActive() {
- if (!window_) {
- DVLOG(2) << "Skipping update with no window being tracked";
- return false;
- }
-
- // If we are sharing the root window, or namely the whole screen, we will
- // render the mouse cursor. For ordinary window, we only render the mouse
- // cursor when the window is active.
- if (!window_->IsRootWindow()) {
- wm::ActivationClient* activation_client =
- wm::GetActivationClient(window_->GetRootWindow());
- if (!activation_client) {
- DVLOG(2) << "Assume window inactive with invalid activation_client";
- return false;
- }
- aura::Window* active_window = activation_client->GetActiveWindow();
- if (!active_window) {
- DVLOG(2) << "Skipping update as there is no active window";
- return false;
- }
- if (!active_window->Contains(window_)) {
- // Return early if the target window is not active.
- DVLOG(2) << "Skipping update on an inactive window";
- return false;
- }
- }
- return true;
-}
-
-gfx::Size CursorRendererAura::GetCapturedViewSize() {
- if (!window_) {
- return gfx::Size();
- }
-
- const gfx::Rect window_bounds = window_->GetBoundsInScreen();
- const gfx::Size view_size(window_bounds.width(), window_bounds.height());
- return view_size;
-}
-
-gfx::Point CursorRendererAura::GetCursorPositionInView() {
- if (!window_) {
- return gfx::Point(-1, -1);
- }
-
- // Convert from screen coordinates to view coordinates.
- aura::Window* const root_window = window_->GetRootWindow();
- if (!root_window)
- return gfx::Point(-1, -1);
- aura::client::ScreenPositionClient* const client =
- aura::client::GetScreenPositionClient(root_window);
- if (!client)
- return gfx::Point(-1, -1);
- gfx::Point cursor_position = aura::Env::GetInstance()->last_mouse_location();
- client->ConvertPointFromScreen(window_, &cursor_position);
- return cursor_position;
-}
-
-gfx::NativeCursor CursorRendererAura::GetLastKnownCursor() {
- if (!window_) {
- return gfx::NativeCursor();
- }
-
- return window_->GetHost()->last_cursor();
-}
-
-SkBitmap CursorRendererAura::GetLastKnownCursorImage(gfx::Point* hot_point) {
- if (!window_) {
- return SkBitmap();
- }
-
- gfx::NativeCursor cursor = window_->GetHost()->last_cursor();
- *hot_point = cursor.GetHotspot();
- return cursor.GetBitmap();
-}
-
-void CursorRendererAura::OnMouseEvent(ui::MouseEvent* event) {
- gfx::Point mouse_location(event->x(), event->y());
- switch (event->type()) {
- case ui::ET_MOUSE_MOVED:
- OnMouseMoved(mouse_location);
- break;
- case ui::ET_MOUSE_PRESSED:
- case ui::ET_MOUSE_RELEASED:
- case ui::ET_MOUSEWHEEL:
- OnMouseClicked(mouse_location);
- break;
- default:
- return;
- }
-}
-
-void CursorRendererAura::OnWindowDestroying(aura::Window* window) {
- DCHECK_EQ(window_, window);
- window_->RemovePreTargetHandler(this);
- window_->RemoveObserver(this);
- window_ = nullptr;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/media/capture/cursor_renderer_aura.h b/chromium/content/browser/media/capture/cursor_renderer_aura.h
deleted file mode 100644
index 8d825fa8756..00000000000
--- a/chromium/content/browser/media/capture/cursor_renderer_aura.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright (c) 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_MEDIA_CAPTURE_CURSOR_RENDERER_AURA_H_
-#define CONTENT_BROWSER_MEDIA_CAPTURE_CURSOR_RENDERER_AURA_H_
-
-#include "content/browser/media/capture/cursor_renderer.h"
-#include "ui/aura/window.h"
-#include "ui/events/event_handler.h"
-
-namespace content {
-
-class CONTENT_EXPORT CursorRendererAura : public CursorRenderer,
- public ui::EventHandler,
- public aura::WindowObserver {
- public:
- explicit CursorRendererAura(CursorDisplaySetting cursor_display);
- ~CursorRendererAura() final;
-
- // CursorRenderer implementation.
- void SetTargetView(gfx::NativeView window) final;
- bool IsCapturedViewActive() final;
- gfx::Size GetCapturedViewSize() final;
- gfx::Point GetCursorPositionInView() final;
- gfx::NativeCursor GetLastKnownCursor() final;
- SkBitmap GetLastKnownCursorImage(gfx::Point* hot_point) final;
-
- // ui::EventHandler overrides.
- void OnMouseEvent(ui::MouseEvent* event) final;
-
- // aura::WindowObserver overrides.
- void OnWindowDestroying(aura::Window* window) final;
-
- private:
- aura::Window* window_ = nullptr;
-
- DISALLOW_COPY_AND_ASSIGN(CursorRendererAura);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_MEDIA_CAPTURE_CURSOR_RENDERER_AURA_H_
diff --git a/chromium/content/browser/media/capture/cursor_renderer_aura_unittest.cc b/chromium/content/browser/media/capture/cursor_renderer_aura_unittest.cc
deleted file mode 100644
index 4a5209e9985..00000000000
--- a/chromium/content/browser/media/capture/cursor_renderer_aura_unittest.cc
+++ /dev/null
@@ -1,261 +0,0 @@
-// Copyright (c) 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/media/capture/cursor_renderer_aura.h"
-
-#include <stdint.h>
-
-#include <memory>
-
-#include "base/files/file_path.h"
-#include "base/path_service.h"
-#include "base/time/time.h"
-#include "media/base/video_frame.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/aura/env.h"
-#include "ui/aura/test/aura_test_base.h"
-#include "ui/aura/test/test_windows.h"
-#include "ui/aura/window.h"
-#include "ui/base/resource/resource_bundle.h"
-#include "ui/events/event.h"
-#include "ui/events/event_utils.h"
-#include "ui/wm/core/default_activation_client.h"
-#include "ui/wm/core/default_screen_position_client.h"
-#include "ui/wm/core/window_util.h"
-
-namespace content {
-
-using aura::test::AuraTestBase;
-
-class CursorRendererAuraTest : public AuraTestBase {
- public:
- CursorRendererAuraTest() {}
- ~CursorRendererAuraTest() override {}
-
- void SetUp() override {
- AuraTestBase::SetUp();
- // This is needed to avoid duplicate initialization across tests that leads
- // to a failure.
- if (!ui::ResourceBundle::HasSharedInstance()) {
- // Initialize the shared global resource bundle that has bitmap
- // resources needed by CursorRenderer
- base::FilePath pak_file;
- bool r = base::PathService::Get(base::DIR_MODULE, &pak_file);
- DCHECK(r);
- pak_file = pak_file.Append(FILE_PATH_LITERAL("content_shell.pak"));
- ui::ResourceBundle::InitSharedInstanceWithPakPath(pak_file);
- }
-
- window_.reset(aura::test::CreateTestWindowWithBounds(
- gfx::Rect(0, 0, 800, 600), root_window()));
- cursor_renderer_.reset(new CursorRendererAura(
- CursorRenderer::CURSOR_DISPLAYED_ON_MOUSE_MOVEMENT));
- cursor_renderer_->SetTargetView(window_.get());
- new wm::DefaultActivationClient(root_window());
- aura::client::SetScreenPositionClient(root_window(),
- &screen_position_client_);
- wm::ActivateWindow(window_.get());
- }
-
- void TearDown() override {
- aura::client::SetScreenPositionClient(root_window(), nullptr);
- cursor_renderer_.reset();
- window_.reset();
- AuraTestBase::TearDown();
- }
-
- base::TimeTicks Now() { return base::TimeTicks::Now(); }
-
- bool CursorDisplayed() {
- // Request rendering into a dummy video frame. If RenderCursorOnVideoFrame()
- // returns true, then the cursor is being displayed.
- if (!dummy_frame_) {
- constexpr gfx::Size dummy_frame_size = gfx::Size(320, 200);
- dummy_frame_ = media::VideoFrame::CreateZeroInitializedFrame(
- media::PIXEL_FORMAT_I420, dummy_frame_size,
- gfx::Rect(dummy_frame_size), dummy_frame_size, base::TimeDelta());
- }
- return RenderCursorOnVideoFrame(dummy_frame_.get(), nullptr);
- }
-
- bool RenderCursorOnVideoFrame(media::VideoFrame* frame,
- CursorRendererUndoer* undoer) {
- return cursor_renderer_->RenderOnVideoFrame(frame, frame->visible_rect(),
- undoer);
- }
-
- bool IsUserInteractingWithView() {
- return cursor_renderer_->IsUserInteractingWithView();
- }
-
- void MoveMouseCursorWithinWindow() {
- gfx::Point point1(20, 20);
- ui::MouseEvent event1(ui::ET_MOUSE_MOVED, point1, point1, Now(), 0, 0);
- aura::Env::GetInstance()->SetLastMouseLocation(point1);
- cursor_renderer_->OnMouseEvent(&event1);
- gfx::Point point2(60, 60);
- ui::MouseEvent event2(ui::ET_MOUSE_MOVED, point2, point2, Now(), 0, 0);
- aura::Env::GetInstance()->SetLastMouseLocation(point2);
- cursor_renderer_->OnMouseEvent(&event2);
- }
-
- void MoveMouseCursorOutsideWindow() {
- gfx::Point point(1000, 1000);
- ui::MouseEvent event1(ui::ET_MOUSE_MOVED, point, point, Now(), 0, 0);
- aura::Env::GetInstance()->SetLastMouseLocation(point);
- cursor_renderer_->OnMouseEvent(&event1);
- }
-
- void SimulateMouseWentIdle() {
- EXPECT_TRUE(cursor_renderer_->mouse_activity_ended_timer_.IsRunning());
- cursor_renderer_->mouse_activity_ended_timer_.Stop();
- cursor_renderer_->OnMouseHasGoneIdle();
- }
-
- // A very simple test of whether there are any non-zero pixels
- // in the region |rect| within |frame|.
- bool NonZeroPixelsInRegion(scoped_refptr<media::VideoFrame> frame,
- gfx::Rect rect) {
- bool y_found = false, u_found = false, v_found = false;
- for (int y = rect.y(); y < rect.bottom(); ++y) {
- uint8_t* yplane = frame->visible_data(media::VideoFrame::kYPlane) +
- y * frame->stride(media::VideoFrame::kYPlane);
- uint8_t* uplane = frame->visible_data(media::VideoFrame::kUPlane) +
- (y / 2) * frame->stride(media::VideoFrame::kUPlane);
- uint8_t* vplane = frame->visible_data(media::VideoFrame::kVPlane) +
- (y / 2) * frame->stride(media::VideoFrame::kVPlane);
- for (int x = rect.x(); x < rect.right(); ++x) {
- if (yplane[x] != 0)
- y_found = true;
- if (uplane[x / 2])
- u_found = true;
- if (vplane[x / 2])
- v_found = true;
- }
- }
- return (y_found && u_found && v_found);
- }
-
- protected:
- wm::DefaultScreenPositionClient screen_position_client_;
- std::unique_ptr<aura::Window> window_;
- std::unique_ptr<CursorRendererAura> cursor_renderer_;
-
- scoped_refptr<media::VideoFrame> dummy_frame_;
-};
-
-TEST_F(CursorRendererAuraTest, CursorAlwaysDisplayed) {
- // Set up cursor renderer to always display cursor.
- cursor_renderer_.reset(
- new CursorRendererAura(CursorRenderer::CURSOR_DISPLAYED_ALWAYS));
- cursor_renderer_->SetTargetView(window_.get());
-
- // Cursor displayed at start.
- EXPECT_TRUE(CursorDisplayed());
- EXPECT_FALSE(IsUserInteractingWithView());
-
- // Cursor displayed after mouse movement.
- MoveMouseCursorWithinWindow();
- EXPECT_TRUE(CursorDisplayed());
- EXPECT_TRUE(IsUserInteractingWithView());
-
- // Cursor displayed after idle period.
- SimulateMouseWentIdle();
- EXPECT_TRUE(CursorDisplayed());
- EXPECT_FALSE(IsUserInteractingWithView());
-
- // Cursor not displayed with mouse outside the window.
- MoveMouseCursorOutsideWindow();
- EXPECT_FALSE(CursorDisplayed());
-}
-
-TEST_F(CursorRendererAuraTest, CursorDuringMouseMovement) {
- // Cursor not displayed at start.
- EXPECT_FALSE(CursorDisplayed());
- EXPECT_FALSE(IsUserInteractingWithView());
-
- // Cursor displayed after mouse movement.
- MoveMouseCursorWithinWindow();
- EXPECT_TRUE(CursorDisplayed());
- EXPECT_TRUE(IsUserInteractingWithView());
-
- // Cursor not displayed after idle period.
- SimulateMouseWentIdle();
- EXPECT_FALSE(CursorDisplayed());
- EXPECT_FALSE(IsUserInteractingWithView());
-
- // Cursor displayed with mouse movement following idle period.
- MoveMouseCursorWithinWindow();
- EXPECT_TRUE(CursorDisplayed());
- EXPECT_TRUE(IsUserInteractingWithView());
-
- // Cursor not displayed if mouse outside the window
- MoveMouseCursorOutsideWindow();
- EXPECT_FALSE(CursorDisplayed());
-}
-
-TEST_F(CursorRendererAuraTest, CursorOnActiveWindow) {
- // Cursor not displayed at start.
- EXPECT_FALSE(CursorDisplayed());
- EXPECT_FALSE(IsUserInteractingWithView());
-
- // Cursor displayed after mouse movement.
- MoveMouseCursorWithinWindow();
- EXPECT_TRUE(CursorDisplayed());
- EXPECT_TRUE(IsUserInteractingWithView());
-
- // Cursor not be displayed if a second window is activated.
- std::unique_ptr<aura::Window> window2(aura::test::CreateTestWindowWithBounds(
- gfx::Rect(0, 0, 800, 600), root_window()));
- wm::ActivateWindow(window2.get());
- MoveMouseCursorWithinWindow();
- EXPECT_FALSE(CursorDisplayed());
- EXPECT_TRUE(IsUserInteractingWithView());
-
- // Cursor displayed if window activated again.
- wm::ActivateWindow(window_.get());
- MoveMouseCursorWithinWindow();
- EXPECT_TRUE(CursorDisplayed());
- EXPECT_TRUE(IsUserInteractingWithView());
-}
-
-TEST_F(CursorRendererAuraTest, CursorRenderedOnFrame) {
- // Cursor not displayed at start.
- EXPECT_FALSE(CursorDisplayed());
-
- gfx::Size size(800, 600);
- scoped_refptr<media::VideoFrame> frame =
- media::VideoFrame::CreateZeroInitializedFrame(media::PIXEL_FORMAT_I420,
- size, gfx::Rect(size), size,
- base::TimeDelta());
-
- MoveMouseCursorWithinWindow();
- EXPECT_TRUE(CursorDisplayed());
-
- EXPECT_FALSE(NonZeroPixelsInRegion(frame, frame->visible_rect()));
- CursorRendererUndoer undoer;
- EXPECT_TRUE(RenderCursorOnVideoFrame(frame.get(), &undoer));
- EXPECT_TRUE(NonZeroPixelsInRegion(frame, gfx::Rect(50, 50, 70, 70)));
- undoer.Undo(frame.get());
- EXPECT_FALSE(NonZeroPixelsInRegion(frame, frame->visible_rect()));
-}
-
-TEST_F(CursorRendererAuraTest, CursorRenderedOnRootWindow) {
- cursor_renderer_->SetTargetView(root_window());
-
- // Cursor not displayed at start.
- EXPECT_FALSE(CursorDisplayed());
-
- // Cursor displayed after mouse movement.
- MoveMouseCursorWithinWindow();
- EXPECT_TRUE(CursorDisplayed());
-
- // Cursor being displayed even if another window is activated.
- std::unique_ptr<aura::Window> window2(aura::test::CreateTestWindowWithBounds(
- gfx::Rect(0, 0, 800, 600), root_window()));
- wm::ActivateWindow(window2.get());
- EXPECT_TRUE(CursorDisplayed());
-}
-
-} // namespace content
diff --git a/chromium/content/browser/media/capture/cursor_renderer_mac.h b/chromium/content/browser/media/capture/cursor_renderer_mac.h
deleted file mode 100644
index cdf77a03090..00000000000
--- a/chromium/content/browser/media/capture/cursor_renderer_mac.h
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_MEDIA_CAPTURE_CURSOR_RENDERER_MAC_H_
-#define CONTENT_BROWSER_MEDIA_CAPTURE_CURSOR_RENDERER_MAC_H_
-
-#import <AppKit/AppKit.h>
-
-#include "base/mac/scoped_nsobject.h"
-#include "content/browser/media/capture/cursor_renderer.h"
-#import "ui/base/cocoa/tracking_area.h"
-
-@interface CursorRendererMouseTracker : NSObject {
- @private
- ui::ScopedCrTrackingArea trackingArea_;
-
- // The view on which mouse movement is detected.
- base::scoped_nsobject<NSView> capturedView_;
-
- // Runs on any mouse interaction from user.
- base::RepeatingClosure mouseInteractionObserver_;
-}
-
-- (instancetype)initWithView:(NSView*)nsView;
-
-// Register an observer for mouse interaction.
-- (void)registerMouseInteractionObserver:
- (const base::RepeatingClosure&)observer;
-
-@end
-
-namespace content {
-
-class CONTENT_EXPORT CursorRendererMac : public CursorRenderer {
- public:
- explicit CursorRendererMac(CursorDisplaySetting cursor_display);
- ~CursorRendererMac() final;
-
- // CursorRenderer implementation.
- void SetTargetView(gfx::NativeView window) final;
- bool IsCapturedViewActive() final;
- gfx::Size GetCapturedViewSize() final;
- gfx::Point GetCursorPositionInView() final;
- gfx::NativeCursor GetLastKnownCursor() final;
- SkBitmap GetLastKnownCursorImage(gfx::Point* hot_point) final;
-
- private:
- friend class CursorRendererMacTest;
-
- // Called for mouse activity events.
- void OnMouseEvent();
-
- NSView* view_ = nil;
-
- base::scoped_nsobject<CursorRendererMouseTracker> mouse_tracker_;
-
- DISALLOW_COPY_AND_ASSIGN(CursorRendererMac);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_MEDIA_CAPTURE_CURSOR_RENDERER_MAC_H_
diff --git a/chromium/content/browser/media/capture/cursor_renderer_mac.mm b/chromium/content/browser/media/capture/cursor_renderer_mac.mm
deleted file mode 100644
index 800bef2619d..00000000000
--- a/chromium/content/browser/media/capture/cursor_renderer_mac.mm
+++ /dev/null
@@ -1,140 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/media/capture/cursor_renderer_mac.h"
-
-#include <Cocoa/Cocoa.h>
-#include <CoreFoundation/CoreFoundation.h>
-
-#include "base/bind.h"
-#include "base/logging.h"
-#include "base/mac/mac_util.h"
-#include "skia/ext/skia_utils_mac.h"
-#include "ui/gfx/image/image.h"
-
-@implementation CursorRendererMouseTracker
-
-- (instancetype)initWithView:(NSView*)nsView {
- if ((self = [super init])) {
- NSTrackingAreaOptions trackingOptions =
- NSTrackingMouseMoved | NSTrackingMouseEnteredAndExited |
- NSTrackingActiveInKeyWindow | NSTrackingInVisibleRect;
- trackingArea_.reset([[CrTrackingArea alloc] initWithRect:NSZeroRect
- options:trackingOptions
- owner:self
- userInfo:nil]);
- [nsView addTrackingArea:trackingArea_.get()];
- capturedView_.reset([nsView retain]);
- }
- return self;
-}
-
-- (void)stopTracking {
- if (trackingArea_.get()) {
- [capturedView_ removeTrackingArea:trackingArea_.get()];
- trackingArea_.reset();
- capturedView_.reset();
- }
-}
-
-- (void)registerMouseInteractionObserver:
- (const base::RepeatingClosure&)observer {
- mouseInteractionObserver_ = observer;
-}
-
-- (void)mouseMoved:(NSEvent*)theEvent {
- mouseInteractionObserver_.Run();
-}
-
-- (void)mouseEntered:(NSEvent*)theEvent {
- mouseInteractionObserver_.Run();
-}
-
-- (void)mouseExited:(NSEvent*)theEvent {
-}
-
-@end
-
-namespace content {
-
-// static
-std::unique_ptr<CursorRenderer> CursorRenderer::Create(
- CursorRenderer::CursorDisplaySetting display) {
- return std::make_unique<CursorRendererMac>(display);
-}
-
-CursorRendererMac::CursorRendererMac(CursorDisplaySetting display)
- : CursorRenderer(display) {}
-
-CursorRendererMac::~CursorRendererMac() {
- SetTargetView(nil);
-}
-
-void CursorRendererMac::SetTargetView(NSView* view) {
- if (view_) {
- [mouse_tracker_ stopTracking];
- mouse_tracker_.reset();
- }
- view_ = view;
- OnMouseHasGoneIdle();
- if (view_) {
- mouse_tracker_.reset(
- [[CursorRendererMouseTracker alloc] initWithView:view_]);
- [mouse_tracker_
- registerMouseInteractionObserver:base::BindRepeating(
- &CursorRendererMac::OnMouseEvent,
- base::Unretained(this))];
- }
-}
-
-bool CursorRendererMac::IsCapturedViewActive() {
- if (![[view_ window] isKeyWindow]) {
- return false;
- }
- return true;
-}
-
-gfx::Size CursorRendererMac::GetCapturedViewSize() {
- NSRect frame_rect = [view_ bounds];
- return gfx::Size(frame_rect.size.width, frame_rect.size.height);
-}
-
-gfx::Point CursorRendererMac::GetCursorPositionInView() {
- // Mouse location in window co-ordinates.
- NSPoint mouse_window_location =
- [view_ window].mouseLocationOutsideOfEventStream;
- // Mouse location with respect to the view within the window.
- NSPoint mouse_view_location =
- [view_ convertPoint:mouse_window_location fromView:nil];
-
- // Invert y coordinate to unify with Aura.
- gfx::Point cursor_position_in_view(
- mouse_view_location.x,
- GetCapturedViewSize().height() - mouse_view_location.y);
-
- return cursor_position_in_view;
-}
-
-gfx::NativeCursor CursorRendererMac::GetLastKnownCursor() {
- // Grab system cursor.
- return [NSCursor currentSystemCursor];
-}
-
-SkBitmap CursorRendererMac::GetLastKnownCursorImage(gfx::Point* hot_point) {
- // Grab system cursor.
- NSCursor* nscursor = [NSCursor currentSystemCursor];
- NSImage* nsimage = [nscursor image];
- NSPoint nshotspot = [nscursor hotSpot];
-
- *hot_point = gfx::Point(nshotspot.x, nshotspot.y);
- return skia::NSImageToSkBitmapWithColorSpace(
- nsimage, /*is_opaque=*/false, base::mac::GetSystemColorSpace());
-}
-
-void CursorRendererMac::OnMouseEvent() {
- // Update cursor movement info to CursorRenderer.
- OnMouseMoved(GetCursorPositionInView());
-}
-
-} // namespace content
diff --git a/chromium/content/browser/media/capture/cursor_renderer_mac_unittest.mm b/chromium/content/browser/media/capture/cursor_renderer_mac_unittest.mm
deleted file mode 100644
index 68f70d37be6..00000000000
--- a/chromium/content/browser/media/capture/cursor_renderer_mac_unittest.mm
+++ /dev/null
@@ -1,227 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/media/capture/cursor_renderer_mac.h"
-
-#include <Cocoa/Cocoa.h>
-
-#include "base/mac/scoped_nsobject.h"
-#include "base/test/scoped_task_environment.h"
-#include "base/time/time.h"
-#include "media/base/video_frame.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/base/test/cocoa_helper.h"
-#include "ui/gfx/mac/coordinate_conversion.h"
-
-namespace content {
-
-const int kTestViewWidth = 320;
-const int kTestViewHeight = 240;
-
-CGEventRef myCGEventCallback(CGEventTapProxy proxy,
- CGEventType type,
- CGEventRef event,
- void* refcon) {
- // Paranoid sanity check.
- if (type != kCGEventMouseMoved)
- return event;
- // Discard mouse-moved event.
- return NULL;
-}
-
-class CursorRendererMacTest : public ui::CocoaTest {
- public:
- CursorRendererMacTest() {}
- ~CursorRendererMacTest() override {}
-
- void SetUp() override {
- ui::CocoaTest::SetUp();
- base::scoped_nsobject<NSView> view([[NSView alloc]
- initWithFrame:NSMakeRect(0, 0, kTestViewWidth, kTestViewHeight)]);
- view_ = view.get();
- [[test_window() contentView] addSubview:view_];
- cursor_renderer_.reset(new CursorRendererMac(
- CursorRenderer::CURSOR_DISPLAYED_ON_MOUSE_MOVEMENT));
- cursor_renderer_->SetTargetView(view_);
- // Dis-associate mouse and cursor.
- StartEventTap();
- [test_window() setPretendIsKeyWindow:YES];
- }
-
- void TearDown() override {
- StopEventTap();
- cursor_renderer_.reset();
- ui::CocoaTest::TearDown();
- }
-
- bool CursorDisplayed() {
- // Request rendering into a dummy video frame. If RenderCursorOnVideoFrame()
- // returns true, then the cursor is being displayed.
- if (!dummy_frame_) {
- constexpr gfx::Size dummy_frame_size = gfx::Size(320, 200);
- dummy_frame_ = media::VideoFrame::CreateZeroInitializedFrame(
- media::PIXEL_FORMAT_I420, dummy_frame_size,
- gfx::Rect(dummy_frame_size), dummy_frame_size, base::TimeDelta());
- }
- return RenderCursorOnVideoFrame(dummy_frame_.get(), nullptr);
- }
-
- bool RenderCursorOnVideoFrame(media::VideoFrame* frame,
- CursorRendererUndoer* undoer) {
- return cursor_renderer_->RenderOnVideoFrame(frame, frame->visible_rect(),
- undoer);
- }
-
- bool IsUserInteractingWithView() {
- return cursor_renderer_->IsUserInteractingWithView();
- }
-
- // Here the |point| is in Aura coordinates (the origin (0, 0) is at top-left
- // of the view). To move the cursor to that point by Quartz Display service,
- // it needs to be converted into Cocoa coordinates (the origin is at
- // bottom-left of the main screen) first, and then info Quartz coordinates
- // (the origin is at top-left of the main display).
- void MoveMouseCursorWithinWindow() {
- CGWarpMouseCursorPosition(
- gfx::ScreenPointToNSPoint(gfx::Point(50, kTestViewHeight - 50)));
- cursor_renderer_->OnMouseEvent();
-
- CGWarpMouseCursorPosition(
- gfx::ScreenPointToNSPoint(gfx::Point(100, kTestViewHeight - 100)));
- cursor_renderer_->OnMouseEvent();
- }
-
- void MoveMouseCursorOutsideWindow() {
- CGWarpMouseCursorPosition(CGPointMake(1000, 200));
- cursor_renderer_->OnMouseEvent();
- }
-
- void SimulateMouseWentIdle() {
- EXPECT_TRUE(cursor_renderer_->mouse_activity_ended_timer_.IsRunning());
- cursor_renderer_->mouse_activity_ended_timer_.Stop();
- cursor_renderer_->OnMouseHasGoneIdle();
- }
-
- // A very simple test of whether there are any non-zero pixels
- // in the region |rect| within |frame|.
- bool NonZeroPixelsInRegion(scoped_refptr<media::VideoFrame> frame,
- gfx::Rect rect) {
- bool y_found = false, u_found = false, v_found = false;
- for (int y = rect.y(); y < rect.bottom(); ++y) {
- uint8_t* yplane = frame->visible_data(media::VideoFrame::kYPlane) +
- y * frame->stride(media::VideoFrame::kYPlane);
- uint8_t* uplane = frame->visible_data(media::VideoFrame::kUPlane) +
- (y / 2) * frame->stride(media::VideoFrame::kUPlane);
- uint8_t* vplane = frame->visible_data(media::VideoFrame::kVPlane) +
- (y / 2) * frame->stride(media::VideoFrame::kVPlane);
- for (int x = rect.x(); x < rect.right(); ++x) {
- if (yplane[x] != 0)
- y_found = true;
- if (uplane[x / 2])
- u_found = true;
- if (vplane[x / 2])
- v_found = true;
- }
- }
- return (y_found && u_found && v_found);
- }
-
- // The test cases here need to move the actual cursor. If the mouse moves the
- // cursor at same time, the cursor position might be unexpected and test cases
- // will fail. So dis-associate mouse and cursor by enabling event tap for
- // mouse-moved event during tests runnning.
- void StartEventTap() {
- // Create an event tap. We are interested in mouse moved.
- CGEventMask eventMask = 1 << kCGEventMouseMoved;
- event_tap_ = CGEventTapCreate(kCGSessionEventTap, kCGHeadInsertEventTap,
- kCGEventTapOptionDefault, eventMask,
- myCGEventCallback, NULL);
- if (event_tap_) {
- // Enable the event tap.
- CGEventTapEnable(event_tap_, true);
- }
- }
-
- void StopEventTap() { CGEventTapEnable(event_tap_, false); }
-
- protected:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
- NSView* view_;
- std::unique_ptr<CursorRendererMac> cursor_renderer_;
-
- CFMachPortRef event_tap_;
-
- scoped_refptr<media::VideoFrame> dummy_frame_;
-};
-
-TEST_F(CursorRendererMacTest, CursorDuringMouseMovement) {
- // Cursor not displayed at start.
- EXPECT_FALSE(CursorDisplayed());
- EXPECT_FALSE(IsUserInteractingWithView());
-
- // Cursor displayed after mouse movement.
- MoveMouseCursorWithinWindow();
- EXPECT_TRUE(CursorDisplayed());
- EXPECT_TRUE(IsUserInteractingWithView());
-
- // Cursor not displayed after idle period.
- SimulateMouseWentIdle();
- EXPECT_FALSE(CursorDisplayed());
- EXPECT_FALSE(IsUserInteractingWithView());
-
- // Cursor displayed with mouse movement following idle period.
- MoveMouseCursorWithinWindow();
- EXPECT_TRUE(CursorDisplayed());
- EXPECT_TRUE(IsUserInteractingWithView());
-
- // Cursor not displayed if mouse outside the window
- MoveMouseCursorOutsideWindow();
- EXPECT_FALSE(CursorDisplayed());
-}
-
-TEST_F(CursorRendererMacTest, CursorOnActiveWindow) {
- // Cursor not displayed at start.
- EXPECT_FALSE(CursorDisplayed());
- EXPECT_FALSE(IsUserInteractingWithView());
-
- // Cursor displayed after mouse movement.
- MoveMouseCursorWithinWindow();
- EXPECT_TRUE(CursorDisplayed());
- EXPECT_TRUE(IsUserInteractingWithView());
-
- // Cursor not displayed if window is not activated.
- [test_window() setPretendIsKeyWindow:NO];
- MoveMouseCursorWithinWindow();
- EXPECT_FALSE(CursorDisplayed());
- EXPECT_TRUE(IsUserInteractingWithView());
-
- // Cursor is displayed again if window is activated again.
- [test_window() setPretendIsKeyWindow:YES];
- MoveMouseCursorWithinWindow();
- EXPECT_TRUE(CursorDisplayed());
- EXPECT_TRUE(IsUserInteractingWithView());
-}
-
-TEST_F(CursorRendererMacTest, CursorRenderedOnFrame) {
- // Cursor not displayed at start.
- EXPECT_FALSE(CursorDisplayed());
-
- gfx::Size size(kTestViewWidth, kTestViewHeight);
- scoped_refptr<media::VideoFrame> frame =
- media::VideoFrame::CreateZeroInitializedFrame(media::PIXEL_FORMAT_I420,
- size, gfx::Rect(size), size,
- base::TimeDelta());
-
- MoveMouseCursorWithinWindow();
- EXPECT_TRUE(CursorDisplayed());
-
- EXPECT_FALSE(NonZeroPixelsInRegion(frame, frame->visible_rect()));
- CursorRendererUndoer undoer;
- EXPECT_TRUE(RenderCursorOnVideoFrame(frame.get(), &undoer));
- EXPECT_TRUE(NonZeroPixelsInRegion(frame, gfx::Rect(50, 50, 70, 70)));
- undoer.Undo(frame.get());
- EXPECT_FALSE(NonZeroPixelsInRegion(frame, frame->visible_rect()));
-}
-
-} // namespace content
diff --git a/chromium/content/browser/media/capture/desktop_capture_device.cc b/chromium/content/browser/media/capture/desktop_capture_device.cc
index 01954292117..50510bdefb7 100644
--- a/chromium/content/browser/media/capture/desktop_capture_device.cc
+++ b/chromium/content/browser/media/capture/desktop_capture_device.cc
@@ -313,7 +313,9 @@ void DesktopCaptureDevice::Core::OnCaptureResult(
IncrementDesktopCaptureCounter(WINDOW_CAPTURER_PERMANENT_ERROR);
}
}
- client_->OnError(FROM_HERE, "The desktop capturer has failed.");
+ client_->OnError(media::VideoCaptureError::
+ kDesktopCaptureDeviceWebrtcDesktopCapturerHasFailed,
+ FROM_HERE, "The desktop capturer has failed.");
}
return;
}
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 96e5f8c1e81..636f20a88bd 100644
--- a/chromium/content/browser/media/capture/desktop_capture_device_unittest.cc
+++ b/chromium/content/browser/media/capture/desktop_capture_device_unittest.cc
@@ -20,6 +20,7 @@
#include "base/test/test_timeouts.h"
#include "base/time/tick_clock.h"
#include "base/time/time.h"
+#include "media/capture/video/mock_video_capture_device_client.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h"
@@ -63,65 +64,6 @@ const uint8_t kFakePixelValue = 1;
// frame test.
const uint8_t kFakePixelValueFirst = 2;
-class MockDeviceClient : public media::VideoCaptureDevice::Client {
- public:
- MOCK_METHOD7(OnIncomingCapturedData,
- void(const uint8_t* data,
- int length,
- const media::VideoCaptureFormat& frame_format,
- int rotation,
- base::TimeTicks reference_time,
- base::TimeDelta timestamp,
- int frame_feedback_id));
- MOCK_METHOD6(OnIncomingCapturedGfxBuffer,
- void(gfx::GpuMemoryBuffer* buffer,
- const media::VideoCaptureFormat& frame_format,
- int clockwise_rotation,
- base::TimeTicks reference_time,
- base::TimeDelta timestamp,
- int frame_feedback_id));
- MOCK_METHOD0(DoReserveOutputBuffer, void(void));
- MOCK_METHOD0(DoOnIncomingCapturedBuffer, void(void));
- MOCK_METHOD0(DoOnIncomingCapturedVideoFrame, void(void));
- MOCK_METHOD0(DoResurrectLastOutputBuffer, void(void));
- MOCK_METHOD2(OnError,
- void(const base::Location& from_here,
- const std::string& reason));
- MOCK_METHOD0(OnStarted, void(void));
-
- // Trampoline methods to workaround GMOCK problems with std::unique_ptr<>.
- Buffer ReserveOutputBuffer(const gfx::Size& dimensions,
- media::VideoPixelFormat format,
- int frame_feedback_id) override {
- EXPECT_TRUE(format == media::PIXEL_FORMAT_I420);
- DoReserveOutputBuffer();
- return Buffer();
- }
- void OnIncomingCapturedBuffer(Buffer buffer,
- const media::VideoCaptureFormat& format,
- base::TimeTicks reference_time,
- base::TimeDelta timestamp) override {
- DoOnIncomingCapturedBuffer();
- }
- void OnIncomingCapturedBufferExt(
- Buffer buffer,
- const media::VideoCaptureFormat& format,
- base::TimeTicks reference_time,
- base::TimeDelta timestamp,
- gfx::Rect visible_rect,
- const media::VideoFrameMetadata& additional_metadata) override {
- DoOnIncomingCapturedVideoFrame();
- }
- Buffer ResurrectLastOutputBuffer(const gfx::Size& dimensions,
- media::VideoPixelFormat format,
- int frame_feedback_id) override {
- EXPECT_TRUE(format == media::PIXEL_FORMAT_I420);
- DoResurrectLastOutputBuffer();
- return Buffer();
- }
- double GetBufferPoolUtilization() const override { return 0.0; }
-};
-
// Creates a DesktopFrame that has the first pixel bytes set to
// kFakePixelValueFirst, and the rest of the bytes set to kFakePixelValue, for
// UnpackedFrame and InvertedFrame verification.
@@ -285,6 +227,24 @@ class DesktopCaptureDeviceTest : public testing::Test {
}
protected:
+ std::unique_ptr<media::MockVideoCaptureDeviceClient>
+ CreateMockVideoCaptureDeviceClient() {
+ auto result = std::make_unique<media::MockVideoCaptureDeviceClient>();
+ ON_CALL(*result, ReserveOutputBuffer(_, _, _))
+ .WillByDefault(
+ Invoke([](const gfx::Size&, media::VideoPixelFormat format, int) {
+ EXPECT_TRUE(format == media::PIXEL_FORMAT_I420);
+ return media::VideoCaptureDevice::Client::Buffer();
+ }));
+ ON_CALL(*result, ResurrectLastOutputBuffer(_, _, _))
+ .WillByDefault(
+ Invoke([](const gfx::Size&, media::VideoPixelFormat format, int) {
+ EXPECT_TRUE(format == media::PIXEL_FORMAT_I420);
+ return media::VideoCaptureDevice::Client::Buffer();
+ }));
+ return result;
+ }
+
std::unique_ptr<DesktopCaptureDevice> capture_device_;
std::unique_ptr<webrtc::DesktopFrame> output_frame_;
};
@@ -309,8 +269,9 @@ TEST_F(DesktopCaptureDeviceTest, MAYBE_Capture) {
base::WaitableEvent::InitialState::NOT_SIGNALED);
int frame_size;
- std::unique_ptr<MockDeviceClient> client(new MockDeviceClient());
- EXPECT_CALL(*client, OnError(_, _)).Times(0);
+ std::unique_ptr<media::MockVideoCaptureDeviceClient> client(
+ CreateMockVideoCaptureDeviceClient());
+ EXPECT_CALL(*client, OnError(_, _, _)).Times(0);
EXPECT_CALL(*client, OnStarted());
EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _, _, _))
.WillRepeatedly(
@@ -347,8 +308,9 @@ TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChangeConstantResolution) {
base::WaitableEvent::ResetPolicy::AUTOMATIC,
base::WaitableEvent::InitialState::NOT_SIGNALED);
- std::unique_ptr<MockDeviceClient> client(new MockDeviceClient());
- EXPECT_CALL(*client, OnError(_, _)).Times(0);
+ std::unique_ptr<media::MockVideoCaptureDeviceClient> client(
+ CreateMockVideoCaptureDeviceClient());
+ EXPECT_CALL(*client, OnError(_, _, _)).Times(0);
EXPECT_CALL(*client, OnStarted());
EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _, _, _))
.WillRepeatedly(
@@ -392,8 +354,9 @@ TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChangeFixedAspectRatio) {
base::WaitableEvent::ResetPolicy::AUTOMATIC,
base::WaitableEvent::InitialState::NOT_SIGNALED);
- std::unique_ptr<MockDeviceClient> client(new MockDeviceClient());
- EXPECT_CALL(*client, OnError(_,_)).Times(0);
+ std::unique_ptr<media::MockVideoCaptureDeviceClient> client(
+ CreateMockVideoCaptureDeviceClient());
+ EXPECT_CALL(*client, OnError(_, _, _)).Times(0);
EXPECT_CALL(*client, OnStarted());
EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _, _, _))
.WillRepeatedly(
@@ -441,8 +404,9 @@ TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChangeVariableResolution) {
base::WaitableEvent::ResetPolicy::AUTOMATIC,
base::WaitableEvent::InitialState::NOT_SIGNALED);
- std::unique_ptr<MockDeviceClient> client(new MockDeviceClient());
- EXPECT_CALL(*client, OnError(_,_)).Times(0);
+ std::unique_ptr<media::MockVideoCaptureDeviceClient> client(
+ CreateMockVideoCaptureDeviceClient());
+ EXPECT_CALL(*client, OnError(_, _, _)).Times(0);
EXPECT_CALL(*client, OnStarted());
EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _, _, _))
.WillRepeatedly(
@@ -492,8 +456,9 @@ TEST_F(DesktopCaptureDeviceTest, UnpackedFrame) {
output_frame_.reset(new webrtc::BasicDesktopFrame(
webrtc::DesktopSize(kTestFrameWidth1, kTestFrameHeight1)));
- std::unique_ptr<MockDeviceClient> client(new MockDeviceClient());
- EXPECT_CALL(*client, OnError(_,_)).Times(0);
+ std::unique_ptr<media::MockVideoCaptureDeviceClient> client(
+ CreateMockVideoCaptureDeviceClient());
+ EXPECT_CALL(*client, OnError(_, _, _)).Times(0);
EXPECT_CALL(*client, OnStarted());
EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _, _, _))
.WillRepeatedly(
@@ -540,8 +505,9 @@ TEST_F(DesktopCaptureDeviceTest, InvertedFrame) {
output_frame_.reset(new webrtc::BasicDesktopFrame(
webrtc::DesktopSize(kTestFrameWidth1, kTestFrameHeight1)));
- std::unique_ptr<MockDeviceClient> client(new MockDeviceClient());
- EXPECT_CALL(*client, OnError(_,_)).Times(0);
+ std::unique_ptr<media::MockVideoCaptureDeviceClient> client(
+ CreateMockVideoCaptureDeviceClient());
+ EXPECT_CALL(*client, OnError(_, _, _)).Times(0);
EXPECT_CALL(*client, OnStarted());
EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _, _, _))
.WillRepeatedly(
@@ -595,8 +561,9 @@ class DesktopCaptureDeviceThrottledTest : public DesktopCaptureDeviceTest {
scoped_refptr<base::TestMockTimeTaskRunner> task_runner;
int nb_frames = 0;
- std::unique_ptr<MockDeviceClient> client(new MockDeviceClient());
- EXPECT_CALL(*client, OnError(_, _)).Times(0);
+ std::unique_ptr<media::MockVideoCaptureDeviceClient> client(
+ CreateMockVideoCaptureDeviceClient());
+ EXPECT_CALL(*client, OnError(_, _, _)).Times(0);
// On started is called from the capture thread.
EXPECT_CALL(*client, OnStarted())
.WillOnce(InvokeWithoutArgs([this, &task_runner] {
diff --git a/chromium/content/browser/media/capture/desktop_streams_registry_impl.cc b/chromium/content/browser/media/capture/desktop_streams_registry_impl.cc
new file mode 100644
index 00000000000..347e00ab4d1
--- /dev/null
+++ b/chromium/content/browser/media/capture/desktop_streams_registry_impl.cc
@@ -0,0 +1,113 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/media/capture/desktop_streams_registry_impl.h"
+
+#include "base/base64.h"
+#include "base/location.h"
+#include "base/macros.h"
+#include "base/no_destructor.h"
+#include "base/stl_util.h"
+#include "base/time/time.h"
+#include "content/public/browser/browser_thread.h"
+#include "crypto/random.h"
+
+namespace {
+
+const int kStreamIdLengthBytes = 16;
+
+const int kApprovedStreamTimeToLiveSeconds = 10;
+
+std::string GenerateRandomStreamId() {
+ char buffer[kStreamIdLengthBytes];
+ crypto::RandBytes(buffer, base::size(buffer));
+ std::string result;
+ base::Base64Encode(base::StringPiece(buffer, base::size(buffer)), &result);
+ return result;
+}
+
+} // namespace
+
+namespace content {
+
+// static
+DesktopStreamsRegistry* DesktopStreamsRegistry::GetInstance() {
+ return DesktopStreamsRegistryImpl::GetInstance();
+}
+
+// static
+DesktopStreamsRegistryImpl* DesktopStreamsRegistryImpl::GetInstance() {
+ static base::NoDestructor<DesktopStreamsRegistryImpl> instance;
+ return instance.get();
+}
+
+DesktopStreamsRegistryImpl::DesktopStreamsRegistryImpl() {}
+DesktopStreamsRegistryImpl::~DesktopStreamsRegistryImpl() {}
+
+std::string DesktopStreamsRegistryImpl::RegisterStream(
+ int render_process_id,
+ int render_frame_id,
+ const GURL& origin,
+ const DesktopMediaID& source,
+ const std::string& extension_name,
+ const DesktopStreamRegistryType type) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ std::string id = GenerateRandomStreamId();
+ DCHECK(approved_streams_.find(id) == approved_streams_.end());
+ ApprovedDesktopMediaStream& stream = approved_streams_[id];
+ stream.render_process_id = render_process_id;
+ stream.render_frame_id = render_frame_id;
+ stream.origin = origin;
+ stream.source = source;
+ stream.extension_name = extension_name;
+ stream.type = type;
+
+ BrowserThread::PostDelayedTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&DesktopStreamsRegistryImpl::CleanupStream,
+ base::Unretained(this), id),
+ base::TimeDelta::FromSeconds(kApprovedStreamTimeToLiveSeconds));
+
+ return id;
+}
+
+DesktopMediaID DesktopStreamsRegistryImpl::RequestMediaForStreamId(
+ const std::string& id,
+ int render_process_id,
+ int render_frame_id,
+ const GURL& origin,
+ std::string* extension_name,
+ const DesktopStreamRegistryType type) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ StreamsMap::iterator it = approved_streams_.find(id);
+
+ // Verify that if there is a request with the specified ID it was created for
+ // the same origin and the same renderer.
+ if (it == approved_streams_.end() ||
+ render_process_id != it->second.render_process_id ||
+ render_frame_id != it->second.render_frame_id ||
+ origin != it->second.origin || type != it->second.type) {
+ return DesktopMediaID();
+ }
+
+ DesktopMediaID result = it->second.source;
+ if (extension_name) {
+ *extension_name = it->second.extension_name;
+ }
+ approved_streams_.erase(it);
+ return result;
+}
+
+void DesktopStreamsRegistryImpl::CleanupStream(const std::string& id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ approved_streams_.erase(id);
+}
+
+DesktopStreamsRegistryImpl::ApprovedDesktopMediaStream::
+ ApprovedDesktopMediaStream()
+ : render_process_id(-1), render_frame_id(-1) {}
+
+} // namespace content \ No newline at end of file
diff --git a/chromium/content/browser/media/capture/desktop_streams_registry_impl.h b/chromium/content/browser/media/capture/desktop_streams_registry_impl.h
new file mode 100644
index 00000000000..baa45e15439
--- /dev/null
+++ b/chromium/content/browser/media/capture/desktop_streams_registry_impl.h
@@ -0,0 +1,66 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_MEDIA_CAPTURE_DESKTOP_STREAMS_REGISTRY_IMPL_H_
+#define CONTENT_BROWSER_MEDIA_CAPTURE_DESKTOP_STREAMS_REGISTRY_IMPL_H_
+
+#include <map>
+#include <string>
+
+#include "content/common/content_export.h"
+#include "content/public/browser/desktop_media_id.h"
+#include "content/public/browser/desktop_streams_registry.h"
+#include "url/gurl.h"
+
+namespace content {
+
+class CONTENT_EXPORT DesktopStreamsRegistryImpl
+ : public DesktopStreamsRegistry {
+ public:
+ DesktopStreamsRegistryImpl();
+ ~DesktopStreamsRegistryImpl() override;
+
+ // Returns the DesktopStreamRegistryImpl singleton.
+ static DesktopStreamsRegistryImpl* GetInstance();
+
+ std::string RegisterStream(int render_process_id,
+ int render_frame_id,
+ const GURL& origin,
+ const DesktopMediaID& source,
+ const std::string& extension_name,
+ const DesktopStreamRegistryType type) override;
+
+ DesktopMediaID RequestMediaForStreamId(
+ const std::string& id,
+ int render_process_id,
+ int render_frame_id,
+ const GURL& origin,
+ std::string* extension_name,
+ const DesktopStreamRegistryType type) override;
+
+ private:
+ // Type used to store list of accepted desktop media streams.
+ struct ApprovedDesktopMediaStream {
+ ApprovedDesktopMediaStream();
+
+ int render_process_id;
+ int render_frame_id;
+ GURL origin;
+ DesktopMediaID source;
+ std::string extension_name;
+ DesktopStreamRegistryType type;
+ };
+ typedef std::map<std::string, ApprovedDesktopMediaStream> StreamsMap;
+
+ // Helper function that removes an expired stream from the registry.
+ void CleanupStream(const std::string& id);
+
+ StreamsMap approved_streams_;
+
+ DISALLOW_COPY_AND_ASSIGN(DesktopStreamsRegistryImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MEDIA_CAPTURE_DESKTOP_STREAMS_REGISTRY_IMPL_H_
diff --git a/chromium/content/browser/media/capture/fake_video_capture_stack.cc b/chromium/content/browser/media/capture/fake_video_capture_stack.cc
index 8bd1c9c1540..11429d03374 100644
--- a/chromium/content/browser/media/capture/fake_video_capture_stack.cc
+++ b/chromium/content/browser/media/capture/fake_video_capture_stack.cc
@@ -48,29 +48,28 @@ class FakeVideoCaptureStack::Receiver : public media::VideoFrameReceiver {
media::mojom::VideoFrameInfoPtr frame_info) final {
const auto it = buffers_.find(buffer_id);
CHECK(it != buffers_.end());
- CHECK(it->second->is_shared_buffer_handle());
- mojo::ScopedSharedBufferHandle& buffer =
- it->second->get_shared_buffer_handle();
- const size_t mapped_size =
- media::VideoCaptureFormat(frame_info->coded_size, 0.0f,
- frame_info->pixel_format)
- .ImageAllocationSize();
- mojo::ScopedSharedBufferMapping mapping = buffer->Map(mapped_size);
- CHECK(mapping.get());
+ CHECK(it->second->is_read_only_shmem_region());
+ base::ReadOnlySharedMemoryMapping mapping =
+ it->second->get_read_only_shmem_region().Map();
+ CHECK(mapping.IsValid());
+ CHECK_LE(media::VideoCaptureFormat(frame_info->coded_size, 0.0f,
+ frame_info->pixel_format)
+ .ImageAllocationSize(),
+ mapping.size());
auto frame = media::VideoFrame::WrapExternalData(
frame_info->pixel_format, frame_info->coded_size,
frame_info->visible_rect, frame_info->visible_rect.size(),
- reinterpret_cast<uint8_t*>(mapping.get()), mapped_size,
- frame_info->timestamp);
+ const_cast<uint8_t*>(static_cast<const uint8_t*>(mapping.memory())),
+ mapping.size(), frame_info->timestamp);
CHECK(frame);
frame->metadata()->MergeInternalValuesFrom(frame_info->metadata);
// This destruction observer will unmap the shared memory when the
// VideoFrame goes out-of-scope.
- frame->AddDestructionObserver(
- base::BindOnce(base::DoNothing::Once<mojo::ScopedSharedBufferMapping>(),
- std::move(mapping)));
+ frame->AddDestructionObserver(base::BindOnce(
+ base::DoNothing::Once<base::ReadOnlySharedMemoryMapping>(),
+ std::move(mapping)));
// This destruction observer will notify the video capture device once all
// downstream code is done using the VideoFrame.
frame->AddDestructionObserver(base::BindOnce(
@@ -86,7 +85,11 @@ class FakeVideoCaptureStack::Receiver : public media::VideoFrameReceiver {
buffers_.erase(it);
}
- void OnError() final { capture_stack_->error_occurred_ = true; }
+ void OnError(media::VideoCaptureError) final {
+ capture_stack_->error_occurred_ = true;
+ }
+
+ void OnFrameDropped(media::VideoCaptureFrameDropReason) final {}
void OnLog(const std::string& message) final {
capture_stack_->log_messages_.push_back(message);
diff --git a/chromium/content/browser/media/capture/frame_sink_video_capture_device.cc b/chromium/content/browser/media/capture/frame_sink_video_capture_device.cc
index e096bf8cc5b..cded50f3122 100644
--- a/chromium/content/browser/media/capture/frame_sink_video_capture_device.cc
+++ b/chromium/content/browser/media/capture/frame_sink_video_capture_device.cc
@@ -14,17 +14,20 @@
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/numerics/safe_conversions.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "components/viz/host/host_frame_sink_manager.h"
#include "content/browser/compositor/surface_utils.h"
+#include "content/browser/media/capture/mouse_cursor_overlay_controller.h"
#include "media/base/bind_to_current_loop.h"
#include "media/capture/mojom/video_capture_types.mojom.h"
-#include "mojo/public/cpp/system/buffer.h"
namespace content {
namespace {
+constexpr int32_t kMouseCursorStackingIndex = 1;
+
// Transfers ownership of an object to a std::unique_ptr with a custom deleter
// that ensures the object is destroyed on the UI BrowserThread.
template <typename T>
@@ -49,10 +52,10 @@ class ScopedFrameDoneHelper
} // namespace
FrameSinkVideoCaptureDevice::FrameSinkVideoCaptureDevice()
- : cursor_renderer_(RescopeToUIThread(CursorRenderer::Create(
- CursorRenderer::CURSOR_DISPLAYED_ON_MOUSE_MOVEMENT))),
+ : cursor_controller_(
+ RescopeToUIThread(std::make_unique<MouseCursorOverlayController>())),
weak_factory_(this) {
- DCHECK(cursor_renderer_);
+ DCHECK(cursor_controller_);
}
FrameSinkVideoCaptureDevice::~FrameSinkVideoCaptureDevice() {
@@ -70,7 +73,8 @@ void FrameSinkVideoCaptureDevice::AllocateAndStartWithReceiver(
// If the device has already ended on a fatal error, abort immediately.
if (fatal_error_message_) {
receiver->OnLog(*fatal_error_message_);
- receiver->OnError();
+ receiver->OnError(media::VideoCaptureError::
+ kFrameSinkVideoCaptureDeviceAleradyEndedOnFatalError);
return;
}
@@ -79,17 +83,6 @@ void FrameSinkVideoCaptureDevice::AllocateAndStartWithReceiver(
DCHECK(!receiver_);
receiver_ = std::move(receiver);
- // Set a callback that will be run whenever the mouse moves, to trampoline
- // back to the device thread and request a refresh frame so that the new mouse
- // cursor location can be drawn in a new video frame.
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(&CursorRenderer::SetNeedsRedrawCallback,
- cursor_renderer_->GetWeakPtr(),
- media::BindToCurrentLoop(base::BindRepeating(
- &FrameSinkVideoCaptureDevice::RequestRefreshFrame,
- weak_factory_.GetWeakPtr()))));
-
// Shutdown the prior capturer, if any.
MaybeStopConsuming();
@@ -112,6 +105,13 @@ void FrameSinkVideoCaptureDevice::AllocateAndStartWithReceiver(
capturer_->ChangeTarget(target_);
}
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&MouseCursorOverlayController::Start,
+ cursor_controller_->GetWeakPtr(),
+ capturer_->CreateOverlay(kMouseCursorStackingIndex),
+ base::ThreadTaskRunnerHandle::Get()));
+
receiver_->OnStarted();
if (!suspend_requested_) {
@@ -153,11 +153,9 @@ void FrameSinkVideoCaptureDevice::Resume() {
void FrameSinkVideoCaptureDevice::StopAndDeAllocate() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- // Discontinue requesting extra video frames to render mouse cursor changes.
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(&CursorRenderer::SetNeedsRedrawCallback,
- cursor_renderer_->GetWeakPtr(), base::RepeatingClosure()));
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&MouseCursorOverlayController::Stop,
+ cursor_controller_->GetWeakPtr()));
MaybeStopConsuming();
capturer_.reset();
@@ -171,17 +169,16 @@ void FrameSinkVideoCaptureDevice::OnUtilizationReport(int frame_feedback_id,
double utilization) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- // Assumption: The "slot" should be valid at this point because this method
- // will always be called before the VideoFrameReceiver signals it is done
- // consuming the frame.
- const auto slot_index = static_cast<size_t>(frame_feedback_id);
- DCHECK_LT(slot_index, slots_.size());
- slots_[slot_index].callbacks->ProvideFeedback(utilization);
+ // Assumption: The mojo InterfacePtr in |frame_callbacks_| should be valid at
+ // this point because this method will always be called before the
+ // VideoFrameReceiver signals it is done consuming the frame.
+ const auto index = static_cast<size_t>(frame_feedback_id);
+ DCHECK_LT(index, frame_callbacks_.size());
+ frame_callbacks_[index]->ProvideFeedback(utilization);
}
void FrameSinkVideoCaptureDevice::OnFrameCaptured(
- mojo::ScopedSharedBufferHandle buffer,
- uint32_t buffer_size,
+ base::ReadOnlySharedMemoryRegion data,
media::mojom::VideoFrameInfoPtr info,
const gfx::Rect& update_rect,
const gfx::Rect& content_rect,
@@ -189,72 +186,50 @@ void FrameSinkVideoCaptureDevice::OnFrameCaptured(
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(callbacks);
- if (!receiver_ || !buffer.is_valid()) {
+ if (!receiver_ || !data.IsValid()) {
callbacks->Done();
return;
}
- // Search for the next available ConsumptionState slot and bind |callbacks|
- // there.
- size_t slot_index = 0;
- for (;; ++slot_index) {
- if (slot_index == slots_.size()) {
- // The growth of |slots_| should be bounded because the
+ // Search for the next available element in |frame_callbacks_| and bind
+ // |callbacks| there.
+ size_t index = 0;
+ for (;; ++index) {
+ if (index == frame_callbacks_.size()) {
+ // The growth of |frame_callbacks_| should be bounded because the
// viz::mojom::FrameSinkVideoCapturer should enforce an upper-bound on the
// number of frames in-flight.
constexpr size_t kMaxInFlightFrames = 32; // Arbitrarily-chosen limit.
- DCHECK_LT(slots_.size(), kMaxInFlightFrames);
- slots_.emplace_back();
+ DCHECK_LT(frame_callbacks_.size(), kMaxInFlightFrames);
+ frame_callbacks_.emplace_back(std::move(callbacks));
break;
}
- if (!slots_[slot_index].callbacks.is_bound()) {
+ if (!frame_callbacks_[index].is_bound()) {
+ frame_callbacks_[index] = std::move(callbacks);
break;
}
}
- ConsumptionState& slot = slots_[slot_index];
- slot.callbacks = std::move(callbacks);
-
- // Render the mouse cursor on the video frame, but first map the shared memory
- // into the current process in order to render the cursor.
- mojo::ScopedSharedBufferMapping mapping = buffer->Map(buffer_size);
- scoped_refptr<media::VideoFrame> frame;
- if (mapping) {
- frame = media::VideoFrame::WrapExternalData(
- info->pixel_format, info->coded_size, info->visible_rect,
- info->visible_rect.size(), static_cast<uint8_t*>(mapping.get()),
- buffer_size, info->timestamp);
- if (frame) {
- frame->AddDestructionObserver(base::BindOnce(
- [](mojo::ScopedSharedBufferMapping mapping) {}, std::move(mapping)));
- if (!cursor_renderer_->RenderOnVideoFrame(frame.get(), content_rect,
- &slot.undoer)) {
- // Release |frame| now, since no "undo cursor rendering" will be needed.
- frame = nullptr;
- }
- }
- }
+ const BufferId buffer_id = static_cast<BufferId>(index);
// Set the INTERACTIVE_CONTENT frame metadata.
media::VideoFrameMetadata modified_metadata;
modified_metadata.MergeInternalValuesFrom(info->metadata);
modified_metadata.SetBoolean(media::VideoFrameMetadata::INTERACTIVE_CONTENT,
- cursor_renderer_->IsUserInteractingWithView());
+ cursor_controller_->IsUserInteractingWithView());
info->metadata = modified_metadata.GetInternalValues().Clone();
// Pass the video frame to the VideoFrameReceiver. This is done by first
// passing the shared memory buffer handle and then notifying it that a new
// frame is ready to be read from the buffer.
- media::mojom::VideoBufferHandlePtr buffer_handle =
- media::mojom::VideoBufferHandle::New();
- buffer_handle->set_shared_buffer_handle(std::move(buffer));
- receiver_->OnNewBuffer(static_cast<BufferId>(slot_index),
- std::move(buffer_handle));
+ receiver_->OnNewBuffer(
+ buffer_id,
+ media::mojom::VideoBufferHandle::NewReadOnlyShmemRegion(std::move(data)));
receiver_->OnFrameReadyInBuffer(
- static_cast<BufferId>(slot_index), slot_index,
+ buffer_id, buffer_id,
std::make_unique<ScopedFrameDoneHelper>(
media::BindToCurrentLoop(base::BindOnce(
&FrameSinkVideoCaptureDevice::OnFramePropagationComplete,
- weak_factory_.GetWeakPtr(), slot_index, std::move(frame)))),
+ weak_factory_.GetWeakPtr(), buffer_id))),
std::move(info));
}
@@ -333,26 +308,20 @@ void FrameSinkVideoCaptureDevice::MaybeStopConsuming() {
}
void FrameSinkVideoCaptureDevice::OnFramePropagationComplete(
- size_t slot_index,
- scoped_refptr<media::VideoFrame> frame) {
+ BufferId buffer_id) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK_LT(slot_index, slots_.size());
// Notify the VideoFrameReceiver that the buffer is no longer valid.
if (receiver_) {
- receiver_->OnBufferRetired(static_cast<BufferId>(slot_index));
- }
-
- // Undo the mouse cursor rendering, if any.
- ConsumptionState& slot = slots_[slot_index];
- if (frame) {
- slot.undoer.Undo(frame.get());
- frame = nullptr;
+ receiver_->OnBufferRetired(buffer_id);
}
// Notify the capturer that consumption of the frame is complete.
- slot.callbacks->Done();
- slot.callbacks.reset();
+ const size_t index = static_cast<size_t>(buffer_id);
+ DCHECK_LT(index, frame_callbacks_.size());
+ auto& callbacks_ptr = frame_callbacks_[index];
+ callbacks_ptr->Done();
+ callbacks_ptr.reset();
}
void FrameSinkVideoCaptureDevice::OnFatalError(std::string message) {
@@ -361,18 +330,11 @@ void FrameSinkVideoCaptureDevice::OnFatalError(std::string message) {
fatal_error_message_ = std::move(message);
if (receiver_) {
receiver_->OnLog(*fatal_error_message_);
- receiver_->OnError();
+ receiver_->OnError(media::VideoCaptureError::
+ kFrameSinkVideoCaptureDeviceEncounteredFatalError);
}
StopAndDeAllocate();
}
-FrameSinkVideoCaptureDevice::ConsumptionState::ConsumptionState() = default;
-FrameSinkVideoCaptureDevice::ConsumptionState::~ConsumptionState() = default;
-FrameSinkVideoCaptureDevice::ConsumptionState::ConsumptionState(
- FrameSinkVideoCaptureDevice::ConsumptionState&& other) noexcept = default;
-FrameSinkVideoCaptureDevice::ConsumptionState&
-FrameSinkVideoCaptureDevice::ConsumptionState::operator=(
- FrameSinkVideoCaptureDevice::ConsumptionState&& other) noexcept = default;
-
} // namespace content
diff --git a/chromium/content/browser/media/capture/frame_sink_video_capture_device.h b/chromium/content/browser/media/capture/frame_sink_video_capture_device.h
index 341248435ea..7a58699fbb2 100644
--- a/chromium/content/browser/media/capture/frame_sink_video_capture_device.h
+++ b/chromium/content/browser/media/capture/frame_sink_video_capture_device.h
@@ -16,7 +16,6 @@
#include "base/sequence_checker.h"
#include "components/viz/common/surfaces/frame_sink_id.h"
#include "components/viz/host/client_frame_sink_video_capturer.h"
-#include "content/browser/media/capture/cursor_renderer.h"
#include "content/common/content_export.h"
#include "content/public/browser/browser_thread.h"
#include "media/base/video_frame.h"
@@ -27,6 +26,8 @@
namespace content {
+class MouseCursorOverlayController;
+
// A virtualized VideoCaptureDevice that captures the displayed contents of a
// frame sink (see viz::CompositorFrameSink), such as the composited main view
// of a WebContents instance, producing a stream of video frames.
@@ -72,8 +73,7 @@ class CONTENT_EXPORT FrameSinkVideoCaptureDevice
// FrameSinkVideoConsumer implementation.
void OnFrameCaptured(
- mojo::ScopedSharedBufferHandle buffer,
- uint32_t buffer_size,
+ base::ReadOnlySharedMemoryRegion data,
media::mojom::VideoFrameInfoPtr info,
const gfx::Rect& update_rect,
const gfx::Rect& content_rect,
@@ -86,7 +86,9 @@ class CONTENT_EXPORT FrameSinkVideoCaptureDevice
void OnTargetPermanentlyLost();
protected:
- CursorRenderer* cursor_renderer() const { return cursor_renderer_.get(); }
+ MouseCursorOverlayController* cursor_controller() const {
+ return cursor_controller_.get();
+ }
// Subclasses override these to perform additional start/stop tasks.
virtual void WillStart();
@@ -112,10 +114,8 @@ class CONTENT_EXPORT FrameSinkVideoCaptureDevice
// If consuming, shut it down.
void MaybeStopConsuming();
- // Undoes mouse cursor rendering and notifies the capturer that consumption of
- // the frame is complete.
- void OnFramePropagationComplete(size_t slot_index,
- scoped_refptr<media::VideoFrame> frame);
+ // Notifies the capturer that consumption of the frame is complete.
+ void OnFramePropagationComplete(BufferId buffer_id);
// Helper that logs the given error |message| to the |receiver_| and then
// stops capture and this VideoCaptureDevice.
@@ -140,18 +140,13 @@ class CONTENT_EXPORT FrameSinkVideoCaptureDevice
std::unique_ptr<viz::ClientFrameSinkVideoCapturer> capturer_;
- // A pool of structs that hold state relevant to frames currently being
- // processed by VideoFrameReceiver. Each "slot" is re-used by later frames.
- struct ConsumptionState {
- viz::mojom::FrameSinkVideoConsumerFrameCallbacksPtr callbacks;
- CursorRendererUndoer undoer;
-
- ConsumptionState();
- ~ConsumptionState();
- ConsumptionState(ConsumptionState&& other) noexcept;
- ConsumptionState& operator=(ConsumptionState&& other) noexcept;
- };
- std::vector<ConsumptionState> slots_;
+ // A vector that holds the "callbacks" mojo InterfacePtr for each frame while
+ // the frame is being processed by VideoFrameReceiver. The index corresponding
+ // to a particular frame is used as the BufferId passed to VideoFrameReceiver.
+ // Therefore, non-null pointers in this vector must never move to a different
+ // position.
+ std::vector<viz::mojom::FrameSinkVideoConsumerFrameCallbacksPtr>
+ frame_callbacks_;
// Set when OnFatalError() is called. This prevents any future
// AllocateAndStartWithReceiver() calls from succeeding.
@@ -159,9 +154,10 @@ class CONTENT_EXPORT FrameSinkVideoCaptureDevice
SEQUENCE_CHECKER(sequence_checker_);
- // Renders the mouse cursor on each video frame.
- const std::unique_ptr<CursorRenderer, BrowserThread::DeleteOnUIThread>
- cursor_renderer_;
+ // Controls the overlay that renders the mouse cursor onto each video frame.
+ const std::unique_ptr<MouseCursorOverlayController,
+ BrowserThread::DeleteOnUIThread>
+ cursor_controller_;
// Creates WeakPtrs for use on the device thread.
base::WeakPtrFactory<FrameSinkVideoCaptureDevice> weak_factory_;
diff --git a/chromium/content/browser/media/capture/frame_sink_video_capture_device_unittest.cc b/chromium/content/browser/media/capture/frame_sink_video_capture_device_unittest.cc
index d8de88d4e46..341c3a04df6 100644
--- a/chromium/content/browser/media/capture/frame_sink_video_capture_device_unittest.cc
+++ b/chromium/content/browser/media/capture/frame_sink_video_capture_device_unittest.cc
@@ -9,11 +9,14 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/containers/flat_map.h"
+#include "base/memory/read_only_shared_memory_region.h"
+#include "base/memory/shared_memory_mapping.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_utils.h"
#include "media/base/video_frame.h"
#include "media/capture/video/video_frame_receiver.h"
#include "media/capture/video_capture_types.h"
+#include "mojo/public/cpp/base/shared_memory_utils.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "services/viz/privileged/interfaces/compositing/frame_sink_video_capture.mojom.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -110,6 +113,9 @@ class MockFrameSinkVideoCapturer : public viz::mojom::FrameSinkVideoCapturer {
}
MOCK_METHOD0(MockStop, void());
MOCK_METHOD0(RequestRefreshFrame, void());
+ MOCK_METHOD2(CreateOverlay,
+ void(int32_t stacking_index,
+ viz::mojom::FrameSinkVideoCaptureOverlayRequest request));
private:
mojo::Binding<viz::mojom::FrameSinkVideoCapturer> binding_;
@@ -181,20 +187,21 @@ class MockVideoFrameReceiver : public media::VideoFrameReceiver {
Buffer::ScopedAccessPermission* buffer_read_permission,
const media::mojom::VideoFrameInfo* frame_info));
MOCK_METHOD1(OnBufferRetired, void(int buffer_id));
- MOCK_METHOD0(OnError, void());
+ MOCK_METHOD1(OnError, void(media::VideoCaptureError error));
+ MOCK_METHOD1(OnFrameDropped, void(media::VideoCaptureFrameDropReason reason));
MOCK_METHOD1(OnLog, void(const std::string& message));
MOCK_METHOD0(OnStarted, void());
void OnStartedUsingGpuDecode() final { NOTREACHED(); }
- mojo::ScopedSharedBufferHandle TakeBufferHandle(int buffer_id) {
+ base::ReadOnlySharedMemoryRegion TakeBufferHandle(int buffer_id) {
DCHECK_NOT_ON_DEVICE_THREAD();
const auto it = buffer_handles_.find(buffer_id);
if (it == buffer_handles_.end()) {
ADD_FAILURE() << "Missing entry for buffer_id=" << buffer_id;
- return mojo::ScopedSharedBufferHandle();
+ return base::ReadOnlySharedMemoryRegion();
}
- CHECK(it->second->is_shared_buffer_handle());
- auto buffer = std::move(it->second->get_shared_buffer_handle());
+ CHECK(it->second->is_read_only_shmem_region());
+ auto buffer = std::move(it->second->get_read_only_shmem_region());
buffer_handles_.erase(it);
return buffer;
}
@@ -343,12 +350,11 @@ class FrameSinkVideoCaptureDeviceTest : public testing::Test {
int frame_number,
MockFrameSinkVideoConsumerFrameCallbacks* callbacks) {
// Allocate a buffer and fill it with values based on |frame_number|.
- const size_t buffer_size =
- media::VideoFrame::AllocationSize(kFormat, kResolution);
- mojo::ScopedSharedBufferHandle buffer =
- mojo::SharedBufferHandle::Create(buffer_size);
- memset(buffer->Map(buffer_size).get(), GetFrameFillValue(frame_number),
- buffer_size);
+ base::MappedReadOnlyRegion region = mojo::CreateReadOnlySharedMemoryRegion(
+ media::VideoFrame::AllocationSize(kFormat, kResolution));
+ CHECK(region.IsValid());
+ memset(region.mapping.memory(), GetFrameFillValue(frame_number),
+ region.mapping.size());
viz::mojom::FrameSinkVideoConsumerFrameCallbacksPtr callbacks_ptr;
callbacks->Bind(mojo::MakeRequest(&callbacks_ptr));
@@ -356,13 +362,12 @@ class FrameSinkVideoCaptureDeviceTest : public testing::Test {
// to the device thread before calling OnFrameCaptured().
POST_DEVICE_TASK(base::BindOnce(
[](FrameSinkVideoCaptureDevice* device,
- mojo::ScopedSharedBufferHandle buffer, size_t buffer_size,
- int frame_number,
+ base::ReadOnlySharedMemoryRegion data, int frame_number,
mojo::InterfacePtrInfo<
viz::mojom::FrameSinkVideoConsumerFrameCallbacks>
callbacks_info) {
device->OnFrameCaptured(
- std::move(buffer), buffer_size,
+ std::move(data),
media::mojom::VideoFrameInfo::New(
kMinCapturePeriod * frame_number,
base::Value(base::Value::Type::DICTIONARY), kFormat,
@@ -371,8 +376,8 @@ class FrameSinkVideoCaptureDeviceTest : public testing::Test {
viz::mojom::FrameSinkVideoConsumerFrameCallbacksPtr(
std::move(callbacks_info)));
},
- base::Unretained(device_.get()), std::move(buffer), buffer_size,
- frame_number, callbacks_ptr.PassInterface()));
+ base::Unretained(device_.get()), std::move(region.region), frame_number,
+ callbacks_ptr.PassInterface()));
}
// Returns a byte value based on the given |frame_number|.
@@ -384,13 +389,14 @@ class FrameSinkVideoCaptureDeviceTest : public testing::Test {
// given |frame_number|.
static bool IsExpectedBufferContentForFrame(
int frame_number,
- mojo::ScopedSharedBufferHandle buffer) {
- const size_t buffer_size =
+ base::ReadOnlySharedMemoryRegion buffer) {
+ const auto mapping = buffer.Map();
+ const size_t frame_allocation_size =
media::VideoFrame::AllocationSize(kFormat, kResolution);
- const auto mapping = buffer->Map(buffer_size);
- const uint8_t* src = static_cast<uint8_t*>(mapping.get());
+ CHECK_LE(frame_allocation_size, mapping.size());
+ const uint8_t* src = mapping.GetMemoryAs<const uint8_t>();
const uint8_t expected_value = GetFrameFillValue(frame_number);
- for (size_t i = 0; i < buffer_size; ++i) {
+ for (size_t i = 0; i < frame_allocation_size; ++i) {
if (src[i] != expected_value) {
return false;
}
@@ -413,7 +419,7 @@ TEST_F(FrameSinkVideoCaptureDeviceTest, CapturesAndDeliversFrames) {
auto receiver_ptr = std::make_unique<MockVideoFrameReceiver>();
auto* const receiver = receiver_ptr.get();
EXPECT_CALL(*receiver, OnStarted());
- EXPECT_CALL(*receiver, OnError()).Times(0);
+ EXPECT_CALL(*receiver, OnError(_)).Times(0);
AllocateAndStartSynchronouslyWithExpectations(std::move(receiver_ptr));
// From this point, there is no reason the capturer should be re-started.
@@ -454,7 +460,7 @@ TEST_F(FrameSinkVideoCaptureDeviceTest, CapturesAndDeliversFrames) {
const int buffer_id = buffer_ids[frame_number - first_frame_number];
auto buffer = receiver->TakeBufferHandle(buffer_id);
- ASSERT_TRUE(buffer.is_valid());
+ ASSERT_TRUE(buffer.IsValid());
EXPECT_TRUE(
IsExpectedBufferContentForFrame(frame_number, std::move(buffer)));
@@ -552,7 +558,7 @@ TEST_F(FrameSinkVideoCaptureDeviceTest, ShutsDownOnFatalError) {
Sequence sequence;
EXPECT_CALL(*receiver, OnStarted()).InSequence(sequence);
EXPECT_CALL(*receiver, OnLog(StrNe(""))).InSequence(sequence);
- EXPECT_CALL(*receiver, OnError()).InSequence(sequence);
+ EXPECT_CALL(*receiver, OnError(_)).InSequence(sequence);
AllocateAndStartSynchronouslyWithExpectations(std::move(receiver_ptr));
@@ -578,7 +584,7 @@ TEST_F(FrameSinkVideoCaptureDeviceTest, ShutsDownOnFatalError) {
{
EXPECT_CALL(*receiver, OnStarted()).Times(0);
EXPECT_CALL(*receiver, OnLog(StrNe("")));
- EXPECT_CALL(*receiver, OnError());
+ EXPECT_CALL(*receiver, OnError(_));
EXPECT_CALL(capturer_, MockStart(_)).Times(0);
POST_DEVICE_METHOD_CALL(AllocateAndStartWithReceiver, GetCaptureParams(),
diff --git a/chromium/content/browser/media/capture/lame_capture_overlay_chromeos.cc b/chromium/content/browser/media/capture/lame_capture_overlay_chromeos.cc
new file mode 100644
index 00000000000..1c6f0aff99f
--- /dev/null
+++ b/chromium/content/browser/media/capture/lame_capture_overlay_chromeos.cc
@@ -0,0 +1,178 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/media/capture/lame_capture_overlay_chromeos.h"
+
+#include <algorithm>
+#include <cmath>
+
+#include "base/numerics/safe_conversions.h"
+#include "content/browser/media/capture/lame_window_capturer_chromeos.h"
+#include "media/base/video_frame.h"
+#include "skia/ext/image_operations.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "ui/gfx/geometry/point.h"
+#include "ui/gfx/geometry/rect.h"
+
+namespace content {
+
+LameCaptureOverlayChromeOS::Owner::~Owner() = default;
+
+LameCaptureOverlayChromeOS::LameCaptureOverlayChromeOS(
+ Owner* owner,
+ viz::mojom::FrameSinkVideoCaptureOverlayRequest request)
+ : binding_(this, std::move(request)) {
+ if (owner) {
+ binding_.set_connection_error_handler(base::BindOnce(
+ &Owner::OnOverlayConnectionLost, base::Unretained(owner), this));
+ }
+}
+
+LameCaptureOverlayChromeOS::~LameCaptureOverlayChromeOS() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+}
+
+void LameCaptureOverlayChromeOS::SetImageAndBounds(const SkBitmap& image,
+ const gfx::RectF& bounds) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ image_ = image;
+ bounds_ = bounds;
+ cached_scaled_image_.reset();
+}
+
+void LameCaptureOverlayChromeOS::SetBounds(const gfx::RectF& bounds) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ if (bounds != bounds_) {
+ bounds_ = bounds;
+ cached_scaled_image_.reset();
+ }
+}
+
+namespace {
+
+// Scales a |relative| rect having coordinates in the range [0.0,1.0) by the
+// given |span|, snapping all coordinates to even numbers.
+gfx::Rect ToAbsoluteBoundsForI420(const gfx::RectF& relative,
+ const gfx::Rect& span) {
+ const float absolute_left = std::fma(relative.x(), span.width(), span.x());
+ const float absolute_top = std::fma(relative.y(), span.height(), span.y());
+ const float absolute_right =
+ std::fma(relative.right(), span.width(), span.x());
+ const float absolute_bottom =
+ std::fma(relative.bottom(), span.height(), span.y());
+
+ // Compute the largest I420-friendly Rect that is fully-enclosed by the
+ // absolute rect. Use saturated_cast<> to restrict all extreme results [and
+ // Inf and NaN] to a safe range of integers.
+ const int snapped_left =
+ base::saturated_cast<int16_t>(std::ceil(absolute_left / 2.0f)) * 2;
+ const int snapped_top =
+ base::saturated_cast<int16_t>(std::ceil(absolute_top / 2.0f)) * 2;
+ const int snapped_right =
+ base::saturated_cast<int16_t>(std::floor(absolute_right / 2.0f)) * 2;
+ const int snapped_bottom =
+ base::saturated_cast<int16_t>(std::floor(absolute_bottom / 2.0f)) * 2;
+ return gfx::Rect(snapped_left, snapped_top,
+ std::max(0, snapped_right - snapped_left),
+ std::max(0, snapped_bottom - snapped_top));
+}
+
+inline int clip_byte(int x) {
+ return std::max(0, std::min(x, 255));
+}
+
+inline int alpha_blend(int alpha, int src, int dst) {
+ return (src * alpha + dst * (255 - alpha)) / 255;
+}
+
+} // namespace
+
+LameCaptureOverlayChromeOS::OnceRenderer
+LameCaptureOverlayChromeOS::MakeRenderer(const gfx::Rect& region_in_frame) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ if (bounds_.IsEmpty() || image_.drawsNothing()) {
+ return OnceRenderer();
+ }
+
+ // Determine the bounds of the overlay inside the video frame. The
+ // calculations here align to the 2x2 pixel-quads to simplify later
+ // implementation.
+ const gfx::Rect bounds_in_frame =
+ ToAbsoluteBoundsForI420(bounds_, region_in_frame);
+
+ // Compute the region of the frame to be modified.
+ gfx::Rect blit_rect = region_in_frame;
+ blit_rect.Intersect(bounds_in_frame);
+ // If the two rects didn't intersect at all (i.e., everything has been
+ // clipped), punt.
+ if (blit_rect.IsEmpty()) {
+ return OnceRenderer();
+ }
+
+ if (cached_scaled_image_.drawsNothing() ||
+ cached_scaled_image_.width() != bounds_in_frame.width() ||
+ cached_scaled_image_.height() != bounds_in_frame.height()) {
+ cached_scaled_image_ = skia::ImageOperations::Resize(
+ image_, skia::ImageOperations::RESIZE_BETTER, bounds_in_frame.width(),
+ bounds_in_frame.height());
+ }
+
+ // The following binds all state required to render the overlay on a
+ // VideoFrame at a later time. This callback does not require
+ // LameCaptureOverlayChromeOS to outlive it.
+ return base::BindOnce(
+ [](const SkBitmap& image, const gfx::Point& position,
+ const gfx::Rect& rect, media::VideoFrame* frame) {
+ DCHECK(frame);
+ DCHECK_EQ(frame->format(), media::PIXEL_FORMAT_I420);
+ DCHECK(frame->visible_rect().Contains(rect));
+
+ // Render the overlay in the video frame. This loop also performs a
+ // simple RGB→YUV color space conversion, with alpha-blended
+ // compositing.
+ for (int y = rect.y(); y < rect.bottom(); ++y) {
+ const int source_row = y - position.y();
+ uint8_t* const yplane =
+ frame->visible_data(media::VideoFrame::kYPlane) +
+ y * frame->stride(media::VideoFrame::kYPlane);
+ uint8_t* const uplane =
+ frame->visible_data(media::VideoFrame::kUPlane) +
+ (y / 2) * frame->stride(media::VideoFrame::kUPlane);
+ uint8_t* const vplane =
+ frame->visible_data(media::VideoFrame::kVPlane) +
+ (y / 2) * frame->stride(media::VideoFrame::kVPlane);
+ for (int x = rect.x(); x < rect.right(); ++x) {
+ const int source_col = x - position.x();
+ const SkColor color = image.getColor(source_col, source_row);
+ const int alpha = SkColorGetA(color);
+ const int color_r = SkColorGetR(color);
+ const int color_g = SkColorGetG(color);
+ const int color_b = SkColorGetB(color);
+ const int color_y =
+ ((color_r * 66 + color_g * 129 + color_b * 25 + 128) >> 8) + 16;
+ yplane[x] = clip_byte(alpha_blend(alpha, color_y, yplane[x]));
+
+ // Only sample U and V at even coordinates.
+ if ((x % 2 == 0) && (y % 2 == 0)) {
+ const int color_u =
+ ((color_r * -38 + color_g * -74 + color_b * 112 + 128) >> 8) +
+ 128;
+ const int color_v =
+ ((color_r * 112 + color_g * -94 + color_b * -18 + 128) >> 8) +
+ 128;
+ uplane[x / 2] =
+ clip_byte(alpha_blend(alpha, color_u, uplane[x / 2]));
+ vplane[x / 2] =
+ clip_byte(alpha_blend(alpha, color_v, vplane[x / 2]));
+ }
+ }
+ }
+ },
+ cached_scaled_image_, bounds_in_frame.origin(), blit_rect);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/capture/lame_capture_overlay_chromeos.h b/chromium/content/browser/media/capture/lame_capture_overlay_chromeos.h
new file mode 100644
index 00000000000..b153728c987
--- /dev/null
+++ b/chromium/content/browser/media/capture/lame_capture_overlay_chromeos.h
@@ -0,0 +1,88 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_MEDIA_CAPTURE_LAME_CAPTURE_OVERLAY_CHROMEOS_H_
+#define CONTENT_BROWSER_MEDIA_CAPTURE_LAME_CAPTURE_OVERLAY_CHROMEOS_H_
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/sequence_checker.h"
+#include "content/common/content_export.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "services/viz/privileged/interfaces/compositing/frame_sink_video_capture.mojom.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/geometry/rect_f.h"
+
+namespace media {
+class VideoFrame;
+}
+
+namespace content {
+
+// A minimal FrameSinkVideoCaptureOverlay implementation for aura::Window video
+// capture on ChromeOS (i.e., not desktop capture, and not WebContents capture).
+// See class comments for LameWindowCapturerChromeOS for further details on why
+// this exists and why this placeholder is needed for now.
+//
+// The implementation here is a hodgepodge of code borrowed from
+// viz::VideoCaptureOverlay and the legacy content::CursorRenderer. Like its
+// full-featured VIZ cousin, it will cache the scaled version of the bitmap, and
+// re-use it across multiple frames. However, the rest of the rendering impl is
+// overly-simplified, sufferring from color accuracy and image sampling issues.
+// However, its quality is sufficient for its main use as a mouse cursor
+// renderer.
+//
+// TODO(crbug/806366): The goal is to remove this code by 2019.
+class CONTENT_EXPORT LameCaptureOverlayChromeOS
+ : public viz::mojom::FrameSinkVideoCaptureOverlay {
+ public:
+ // Implemented by LameWindowCapturerChromeOS.
+ class CONTENT_EXPORT Owner {
+ public:
+ // Called to notify that the |overlay| has lost its mojo binding. The owner
+ // will usually delete it during this method call.
+ virtual void OnOverlayConnectionLost(
+ LameCaptureOverlayChromeOS* overlay) = 0;
+
+ protected:
+ virtual ~Owner();
+ };
+
+ // A OnceCallback that, when run, renders the overlay on a VideoFrame.
+ using OnceRenderer = base::OnceCallback<void(media::VideoFrame*)>;
+
+ LameCaptureOverlayChromeOS(
+ Owner* owner,
+ viz::mojom::FrameSinkVideoCaptureOverlayRequest request);
+ ~LameCaptureOverlayChromeOS() final;
+
+ // viz::mojom::FrameSinkVideoCaptureOverlay implementation.
+ void SetImageAndBounds(const SkBitmap& image, const gfx::RectF& bounds) final;
+ void SetBounds(const gfx::RectF& bounds) final;
+
+ // Returns a OnceCallback that, when run, renders this overlay on an
+ // I420-format VideoFrame. The overlay's position and size are computed based
+ // on the given content |region_in_frame|. Returns a null OnceCallback if
+ // there is nothing to render at this time.
+ OnceRenderer MakeRenderer(const gfx::Rect& region_in_frame);
+
+ private:
+ SEQUENCE_CHECKER(sequence_checker_);
+
+ mojo::Binding<viz::mojom::FrameSinkVideoCaptureOverlay> binding_;
+
+ SkBitmap image_;
+ gfx::RectF bounds_;
+
+ // The scaled |image_| used in the last call to MakeRenderer(). This is reset
+ // and re-generated whenever: a) the |image_| changes, or b) the required
+ // bitmap size changes.
+ SkBitmap cached_scaled_image_;
+
+ DISALLOW_COPY_AND_ASSIGN(LameCaptureOverlayChromeOS);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MEDIA_CAPTURE_LAME_CAPTURE_OVERLAY_CHROMEOS_H_
diff --git a/chromium/content/browser/media/capture/lame_capture_overlay_chromeos_unittest.cc b/chromium/content/browser/media/capture/lame_capture_overlay_chromeos_unittest.cc
new file mode 100644
index 00000000000..4af85e5e38a
--- /dev/null
+++ b/chromium/content/browser/media/capture/lame_capture_overlay_chromeos_unittest.cc
@@ -0,0 +1,174 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/media/capture/lame_capture_overlay_chromeos.h"
+
+#include <stdint.h>
+
+#include <memory>
+#include <utility>
+
+#include "base/test/scoped_task_environment.h"
+#include "base/time/time.h"
+#include "media/base/video_frame.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/rect_conversions.h"
+#include "ui/gfx/geometry/rect_f.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace content {
+namespace {
+
+constexpr gfx::Size kFrameSize = gfx::Size(320, 200);
+constexpr gfx::Rect kContentRegion = gfx::Rect(kFrameSize);
+constexpr gfx::RectF kSpanOfEntireFrame = gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f);
+
+class LameCaptureOverlayChromeOSTest : public testing::Test {
+ public:
+ void RunUntilIdle() { env_.RunUntilIdle(); }
+
+ // Returns a 32x32 bitmap filled with red.
+ static SkBitmap CreateTestBitmap() {
+ SkBitmap bitmap;
+ bitmap.allocN32Pixels(32, 32);
+ CHECK(!bitmap.isNull());
+ bitmap.eraseColor(SK_ColorRED);
+ return bitmap;
+ }
+
+ // Returns true if there are any non-zero pixels in the region |rect| within
+ // |frame|.
+ static bool NonZeroPixelsInRegion(const media::VideoFrame* frame,
+ const gfx::Rect& rect) {
+ bool y_found = false, u_found = false, v_found = false;
+ for (int y = rect.y(); y < rect.bottom(); ++y) {
+ auto* const yplane = frame->visible_data(media::VideoFrame::kYPlane) +
+ y * frame->stride(media::VideoFrame::kYPlane);
+ auto* const uplane = frame->visible_data(media::VideoFrame::kUPlane) +
+ (y / 2) * frame->stride(media::VideoFrame::kUPlane);
+ auto* const vplane = frame->visible_data(media::VideoFrame::kVPlane) +
+ (y / 2) * frame->stride(media::VideoFrame::kVPlane);
+ for (int x = rect.x(); x < rect.right(); ++x) {
+ if (yplane[x] != 0)
+ y_found = true;
+ if (uplane[x / 2])
+ u_found = true;
+ if (vplane[x / 2])
+ v_found = true;
+ }
+ }
+ return (y_found && u_found && v_found);
+ }
+
+ private:
+ base::test::ScopedTaskEnvironment env_;
+};
+
+TEST_F(LameCaptureOverlayChromeOSTest, UnsetImageNotRenderedOnFrame) {
+ LameCaptureOverlayChromeOS overlay(
+ nullptr, viz::mojom::FrameSinkVideoCaptureOverlayRequest());
+
+ // Bounds set, but no image. → Should not render anything.
+ overlay.SetBounds(kSpanOfEntireFrame);
+ EXPECT_FALSE(overlay.MakeRenderer(kContentRegion));
+
+ // Both image and bounds set. → Should render something.
+ overlay.SetImageAndBounds(CreateTestBitmap(), kSpanOfEntireFrame);
+ EXPECT_TRUE(overlay.MakeRenderer(kContentRegion));
+}
+
+TEST_F(LameCaptureOverlayChromeOSTest, HiddenImageNotRenderedOnFrame) {
+ LameCaptureOverlayChromeOS overlay(
+ nullptr, viz::mojom::FrameSinkVideoCaptureOverlayRequest());
+
+ // Both image and bounds set. → Should render something.
+ overlay.SetImageAndBounds(CreateTestBitmap(), kSpanOfEntireFrame);
+ EXPECT_TRUE(overlay.MakeRenderer(kContentRegion));
+
+ // Bounds set to empty. → Should render nothing.
+ overlay.SetBounds(gfx::RectF());
+ EXPECT_FALSE(overlay.MakeRenderer(kContentRegion));
+}
+
+TEST_F(LameCaptureOverlayChromeOSTest, OutOfBoundsOverlayNotRenderedOnFrame) {
+ LameCaptureOverlayChromeOS overlay(
+ nullptr, viz::mojom::FrameSinkVideoCaptureOverlayRequest());
+
+ // Both image and bounds set. → Should render something.
+ overlay.SetImageAndBounds(CreateTestBitmap(), kSpanOfEntireFrame);
+ EXPECT_TRUE(overlay.MakeRenderer(kContentRegion));
+
+ // Move overlay to above and left of content area. → Should render nothing.
+ overlay.SetBounds(gfx::RectF(-0.5f, -0.5f, 0.25f, 0.25f));
+ EXPECT_FALSE(overlay.MakeRenderer(kContentRegion));
+}
+
+TEST_F(LameCaptureOverlayChromeOSTest, ImageRenderedOnFrame) {
+ LameCaptureOverlayChromeOS overlay(
+ nullptr, viz::mojom::FrameSinkVideoCaptureOverlayRequest());
+
+ // Create blank black frame. No non-zero pixels should be present.
+ const auto frame = media::VideoFrame::CreateZeroInitializedFrame(
+ media::PIXEL_FORMAT_I420, kFrameSize, gfx::Rect(kFrameSize), kFrameSize,
+ base::TimeDelta());
+ ASSERT_FALSE(NonZeroPixelsInRegion(frame.get(), frame->visible_rect()));
+
+ // Set image and bounds to a location in the lower-right quadrant of the
+ // frame.
+ const gfx::RectF bounds(0.8f, 0.8f, 0.1f, 0.1f);
+ overlay.SetImageAndBounds(CreateTestBitmap(), bounds);
+
+ // Render the overlay in the VideoFrame.
+ auto renderer = overlay.MakeRenderer(kContentRegion);
+ ASSERT_TRUE(renderer);
+ std::move(renderer).Run(frame.get());
+
+ // Check that there are non-zero pixels present in the modified region.
+ const gfx::Rect mutated_region = gfx::ToEnclosingRect(
+ gfx::ScaleRect(bounds, kContentRegion.width(), kContentRegion.height()));
+ EXPECT_TRUE(NonZeroPixelsInRegion(frame.get(), mutated_region));
+
+ // Check that there are no non-zero pixels present in the rest of the frame.
+ const struct BlankRegion {
+ const char* const description;
+ gfx::Rect rect;
+ } regions_around_mutation[] = {
+ {"above", gfx::Rect(0, 0, kContentRegion.width(), mutated_region.y())},
+ {"left", gfx::Rect(0, mutated_region.y(), mutated_region.x(),
+ mutated_region.height())},
+ {"right", gfx::Rect(mutated_region.right(), mutated_region.y(),
+ kContentRegion.width() - mutated_region.right(),
+ mutated_region.height())},
+ {"below", gfx::Rect(0, mutated_region.bottom(), kContentRegion.width(),
+ kContentRegion.height() - mutated_region.bottom())},
+ };
+ for (const BlankRegion& region : regions_around_mutation) {
+ SCOPED_TRACE(testing::Message() << region.description);
+ EXPECT_FALSE(NonZeroPixelsInRegion(frame.get(), region.rect));
+ }
+}
+
+TEST_F(LameCaptureOverlayChromeOSTest, ReportsLostMojoConnection) {
+ class MockOwner : public LameCaptureOverlayChromeOS::Owner {
+ public:
+ ~MockOwner() final = default;
+ MOCK_METHOD1(OnOverlayConnectionLost,
+ void(LameCaptureOverlayChromeOS* overlay));
+ } mock_owner;
+
+ viz::mojom::FrameSinkVideoCaptureOverlayPtr overlay_ptr;
+ LameCaptureOverlayChromeOS overlay(&mock_owner,
+ mojo::MakeRequest(&overlay_ptr));
+ ASSERT_TRUE(overlay_ptr);
+ RunUntilIdle(); // Propagate mojo tasks.
+
+ EXPECT_CALL(mock_owner, OnOverlayConnectionLost(&overlay));
+ overlay_ptr.reset();
+ RunUntilIdle(); // Propagate mojo tasks.
+}
+
+} // namespace
+} // namespace content
diff --git a/chromium/content/browser/media/capture/lame_window_capturer_chromeos.cc b/chromium/content/browser/media/capture/lame_window_capturer_chromeos.cc
index 1086b27f68f..2a9275ecb73 100644
--- a/chromium/content/browser/media/capture/lame_window_capturer_chromeos.cc
+++ b/chromium/content/browser/media/capture/lame_window_capturer_chromeos.cc
@@ -13,6 +13,7 @@
#include "components/viz/common/frame_sinks/copy_output_result.h"
#include "media/base/limits.h"
#include "media/base/video_util.h"
+#include "mojo/public/cpp/base/shared_memory_utils.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "ui/gfx/geometry/rect.h"
@@ -140,22 +141,28 @@ void LameWindowCapturerChromeOS::RequestRefreshFrame() {
// continuously.
}
+void LameWindowCapturerChromeOS::CreateOverlay(
+ int32_t stacking_index,
+ viz::mojom::FrameSinkVideoCaptureOverlayRequest request) {
+ // LameWindowCapturerChromeOS only supports one overlay at a time. If one
+ // already exists, the following will cause it to be dropped.
+ overlay_ =
+ std::make_unique<LameCaptureOverlayChromeOS>(this, std::move(request));
+}
+
class LameWindowCapturerChromeOS::InFlightFrame
: public viz::mojom::FrameSinkVideoConsumerFrameCallbacks {
public:
InFlightFrame(base::WeakPtr<LameWindowCapturerChromeOS> capturer,
- BufferAndSize buffer)
+ base::MappedReadOnlyRegion buffer)
: capturer_(std::move(capturer)), buffer_(std::move(buffer)) {}
~InFlightFrame() final { Done(); }
- mojo::ScopedSharedBufferHandle CloneBufferHandle() {
- return buffer_.first->Clone(
- mojo::SharedBufferHandle::AccessMode::READ_WRITE);
+ base::ReadOnlySharedMemoryRegion CloneBufferHandle() {
+ return buffer_.region.Duplicate();
}
- size_t buffer_size() const { return buffer_.second; }
-
VideoFrame* video_frame() const { return video_frame_.get(); }
void set_video_frame(scoped_refptr<VideoFrame> frame) {
video_frame_ = std::move(frame);
@@ -164,12 +171,23 @@ class LameWindowCapturerChromeOS::InFlightFrame
const gfx::Rect& content_rect() const { return content_rect_; }
void set_content_rect(const gfx::Rect& rect) { content_rect_ = rect; }
+ void set_overlay_renderer(LameCaptureOverlayChromeOS::OnceRenderer renderer) {
+ overlay_renderer_ = std::move(renderer);
+ }
+ void RenderOptionalOverlay() {
+ if (overlay_renderer_) {
+ std::move(overlay_renderer_).Run(video_frame_.get());
+ }
+ }
+
void Done() final {
+ video_frame_ = nullptr;
+
if (auto* capturer = capturer_.get()) {
DCHECK_GT(capturer->in_flight_count_, 0);
--capturer->in_flight_count_;
// If the capture size hasn't changed, return the buffer to the pool.
- if (buffer_.second ==
+ if (buffer_.mapping.size() ==
VideoFrame::AllocationSize(media::PIXEL_FORMAT_I420,
capturer->capture_size_)) {
capturer->buffer_pool_.emplace_back(std::move(buffer_));
@@ -177,21 +195,28 @@ class LameWindowCapturerChromeOS::InFlightFrame
capturer_ = nullptr;
}
- buffer_.first.reset();
- buffer_.second = 0;
+ buffer_ = base::MappedReadOnlyRegion();
}
void ProvideFeedback(double utilization) final {}
private:
base::WeakPtr<LameWindowCapturerChromeOS> capturer_;
- BufferAndSize buffer_;
+ base::MappedReadOnlyRegion buffer_;
scoped_refptr<VideoFrame> video_frame_;
gfx::Rect content_rect_;
+ LameCaptureOverlayChromeOS::OnceRenderer overlay_renderer_;
DISALLOW_COPY_AND_ASSIGN(InFlightFrame);
};
+void LameWindowCapturerChromeOS::OnOverlayConnectionLost(
+ LameCaptureOverlayChromeOS* overlay) {
+ if (overlay_.get() == overlay) {
+ overlay_.reset();
+ }
+}
+
void LameWindowCapturerChromeOS::CaptureNextFrame() {
// If the maximum frame in-flight count has been reached, skip this frame.
if (in_flight_count_ >= kMaxFramesInFlight) {
@@ -201,30 +226,22 @@ void LameWindowCapturerChromeOS::CaptureNextFrame() {
// Attempt to re-use a buffer from the pool. Otherwise, create a new one.
const size_t allocation_size =
VideoFrame::AllocationSize(media::PIXEL_FORMAT_I420, capture_size_);
- BufferAndSize buffer;
+ base::MappedReadOnlyRegion buffer;
if (buffer_pool_.empty()) {
- buffer.first = mojo::SharedBufferHandle::Create(allocation_size);
- if (!buffer.first.is_valid()) {
- // If creating the shared memory failed, abort the frame, and hope this
- // is a transient problem.
+ buffer = mojo::CreateReadOnlySharedMemoryRegion(allocation_size);
+ if (!buffer.IsValid()) {
+ // If the shared memory region creation failed, just abort this frame,
+ // hoping the issue is a transient one (e.g., lack of an available region
+ // in the address space).
return;
}
- buffer.second = allocation_size;
} else {
buffer = std::move(buffer_pool_.back());
buffer_pool_.pop_back();
- DCHECK(buffer.first.is_valid());
- DCHECK_EQ(buffer.second, allocation_size);
- }
-
- // Map the shared memory buffer, to populate its data.
- mojo::ScopedSharedBufferMapping mapping = buffer.first->Map(buffer.second);
- if (!mapping) {
- // If the shared memory mapping failed, just abort this frame, hoping the
- // issue is a transient one (e.g., lack of an available region in address
- // space).
- return;
+ DCHECK(buffer.IsValid());
+ DCHECK_EQ(buffer.mapping.size(), allocation_size);
}
+ void* const backing_memory = buffer.mapping.memory();
// At this point, frame capture will proceed. Create an InFlightFrame to track
// population and consumption of the frame, and to eventually return the
@@ -240,13 +257,10 @@ void LameWindowCapturerChromeOS::CaptureNextFrame() {
}
in_flight_frame->set_video_frame(VideoFrame::WrapExternalData(
media::PIXEL_FORMAT_I420, capture_size_, gfx::Rect(capture_size_),
- capture_size_, static_cast<uint8_t*>(mapping.get()), allocation_size,
+ capture_size_, static_cast<uint8_t*>(backing_memory), allocation_size,
begin_time - first_frame_reference_time_));
auto* const frame = in_flight_frame->video_frame();
DCHECK(frame);
- frame->AddDestructionObserver(
- base::BindOnce(base::DoNothing::Once<mojo::ScopedSharedBufferMapping>(),
- std::move(mapping)));
VideoFrameMetadata* const metadata = frame->metadata();
metadata->SetTimeTicks(VideoFrameMetadata::CAPTURE_BEGIN_TIME, begin_time);
metadata->SetInteger(VideoFrameMetadata::COLOR_SPACE,
@@ -273,6 +287,10 @@ void LameWindowCapturerChromeOS::CaptureNextFrame() {
}
DCHECK(target_);
+ if (overlay_) {
+ in_flight_frame->set_overlay_renderer(overlay_->MakeRenderer(content_rect));
+ }
+
// Request a copy of the Layer associated with the |target_| aura::Window.
auto request = std::make_unique<viz::CopyOutputRequest>(
// Note: As of this writing, I420_PLANES is not supported external to VIZ.
@@ -308,6 +326,8 @@ void LameWindowCapturerChromeOS::DidCopyFrame(
return; // Copy request failed, punt.
}
+ in_flight_frame->RenderOptionalOverlay();
+
// The result may be smaller than what was requested, if unforeseen clamping
// to the source boundaries occurred by the executor of the copy request.
// However, the result should never contain more than what was requested.
@@ -328,12 +348,11 @@ void LameWindowCapturerChromeOS::DeliverFrame(
base::TimeTicks::Now());
// Clone the buffer handle for the consumer.
- mojo::ScopedSharedBufferHandle buffer_for_consumer =
+ base::ReadOnlySharedMemoryRegion handle =
in_flight_frame->CloneBufferHandle();
- if (!buffer_for_consumer.is_valid()) {
+ if (!handle.IsValid()) {
return; // This should only fail if the OS is exhausted of handles.
}
- const size_t buffer_allocation_size = in_flight_frame->buffer_size();
// Assemble frame layout, format, and metadata into a mojo struct to send to
// the consumer.
@@ -346,10 +365,6 @@ void LameWindowCapturerChromeOS::DeliverFrame(
const gfx::Rect update_rect = frame->visible_rect();
const gfx::Rect content_rect = in_flight_frame->content_rect();
- // Drop the VideoFrame wrapper, which will unmap the shared memory from this
- // process.
- in_flight_frame->set_video_frame(nullptr);
-
// Create a mojo message pipe and bind to the InFlightFrame to wait for the
// Done() signal from the consumer. The mojo::StrongBinding takes ownership of
// the InFlightFrame.
@@ -358,9 +373,8 @@ void LameWindowCapturerChromeOS::DeliverFrame(
mojo::MakeRequest(&callbacks));
// Send the frame to the consumer.
- consumer_->OnFrameCaptured(std::move(buffer_for_consumer),
- buffer_allocation_size, std::move(info),
- update_rect, content_rect, std::move(callbacks));
+ consumer_->OnFrameCaptured(std::move(handle), std::move(info), update_rect,
+ content_rect, std::move(callbacks));
}
void LameWindowCapturerChromeOS::OnWindowDestroying(aura::Window* window) {
diff --git a/chromium/content/browser/media/capture/lame_window_capturer_chromeos.h b/chromium/content/browser/media/capture/lame_window_capturer_chromeos.h
index 2a467ecc20b..6af4c60068e 100644
--- a/chromium/content/browser/media/capture/lame_window_capturer_chromeos.h
+++ b/chromium/content/browser/media/capture/lame_window_capturer_chromeos.h
@@ -10,12 +10,13 @@
#include <vector>
#include "base/macros.h"
+#include "base/memory/read_only_shared_memory_region.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "base/unguessable_token.h"
+#include "content/browser/media/capture/lame_capture_overlay_chromeos.h"
#include "media/base/video_frame.h"
-#include "mojo/public/cpp/system/buffer.h"
#include "services/viz/privileged/interfaces/compositing/frame_sink_video_capture.mojom.h"
#include "ui/aura/window.h"
#include "ui/aura/window_observer.h"
@@ -47,6 +48,7 @@ namespace content {
//
// TODO(crbug/806366): The goal is to remove this code by 2019.
class LameWindowCapturerChromeOS : public viz::mojom::FrameSinkVideoCapturer,
+ public LameCaptureOverlayChromeOS::Owner,
public aura::WindowObserver {
public:
explicit LameWindowCapturerChromeOS(aura::Window* target);
@@ -66,6 +68,9 @@ class LameWindowCapturerChromeOS : public viz::mojom::FrameSinkVideoCapturer,
void Start(viz::mojom::FrameSinkVideoConsumerPtr consumer) final;
void Stop() final;
void RequestRefreshFrame() final;
+ void CreateOverlay(
+ int32_t stacking_index,
+ viz::mojom::FrameSinkVideoCaptureOverlayRequest request) final;
private:
// Represents an in-flight frame, being populated by this capturer and then
@@ -73,6 +78,9 @@ class LameWindowCapturerChromeOS : public viz::mojom::FrameSinkVideoCapturer,
// returns the buffer back to the pool.
class InFlightFrame;
+ // LameWindowCapturerChromeOS::Owner implementation.
+ void OnOverlayConnectionLost(LameCaptureOverlayChromeOS* overlay) final;
+
// Initiates capture of the next frame. This is called periodically by the
// |timer_|.
void CaptureNextFrame();
@@ -106,8 +114,7 @@ class LameWindowCapturerChromeOS : public viz::mojom::FrameSinkVideoCapturer,
base::RepeatingTimer timer_;
// A pool of shared memory buffers for re-use.
- using BufferAndSize = std::pair<mojo::ScopedSharedBufferHandle, size_t>;
- std::vector<BufferAndSize> buffer_pool_;
+ std::vector<base::MappedReadOnlyRegion> buffer_pool_;
// The current number of frames in-flight. If incrementing this would be
// exceed kMaxInFlightFrames, frame capture is not attempted.
@@ -121,6 +128,9 @@ class LameWindowCapturerChromeOS : public viz::mojom::FrameSinkVideoCapturer,
// video capture.
const base::UnguessableToken copy_request_source_;
+ // An optional overlay to be rendered over each captured video frame.
+ std::unique_ptr<LameCaptureOverlayChromeOS> overlay_;
+
// Used for cancelling any outstanding activities' results, once Stop() is
// called and there is no longer a consumer to receive another frame.
base::WeakPtrFactory<LameWindowCapturerChromeOS> weak_factory_;
diff --git a/chromium/content/browser/media/capture/mouse_cursor_overlay_controller.cc b/chromium/content/browser/media/capture/mouse_cursor_overlay_controller.cc
new file mode 100644
index 00000000000..0bc6700725b
--- /dev/null
+++ b/chromium/content/browser/media/capture/mouse_cursor_overlay_controller.cc
@@ -0,0 +1,166 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/media/capture/mouse_cursor_overlay_controller.h"
+
+#include <cmath>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/logging.h"
+
+namespace content {
+
+// static
+constexpr base::TimeDelta MouseCursorOverlayController::kIdleTimeout;
+
+void MouseCursorOverlayController::Start(
+ std::unique_ptr<Overlay> overlay,
+ scoped_refptr<base::SequencedTaskRunner> task_runner) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(ui_sequence_checker_);
+ DCHECK(overlay);
+ DCHECK(task_runner);
+
+ Stop();
+ overlay_ = std::move(overlay);
+ overlay_task_runner_ = std::move(task_runner);
+}
+
+void MouseCursorOverlayController::Stop() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(ui_sequence_checker_);
+
+ if (overlay_) {
+ overlay_task_runner_->DeleteSoon(FROM_HERE, overlay_.release());
+ overlay_task_runner_ = nullptr;
+ }
+}
+
+bool MouseCursorOverlayController::IsUserInteractingWithView() const {
+ return mouse_move_behavior() == kRecentlyMovedOrClicked;
+}
+
+base::WeakPtr<MouseCursorOverlayController>
+MouseCursorOverlayController::GetWeakPtr() {
+ return weak_factory_.GetWeakPtr();
+}
+
+void MouseCursorOverlayController::OnMouseMoved(const gfx::PointF& location) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(ui_sequence_checker_);
+
+ switch (mouse_move_behavior()) {
+ case kNotMoving:
+ set_mouse_move_behavior(kStartingToMove);
+ mouse_move_start_location_ = location;
+ mouse_activity_ended_timer_.Start(
+ FROM_HERE, kIdleTimeout,
+ base::BindRepeating(&MouseCursorOverlayController::OnMouseHasGoneIdle,
+ base::Unretained(this)));
+ break;
+ case kStartingToMove:
+ if (std::abs(location.x() - mouse_move_start_location_.x()) >
+ kMinMovementPixels ||
+ std::abs(location.y() - mouse_move_start_location_.y()) >
+ kMinMovementPixels) {
+ set_mouse_move_behavior(kRecentlyMovedOrClicked);
+ mouse_activity_ended_timer_.Reset();
+ }
+ break;
+ case kRecentlyMovedOrClicked:
+ mouse_activity_ended_timer_.Reset();
+ break;
+ }
+
+ if (mouse_move_behavior() == kRecentlyMovedOrClicked) {
+ UpdateOverlay(location);
+ }
+}
+
+void MouseCursorOverlayController::OnMouseClicked(const gfx::PointF& location) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(ui_sequence_checker_);
+
+ if (mouse_activity_ended_timer_.IsRunning()) {
+ mouse_activity_ended_timer_.Reset();
+ } else {
+ mouse_activity_ended_timer_.Start(
+ FROM_HERE, kIdleTimeout,
+ base::BindRepeating(&MouseCursorOverlayController::OnMouseHasGoneIdle,
+ base::Unretained(this)));
+ }
+ set_mouse_move_behavior(kRecentlyMovedOrClicked);
+
+ UpdateOverlay(location);
+}
+
+void MouseCursorOverlayController::OnMouseHasGoneIdle() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(ui_sequence_checker_);
+
+ // Note that the following is not redundant since callers other than the timer
+ // may have invoked this method.
+ mouse_activity_ended_timer_.Stop();
+
+ set_mouse_move_behavior(kNotMoving);
+
+ UpdateOverlay(gfx::PointF());
+}
+
+void MouseCursorOverlayController::UpdateOverlay(const gfx::PointF& location) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(ui_sequence_checker_);
+
+ if (!overlay_) {
+ return;
+ }
+
+ // Breaking out of the following do-block indicates one or more prerequisites
+ // are not met and the cursor should be(come) hidden.
+ do {
+ // If the mouse has not recently moved, hide the overlay.
+ if (mouse_move_behavior() != kRecentlyMovedOrClicked) {
+ break;
+ }
+
+ const gfx::NativeCursor cursor = GetCurrentCursorOrDefault();
+ const gfx::RectF relative_bounds =
+ ComputeRelativeBoundsForOverlay(cursor, location);
+
+ // If the cursor (and, by implication, the cursor image) has not changed,
+ // just move the overlay to its new position, if any.
+ if (cursor == last_cursor_) {
+ if (bounds_ != relative_bounds) {
+ bounds_ = relative_bounds;
+ overlay_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&Overlay::SetBounds,
+ base::Unretained(overlay_.get()), bounds_));
+ }
+ return;
+ }
+
+ // The cursor image has changed. Edge-case: If the platform does not provide
+ // a cursor image (e.g., this can occur at browser shutdown), just hide the
+ // overlay.
+ const SkBitmap cursor_image = GetCursorImage(cursor);
+ if (cursor_image.drawsNothing()) {
+ last_cursor_ = gfx::NativeCursor();
+ break;
+ }
+ last_cursor_ = cursor;
+ bounds_ = relative_bounds;
+ overlay_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&Overlay::SetImageAndBounds,
+ base::Unretained(overlay_.get()),
+ cursor_image, bounds_));
+ return;
+ } while (false);
+
+ // If this point has been reached, then the overlay should be hidden.
+ if (!bounds_.IsEmpty()) {
+ bounds_ = gfx::RectF();
+ overlay_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&Overlay::SetBounds,
+ base::Unretained(overlay_.get()), bounds_));
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/capture/mouse_cursor_overlay_controller.h b/chromium/content/browser/media/capture/mouse_cursor_overlay_controller.h
new file mode 100644
index 00000000000..5902ac6db24
--- /dev/null
+++ b/chromium/content/browser/media/capture/mouse_cursor_overlay_controller.h
@@ -0,0 +1,164 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_MEDIA_CAPTURE_MOUSE_CURSOR_OVERLAY_CONTROLLER_H_
+#define CONTENT_BROWSER_MEDIA_CAPTURE_MOUSE_CURSOR_OVERLAY_CONTROLLER_H_
+
+#include <atomic>
+#include <memory>
+
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/sequence_checker.h"
+#include "base/sequenced_task_runner.h"
+#include "base/timer/timer.h"
+#include "content/common/content_export.h"
+#include "services/viz/privileged/interfaces/compositing/frame_sink_video_capture.mojom.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/cursor/cursor.h"
+#include "ui/gfx/geometry/point_f.h"
+#include "ui/gfx/geometry/rect_f.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/native_widget_types.h"
+
+namespace content {
+
+// MouseCursorOverlayController is used by FrameSinkVideoCaptureDevice to manage
+// the mouse cursor overlay in the viz::FrameSinkVideoCapturer session based on
+// the behavior of the mouse cursor reported by the windowing system.
+//
+// All parts of this class are meant to run on the UI BrowserThread, except for
+// IsUserInteractingWithView(), which may be called from any thread. It is up to
+// the client code to ensure the controller's lifetime while in use across
+// multiple threads.
+class CONTENT_EXPORT MouseCursorOverlayController {
+ public:
+ using Overlay = viz::mojom::FrameSinkVideoCaptureOverlay;
+
+ MouseCursorOverlayController();
+ ~MouseCursorOverlayController();
+
+ // Sets a new target view to monitor for mouse cursor updates.
+ void SetTargetView(gfx::NativeView view);
+
+ // Takes ownership of and starts controlling the given |overlay|, invoking its
+ // methods (and destruction) via the given |task_runner|.
+ void Start(std::unique_ptr<Overlay> overlay,
+ scoped_refptr<base::SequencedTaskRunner> task_runner);
+
+ // Stops controlling the Overlay (passed to Start()) and schedules its
+ // destruction.
+ void Stop();
+
+ // Returns true if the user has recently interacted with the view.
+ bool IsUserInteractingWithView() const;
+
+ // Returns a weak pointer.
+ base::WeakPtr<MouseCursorOverlayController> GetWeakPtr();
+
+ private:
+ friend class MouseCursorOverlayControllerBrowserTest;
+
+ // Observes mouse events from the windowing system and reports them via
+ // OnMouseMoved(), OnMouseClicked(), and OnMouseHasGoneIdle().
+ class Observer;
+
+ enum MouseMoveBehavior {
+ kNotMoving, // Mouse has not moved recently.
+ kStartingToMove, // Mouse has moved, but not significantly.
+ kRecentlyMovedOrClicked, // Sufficient mouse activity present.
+ };
+
+ // Called from platform-specific code to report on mouse events within the
+ // captured view.
+ void OnMouseMoved(const gfx::PointF& location);
+ void OnMouseClicked(const gfx::PointF& location);
+
+ // Called by the |mouse_activity_ended_timer_| once no mouse events have
+ // occurred for kIdleTimeout. Also, called by platform-specific code when
+ // changing the target view.
+ void OnMouseHasGoneIdle();
+
+ // Accessors for |mouse_move_behavior_atomic_|. See comments below.
+ MouseMoveBehavior mouse_move_behavior() const {
+ return mouse_move_behavior_atomic_.load(std::memory_order_relaxed);
+ }
+ void set_mouse_move_behavior(MouseMoveBehavior behavior) {
+ mouse_move_behavior_atomic_.store(behavior, std::memory_order_relaxed);
+ }
+
+ // Examines the current mouse movement behavior, view properties, and cursor
+ // changes to determine whether to show or hide the overlay. |location| is the
+ // current mouse cursor location.
+ void UpdateOverlay(const gfx::PointF& location);
+
+ // Returns the current mouse cursor. The default "arrow pointer" cursor will
+ // be returned in lieu of a null cursor.
+ gfx::NativeCursor GetCurrentCursorOrDefault() const;
+
+ // Computes where the overlay should be shown, in terms of relative
+ // coordinates. This takes the view size, coordinate systems of the view and
+ // cursor bitmap, and cursor hotspot offset; all into account.
+ gfx::RectF ComputeRelativeBoundsForOverlay(const gfx::NativeCursor& cursor,
+ const gfx::PointF& location) const;
+
+ // Called after SetTargetView() to ignore mouse events from the
+ // platform/toolkit and set a default mouse cursor. This is used by the
+ // browser tests to prevent actual mouse movement from interfering with the
+ // testing of the control logic.
+ void DisconnectFromToolkitForTesting();
+
+ // Returns the image of the mouse cursor.
+ static SkBitmap GetCursorImage(const gfx::NativeCursor&);
+
+ // Platform-specific mouse event observer. Updated by SetTargetView().
+ std::unique_ptr<Observer> observer_;
+
+ // Updated in the mouse event handlers and used to decide whether the user is
+ // interacting with the view and whether to update the overlay.
+ gfx::PointF mouse_move_start_location_;
+ base::OneShotTimer mouse_activity_ended_timer_;
+
+ // Updated in the mouse event handlers and read by IsUserInteractingWithView()
+ // (on any thread). This is not protected by a mutex since strict memory
+ // ordering semantics are not necessary, just atomicity between threads. All
+ // code should use the accessors to read or set this value.
+ std::atomic<MouseMoveBehavior> mouse_move_behavior_atomic_;
+
+ // The overlay being controlled, and the task runner to use to invoke its
+ // methods and destruction.
+ std::unique_ptr<Overlay> overlay_;
+ scoped_refptr<base::SequencedTaskRunner> overlay_task_runner_;
+
+ // The last-shown mouse cursor. UpdateOverlay() uses this to determine whether
+ // to update the cursor image, or just the overlay position.
+ gfx::NativeCursor last_cursor_ = gfx::NativeCursor();
+
+ // This is empty if the overlay should be hidden. Otherwise, it represents a
+ // shown overlay with a relative position within the view in terms of the
+ // range [0.0,1.0). It can sometimes be a little bit outside of that range,
+ // depending on the cursor's hotspot.
+ gfx::RectF bounds_;
+
+ // Everything except the constructor and IsUserInteractingWithView() must be
+ // called on the UI BrowserThread.
+ SEQUENCE_CHECKER(ui_sequence_checker_);
+
+ base::WeakPtrFactory<MouseCursorOverlayController> weak_factory_;
+
+ // Minium movement before the cursor has been considered intentionally moved
+ // by the user.
+ static constexpr int kMinMovementPixels = 15;
+
+ // Amount of time to elapse with no mouse activity before the cursor should
+ // stop showing.
+ static constexpr base::TimeDelta kIdleTimeout =
+ base::TimeDelta::FromSeconds(2);
+
+ DISALLOW_COPY_AND_ASSIGN(MouseCursorOverlayController);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MEDIA_CAPTURE_MOUSE_CURSOR_OVERLAY_CONTROLLER_H_
diff --git a/chromium/content/browser/media/capture/mouse_cursor_overlay_controller_aura.cc b/chromium/content/browser/media/capture/mouse_cursor_overlay_controller_aura.cc
new file mode 100644
index 00000000000..0075be20bb2
--- /dev/null
+++ b/chromium/content/browser/media/capture/mouse_cursor_overlay_controller_aura.cc
@@ -0,0 +1,226 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/media/capture/mouse_cursor_overlay_controller.h"
+
+#include "ui/aura/window.h"
+#include "ui/aura/window_tree_host.h"
+#include "ui/base/cursor/cursor.h"
+#include "ui/base/cursor/cursor_loader.h"
+#include "ui/base/cursor/cursor_type.h"
+#include "ui/events/event.h"
+#include "ui/events/event_handler.h"
+#include "ui/wm/public/activation_client.h"
+
+namespace content {
+
+namespace {
+
+ui::Cursor CreateDefaultPointerCursor() {
+ ui::Cursor cursor(ui::CursorType::kPointer);
+ std::unique_ptr<ui::CursorLoader> loader(ui::CursorLoader::Create());
+ loader->SetPlatformCursor(&cursor);
+ return cursor;
+}
+
+} // namespace
+
+class MouseCursorOverlayController::Observer : public ui::EventHandler,
+ public aura::WindowObserver {
+ public:
+ explicit Observer(MouseCursorOverlayController* controller,
+ aura::Window* window)
+ : controller_(controller), window_(window) {
+ DCHECK(controller_);
+ DCHECK(window_);
+ controller_->OnMouseHasGoneIdle();
+ window_->AddObserver(this);
+ window_->AddPreTargetHandler(this);
+ }
+
+ ~Observer() final {
+ if (window_) {
+ OnWindowDestroying(window_);
+ }
+ }
+
+ void StopTracking() {
+ if (window_) {
+ window_->RemovePreTargetHandler(this);
+ controller_->OnMouseHasGoneIdle();
+ }
+ }
+
+ static aura::Window* GetTargetWindow(
+ const std::unique_ptr<Observer>& observer) {
+ if (observer) {
+ return observer->window_;
+ }
+ return nullptr;
+ }
+
+ private:
+ bool IsWindowActive() const {
+ if (window_) {
+ if (auto* root_window = window_->GetRootWindow()) {
+ if (window_ == root_window) {
+ return true;
+ }
+ if (auto* client = wm::GetActivationClient(root_window)) {
+ if (auto* active_window = client->GetActiveWindow()) {
+ return active_window->Contains(window_);
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ gfx::PointF AsLocationInWindow(const ui::Event& event) const {
+ gfx::PointF location = event.AsLocatedEvent()->location_f();
+ if (event.target() != window_) {
+ aura::Window::ConvertPointToTarget(
+ static_cast<aura::Window*>(event.target()), window_, &location);
+ }
+ return location;
+ }
+
+ // ui::EventHandler overrides.
+ void OnEvent(ui::Event* event) final {
+ switch (event->type()) {
+ case ui::ET_MOUSE_DRAGGED:
+ case ui::ET_MOUSE_MOVED:
+ case ui::ET_MOUSE_ENTERED:
+ case ui::ET_MOUSE_EXITED:
+ case ui::ET_TOUCH_MOVED:
+ if (IsWindowActive()) {
+ controller_->OnMouseMoved(AsLocationInWindow(*event));
+ }
+ break;
+
+ case ui::ET_MOUSE_PRESSED:
+ case ui::ET_MOUSE_RELEASED:
+ case ui::ET_MOUSEWHEEL:
+ case ui::ET_TOUCH_PRESSED:
+ case ui::ET_TOUCH_RELEASED: {
+ controller_->OnMouseClicked(AsLocationInWindow(*event));
+ break;
+ }
+
+ default:
+ return;
+ }
+ }
+
+ // aura::WindowObserver overrides.
+ void OnWindowDestroying(aura::Window* window) final {
+ DCHECK_EQ(window_, window);
+ StopTracking();
+ window_->RemoveObserver(this);
+ window_ = nullptr;
+ }
+
+ MouseCursorOverlayController* const controller_;
+ aura::Window* window_;
+
+ DISALLOW_COPY_AND_ASSIGN(Observer);
+};
+
+MouseCursorOverlayController::MouseCursorOverlayController()
+ : mouse_move_behavior_atomic_(kNotMoving), weak_factory_(this) {
+ // MouseCursorOverlayController can be constructed on any thread, but
+ // thereafter must be used according to class-level comments.
+ DETACH_FROM_SEQUENCE(ui_sequence_checker_);
+}
+
+MouseCursorOverlayController::~MouseCursorOverlayController() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(ui_sequence_checker_);
+
+ observer_.reset();
+ Stop();
+}
+
+void MouseCursorOverlayController::SetTargetView(aura::Window* window) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(ui_sequence_checker_);
+
+ observer_.reset();
+ if (window) {
+ observer_ = std::make_unique<Observer>(this, window);
+ }
+}
+
+gfx::NativeCursor MouseCursorOverlayController::GetCurrentCursorOrDefault()
+ const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(ui_sequence_checker_);
+
+ if (auto* window = Observer::GetTargetWindow(observer_)) {
+ if (auto* host = window->GetHost()) {
+ const gfx::NativeCursor cursor = host->last_cursor();
+ if (cursor != ui::CursorType::kNull) {
+ return cursor;
+ }
+ }
+ }
+
+ return CreateDefaultPointerCursor();
+}
+
+gfx::RectF MouseCursorOverlayController::ComputeRelativeBoundsForOverlay(
+ const gfx::NativeCursor& cursor,
+ const gfx::PointF& location) const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(ui_sequence_checker_);
+
+ if (auto* window = Observer::GetTargetWindow(observer_)) {
+ const gfx::Size window_size = window->bounds().size();
+ if (!window_size.IsEmpty()) {
+ if (auto* root_window = window->GetRootWindow()) {
+ // Compute the cursor size in terms of DIP coordinates.
+ const SkBitmap& bitmap = cursor.GetBitmap();
+ const float scale_factor = cursor.device_scale_factor();
+ const gfx::SizeF size =
+ scale_factor > 0.0f
+ ? gfx::ScaleSize(gfx::SizeF(bitmap.width(), bitmap.height()),
+ 1.0f / scale_factor)
+ : gfx::SizeF(bitmap.width(), bitmap.height());
+
+ // Compute the hotspot in terms of DIP coordinates.
+ const gfx::PointF hotspot =
+ scale_factor > 0.0f
+ ? gfx::ScalePoint(gfx::PointF(cursor.GetHotspot()),
+ 1.0f / scale_factor)
+ : gfx::PointF(cursor.GetHotspot());
+
+ // Finally, put it all together: Scale the absolute bounds of the
+ // overlay by the window size to produce relative coordinates.
+ return gfx::ScaleRect(
+ gfx::RectF(location - hotspot.OffsetFromOrigin(), size),
+ 1.0f / window_size.width(), 1.0f / window_size.height());
+ }
+ }
+ }
+
+ return gfx::RectF();
+}
+
+void MouseCursorOverlayController::DisconnectFromToolkitForTesting() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(ui_sequence_checker_);
+
+ observer_->StopTracking();
+
+ // The default cursor is ui::CursorType::kNone. Make it kPointer so the tests
+ // have a non-empty cursor bitmap to work with.
+ auto* const window = Observer::GetTargetWindow(observer_);
+ CHECK(window);
+ auto* const host = window->GetHost();
+ CHECK(host);
+ host->SetCursor(CreateDefaultPointerCursor());
+}
+
+// static
+SkBitmap MouseCursorOverlayController::GetCursorImage(
+ const gfx::NativeCursor& cursor) {
+ return cursor.GetBitmap();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/capture/mouse_cursor_overlay_controller_browsertest.cc b/chromium/content/browser/media/capture/mouse_cursor_overlay_controller_browsertest.cc
new file mode 100644
index 00000000000..5a05b17ff0b
--- /dev/null
+++ b/chromium/content/browser/media/capture/mouse_cursor_overlay_controller_browsertest.cc
@@ -0,0 +1,260 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/media/capture/mouse_cursor_overlay_controller.h"
+
+#include "base/macros.h"
+#include "base/run_loop.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/shell/browser/shell.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/geometry/point_f.h"
+#include "ui/gfx/geometry/rect_f.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/geometry/size_f.h"
+
+namespace content {
+namespace {
+
+class FakeOverlay : public MouseCursorOverlayController::Overlay {
+ public:
+ FakeOverlay() = default;
+ ~FakeOverlay() final = default;
+
+ const SkBitmap& image() const { return image_; }
+ const gfx::RectF& bounds() const { return bounds_; }
+
+ void SetImageAndBounds(const SkBitmap& image,
+ const gfx::RectF& bounds) final {
+ image_ = image;
+ bounds_ = bounds;
+ }
+
+ void SetBounds(const gfx::RectF& bounds) final { bounds_ = bounds; }
+
+ private:
+ SkBitmap image_;
+ gfx::RectF bounds_;
+
+ DISALLOW_COPY_AND_ASSIGN(FakeOverlay);
+};
+
+} // namespace
+
+class MouseCursorOverlayControllerBrowserTest : public ContentBrowserTest {
+ public:
+ MouseCursorOverlayControllerBrowserTest() = default;
+ ~MouseCursorOverlayControllerBrowserTest() override = default;
+
+ void SetUpOnMainThread() final {
+ ContentBrowserTest::SetUpOnMainThread();
+ controller_.SetTargetView(shell()->web_contents()->GetNativeView());
+ controller_.DisconnectFromToolkitForTesting();
+ base::RunLoop().RunUntilIdle();
+ }
+
+ FakeOverlay* Start() {
+ auto overlay_ptr = std::make_unique<FakeOverlay>();
+ FakeOverlay* const overlay = overlay_ptr.get();
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ controller_.Start(std::move(overlay_ptr),
+ BrowserThread::GetTaskRunnerForThread(BrowserThread::UI));
+ return overlay;
+ }
+
+ gfx::PointF GetLowerRightMostPointInsideView() {
+ const gfx::Size& view_size = GetAbsoluteViewSize();
+ return gfx::PointF(1.0f - 1.0f / view_size.width(),
+ 1.0f - 1.0f / view_size.height());
+ }
+
+ void SimulateMouseTravel(float from_x, float from_y, float to_x, float to_y) {
+ constexpr int kNumMoves = 10;
+ for (int i = kNumMoves; i >= 0; --i) {
+ const float t = static_cast<float>(i) / kNumMoves;
+ const float x = t * from_x + (1.0f - t) * to_x;
+ const float y = t * from_y + (1.0f - t) * to_y;
+ controller_.OnMouseMoved(ToAbsoluteLocationInView(x, y));
+ }
+ base::RunLoop().RunUntilIdle();
+ }
+
+ void SimulateMouseClick(float x, float y) {
+ controller_.OnMouseClicked(ToAbsoluteLocationInView(x, y));
+ base::RunLoop().RunUntilIdle();
+ }
+
+ void SimulateMouseHasGoneIdle() {
+ controller_.OnMouseHasGoneIdle();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(controller_.mouse_activity_ended_timer_.IsRunning());
+ }
+
+ void SimulateUnintentionalMouseMovement(float x, float y) {
+ const gfx::Size& view_size = GetAbsoluteViewSize();
+ const float distance_x =
+ (0.5f * MouseCursorOverlayController::kMinMovementPixels) /
+ view_size.width();
+ const float distance_y =
+ (0.5f * MouseCursorOverlayController::kMinMovementPixels) /
+ view_size.height();
+ DoSquareDance(x, y, distance_x, distance_y);
+ }
+
+ void SimulateBarelyIntentionalMouseMovement(float x, float y) {
+ const gfx::Size& view_size = GetAbsoluteViewSize();
+ const float distance_x =
+ (1.5f * MouseCursorOverlayController::kMinMovementPixels) /
+ view_size.width();
+ const float distance_y =
+ (1.5f * MouseCursorOverlayController::kMinMovementPixels) /
+ view_size.height();
+ DoSquareDance(x, y, distance_x, distance_y);
+ }
+
+ void ExpectOverlayPositionedAt(const FakeOverlay& overlay,
+ float expected_x,
+ float expected_y) {
+ const gfx::SizeF& overlay_size = GetExpectedOverlaySize();
+ // The position will be slightly off because of the hotspot offset.
+ EXPECT_NEAR(expected_x, overlay.bounds().x(), overlay_size.width() / 2.0f);
+ EXPECT_NEAR(expected_y, overlay.bounds().y(), overlay_size.height() / 2.0f);
+ }
+
+ void ExpectOverlaySizeMatchesCurrentCursor(const FakeOverlay& overlay) const {
+ const gfx::SizeF& expected_size = GetExpectedOverlaySize();
+ EXPECT_FALSE(expected_size.IsEmpty());
+ EXPECT_FALSE(overlay.image().drawsNothing());
+ EXPECT_NEAR(expected_size.width(), overlay.bounds().width(), 0.001);
+ EXPECT_NEAR(expected_size.height(), overlay.bounds().height(), 0.001);
+ }
+
+ bool IsUserInteractingWithView() const {
+ return controller_.IsUserInteractingWithView();
+ }
+
+ private:
+ gfx::Size GetAbsoluteViewSize() const {
+ const gfx::Size view_size =
+ shell()->web_contents()->GetContainerBounds().size();
+ CHECK(!view_size.IsEmpty());
+ return view_size;
+ }
+
+ gfx::PointF ToAbsoluteLocationInView(float relative_x, float relative_y) {
+ const gfx::Size& view_size = GetAbsoluteViewSize();
+ return gfx::PointF(relative_x * view_size.width(),
+ relative_y * view_size.height());
+ }
+
+ gfx::SizeF GetExpectedOverlaySize() const {
+ const gfx::Size& view_size = GetAbsoluteViewSize();
+ const SkBitmap image =
+ controller_.GetCursorImage(controller_.GetCurrentCursorOrDefault());
+ return gfx::SizeF(static_cast<float>(image.width()) / view_size.width(),
+ static_cast<float>(image.height()) / view_size.height());
+ }
+
+ void DoSquareDance(float x, float y, float distance_x, float distance_y) {
+ SimulateMouseTravel(x, y, x + distance_x, y);
+ SimulateMouseTravel(x + distance_x, y, x + distance_x, y + distance_y);
+ SimulateMouseTravel(x + distance_x, y + distance_y, x, y + distance_y);
+ SimulateMouseTravel(x, y + distance_y, x, y);
+ base::RunLoop().RunUntilIdle();
+ }
+
+ MouseCursorOverlayController controller_;
+
+ DISALLOW_COPY_AND_ASSIGN(MouseCursorOverlayControllerBrowserTest);
+};
+
+IN_PROC_BROWSER_TEST_F(MouseCursorOverlayControllerBrowserTest,
+ PositionsOverlayOnMouseMoves) {
+ FakeOverlay* const overlay = Start();
+
+ // Cursor not showing at start.
+ EXPECT_TRUE(overlay->image().drawsNothing());
+ EXPECT_TRUE(overlay->bounds().IsEmpty());
+ EXPECT_FALSE(IsUserInteractingWithView());
+
+ // Move to upper-leftmost corner.
+ {
+ SCOPED_TRACE(testing::Message() << "upper-leftmost corner of view");
+ SimulateMouseTravel(0.5f, 0.5f, 0.0f, 0.0f);
+ ExpectOverlayPositionedAt(*overlay, 0.0f, 0.0f);
+ ExpectOverlaySizeMatchesCurrentCursor(*overlay);
+ EXPECT_TRUE(IsUserInteractingWithView());
+ }
+
+ // Move to middle.
+ {
+ SCOPED_TRACE(testing::Message() << "center of view");
+ SimulateMouseTravel(0.0f, 0.0f, 0.5f, 0.5f);
+ ExpectOverlayPositionedAt(*overlay, 0.5f, 0.5f);
+ ExpectOverlaySizeMatchesCurrentCursor(*overlay);
+ EXPECT_TRUE(IsUserInteractingWithView());
+ }
+
+ // Move to lower-rightmost corner.
+ {
+ SCOPED_TRACE(testing::Message() << "lower-rightmost corner of view");
+ const gfx::PointF lower_right = GetLowerRightMostPointInsideView();
+ SimulateMouseTravel(0.5f, 0.5f, lower_right.x(), lower_right.y());
+ ExpectOverlayPositionedAt(*overlay, lower_right.x(), lower_right.y());
+ ExpectOverlaySizeMatchesCurrentCursor(*overlay);
+ EXPECT_TRUE(IsUserInteractingWithView());
+ }
+}
+
+IN_PROC_BROWSER_TEST_F(MouseCursorOverlayControllerBrowserTest,
+ PositionsOverlayOnMouseClicks) {
+ FakeOverlay* const overlay = Start();
+
+ // Cursor not showing at start.
+ EXPECT_TRUE(overlay->bounds().IsEmpty());
+ EXPECT_FALSE(IsUserInteractingWithView());
+
+ // Click in the middle of the view.
+ SimulateMouseClick(0.5f, 0.5f);
+ ExpectOverlayPositionedAt(*overlay, 0.5f, 0.5f);
+ ExpectOverlaySizeMatchesCurrentCursor(*overlay);
+ EXPECT_TRUE(IsUserInteractingWithView());
+}
+
+IN_PROC_BROWSER_TEST_F(MouseCursorOverlayControllerBrowserTest,
+ CursorHidesWhenMouseStopsMoving) {
+ FakeOverlay* const overlay = Start();
+
+ // Cursor not showing at start.
+ EXPECT_TRUE(overlay->bounds().IsEmpty());
+ EXPECT_FALSE(IsUserInteractingWithView());
+
+ // Move to middle.
+ SimulateMouseTravel(0.0f, 0.0f, 0.5f, 0.5f);
+ ExpectOverlayPositionedAt(*overlay, 0.5f, 0.5f);
+ ExpectOverlaySizeMatchesCurrentCursor(*overlay);
+ EXPECT_TRUE(IsUserInteractingWithView());
+
+ // Simulate no movement for the timeout period.
+ SimulateMouseHasGoneIdle();
+ EXPECT_TRUE(overlay->bounds().IsEmpty());
+ EXPECT_FALSE(IsUserInteractingWithView());
+
+ // Move the mouse a little, but not enough to trip the "intentionally moved"
+ // logic.
+ SimulateUnintentionalMouseMovement(0.5f, 0.5f);
+ EXPECT_TRUE(overlay->bounds().IsEmpty());
+ EXPECT_FALSE(IsUserInteractingWithView());
+
+ // Move the mouse just a bit more, to trip the "intentionally moved" logic.
+ SimulateBarelyIntentionalMouseMovement(0.5f, 0.5f);
+ ExpectOverlayPositionedAt(*overlay, 0.5f, 0.5f);
+ ExpectOverlaySizeMatchesCurrentCursor(*overlay);
+ EXPECT_TRUE(IsUserInteractingWithView());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/capture/mouse_cursor_overlay_controller_mac.mm b/chromium/content/browser/media/capture/mouse_cursor_overlay_controller_mac.mm
new file mode 100644
index 00000000000..fa6a82e6e37
--- /dev/null
+++ b/chromium/content/browser/media/capture/mouse_cursor_overlay_controller_mac.mm
@@ -0,0 +1,198 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/media/capture/mouse_cursor_overlay_controller.h"
+
+#include <Cocoa/Cocoa.h>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/callback.h"
+#include "base/mac/mac_util.h"
+#include "base/mac/scoped_nsobject.h"
+#include "skia/ext/skia_utils_mac.h"
+#include "ui/base/cocoa/tracking_area.h"
+
+namespace {
+using LocationUpdateCallback = base::RepeatingCallback<void(const NSPoint&)>;
+} // namespace;
+
+// Uses a CrTrackingArea to monitor for mouse events and forwards them to the
+// MouseCursorOverlayController::Observer.
+@interface MouseCursorOverlayTracker : NSObject {
+ @private
+ LocationUpdateCallback callback_;
+ ui::ScopedCrTrackingArea trackingArea_;
+}
+- (instancetype)initWithCallback:(LocationUpdateCallback)callback
+ andView:(NSView*)nsView;
+- (void)stopTracking:(NSView*)nsView;
+@end
+
+@implementation MouseCursorOverlayTracker
+
+- (instancetype)initWithCallback:(LocationUpdateCallback)callback
+ andView:(NSView*)nsView {
+ if ((self = [super init])) {
+ callback_ = std::move(callback);
+ constexpr NSTrackingAreaOptions kTrackingOptions =
+ NSTrackingMouseMoved | NSTrackingMouseEnteredAndExited |
+ NSTrackingActiveInKeyWindow | NSTrackingInVisibleRect |
+ NSTrackingEnabledDuringMouseDrag;
+ trackingArea_.reset([[CrTrackingArea alloc] initWithRect:NSZeroRect
+ options:kTrackingOptions
+ owner:self
+ userInfo:nil]);
+ [nsView addTrackingArea:trackingArea_.get()];
+ }
+ return self;
+}
+
+- (void)stopTracking:(NSView*)nsView {
+ [nsView removeTrackingArea:trackingArea_.get()];
+ trackingArea_.reset();
+ callback_.Reset();
+}
+
+- (void)mouseMoved:(NSEvent*)theEvent {
+ callback_.Run([theEvent locationInWindow]);
+}
+
+- (void)mouseEntered:(NSEvent*)theEvent {
+ callback_.Run([theEvent locationInWindow]);
+}
+
+- (void)mouseExited:(NSEvent*)theEvent {
+ callback_.Run([theEvent locationInWindow]);
+}
+
+@end
+
+namespace content {
+
+class MouseCursorOverlayController::Observer {
+ public:
+ explicit Observer(MouseCursorOverlayController* controller, NSView* view)
+ : controller_(controller), view_([view retain]) {
+ DCHECK(controller_);
+ DCHECK(view_);
+ controller_->OnMouseHasGoneIdle();
+ mouse_tracker_.reset([[MouseCursorOverlayTracker alloc]
+ initWithCallback:base::BindRepeating(&Observer::OnMouseMoved,
+ base::Unretained(this))
+ andView:view_.get()]);
+ }
+
+ ~Observer() { StopTracking(); }
+
+ void StopTracking() {
+ if (mouse_tracker_) {
+ [mouse_tracker_ stopTracking:view_.get()];
+ mouse_tracker_.reset();
+ controller_->OnMouseHasGoneIdle();
+ }
+ }
+
+ static NSView* GetTargetView(const std::unique_ptr<Observer>& observer) {
+ if (observer) {
+ return observer->view_.get();
+ }
+ return nil;
+ }
+
+ private:
+ void OnMouseMoved(const NSPoint& location_in_window) {
+ // Compute the location within the view using Aura conventions: (0,0) is the
+ // upper-left corner. So, if the NSView is flipped in Cocoa, it's not
+ // flipped in Aura.
+ NSPoint location_aura =
+ [view_ convertPoint:location_in_window fromView:nil];
+ if (![view_ isFlipped]) {
+ location_aura.y = NSHeight([view_ bounds]) - location_aura.y;
+ }
+ controller_->OnMouseMoved(gfx::PointF(location_aura.x, location_aura.y));
+ }
+
+ MouseCursorOverlayController* const controller_;
+ base::scoped_nsobject<NSView> view_;
+ base::scoped_nsobject<MouseCursorOverlayTracker> mouse_tracker_;
+
+ DISALLOW_COPY_AND_ASSIGN(Observer);
+};
+
+MouseCursorOverlayController::MouseCursorOverlayController()
+ : mouse_move_behavior_atomic_(kNotMoving), weak_factory_(this) {
+ // MouseCursorOverlayController can be constructed on any thread, but
+ // thereafter must be used according to class-level comments.
+ DETACH_FROM_SEQUENCE(ui_sequence_checker_);
+}
+
+MouseCursorOverlayController::~MouseCursorOverlayController() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(ui_sequence_checker_);
+
+ observer_.reset();
+ Stop();
+}
+
+void MouseCursorOverlayController::SetTargetView(NSView* view) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(ui_sequence_checker_);
+
+ observer_.reset();
+ if (view) {
+ observer_ = std::make_unique<Observer>(this, view);
+ }
+}
+
+gfx::NativeCursor MouseCursorOverlayController::GetCurrentCursorOrDefault()
+ const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(ui_sequence_checker_);
+
+ NSCursor* cursor = [NSCursor currentCursor];
+ if (!cursor) {
+ cursor = [NSCursor arrowCursor];
+ }
+ return cursor;
+}
+
+gfx::RectF MouseCursorOverlayController::ComputeRelativeBoundsForOverlay(
+ const gfx::NativeCursor& cursor,
+ const gfx::PointF& location_aura) const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(ui_sequence_checker_);
+
+ if (NSView* view = Observer::GetTargetView(observer_)) {
+ const NSRect view_bounds = [view bounds];
+ if (!NSIsEmptyRect(view_bounds)) {
+ // The documentation on NSCursor reference states that the hot spot is in
+ // flipped coordinates which, from the perspective of the Aura coordinate
+ // system, means it's not flipped.
+ const NSPoint hotspot = [cursor hotSpot];
+ const NSSize size = [[cursor image] size];
+ return gfx::ScaleRect(
+ gfx::RectF(location_aura.x() - hotspot.x,
+ location_aura.y() - hotspot.y, size.width, size.height),
+ 1.0 / NSWidth(view_bounds), 1.0 / NSHeight(view_bounds));
+ }
+ }
+
+ return gfx::RectF();
+}
+
+void MouseCursorOverlayController::DisconnectFromToolkitForTesting() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(ui_sequence_checker_);
+
+ observer_->StopTracking();
+
+ // Note: Not overriding the mouse cursor since the default is already
+ // [NSCursor arrowCursor], which provides the tests a bitmap they can work
+ // with.
+}
+
+// static
+SkBitmap MouseCursorOverlayController::GetCursorImage(
+ const gfx::NativeCursor& cursor) {
+ return skia::NSImageToSkBitmapWithColorSpace(
+ [cursor image], /*is_opaque=*/false, base::mac::GetSystemColorSpace());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/capture/screen_capture_device_android.cc b/chromium/content/browser/media/capture/screen_capture_device_android.cc
index 9d5cf896498..d97c36be52c 100644
--- a/chromium/content/browser/media/capture/screen_capture_device_android.cc
+++ b/chromium/content/browser/media/capture/screen_capture_device_android.cc
@@ -25,8 +25,10 @@ void ScreenCaptureDeviceAndroid::AllocateAndStart(
if (params.requested_format.pixel_format != media::PIXEL_FORMAT_I420) {
client->OnError(
- FROM_HERE, "unsupported format: " + media::VideoCaptureFormat::ToString(
- params.requested_format));
+ media::VideoCaptureError::kAndroidScreenCaptureUnsupportedFormat,
+ FROM_HERE,
+ "unsupported format: " +
+ media::VideoCaptureFormat::ToString(params.requested_format));
return;
}
@@ -34,7 +36,10 @@ void ScreenCaptureDeviceAndroid::AllocateAndStart(
oracle_proxy_ = new media::ThreadSafeCaptureOracle(std::move(client), params);
if (!capture_machine_.Start(oracle_proxy_, params)) {
- oracle_proxy_->ReportError(FROM_HERE, "Failed to start capture machine.");
+ oracle_proxy_->ReportError(
+ media::VideoCaptureError::
+ kAndroidScreenCaptureFailedToStartCaptureMachine,
+ FROM_HERE, "Failed to start capture machine.");
StopAndDeAllocate();
} else {
// The |capture_machine_| will later report to the |oracle_proxy_| whether
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 dda49dcb222..ffbe9c52a13 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
@@ -36,9 +36,11 @@ class MockDeviceClient : public media::VideoCaptureDevice::Client {
MOCK_METHOD0(DoOnIncomingCapturedBuffer, void(void));
MOCK_METHOD0(DoOnIncomingCapturedVideoFrame, void(void));
MOCK_METHOD0(DoResurrectLastOutputBuffer, void(void));
- MOCK_METHOD2(OnError,
- void(const base::Location& from_here,
+ MOCK_METHOD3(OnError,
+ void(media::VideoCaptureError error,
+ const base::Location& from_here,
const std::string& reason));
+ MOCK_METHOD1(OnFrameDropped, void(media::VideoCaptureFrameDropReason reason));
MOCK_CONST_METHOD0(GetBufferPoolUtilization, double(void));
MOCK_METHOD0(OnStarted, void(void));
@@ -95,7 +97,7 @@ TEST_F(ScreenCaptureDeviceAndroidTest, DISABLED_StartAndStop) {
ASSERT_TRUE(capture_device);
std::unique_ptr<MockDeviceClient> client(new MockDeviceClient());
- EXPECT_CALL(*client, OnError(_, _)).Times(0);
+ EXPECT_CALL(*client, OnError(_, _, _)).Times(0);
// |STARTED| is reported asynchronously, which may not be received if capture
// is stopped immediately.
EXPECT_CALL(*client, OnStarted()).Times(AtMost(1));
diff --git a/chromium/content/browser/media/capture/web_contents_audio_input_stream.cc b/chromium/content/browser/media/capture/web_contents_audio_input_stream.cc
index e1593cc807e..75d9bee6e9a 100644
--- a/chromium/content/browser/media/capture/web_contents_audio_input_stream.cc
+++ b/chromium/content/browser/media/capture/web_contents_audio_input_stream.cc
@@ -5,6 +5,7 @@
#include "content/browser/media/capture/web_contents_audio_input_stream.h"
#include <memory>
+#include <set>
#include <string>
#include "base/bind.h"
@@ -60,8 +61,6 @@ class WebContentsAudioInputStream::Impl
private:
friend class base::RefCountedThreadSafe<WebContentsAudioInputStream::Impl>;
- typedef AudioMirroringManager::SourceFrameRef SourceFrameRef;
-
enum State {
CONSTRUCTED,
OPENED,
@@ -88,10 +87,11 @@ class WebContentsAudioInputStream::Impl
void UnmuteWebContentsAudio();
// AudioMirroringManager::MirroringDestination implementation
- void QueryForMatches(const std::set<SourceFrameRef>& candidates,
- const MatchesCallback& results_callback) override;
- void QueryForMatchesOnUIThread(const std::set<SourceFrameRef>& candidates,
- const MatchesCallback& results_callback);
+ void QueryForMatches(const std::set<GlobalFrameRoutingId>& candidates,
+ MatchesCallback results_callback) override;
+ void QueryForMatchesOnUIThread(
+ const std::set<GlobalFrameRoutingId>& candidates,
+ MatchesCallback results_callback);
media::AudioOutputStream* AddInput(
const media::AudioParameters& params) override;
media::AudioPushSink* AddPushInput(
@@ -297,35 +297,34 @@ void WebContentsAudioInputStream::Impl::UnmuteWebContentsAudio() {
}
void WebContentsAudioInputStream::Impl::QueryForMatches(
- const std::set<SourceFrameRef>& candidates,
- const MatchesCallback& results_callback) {
+ const std::set<GlobalFrameRoutingId>& candidates,
+ MatchesCallback results_callback) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::BindOnce(&Impl::QueryForMatchesOnUIThread, this, candidates,
- media::BindToCurrentLoop(results_callback)));
+ media::BindToCurrentLoop(std::move(results_callback))));
}
void WebContentsAudioInputStream::Impl::QueryForMatchesOnUIThread(
- const std::set<SourceFrameRef>& candidates,
- const MatchesCallback& results_callback) {
+ const std::set<GlobalFrameRoutingId>& candidates,
+ MatchesCallback results_callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- std::set<SourceFrameRef> matches;
+ std::set<GlobalFrameRoutingId> matches;
WebContents* const contents = tracker_->web_contents();
if (contents) {
// Add each ID to |matches| if it maps to a RenderFrameHost that maps to the
// currently-tracked WebContents.
- for (std::set<SourceFrameRef>::const_iterator i = candidates.begin();
- i != candidates.end(); ++i) {
+ for (const auto& it : candidates) {
WebContents* const contents_containing_frame =
WebContents::FromRenderFrameHost(
- RenderFrameHost::FromID(i->first, i->second));
+ RenderFrameHost::FromID(it.child_id, it.frame_routing_id));
if (contents_containing_frame == contents)
- matches.insert(*i);
+ matches.insert(it);
}
}
- results_callback.Run(matches, is_duplication_);
+ std::move(results_callback).Run(matches, is_duplication_);
}
media::AudioOutputStream* WebContentsAudioInputStream::Impl::AddInput(
diff --git a/chromium/content/browser/media/capture/web_contents_audio_input_stream_unittest.cc b/chromium/content/browser/media/capture/web_contents_audio_input_stream_unittest.cc
index e0d3842142b..f27817f8604 100644
--- a/chromium/content/browser/media/capture/web_contents_audio_input_stream_unittest.cc
+++ b/chromium/content/browser/media/capture/web_contents_audio_input_stream_unittest.cc
@@ -471,7 +471,9 @@ TEST_P(WebContentsAudioInputStreamTest, MirroringOutputWithinSession) {
RUN_ON_AUDIO_THREAD(Close);
}
-TEST_P(WebContentsAudioInputStreamTest, MirroringNothingWithTargetChange) {
+// TODO(https://crbug.com/872340): Test appears to have timing-dependent flake.
+TEST_P(WebContentsAudioInputStreamTest,
+ DISABLED_MirroringNothingWithTargetChange) {
RUN_ON_AUDIO_THREAD(Open);
RUN_ON_AUDIO_THREAD(Start);
RUN_ON_AUDIO_THREAD(ChangeMirroringTarget);
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 59a30348350..c10f52250b5 100644
--- a/chromium/content/browser/media/capture/web_contents_audio_muter.cc
+++ b/chromium/content/browser/media/capture/web_contents_audio_muter.cc
@@ -80,33 +80,32 @@ class WebContentsAudioMuter::MuteDestination
private:
friend class base::RefCountedThreadSafe<MuteDestination>;
- typedef AudioMirroringManager::SourceFrameRef SourceFrameRef;
-
~MuteDestination() override {}
- void QueryForMatches(const std::set<SourceFrameRef>& candidates,
- const MatchesCallback& results_callback) override {
+ void QueryForMatches(const std::set<GlobalFrameRoutingId>& candidates,
+ MatchesCallback results_callback) override {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::BindOnce(&MuteDestination::QueryForMatchesOnUIThread, this,
- candidates, media::BindToCurrentLoop(results_callback)));
+ candidates,
+ media::BindToCurrentLoop(std::move(results_callback))));
}
- void QueryForMatchesOnUIThread(const std::set<SourceFrameRef>& candidates,
- const MatchesCallback& results_callback) {
+ void QueryForMatchesOnUIThread(
+ const std::set<GlobalFrameRoutingId>& candidates,
+ MatchesCallback results_callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- std::set<SourceFrameRef> matches;
+ std::set<GlobalFrameRoutingId> matches;
// Add each ID to |matches| if it maps to a RenderFrameHost that maps to the
// WebContents being muted.
- for (std::set<SourceFrameRef>::const_iterator i = candidates.begin();
- i != candidates.end(); ++i) {
+ for (const auto& it : candidates) {
WebContents* const contents_containing_frame =
WebContents::FromRenderFrameHost(
- RenderFrameHost::FromID(i->first, i->second));
+ RenderFrameHost::FromID(it.child_id, it.frame_routing_id));
if (contents_containing_frame == web_contents_)
- matches.insert(*i);
+ matches.insert(it);
}
- results_callback.Run(matches, false);
+ std::move(results_callback).Run(matches, false);
}
media::AudioOutputStream* AddInput(
diff --git a/chromium/content/browser/media/capture/web_contents_video_capture_device.cc b/chromium/content/browser/media/capture/web_contents_video_capture_device.cc
index e4122a24cdf..ff8651a5084 100644
--- a/chromium/content/browser/media/capture/web_contents_video_capture_device.cc
+++ b/chromium/content/browser/media/capture/web_contents_video_capture_device.cc
@@ -4,12 +4,15 @@
#include "content/browser/media/capture/web_contents_video_capture_device.h"
+#include <utility>
+
#include "base/bind.h"
#include "base/location.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "content/browser/media/capture/mouse_cursor_overlay_controller.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
@@ -31,14 +34,14 @@ class WebContentsVideoCaptureDevice::FrameTracker
WebContentsVideoCaptureDevice::FrameTracker> {
public:
FrameTracker(base::WeakPtr<WebContentsVideoCaptureDevice> device,
- CursorRenderer* cursor_renderer,
+ MouseCursorOverlayController* cursor_controller,
int render_process_id,
int main_render_frame_id)
: device_(std::move(device)),
device_task_runner_(base::ThreadTaskRunnerHandle::Get()),
- cursor_renderer_(cursor_renderer) {
+ cursor_controller_(cursor_controller) {
DCHECK(device_task_runner_);
- DCHECK(cursor_renderer_);
+ DCHECK(cursor_controller_);
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
@@ -175,10 +178,10 @@ class WebContentsVideoCaptureDevice::FrameTracker
if (native_view != target_native_view_) {
target_native_view_ = native_view;
- // Note: CursorRenderer runs on the UI thread. It's also important that
- // SetTargetView() be called in the current stack while |native_view| is
- // known to be a valid pointer. http://crbug.com/818679
- cursor_renderer_->SetTargetView(native_view);
+ // Note: MouseCursorOverlayController runs on the UI thread. It's also
+ // important that SetTargetView() be called in the current stack while
+ // |native_view| is known to be a valid pointer. http://crbug.com/818679
+ cursor_controller_->SetTargetView(native_view);
}
} else {
device_task_runner_->PostTask(
@@ -186,7 +189,7 @@ class WebContentsVideoCaptureDevice::FrameTracker
base::BindOnce(
&WebContentsVideoCaptureDevice::OnTargetPermanentlyLost,
device_));
- cursor_renderer_->SetTargetView(gfx::NativeView());
+ cursor_controller_->SetTargetView(gfx::NativeView());
}
}
@@ -196,8 +199,8 @@ class WebContentsVideoCaptureDevice::FrameTracker
// Owned by FrameSinkVideoCaptureDevice. This will be valid for the life of
// FrameTracker because the FrameTracker deleter task will be posted to the UI
- // thread before the CursorRenderer deleter task.
- CursorRenderer* const cursor_renderer_;
+ // thread before the MouseCursorOverlayController deleter task.
+ MouseCursorOverlayController* const cursor_controller_;
viz::FrameSinkId target_frame_sink_id_;
gfx::NativeView target_native_view_ = gfx::NativeView();
@@ -212,7 +215,7 @@ WebContentsVideoCaptureDevice::WebContentsVideoCaptureDevice(
int render_process_id,
int main_render_frame_id)
: tracker_(new FrameTracker(AsWeakPtr(),
- cursor_renderer(),
+ cursor_controller(),
render_process_id,
main_render_frame_id)) {}
diff --git a/chromium/content/browser/media/cdm_file_impl.cc b/chromium/content/browser/media/cdm_file_impl.cc
index 4c1657d1b6c..7a0b8ba427b 100644
--- a/chromium/content/browser/media/cdm_file_impl.cc
+++ b/chromium/content/browser/media/cdm_file_impl.cc
@@ -10,7 +10,7 @@
#include "base/callback.h"
#include "base/logging.h"
#include "base/strings/string_util.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "storage/browser/fileapi/file_system_context.h"
#include "storage/browser/fileapi/file_system_operation_context.h"
#include "storage/browser/fileapi/file_system_url.h"
diff --git a/chromium/content/browser/media/flinging_renderer.cc b/chromium/content/browser/media/flinging_renderer.cc
index b6119358422..89ead4205b6 100644
--- a/chromium/content/browser/media/flinging_renderer.cc
+++ b/chromium/content/browser/media/flinging_renderer.cc
@@ -15,10 +15,14 @@
namespace content {
FlingingRenderer::FlingingRenderer(
- std::unique_ptr<media::MediaController> controller)
- : controller_(std::move(controller)) {}
+ std::unique_ptr<media::FlingingController> controller)
+ : controller_(std::move(controller)) {
+ controller_->AddMediaStatusObserver(this);
+}
-FlingingRenderer::~FlingingRenderer() = default;
+FlingingRenderer::~FlingingRenderer() {
+ controller_->RemoveMediaStatusObserver(this);
+};
// static
std::unique_ptr<FlingingRenderer> FlingingRenderer::Create(
@@ -43,15 +47,15 @@ std::unique_ptr<FlingingRenderer> FlingingRenderer::Create(
if (!presentation_delegate)
return nullptr;
- auto media_controller = presentation_delegate->GetMediaController(
+ auto flinging_controller = presentation_delegate->GetFlingingController(
render_frame_host->GetProcess()->GetID(),
render_frame_host->GetRoutingID(), presentation_id);
- if (!media_controller)
+ if (!flinging_controller)
return nullptr;
return base::WrapUnique<FlingingRenderer>(
- new FlingingRenderer(std::move(media_controller)));
+ new FlingingRenderer(std::move(flinging_controller)));
}
// media::Renderer implementation
@@ -59,6 +63,7 @@ void FlingingRenderer::Initialize(media::MediaResource* media_resource,
media::RendererClient* client,
const media::PipelineStatusCB& init_cb) {
DVLOG(2) << __func__;
+ client_ = client;
init_cb.Run(media::PIPELINE_OK);
}
@@ -76,26 +81,40 @@ void FlingingRenderer::Flush(const base::Closure& flush_cb) {
void FlingingRenderer::StartPlayingFrom(base::TimeDelta time) {
DVLOG(2) << __func__;
- controller_->Seek(time);
- controller_->Play();
+ controller_->GetMediaController()->Seek(time);
+
+ // After a seek when using the FlingingRenderer, WMPI will never get back to
+ // BUFFERING_HAVE_ENOUGH. This prevents Blink from getting the appropriate
+ // seek completion signals, and time updates are never re-scheduled.
+ //
+ // The FlingingRenderer doesn't need to buffer, since playback happens on a
+ // different device. This means it's ok to always send BUFFERING_HAVE_ENOUGH
+ // when sending buffering state changes. That being said, sending state
+ // changes here might be surprising, but the same signals are sent from
+ // MediaPlayerRenderer::StartPlayingFrom(), and it has been working mostly
+ // smoothly for all HLS playback.
+ client_->OnBufferingStateChange(media::BUFFERING_HAVE_ENOUGH);
}
void FlingingRenderer::SetPlaybackRate(double playback_rate) {
DVLOG(2) << __func__;
if (playback_rate == 0)
- controller_->Pause();
+ controller_->GetMediaController()->Pause();
else
- controller_->Play();
+ controller_->GetMediaController()->Play();
}
void FlingingRenderer::SetVolume(float volume) {
DVLOG(2) << __func__;
- controller_->SetVolume(volume);
+ controller_->GetMediaController()->SetVolume(volume);
}
base::TimeDelta FlingingRenderer::GetMediaTime() {
- // TODO(https://crbug.com/830871): return correct media time.
- return base::TimeDelta();
+ return controller_->GetApproximateCurrentTime();
+}
+
+void FlingingRenderer::OnMediaStatusUpdated(const media::MediaStatus& status) {
+ // TODO(tguilbert): propagate important changes to RendererClient.
}
} // namespace content
diff --git a/chromium/content/browser/media/flinging_renderer.h b/chromium/content/browser/media/flinging_renderer.h
index 38c411cd6d5..023c216dbcf 100644
--- a/chromium/content/browser/media/flinging_renderer.h
+++ b/chromium/content/browser/media/flinging_renderer.h
@@ -7,8 +7,9 @@
#include "base/callback.h"
#include "content/common/content_export.h"
-#include "media/base/media_controller.h"
+#include "media/base/flinging_controller.h"
#include "media/base/media_resource.h"
+#include "media/base/media_status_observer.h"
#include "media/base/renderer.h"
#include "media/base/renderer_client.h"
#include "url/gurl.h"
@@ -23,7 +24,8 @@ class RenderFrameHost;
// playback commands. In this case, the media we are controlling should be an
// already existing RemotingCastSession, which should have been initiated by a
// blink::RemotePlayback object, using the PresentationService.
-class CONTENT_EXPORT FlingingRenderer : public media::Renderer {
+class CONTENT_EXPORT FlingingRenderer : public media::Renderer,
+ media::MediaStatusObserver {
public:
// Helper method to create a FlingingRenderer from an already existing
// presentation ID.
@@ -47,12 +49,18 @@ class CONTENT_EXPORT FlingingRenderer : public media::Renderer {
void SetVolume(float volume) override;
base::TimeDelta GetMediaTime() override;
+ // media::MediaStatusObserver implementation.
+ void OnMediaStatusUpdated(const media::MediaStatus& status) override;
+
private:
friend class FlingingRendererTest;
- explicit FlingingRenderer(std::unique_ptr<media::MediaController> controller);
+ explicit FlingingRenderer(
+ std::unique_ptr<media::FlingingController> controller);
+
+ media::RendererClient* client_;
- std::unique_ptr<media::MediaController> controller_;
+ 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 680ac22101c..28395a2da23 100644
--- a/chromium/content/browser/media/flinging_renderer_unittest.cc
+++ b/chromium/content/browser/media/flinging_renderer_unittest.cc
@@ -4,6 +4,9 @@
#include "content/browser/media/flinging_renderer.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 "testing/gmock/include/gmock/gmock.h"
@@ -11,6 +14,7 @@
using ::testing::_;
using ::testing::StrictMock;
+using ::testing::NiceMock;
namespace content {
@@ -23,44 +27,82 @@ class MockMediaController : public media::MediaController {
MOCK_METHOD1(Seek, void(base::TimeDelta));
};
+class MockRendererClient : public media::RendererClient {
+ public:
+ MOCK_METHOD1(OnError, void(media::PipelineStatus));
+ MOCK_METHOD0(OnEnded, void());
+ MOCK_METHOD1(OnStatisticsUpdate, void(const media::PipelineStatistics&));
+ MOCK_METHOD1(OnBufferingStateChange, void(media::BufferingState));
+ MOCK_METHOD0(OnWaitingForDecryptionKey, void());
+ MOCK_METHOD1(OnAudioConfigChange, void(const media::AudioDecoderConfig&));
+ MOCK_METHOD1(OnVideoConfigChange, void(const media::VideoDecoderConfig&));
+ MOCK_METHOD1(OnVideoNaturalSizeChange, void(const gfx::Size&));
+ MOCK_METHOD1(OnVideoOpacityChange, void(bool));
+ MOCK_METHOD1(OnDurationChange, void(base::TimeDelta));
+};
+
+class MockFlingingController : public media::FlingingController {
+ public:
+ explicit MockFlingingController(media::MediaController* media_controller)
+ : media_controller_(media_controller) {}
+
+ media::MediaController* GetMediaController() { return media_controller_; }
+
+ MOCK_METHOD1(AddMediaStatusObserver, void(media::MediaStatusObserver*));
+ MOCK_METHOD1(RemoveMediaStatusObserver, void(media::MediaStatusObserver*));
+ MOCK_METHOD0(GetApproximateCurrentTime, base::TimeDelta());
+
+ private:
+ media::MediaController* media_controller_;
+};
+
class FlingingRendererTest : public testing::Test {
public:
FlingingRendererTest()
: media_controller_(new StrictMock<MockMediaController>()),
- renderer_(std::unique_ptr<media::MediaController>(media_controller_)) {}
+ flinging_controller_(
+ new StrictMock<MockFlingingController>(media_controller_.get())) {
+ EXPECT_CALL(*flinging_controller_, AddMediaStatusObserver(_));
+ EXPECT_CALL(*flinging_controller_, RemoveMediaStatusObserver(_));
+
+ renderer_ = base::WrapUnique(new FlingingRenderer(
+ std::unique_ptr<media::FlingingController>(flinging_controller_)));
+
+ renderer_->Initialize(nullptr, &renderer_client_, base::DoNothing());
+ }
protected:
- StrictMock<MockMediaController>* media_controller_;
- FlingingRenderer renderer_;
+ NiceMock<MockRendererClient> renderer_client_;
+ std::unique_ptr<MockMediaController> media_controller_;
+ StrictMock<MockFlingingController>* flinging_controller_;
+ std::unique_ptr<FlingingRenderer> renderer_;
};
TEST_F(FlingingRendererTest, StartPlayingFromTime) {
base::TimeDelta seek_time = base::TimeDelta::FromSeconds(10);
- EXPECT_CALL(*media_controller_, Play());
EXPECT_CALL(*media_controller_, Seek(seek_time));
- renderer_.StartPlayingFrom(seek_time);
+ renderer_->StartPlayingFrom(seek_time);
}
TEST_F(FlingingRendererTest, StartPlayingFromBeginning) {
- EXPECT_CALL(*media_controller_, Play());
EXPECT_CALL(*media_controller_, Seek(base::TimeDelta()));
- renderer_.StartPlayingFrom(base::TimeDelta());
+ renderer_->StartPlayingFrom(base::TimeDelta());
}
TEST_F(FlingingRendererTest, SetPlaybackRate) {
double playback_rate = 1.0;
EXPECT_CALL(*media_controller_, Play());
- renderer_.SetPlaybackRate(playback_rate);
+ renderer_->SetPlaybackRate(playback_rate);
}
TEST_F(FlingingRendererTest, SetPlaybackRateToZero) {
double playback_rate = 0.0;
EXPECT_CALL(*media_controller_, Pause());
- renderer_.SetPlaybackRate(playback_rate);
+ renderer_->SetPlaybackRate(playback_rate);
}
// Setting the volume to a positive value should not change the mute state.
@@ -69,7 +111,7 @@ TEST_F(FlingingRendererTest, SetVolume) {
EXPECT_CALL(*media_controller_, SetVolume(volume));
EXPECT_CALL(*media_controller_, SetMute(_)).Times(0);
- renderer_.SetVolume(volume);
+ renderer_->SetVolume(volume);
}
// Setting the volume to 0 should not set the mute state.
@@ -78,7 +120,7 @@ TEST_F(FlingingRendererTest, SetVolumeToZero) {
EXPECT_CALL(*media_controller_, SetVolume(volume));
EXPECT_CALL(*media_controller_, SetMute(_)).Times(0);
- renderer_.SetVolume(volume);
+ renderer_->SetVolume(volume);
}
} // namespace content
diff --git a/chromium/content/browser/media/forwarding_audio_stream_factory.cc b/chromium/content/browser/media/forwarding_audio_stream_factory.cc
index 694f8bfe4d2..f9181735959 100644
--- a/chromium/content/browser/media/forwarding_audio_stream_factory.cc
+++ b/chromium/content/browser/media/forwarding_audio_stream_factory.cc
@@ -13,11 +13,49 @@
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
+#include "media/audio/audio_device_description.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
#include "services/audio/public/mojom/constants.mojom.h"
#include "services/service_manager/public/cpp/connector.h"
namespace content {
+namespace {
+
+// A mojom::RendererAudioInputStreamFactoryClient that holds a
+// AudioLoopbackStreamCreator::StreamCreatedCallback. The callback runs when the
+// requested audio stream is created.
+class StreamCreatedCallbackAdapter final
+ : public mojom::RendererAudioInputStreamFactoryClient {
+ public:
+ explicit StreamCreatedCallbackAdapter(
+ const AudioLoopbackStreamCreator::StreamCreatedCallback& callback)
+ : callback_(callback) {
+ DCHECK(callback_);
+ }
+
+ ~StreamCreatedCallbackAdapter() override {}
+
+ // mojom::RendererAudioInputStreamFactoryClient implementation.
+ void StreamCreated(
+ media::mojom::AudioInputStreamPtr stream,
+ media::mojom::AudioInputStreamClientRequest client_request,
+ media::mojom::ReadOnlyAudioDataPipePtr data_pipe,
+ bool initially_muted,
+ const base::Optional<base::UnguessableToken>& stream_id) override {
+ DCHECK(!initially_muted); // Loopback streams shouldn't be started muted.
+ callback_.Run(std::move(stream), std::move(client_request),
+ std::move(data_pipe));
+ }
+
+ private:
+ const AudioLoopbackStreamCreator::StreamCreatedCallback callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(StreamCreatedCallbackAdapter);
+};
+
+} // namespace
+
ForwardingAudioStreamFactory::ForwardingAudioStreamFactory(
WebContents* web_contents,
std::unique_ptr<service_manager::Connector> connector,
@@ -27,7 +65,6 @@ ForwardingAudioStreamFactory::ForwardingAudioStreamFactory(
broker_factory_(std::move(broker_factory)),
group_id_(base::UnguessableToken::Create()) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- DCHECK(web_contents);
DCHECK(broker_factory_);
}
@@ -54,15 +91,16 @@ void ForwardingAudioStreamFactory::CreateInputStream(
const media::AudioParameters& params,
uint32_t shared_memory_count,
bool enable_agc,
+ audio::mojom::AudioProcessingConfigPtr processing_config,
mojom::RendererAudioInputStreamFactoryClientPtr renderer_factory_client) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- const int process_id = frame->GetProcess()->GetID();
- const int frame_id = frame->GetRoutingID();
+ const int process_id = frame ? frame->GetProcess()->GetID() : -1;
+ const int frame_id = frame ? frame->GetRoutingID() : -1;
inputs_
.insert(broker_factory_->CreateAudioInputStreamBroker(
process_id, frame_id, device_id, params, shared_memory_count,
- enable_agc,
+ enable_agc, std::move(processing_config),
base::BindOnce(&ForwardingAudioStreamFactory::RemoveInput,
base::Unretained(this)),
std::move(renderer_factory_client)))
@@ -75,7 +113,7 @@ void ForwardingAudioStreamFactory::AssociateInputAndOutputForAec(
const std::string& raw_output_device_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
// Avoid spawning a factory if this for some reason gets called with an
- // invalid input_stream_id before any streams are created.
+ // invalid |input_stream_id| before any streams are created.
if (!inputs_.empty()) {
GetFactory()->AssociateInputAndOutputForAec(input_stream_id,
raw_output_device_id);
@@ -86,6 +124,7 @@ void ForwardingAudioStreamFactory::CreateOutputStream(
RenderFrameHost* frame,
const std::string& device_id,
const media::AudioParameters& params,
+ const base::Optional<base::UnguessableToken>& processing_id,
media::mojom::AudioOutputStreamProviderClientPtr client) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -95,7 +134,7 @@ void ForwardingAudioStreamFactory::CreateOutputStream(
outputs_
.insert(broker_factory_->CreateAudioOutputStreamBroker(
process_id, frame_id, ++stream_id_counter_, device_id, params,
- group_id_,
+ group_id_, processing_id,
base::BindOnce(&ForwardingAudioStreamFactory::RemoveOutput,
base::Unretained(this)),
std::move(client)))
@@ -111,7 +150,6 @@ void ForwardingAudioStreamFactory::CreateLoopbackStream(
bool mute_source,
mojom::RendererAudioInputStreamFactoryClientPtr renderer_factory_client) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- DCHECK(frame);
DCHECK(frame_of_source_web_contents);
TRACE_EVENT_BEGIN1("audio", "CreateLoopbackStream", "group",
@@ -125,8 +163,8 @@ void ForwardingAudioStreamFactory::CreateLoopbackStream(
return;
}
- const int process_id = frame->GetProcess()->GetID();
- const int frame_id = frame->GetRoutingID();
+ const int process_id = frame ? frame->GetProcess()->GetID() : -1;
+ const int frame_id = frame ? frame->GetRoutingID() : -1;
inputs_
.insert(broker_factory_->CreateAudioLoopbackStreamBroker(
process_id, frame_id,
@@ -145,6 +183,29 @@ void ForwardingAudioStreamFactory::CreateLoopbackStream(
.GetLowForSerialization());
}
+void ForwardingAudioStreamFactory::CreateInProcessLoopbackStream(
+ RenderFrameHost* frame_of_source_web_contents,
+ const media::AudioParameters& params,
+ uint32_t shared_memory_count,
+ const AudioLoopbackStreamCreator::StreamCreatedCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ mojom::RendererAudioInputStreamFactoryClientPtr client;
+ mojo::MakeStrongBinding(
+ std::make_unique<StreamCreatedCallbackAdapter>(callback),
+ mojo::MakeRequest(&client));
+ if (frame_of_source_web_contents) {
+ CreateLoopbackStream(nullptr, frame_of_source_web_contents, params,
+ shared_memory_count, true /* mute_source */,
+ std::move(client));
+ } else {
+ // A null |frame_of_source_web_contents| requests system-wide loopback.
+ CreateInputStream(nullptr,
+ media::AudioDeviceDescription::kLoopbackWithMuteDeviceId,
+ params, shared_memory_count, false /* enable_agc */,
+ nullptr /* processing_config */, std::move(client));
+ }
+}
+
void ForwardingAudioStreamFactory::SetMuted(bool muted) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK_NE(muted, IsMuted());
@@ -176,8 +237,10 @@ void ForwardingAudioStreamFactory::CleanupStreamsBelongingTo(
RenderFrameHost* render_frame_host) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- const int process_id = render_frame_host->GetProcess()->GetID();
- const int frame_id = render_frame_host->GetRoutingID();
+ const int process_id =
+ render_frame_host ? render_frame_host->GetProcess()->GetID() : -1;
+ const int frame_id =
+ render_frame_host ? render_frame_host->GetRoutingID() : -1;
TRACE_EVENT_BEGIN2("audio", "CleanupStreamsBelongingTo", "group",
group_id_.GetLowForSerialization(), "process id",
diff --git a/chromium/content/browser/media/forwarding_audio_stream_factory.h b/chromium/content/browser/media/forwarding_audio_stream_factory.h
index 26ffbb89bbb..6c1bfbc8dd9 100644
--- a/chromium/content/browser/media/forwarding_audio_stream_factory.h
+++ b/chromium/content/browser/media/forwarding_audio_stream_factory.h
@@ -17,6 +17,7 @@
#include "content/browser/media/audio_stream_broker.h"
#include "content/common/content_export.h"
#include "content/common/media/renderer_audio_input_stream_factory.mojom.h"
+#include "content/public/browser/audio_loopback_stream_creator.h"
#include "content/public/browser/web_contents_observer.h"
#include "services/audio/public/mojom/stream_factory.mojom.h"
@@ -39,6 +40,8 @@ class WebContents;
class CONTENT_EXPORT ForwardingAudioStreamFactory final
: public WebContentsObserver {
public:
+ // |web_contents| is null in the browser-privileged access case, i.e., when
+ // the streams created with this factory will not be consumed by a renderer.
ForwardingAudioStreamFactory(
WebContents* web_contents,
std::unique_ptr<service_manager::Connector> connector,
@@ -61,6 +64,7 @@ class CONTENT_EXPORT ForwardingAudioStreamFactory final
const media::AudioParameters& params,
uint32_t shared_memory_count,
bool enable_agc,
+ audio::mojom::AudioProcessingConfigPtr processing_config,
mojom::RendererAudioInputStreamFactoryClientPtr renderer_factory_client);
void AssociateInputAndOutputForAec(
@@ -71,6 +75,7 @@ class CONTENT_EXPORT ForwardingAudioStreamFactory final
RenderFrameHost* frame,
const std::string& device_id,
const media::AudioParameters& params,
+ const base::Optional<base::UnguessableToken>& processing_id,
media::mojom::AudioOutputStreamProviderClientPtr client);
void CreateLoopbackStream(
@@ -81,6 +86,15 @@ class CONTENT_EXPORT ForwardingAudioStreamFactory final
bool mute_source,
mojom::RendererAudioInputStreamFactoryClientPtr renderer_factory_client);
+ // Creates a loopback stream that captures the audio from
+ // |frame_of_source_web_contents|, or the default system playback if the
+ // source is not provided. The source/system audio is muted during capturing.
+ void CreateInProcessLoopbackStream(
+ RenderFrameHost* frame_of_source_web_contents,
+ const media::AudioParameters& params,
+ uint32_t shared_memory_count,
+ const AudioLoopbackStreamCreator::StreamCreatedCallback& callback);
+
// Sets the muting state for all output streams created through this factory.
void SetMuted(bool muted);
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 e0764947aa1..421f66bdac7 100644
--- a/chromium/content/browser/media/forwarding_audio_stream_factory_unittest.cc
+++ b/chromium/content/browser/media/forwarding_audio_stream_factory_unittest.cc
@@ -111,6 +111,7 @@ class MockBrokerFactory : public AudioStreamBrokerFactory {
const media::AudioParameters& params,
uint32_t shared_memory_count,
bool enable_agc,
+ audio::mojom::AudioProcessingConfigPtr processing_config,
AudioStreamBroker::DeleterCallback deleter,
mojom::RendererAudioInputStreamFactoryClientPtr renderer_factory_client)
final {
@@ -131,6 +132,7 @@ class MockBrokerFactory : public AudioStreamBrokerFactory {
const std::string& output_device_id,
const media::AudioParameters& params,
const base::UnguessableToken& group_id,
+ const base::Optional<base::UnguessableToken>& processing_id,
AudioStreamBroker::DeleterCallback deleter,
media::mojom::AudioOutputStreamProviderClientPtr client) final {
std::unique_ptr<MockBroker> prepared_broker =
@@ -257,7 +259,8 @@ TEST_F(ForwardingAudioStreamFactoryTest, CreateInputStream_CreatesInputStream) {
EXPECT_CALL(*broker, CreateStream(NotNull()));
mojo::MakeRequest(&client);
factory.CreateInputStream(main_rfh(), kInputDeviceId, kParams,
- kSharedMemoryCount, kEnableAgc, std::move(client));
+ kSharedMemoryCount, kEnableAgc, nullptr,
+ std::move(client));
}
TEST_F(ForwardingAudioStreamFactoryTest,
@@ -288,7 +291,7 @@ TEST_F(ForwardingAudioStreamFactoryTest,
EXPECT_CALL(*broker, CreateStream(NotNull()));
mojo::MakeRequest(&client);
factory.CreateOutputStream(main_rfh(), kOutputDeviceId, kParams,
- std::move(client));
+ base::nullopt, std::move(client));
}
TEST_F(ForwardingAudioStreamFactoryTest,
@@ -306,7 +309,7 @@ TEST_F(ForwardingAudioStreamFactoryTest,
EXPECT_CALL(*main_rfh_broker, CreateStream(NotNull()));
mojo::MakeRequest(&client);
factory.CreateInputStream(main_rfh(), kInputDeviceId, kParams,
- kSharedMemoryCount, kEnableAgc,
+ kSharedMemoryCount, kEnableAgc, nullptr,
std::move(client));
testing::Mock::VerifyAndClear(&*main_rfh_broker);
}
@@ -314,7 +317,7 @@ TEST_F(ForwardingAudioStreamFactoryTest,
EXPECT_CALL(*other_rfh_broker, CreateStream(NotNull()));
mojo::MakeRequest(&client);
factory.CreateInputStream(other_rfh(), kInputDeviceId, kParams,
- kSharedMemoryCount, kEnableAgc,
+ kSharedMemoryCount, kEnableAgc, nullptr,
std::move(client));
testing::Mock::VerifyAndClear(&*other_rfh_broker);
}
@@ -375,14 +378,14 @@ TEST_F(ForwardingAudioStreamFactoryTest,
EXPECT_CALL(*main_rfh_broker, CreateStream(NotNull()));
mojo::MakeRequest(&client);
factory.CreateOutputStream(main_rfh(), kOutputDeviceId, kParams,
- std::move(client));
+ base::nullopt, std::move(client));
testing::Mock::VerifyAndClear(&*main_rfh_broker);
}
{
EXPECT_CALL(*other_rfh_broker, CreateStream(NotNull()));
mojo::MakeRequest(&client);
factory.CreateOutputStream(other_rfh(), kOutputDeviceId, kParams,
- std::move(client));
+ base::nullopt, std::move(client));
testing::Mock::VerifyAndClear(&*other_rfh_broker);
}
@@ -419,7 +422,7 @@ TEST_F(ForwardingAudioStreamFactoryTest, DestroyFrame_DestroysRelatedStreams) {
EXPECT_CALL(*main_rfh_input_broker, CreateStream(NotNull()));
mojo::MakeRequest(&input_client);
factory.CreateInputStream(main_rfh(), kInputDeviceId, kParams,
- kSharedMemoryCount, kEnableAgc,
+ kSharedMemoryCount, kEnableAgc, nullptr,
std::move(input_client));
testing::Mock::VerifyAndClear(&*main_rfh_input_broker);
}
@@ -427,7 +430,7 @@ TEST_F(ForwardingAudioStreamFactoryTest, DestroyFrame_DestroysRelatedStreams) {
EXPECT_CALL(*other_rfh_input_broker, CreateStream(NotNull()));
mojo::MakeRequest(&input_client);
factory.CreateInputStream(other_rfh(), kInputDeviceId, kParams,
- kSharedMemoryCount, kEnableAgc,
+ kSharedMemoryCount, kEnableAgc, nullptr,
std::move(input_client));
testing::Mock::VerifyAndClear(&*other_rfh_input_broker);
}
@@ -453,14 +456,14 @@ TEST_F(ForwardingAudioStreamFactoryTest, DestroyFrame_DestroysRelatedStreams) {
EXPECT_CALL(*main_rfh_output_broker, CreateStream(NotNull()));
mojo::MakeRequest(&output_client);
factory.CreateOutputStream(main_rfh(), kOutputDeviceId, kParams,
- std::move(output_client));
+ base::nullopt, std::move(output_client));
testing::Mock::VerifyAndClear(&*main_rfh_output_broker);
}
{
EXPECT_CALL(*other_rfh_output_broker, CreateStream(NotNull()));
mojo::MakeRequest(&output_client);
factory.CreateOutputStream(other_rfh(), kOutputDeviceId, kParams,
- std::move(output_client));
+ base::nullopt, std::move(output_client));
testing::Mock::VerifyAndClear(&*other_rfh_output_broker);
}
@@ -493,13 +496,13 @@ TEST_F(ForwardingAudioStreamFactoryTest, DestroyWebContents_DestroysStreams) {
EXPECT_CALL(*input_broker, CreateStream(NotNull()));
mojo::MakeRequest(&input_client);
factory.CreateInputStream(main_rfh(), kInputDeviceId, kParams,
- kSharedMemoryCount, kEnableAgc,
+ kSharedMemoryCount, kEnableAgc, nullptr,
std::move(input_client));
EXPECT_CALL(*output_broker, CreateStream(NotNull()));
mojo::MakeRequest(&output_client);
factory.CreateOutputStream(main_rfh(), kOutputDeviceId, kParams,
- std::move(output_client));
+ base::nullopt, std::move(output_client));
DeleteContents();
base::RunLoop().RunUntilIdle();
@@ -530,7 +533,7 @@ TEST_F(ForwardingAudioStreamFactoryTest, LastStreamDeleted_ClearsFactoryPtr) {
EXPECT_CALL(*main_rfh_input_broker, CreateStream(NotNull()));
mojo::MakeRequest(&input_client);
factory.CreateInputStream(main_rfh(), kInputDeviceId, kParams,
- kSharedMemoryCount, kEnableAgc,
+ kSharedMemoryCount, kEnableAgc, nullptr,
std::move(input_client));
testing::Mock::VerifyAndClear(&*main_rfh_input_broker);
}
@@ -538,7 +541,7 @@ TEST_F(ForwardingAudioStreamFactoryTest, LastStreamDeleted_ClearsFactoryPtr) {
EXPECT_CALL(*other_rfh_input_broker, CreateStream(NotNull()));
mojo::MakeRequest(&input_client);
factory.CreateInputStream(other_rfh(), kInputDeviceId, kParams,
- kSharedMemoryCount, kEnableAgc,
+ kSharedMemoryCount, kEnableAgc, nullptr,
std::move(input_client));
testing::Mock::VerifyAndClear(&*other_rfh_input_broker);
}
@@ -547,14 +550,14 @@ TEST_F(ForwardingAudioStreamFactoryTest, LastStreamDeleted_ClearsFactoryPtr) {
EXPECT_CALL(*main_rfh_output_broker, CreateStream(NotNull()));
mojo::MakeRequest(&output_client);
factory.CreateOutputStream(main_rfh(), kOutputDeviceId, kParams,
- std::move(output_client));
+ base::nullopt, std::move(output_client));
testing::Mock::VerifyAndClear(&*main_rfh_output_broker);
}
{
EXPECT_CALL(*other_rfh_output_broker, CreateStream(NotNull()));
mojo::MakeRequest(&output_client);
factory.CreateOutputStream(other_rfh(), kOutputDeviceId, kParams,
- std::move(output_client));
+ base::nullopt, std::move(output_client));
testing::Mock::VerifyAndClear(&*other_rfh_output_broker);
}
@@ -606,7 +609,7 @@ TEST_F(ForwardingAudioStreamFactoryTest, MuteWithOutputStream_ConnectsMuter) {
EXPECT_CALL(*broker, CreateStream(NotNull()));
mojo::MakeRequest(&client);
factory.CreateOutputStream(main_rfh(), kOutputDeviceId, kParams,
- std::move(client));
+ base::nullopt, std::move(client));
base::RunLoop().RunUntilIdle();
testing::Mock::VerifyAndClear(&*broker);
@@ -645,7 +648,7 @@ TEST_F(ForwardingAudioStreamFactoryTest,
EXPECT_CALL(*broker, CreateStream(NotNull()));
mojo::MakeRequest(&client);
factory.CreateOutputStream(main_rfh(), kOutputDeviceId, kParams,
- std::move(client));
+ base::nullopt, std::move(client));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(factory.IsMuted());
EXPECT_TRUE(stream_factory_.IsConnected());
@@ -673,7 +676,7 @@ TEST_F(ForwardingAudioStreamFactoryTest,
EXPECT_CALL(*broker, CreateStream(NotNull()));
mojo::MakeRequest(&client);
factory.CreateOutputStream(main_rfh(), kOutputDeviceId, kParams,
- std::move(client));
+ base::nullopt, std::move(client));
base::RunLoop().RunUntilIdle();
testing::Mock::VerifyAndClear(&*broker);
}
@@ -690,7 +693,7 @@ TEST_F(ForwardingAudioStreamFactoryTest,
EXPECT_CALL(*another_broker, CreateStream(NotNull()));
mojo::MakeRequest(&client);
factory.CreateOutputStream(main_rfh(), kOutputDeviceId, kParams,
- std::move(client));
+ base::nullopt, std::move(client));
base::RunLoop().RunUntilIdle();
testing::Mock::VerifyAndClear(&*another_broker);
}
diff --git a/chromium/content/browser/media/in_process_audio_loopback_stream_creator.cc b/chromium/content/browser/media/in_process_audio_loopback_stream_creator.cc
new file mode 100644
index 00000000000..618c9b8f3a5
--- /dev/null
+++ b/chromium/content/browser/media/in_process_audio_loopback_stream_creator.cc
@@ -0,0 +1,44 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/media/in_process_audio_loopback_stream_creator.h"
+
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/common/service_manager_connection.h"
+#include "services/service_manager/public/cpp/connector.h"
+
+namespace content {
+
+InProcessAudioLoopbackStreamCreator::InProcessAudioLoopbackStreamCreator()
+ : factory_(nullptr,
+ content::ServiceManagerConnection::GetForProcess()
+ ->GetConnector()
+ ->Clone(),
+ AudioStreamBrokerFactory::CreateImpl()) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+}
+
+InProcessAudioLoopbackStreamCreator::~InProcessAudioLoopbackStreamCreator() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ factory_.FrameDeleted(nullptr);
+}
+
+void InProcessAudioLoopbackStreamCreator::CreateLoopbackStream(
+ WebContents* loopback_source,
+ const media::AudioParameters& params,
+ uint32_t total_segments,
+ const StreamCreatedCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ RenderFrameHost* loopback_source_frame = nullptr;
+ if (loopback_source) {
+ loopback_source_frame = loopback_source->GetMainFrame();
+ DCHECK(loopback_source_frame);
+ }
+ factory_.CreateInProcessLoopbackStream(loopback_source_frame, params,
+ total_segments, callback);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/in_process_audio_loopback_stream_creator.h b/chromium/content/browser/media/in_process_audio_loopback_stream_creator.h
new file mode 100644
index 00000000000..09b9c050915
--- /dev/null
+++ b/chromium/content/browser/media/in_process_audio_loopback_stream_creator.h
@@ -0,0 +1,41 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_MEDIA_IN_PROCESS_AUDIO_LOOPBACK_STREAM_CREATOR_H_
+#define CONTENT_BROWSER_MEDIA_IN_PROCESS_AUDIO_LOOPBACK_STREAM_CREATOR_H_
+
+#include "base/macros.h"
+#include "content/browser/media/forwarding_audio_stream_factory.h"
+#include "content/public/browser/audio_loopback_stream_creator.h"
+
+namespace media {
+class AudioParameters;
+}
+
+namespace content {
+
+// This class handles creating a loopback stream that either captures audio from
+// a WebContents or the system-wide loopback through the Audio Service.
+// This class is operated on the UI thread.
+class CONTENT_EXPORT InProcessAudioLoopbackStreamCreator final
+ : public AudioLoopbackStreamCreator {
+ public:
+ InProcessAudioLoopbackStreamCreator();
+ ~InProcessAudioLoopbackStreamCreator() override;
+
+ private:
+ // AudioLoopbackStreamCreator implementation.
+ void CreateLoopbackStream(WebContents* loopback_source,
+ const media::AudioParameters& params,
+ uint32_t total_segments,
+ const StreamCreatedCallback& callback) override;
+
+ ForwardingAudioStreamFactory factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(InProcessAudioLoopbackStreamCreator);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MEDIA_IN_PROCESS_AUDIO_LOOPBACK_STREAM_CREATOR_H_
diff --git a/chromium/content/browser/media/media_browsertest.cc b/chromium/content/browser/media/media_browsertest.cc
index 8e6045d5d33..93bea4f82b9 100644
--- a/chromium/content/browser/media/media_browsertest.cc
+++ b/chromium/content/browser/media/media_browsertest.cc
@@ -156,11 +156,15 @@ IN_PROC_BROWSER_TEST_P(MediaTest, VideoBearWebm) {
PlayVideo("bear.webm", GetParam());
}
-IN_PROC_BROWSER_TEST_P(MediaTest, VideoBearOpusWebm) {
+IN_PROC_BROWSER_TEST_P(MediaTest, AudioBearOpusWebm) {
PlayVideo("bear-opus.webm", GetParam());
}
-IN_PROC_BROWSER_TEST_P(MediaTest, VideoBearOpusOgg) {
+IN_PROC_BROWSER_TEST_P(MediaTest, AudioBearOpusMp4) {
+ PlayVideo("bear-opus.mp4", GetParam());
+}
+
+IN_PROC_BROWSER_TEST_P(MediaTest, AudioBearOpusOgg) {
PlayVideo("bear-opus.ogg", GetParam());
}
@@ -179,11 +183,6 @@ IN_PROC_BROWSER_TEST_P(MediaTest, VideoBear12DepthVP9) {
}
#endif
-#if BUILDFLAG(USE_PROPRIETARY_CODECS)
-IN_PROC_BROWSER_TEST_P(MediaTest, VideoBearMp4) {
- PlayVideo("bear.mp4", GetParam());
-}
-
IN_PROC_BROWSER_TEST_P(MediaTest, VideoBearMp4Vp9) {
PlayVideo("bear-320x240-v_frag-vp9.mp4", GetParam());
}
@@ -196,20 +195,6 @@ IN_PROC_BROWSER_TEST_P(MediaTest, AudioBearFlac192kHzMp4) {
PlayAudio("bear-flac-192kHz.mp4", GetParam());
}
-// Android devices usually only support baseline, main and high.
-#if !defined(OS_ANDROID)
-IN_PROC_BROWSER_TEST_P(MediaTest, VideoBearHighBitDepthMp4) {
- PlayVideo("bear-320x180-hi10p.mp4", GetParam());
-}
-#endif // !defined(OS_ANDROID)
-
-IN_PROC_BROWSER_TEST_P(MediaTest, VideoBearSilentMp4) {
- PlayVideo("bear_silent.mp4", GetParam());
-}
-
-// While we support the big endian (be) PCM codecs on Chromium, Quicktime seems
-// to be the only creator of this format and only for .mov files.
-// TODO(dalecurtis/ihf): Find or create some .wav test cases for "be" format.
IN_PROC_BROWSER_TEST_P(MediaTest, VideoBearMovPcmS16be) {
PlayVideo("bear_pcm_s16be.mov", GetParam());
}
@@ -218,6 +203,15 @@ IN_PROC_BROWSER_TEST_P(MediaTest, VideoBearMovPcmS24be) {
PlayVideo("bear_pcm_s24be.mov", GetParam());
}
+#if BUILDFLAG(USE_PROPRIETARY_CODECS)
+IN_PROC_BROWSER_TEST_P(MediaTest, VideoBearMp4) {
+ PlayVideo("bear.mp4", GetParam());
+}
+
+IN_PROC_BROWSER_TEST_P(MediaTest, VideoBearSilentMp4) {
+ PlayVideo("bear_silent.mp4", GetParam());
+}
+
IN_PROC_BROWSER_TEST_F(MediaTest, VideoBearRotated0) {
RunVideoSizeTest("bear_rotate_0.mp4", 1280, 720);
}
@@ -234,18 +228,21 @@ IN_PROC_BROWSER_TEST_F(MediaTest, VideoBearRotated270) {
RunVideoSizeTest("bear_rotate_270.mp4", 720, 1280);
}
+#if !defined(OS_ANDROID)
+// Android devices usually only support baseline, main and high.
+IN_PROC_BROWSER_TEST_P(MediaTest, VideoBearHighBitDepthMp4) {
+ PlayVideo("bear-320x180-hi10p.mp4", GetParam());
+}
+
// Android can't reliably load lots of videos on a page.
// See http://crbug.com/749265
-#if !defined(OS_ANDROID)
IN_PROC_BROWSER_TEST_F(MediaTest, LoadManyVideos) {
base::StringPairs query_params;
RunMediaTestPage("load_many_videos.html", query_params, media::kEnded, true);
}
#endif // !defined(OS_ANDROID)
-#endif // BUILDFLAG(USE_PROPRIETARY_CODECS)
#if defined(OS_CHROMEOS)
-#if BUILDFLAG(USE_PROPRIETARY_CODECS)
IN_PROC_BROWSER_TEST_P(MediaTest, VideoBearAviMp3Mpeg4) {
PlayVideo("bear_mpeg4_mp3.avi", GetParam());
}
@@ -269,8 +266,8 @@ IN_PROC_BROWSER_TEST_P(MediaTest, VideoBear3gpAmrnbMpeg4) {
IN_PROC_BROWSER_TEST_P(MediaTest, VideoBearWavGsmms) {
PlayAudio("bear_gsm_ms.wav", GetParam());
}
-#endif // BUILDFLAG(USE_PROPRIETARY_CODECS)
#endif // defined(OS_CHROMEOS)
+#endif // BUILDFLAG(USE_PROPRIETARY_CODECS)
IN_PROC_BROWSER_TEST_P(MediaTest, AudioBearFlac) {
PlayAudio("bear.flac", GetParam());
diff --git a/chromium/content/browser/media/media_canplaytype_browsertest.cc b/chromium/content/browser/media/media_canplaytype_browsertest.cc
index c517a4bf7c4..47a3ad4f528 100644
--- a/chromium/content/browser/media/media_canplaytype_browsertest.cc
+++ b/chromium/content/browser/media/media_canplaytype_browsertest.cc
@@ -203,11 +203,13 @@ class MediaCanPlayTypeTest : public MediaBrowserTest {
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.4D401E, vorbis\"'"));
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3.64001F, vorbis\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"opus\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1, opus\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3, opus\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.4D401E, opus\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3.64001F, opus\"'"));
+ if (mime != "audio/mp4" && mime != "video/mp4") {
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"opus\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1, opus\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3, opus\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.4D401E, opus\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3.64001F, opus\"'"));
+ }
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp8\"'"));
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp9\"'"));
@@ -825,6 +827,8 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_mp4) {
EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc1, avc3\"'"));
EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc1, flac\"'"));
EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc3, flac\"'"));
+ EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc1, opus\"'"));
+ EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc3, opus\"'"));
EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.42E01E\"'"));
EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.42101E\"'"));
@@ -896,6 +900,11 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_mp4) {
CanPlay("'video/mp4; codecs=\"avc1.4D401E, flac\"'"));
EXPECT_EQ(kPropProbably,
CanPlay("'video/mp4; codecs=\"avc3.64001F, flac\"'"));
+ EXPECT_EQ(kProbably, CanPlay("'video/mp4; codecs=\"opus\"'"));
+ EXPECT_EQ(kPropProbably,
+ CanPlay("'video/mp4; codecs=\"avc1.4D401E, opus\"'"));
+ EXPECT_EQ(kPropProbably,
+ CanPlay("'video/mp4; codecs=\"avc3.64001F, opus\"'"));
TestMPEGUnacceptableCombinations("video/mp4");
// This result is incorrect. See https://crbug.com/592889.
@@ -970,6 +979,7 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_mp4) {
EXPECT_EQ(kNot, CanPlay("'video/x-m4v; codecs=\"avc1.640028,mp4a.A6\"'"));
EXPECT_EQ(kNot, CanPlay("'video/x-m4v; codecs=\"flac\"'"));
+ EXPECT_EQ(kNot, CanPlay("'video/x-m4v; codecs=\"opus\"'"));
TestMPEGUnacceptableCombinations("video/x-m4v");
@@ -988,6 +998,7 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_mp4) {
EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"mp4a.40.29\"'"));
EXPECT_EQ(kProbably, CanPlay("'audio/mp4; codecs=\"flac\"'"));
+ EXPECT_EQ(kProbably, CanPlay("'audio/mp4; codecs=\"opus\"'"));
EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"avc1\"'"));
EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"avc3\"'"));
@@ -1055,6 +1066,7 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_mp4) {
EXPECT_EQ(kNot, CanPlay("'audio/x-m4a; codecs=\"mp4a.A6\"'"));
EXPECT_EQ(kNot, CanPlay("'video/x-m4a; codecs=\"flac\"'"));
+ EXPECT_EQ(kNot, CanPlay("'video/x-m4a; codecs=\"opus\"'"));
TestMPEGUnacceptableCombinations("audio/x-m4a");
}
diff --git a/chromium/content/browser/media/media_color_browsertest.cc b/chromium/content/browser/media/media_color_browsertest.cc
index 158109139a5..6cc930bb586 100644
--- a/chromium/content/browser/media/media_color_browsertest.cc
+++ b/chromium/content/browser/media/media_color_browsertest.cc
@@ -18,17 +18,15 @@ class MediaColorTest : public MediaBrowserTest {
RunTest(GetFileUrlWithQuery(path, video_file), media::kEnded);
EXPECT_EQ(media::kEnded, final_title);
}
+ void SetUp() override {
+ EnablePixelOutput();
+ MediaBrowserTest::SetUp();
+ }
};
// Android doesn't support Theora.
#if !defined(OS_ANDROID)
-// This fails on Linux: http://crbug.com/767926.
-#if defined(OS_LINUX)
-#define MAYBE_Yuv420pTheora DISABLED_Yuv420pTheora
-#else
-#define MAYBE_Yuv420pTheora Yuv420pTheora
-#endif
-IN_PROC_BROWSER_TEST_F(MediaColorTest, MAYBE_Yuv420pTheora) {
+IN_PROC_BROWSER_TEST_F(MediaColorTest, Yuv420pTheora) {
RunColorTest("yuv420p.ogv");
}
@@ -41,13 +39,7 @@ IN_PROC_BROWSER_TEST_F(MediaColorTest, Yuv444pTheora) {
}
#endif // !defined(OS_ANDROID)
-// This fails on Linux: http://crbug.com/767926.
-#if defined(OS_LINUX)
-#define MAYBE_Yuv420pVp8 DISABLED_Yuv420pVp8
-#else
-#define MAYBE_Yuv420pVp8 Yuv420pVp8
-#endif
-IN_PROC_BROWSER_TEST_F(MediaColorTest, MAYBE_Yuv420pVp8) {
+IN_PROC_BROWSER_TEST_F(MediaColorTest, Yuv420pVp8) {
RunColorTest("yuv420p.webm");
}
@@ -57,20 +49,13 @@ IN_PROC_BROWSER_TEST_F(MediaColorTest, Yuv444pVp9) {
#if BUILDFLAG(USE_PROPRIETARY_CODECS)
-// This fails on some Android devices: http://crbug.com/649199,
-// and Linux: http://crbug.com/767926.
-#if defined(OS_LINUX) || defined(OS_ANDROID)
-#define MAYBE_Yuv420pH264 DISABLED_Yuv420pH264
-#else
-#define MAYBE_Yuv420pH264 Yuv420pH264
-#endif
-IN_PROC_BROWSER_TEST_F(MediaColorTest, MAYBE_Yuv420pH264) {
+IN_PROC_BROWSER_TEST_F(MediaColorTest, Yuv420pH264) {
RunColorTest("yuv420p.mp4");
}
-// This test fails on Android: http://crbug.com/647818, OSX:
-// http://crbug.com/647838 and Linux: http://crbug.com/767926.
-#if defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_ANDROID)
+// This test fails on Android: http://crbug.com/647818 and OSX:
+// http://crbug.com/647838
+#if defined(OS_MACOSX) || defined(OS_ANDROID)
#define MAYBE_Yuvj420pH264 DISABLED_Yuvj420pH264
#else
#define MAYBE_Yuvj420pH264 Yuvj420pH264
@@ -79,11 +64,8 @@ IN_PROC_BROWSER_TEST_F(MediaColorTest, MAYBE_Yuvj420pH264) {
RunColorTest("yuvj420p.mp4");
}
-// This fails on Linux & ChromeOS: http://crbug.com/647400,
-// Windows: http://crbug.com/647842, and Android: http://crbug.com/649199,
-// http://crbug.com/649185.
-#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_WIN) || \
- defined(OS_ANDROID)
+// This fails on ChromeOS: http://crbug.com/647400,
+#if defined(OS_CHROMEOS)
#define MAYBE_Yuv420pRec709H264 DISABLED_Yuv420pRec709H264
#else
#define MAYBE_Yuv420pRec709H264 Yuv420pRec709H264
@@ -92,9 +74,9 @@ IN_PROC_BROWSER_TEST_F(MediaColorTest, MAYBE_Yuv420pRec709H264) {
RunColorTest("yuv420p_rec709.mp4");
}
-// This fails on Linux: http://crbug.com/767926. Android doesn't support 10bpc.
+// Android doesn't support 10bpc.
// This test flakes on mac: http://crbug.com/810908
-#if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_MACOSX)
+#if defined(OS_ANDROID) || defined(OS_MACOSX)
#define MAYBE_Yuv420pHighBitDepth DISABLED_Yuv420pHighBitDepth
#else
#define MAYBE_Yuv420pHighBitDepth Yuv420pHighBitDepth
diff --git a/chromium/content/browser/media/media_devices_permission_checker.cc b/chromium/content/browser/media/media_devices_permission_checker.cc
index 6a8aee944a5..8c16627a4a1 100644
--- a/chromium/content/browser/media/media_devices_permission_checker.cc
+++ b/chromium/content/browser/media/media_devices_permission_checker.cc
@@ -9,14 +9,12 @@
#include "base/bind.h"
#include "base/command_line.h"
-#include "base/feature_list.h"
#include "content/browser/frame_host/render_frame_host_delegate.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/common/media/media_devices.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
-#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "url/gurl.h"
#include "url/origin.h"
@@ -43,12 +41,10 @@ MediaDevicesManager::BoolDeviceTypes DoCheckPermissionsOnUIThread(
frame_host, origin, MEDIA_DEVICE_AUDIO_CAPTURE);
bool mic_feature_policy = true;
bool camera_feature_policy = true;
- if (base::FeatureList::IsEnabled(features::kUseFeaturePolicyForPermissions)) {
- mic_feature_policy = frame_host->IsFeatureEnabled(
- blink::mojom::FeaturePolicyFeature::kMicrophone);
- camera_feature_policy = frame_host->IsFeatureEnabled(
- blink::mojom::FeaturePolicyFeature::kCamera);
- }
+ mic_feature_policy = frame_host->IsFeatureEnabled(
+ blink::mojom::FeaturePolicyFeature::kMicrophone);
+ camera_feature_policy =
+ frame_host->IsFeatureEnabled(blink::mojom::FeaturePolicyFeature::kCamera);
MediaDevicesManager::BoolDeviceTypes result;
// Speakers.
diff --git a/chromium/content/browser/media/media_devices_permission_checker_unittest.cc b/chromium/content/browser/media/media_devices_permission_checker_unittest.cc
index 5e95d2bdd69..bb82f2e182e 100644
--- a/chromium/content/browser/media/media_devices_permission_checker_unittest.cc
+++ b/chromium/content/browser/media/media_devices_permission_checker_unittest.cc
@@ -5,12 +5,10 @@
#include "content/browser/media/media_devices_permission_checker.h"
#include "base/run_loop.h"
-#include "base/test/scoped_feature_list.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_delegate.h"
-#include "content/public/common/content_features.h"
#include "content/public/common/media_stream_request.h"
#include "content/public/test/test_renderer_host.h"
#include "content/test/test_render_view_host.h"
@@ -101,8 +99,6 @@ class MediaDevicesPermissionCheckerTest : public RenderViewHostImplTestHarness {
// feature_policy_unittest.cc and in
// render_frame_host_feature_policy_unittest.cc.
TEST_F(MediaDevicesPermissionCheckerTest, CheckPermissionWithFeaturePolicy) {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(features::kUseFeaturePolicyForPermissions);
// Mic and Camera should be enabled by default for a frame (if permission is
// granted).
EXPECT_TRUE(CheckPermission(MEDIA_DEVICE_TYPE_AUDIO_INPUT));
@@ -117,14 +113,6 @@ TEST_F(MediaDevicesPermissionCheckerTest, CheckPermissionWithFeaturePolicy) {
/*enabled=*/false);
EXPECT_TRUE(CheckPermission(MEDIA_DEVICE_TYPE_AUDIO_INPUT));
EXPECT_FALSE(CheckPermission(MEDIA_DEVICE_TYPE_VIDEO_INPUT));
-
- // Ensure that the policy is ignored if kUseFeaturePolicyForPermissions is
- // disabled.
- base::test::ScopedFeatureList empty_feature_list;
- empty_feature_list.InitAndDisableFeature(
- features::kUseFeaturePolicyForPermissions);
- EXPECT_TRUE(CheckPermission(MEDIA_DEVICE_TYPE_AUDIO_INPUT));
- EXPECT_TRUE(CheckPermission(MEDIA_DEVICE_TYPE_VIDEO_INPUT));
}
} // namespace
diff --git a/chromium/content/browser/media/media_internals.cc b/chromium/content/browser/media/media_internals.cc
index 54b72c76803..a4257d16db9 100644
--- a/chromium/content/browser/media/media_internals.cc
+++ b/chromium/content/browser/media/media_internals.cc
@@ -16,6 +16,8 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "build/build_config.h"
+#include "content/browser/media/session/audio_focus_manager.h"
+#include "content/browser/media/session/media_session_impl.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
@@ -136,6 +138,7 @@ class MediaInternals::AudioLogImpl : public media::mojom::AudioLog,
void OnError() override;
void OnSetVolume(double volume) override;
void OnLogMessage(const std::string& message) override;
+ void OnProcessingStateChanged(const std::string& message) override;
private:
// If possible, i.e. a WebContents exists for the given RenderFrameHostID,
@@ -236,6 +239,11 @@ void MediaInternals::AudioLogImpl::OnSetVolume(double volume) {
&dict);
}
+void MediaInternals::AudioLogImpl::OnProcessingStateChanged(
+ const std::string& message) {
+ SendSingleStringUpdate("processing state", message);
+}
+
void MediaInternals::AudioLogImpl::OnLogMessage(const std::string& message) {
MediaStreamManager::SendMessageToNativeLog(message);
}
@@ -645,6 +653,8 @@ void MediaInternals::AddUpdateCallback(const UpdateCallback& callback) {
base::AutoLock auto_lock(lock_);
can_update_ = true;
+
+ RegisterAudioFocusObserver();
}
void MediaInternals::RemoveUpdateCallback(const UpdateCallback& callback) {
@@ -658,6 +668,9 @@ void MediaInternals::RemoveUpdateCallback(const UpdateCallback& callback) {
base::AutoLock auto_lock(lock_);
can_update_ = !update_callbacks_.empty();
+
+ if (!can_update_)
+ UnregisterAudioFocusObserver();
}
bool MediaInternals::CanUpdate() {
@@ -698,6 +711,35 @@ void MediaInternals::SendVideoCaptureDeviceCapabilities() {
&video_capture_capabilities_cached_data_));
}
+void MediaInternals::SendAudioFocusState() {
+#if !defined(OS_ANDROID)
+ if (!CanUpdate())
+ return;
+
+ base::DictionaryValue audio_focus_data;
+ const std::list<AudioFocusManager::StackRow>& stack =
+ AudioFocusManager::GetInstance()->audio_focus_stack_;
+
+ // We should go backwards through the stack so the top of the stack is always
+ // shown first in the list.
+ base::ListValue stack_data;
+ for (auto iter = stack.rbegin(); iter != stack.rend(); ++iter) {
+ MediaSessionImpl::DebugInfo debug_info =
+ (*iter).media_session->GetDebugInfo();
+ base::DictionaryValue media_session_data;
+ media_session_data.SetKey("name", base::Value(debug_info.name));
+ media_session_data.SetKey("owner", base::Value(debug_info.owner));
+ media_session_data.SetKey("state", base::Value(debug_info.state));
+ stack_data.GetList().push_back(std::move(media_session_data));
+ }
+
+ audio_focus_data.SetKey("sessions", std::move(stack_data));
+
+ SendUpdate(
+ SerializeUpdate("media.onReceiveAudioFocusState", &audio_focus_data));
+#endif // !defined(OS_ANDROID)
+}
+
void MediaInternals::UpdateVideoCaptureDeviceCapabilities(
const std::vector<std::tuple<media::VideoCaptureDeviceDescriptor,
media::VideoCaptureFormats>>&
@@ -778,6 +820,25 @@ void MediaInternals::OnProcessTerminatedForTesting(int process_id) {
uma_handler_->OnProcessTerminated(process_id);
}
+void MediaInternals::OnFocusGained(
+ media_session::mojom::MediaSessionPtr media_session,
+ media_session::mojom::AudioFocusType type) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&MediaInternals::SendAudioFocusState,
+ base::Unretained(this)));
+}
+
+void MediaInternals::OnFocusLost(
+ media_session::mojom::MediaSessionPtr media_session) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&MediaInternals::SendAudioFocusState,
+ base::Unretained(this)));
+}
+
void MediaInternals::SendUpdate(const base::string16& update) {
// SendUpdate() may be called from any thread, but must run on the UI thread.
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
diff --git a/chromium/content/browser/media/media_internals.h b/chromium/content/browser/media/media_internals.h
index 494c251ad9c..7aa7ddcaaa8 100644
--- a/chromium/content/browser/media/media_internals.h
+++ b/chromium/content/browser/media/media_internals.h
@@ -18,6 +18,7 @@
#include "base/strings/string16.h"
#include "base/synchronization/lock.h"
#include "base/values.h"
+#include "content/browser/media/session/audio_focus_observer.h"
#include "content/common/content_export.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
@@ -31,12 +32,19 @@ namespace media {
struct MediaLogEvent;
}
+namespace media_session {
+namespace mojom {
+enum class AudioFocusType;
+} // namespace mojom
+} // namespace media_session
+
namespace content {
// This class stores information about currently active media.
// TODO(crbug.com/812557): Remove inheritance from media::AudioLogFactory once
// the creation of the AudioManager instance moves to the audio service.
class CONTENT_EXPORT MediaInternals : public media::AudioLogFactory,
+ public AudioFocusObserver,
public NotificationObserver {
public:
// Called with the update string.
@@ -74,6 +82,9 @@ class CONTENT_EXPORT MediaInternals : public media::AudioLogFactory,
// UpdateCallback.
void SendVideoCaptureDeviceCapabilities();
+ // Sends all audio focus information to each registered UpdateCallback.
+ void SendAudioFocusState();
+
// Called to inform of the capabilities enumerated for video devices.
void UpdateVideoCaptureDeviceCapabilities(
const std::vector<std::tuple<media::VideoCaptureDeviceDescriptor,
@@ -109,6 +120,12 @@ class CONTENT_EXPORT MediaInternals : public media::AudioLogFactory,
MediaInternals();
+ // AudioFocusObserver implementation.
+ void OnFocusGained(media_session::mojom::MediaSessionPtr media_session,
+ media_session::mojom::AudioFocusType type) override;
+ void OnFocusLost(
+ media_session::mojom::MediaSessionPtr media_session) override;
+
// Sends |update| to each registered UpdateCallback. Safe to call from any
// thread, but will forward to the IO thread.
void SendUpdate(const base::string16& update);
diff --git a/chromium/content/browser/media/media_internals_proxy.cc b/chromium/content/browser/media/media_internals_proxy.cc
index dfadf6b30c4..8526ebc04a4 100644
--- a/chromium/content/browser/media/media_internals_proxy.cc
+++ b/chromium/content/browser/media/media_internals_proxy.cc
@@ -6,6 +6,7 @@
#include "base/bind.h"
#include "base/location.h"
+#include "build/build_config.h"
#include "content/browser/media/media_internals.h"
#include "content/browser/media/media_internals_handler.h"
#include "content/public/browser/browser_thread.h"
@@ -48,6 +49,10 @@ void MediaInternalsProxy::GetEverythingOnIOThread() {
// TODO(xhwang): Investigate whether we can update on UI thread directly.
MediaInternals::GetInstance()->SendAudioStreamData();
MediaInternals::GetInstance()->SendVideoCaptureDeviceCapabilities();
+
+#if !defined(OS_ANDROID)
+ MediaInternals::GetInstance()->SendAudioFocusState();
+#endif
}
void MediaInternalsProxy::UpdateUIOnUIThread(const base::string16& update) {
diff --git a/chromium/content/browser/media/media_internals_unittest.cc b/chromium/content/browser/media/media_internals_unittest.cc
index a02bcadfbf0..033385ac2de 100644
--- a/chromium/content/browser/media/media_internals_unittest.cc
+++ b/chromium/content/browser/media/media_internals_unittest.cc
@@ -12,13 +12,21 @@
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_command_line.h"
#include "base/test/test_message_loop.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
+#include "content/browser/media/session/audio_focus_manager.h"
+#include "content/browser/media/session/media_session_impl.h"
+#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/test/test_web_contents.h"
#include "media/base/audio_parameters.h"
#include "media/base/channel_layout.h"
#include "media/base/media_log.h"
+#include "media/base/media_switches.h"
+#include "services/media_session/public/cpp/switches.h"
+#include "services/media_session/public/mojom/audio_focus.mojom.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/geometry/size.h"
@@ -97,6 +105,8 @@ class MediaInternalsTestBase {
namespace content {
+using media_session::mojom::AudioFocusType;
+
class MediaInternalsVideoCaptureDeviceTest : public testing::Test,
public MediaInternalsTestBase {
public:
@@ -279,4 +289,145 @@ INSTANTIATE_TEST_CASE_P(
media::AudioLogFactory::AUDIO_OUTPUT_CONTROLLER,
media::AudioLogFactory::AUDIO_OUTPUT_STREAM));
+// TODO(https://crbug.com/873320): AudioFocusManager is not available on
+// Android.
+#if !defined(OS_ANDROID)
+
+namespace {
+
+// Test page titles.
+const char kTestTitle1[] = "Test Title 1";
+const char kTestTitle2[] = "Test Title 2";
+
+} // namespace
+
+class MediaInternalsAudioFocusTest : public testing::Test,
+ public MediaInternalsTestBase {
+ public:
+ void SetUp() override {
+ update_cb_ =
+ base::BindRepeating(&MediaInternalsAudioFocusTest::UpdateCallbackImpl,
+ base::Unretained(this));
+
+ scoped_command_line_.GetProcessCommandLine()->AppendSwitch(
+ media_session::switches::kEnableAudioFocus);
+
+ content::MediaInternals::GetInstance()->AddUpdateCallback(update_cb_);
+ browser_context_.reset(new TestBrowserContext());
+ }
+
+ void TearDown() override {
+ content::MediaInternals::GetInstance()->RemoveUpdateCallback(update_cb_);
+ browser_context_.reset();
+ }
+
+ protected:
+ void ExpectValue(base::ListValue expected_list) {
+ base::DictionaryValue expected_data;
+ expected_data.SetKey("sessions", std::move(expected_list));
+ EXPECT_EQ(expected_data, update_data_);
+ }
+
+ std::unique_ptr<TestWebContents> CreateWebContents() {
+ return TestWebContents::Create(
+ browser_context_.get(), SiteInstance::Create(browser_context_.get()));
+ }
+
+ base::Value GetAddressAsValue(MediaSessionImpl* media_session) {
+ std::stringstream stream;
+ stream << media_session;
+ return base::Value(stream.str());
+ }
+
+ void RemoveAllPlayersForTest(MediaSessionImpl* session) {
+ session->RemoveAllPlayersForTest();
+ }
+
+ void WaitForCallback() {
+ AudioFocusManager::GetInstance()->FlushForTesting();
+ base::RunLoop().RunUntilIdle();
+ }
+
+ MediaInternals::UpdateCallback update_cb_;
+
+ private:
+ base::test::ScopedCommandLine scoped_command_line_;
+ std::unique_ptr<TestBrowserContext> browser_context_;
+};
+
+TEST_F(MediaInternalsAudioFocusTest, AudioFocusStateIsUpdated) {
+ // Create a test media session and request audio focus.
+ std::unique_ptr<TestWebContents> web_contents1 = CreateWebContents();
+ web_contents1->SetTitle(base::UTF8ToUTF16(kTestTitle1));
+ MediaSessionImpl* media_session1 = MediaSessionImpl::Get(web_contents1.get());
+ media_session1->RequestSystemAudioFocus(AudioFocusType::kGain);
+ WaitForCallback();
+
+ // Check JSON is what we expect.
+ {
+ base::DictionaryValue expected_session;
+ expected_session.SetKey("name", GetAddressAsValue(media_session1));
+ expected_session.SetKey("owner", base::Value(kTestTitle1));
+ expected_session.SetKey("state", base::Value("Active"));
+
+ base::ListValue expected_list;
+ expected_list.GetList().push_back(std::move(expected_session));
+ ExpectValue(std::move(expected_list));
+ }
+
+ // Create another media session.
+ std::unique_ptr<TestWebContents> web_contents2 = CreateWebContents();
+ web_contents2->SetTitle(base::UTF8ToUTF16(kTestTitle2));
+ MediaSessionImpl* media_session2 = MediaSessionImpl::Get(web_contents2.get());
+ media_session2->RequestSystemAudioFocus(
+ AudioFocusType::kGainTransientMayDuck);
+ WaitForCallback();
+
+ // Check JSON is what we expect.
+ {
+ base::DictionaryValue expected_session1;
+ expected_session1.SetKey("name", GetAddressAsValue(media_session2));
+ expected_session1.SetKey("owner", base::Value(kTestTitle2));
+ expected_session1.SetKey("state", base::Value("Active"));
+
+ base::DictionaryValue expected_session2;
+ expected_session2.SetKey("name", GetAddressAsValue(media_session1));
+ expected_session2.SetKey("owner", base::Value(kTestTitle1));
+ expected_session2.SetKey("state", base::Value("Active Ducked"));
+
+ base::ListValue expected_list;
+ expected_list.GetList().push_back(std::move(expected_session1));
+ expected_list.GetList().push_back(std::move(expected_session2));
+ ExpectValue(std::move(expected_list));
+ }
+
+ // Abandon audio focus.
+ RemoveAllPlayersForTest(media_session2);
+ WaitForCallback();
+
+ // Check JSON is what we expect.
+ {
+ base::DictionaryValue expected_session;
+ expected_session.SetKey("name", GetAddressAsValue(media_session1));
+ expected_session.SetKey("owner", base::Value(kTestTitle1));
+ expected_session.SetKey("state", base::Value("Active"));
+
+ base::ListValue expected_list;
+ expected_list.GetList().push_back(std::move(expected_session));
+ ExpectValue(std::move(expected_list));
+ }
+
+ // Abandon audio focus.
+ RemoveAllPlayersForTest(media_session1);
+ WaitForCallback();
+
+ // Check JSON is what we expect.
+ {
+ base::ListValue expected_list;
+ ExpectValue(std::move(expected_list));
+ }
+}
+
+#endif // !defined(OS_ANDROID)
+
} // namespace content
diff --git a/chromium/content/browser/media/media_source_browsertest.cc b/chromium/content/browser/media/media_source_browsertest.cc
index a7d782ba920..c03bf22239e 100644
--- a/chromium/content/browser/media/media_source_browsertest.cc
+++ b/chromium/content/browser/media/media_source_browsertest.cc
@@ -28,10 +28,7 @@ const char kMp4FlacAudioOnly[] = "audio/mp4; codecs=\"flac\"";
#if BUILDFLAG(USE_PROPRIETARY_CODECS)
const char kMp4AudioOnly[] = "audio/mp4; codecs=\"mp4a.40.2\"'";
-
-#if !defined(OS_ANDROID)
const char kMp4VideoOnly[] = "video/mp4; codecs=\"avc1.4D4041\"'";
-#endif // !defined(OS_ANDROID)
#if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER)
const char kMp2tAudioVideo[] = "video/mp2t; codecs=\"mp4a.40.2, avc1.42E01E\"";
@@ -105,9 +102,6 @@ IN_PROC_BROWSER_TEST_F(MediaSourceTest, ConfigChangeVideo) {
}
#if BUILDFLAG(USE_PROPRIETARY_CODECS)
-
-// TODO(chcunningham): Figure out why this is flaky on android. crbug/607841
-#if !defined(OS_ANDROID)
IN_PROC_BROWSER_TEST_F(MediaSourceTest, Playback_Video_MP4_Audio_WEBM) {
base::StringPairs query_params;
query_params.push_back(
@@ -119,7 +113,6 @@ IN_PROC_BROWSER_TEST_F(MediaSourceTest, Playback_Video_MP4_Audio_WEBM) {
RunMediaTestPage("mse_different_containers.html", query_params, media::kEnded,
true);
}
-#endif // !defined(OS_ANDROID)
IN_PROC_BROWSER_TEST_F(MediaSourceTest, Playback_Video_WEBM_Audio_MP4) {
base::StringPairs query_params;
diff --git a/chromium/content/browser/media/media_web_contents_observer.cc b/chromium/content/browser/media/media_web_contents_observer.cc
index 1b013f92874..c605c930a59 100644
--- a/chromium/content/browser/media/media_web_contents_observer.cc
+++ b/chromium/content/browser/media/media_web_contents_observer.cc
@@ -123,6 +123,10 @@ MediaWebContentsObserver::GetPictureInPictureVideoMediaPlayerId() const {
return pip_player_;
}
+void MediaWebContentsObserver::ResetPictureInPictureVideoMediaPlayerId() {
+ pip_player_.reset();
+}
+
bool MediaWebContentsObserver::OnMessageReceived(
const IPC::Message& msg,
RenderFrameHost* render_frame_host) {
@@ -147,6 +151,9 @@ bool MediaWebContentsObserver::OnMessageReceived(
IPC_MESSAGE_HANDLER(MediaPlayerDelegateHostMsg_OnPictureInPictureModeEnded,
OnPictureInPictureModeEnded)
IPC_MESSAGE_HANDLER(
+ MediaPlayerDelegateHostMsg_OnSetPictureInPictureCustomControls,
+ OnSetPictureInPictureCustomControls)
+ IPC_MESSAGE_HANDLER(
MediaPlayerDelegateHostMsg_OnPictureInPictureSurfaceChanged,
OnPictureInPictureSurfaceChanged)
IPC_MESSAGE_UNHANDLED(handled = false)
@@ -159,6 +166,10 @@ void MediaWebContentsObserver::OnVisibilityChanged(
UpdateVideoLock();
}
+void MediaWebContentsObserver::DidUpdateAudioMutingState(bool muted) {
+ session_controllers_manager_.WebContentsMutedStateChanged(muted);
+}
+
void MediaWebContentsObserver::RequestPersistentVideo(bool value) {
if (!fullscreen_player_)
return;
@@ -206,9 +217,7 @@ void MediaWebContentsObserver::OnMediaPaused(RenderFrameHost* render_frame_host,
UpdateVideoLock();
- // TODO(872066): check for |pip_player_| fully matching paused player.
- if (!web_contents()->IsBeingDestroyed() && pip_player_.has_value() &&
- pip_player_->render_frame_host == render_frame_host) {
+ if (!web_contents()->IsBeingDestroyed() && pip_player_ == player_id) {
PictureInPictureWindowControllerImpl* pip_controller =
PictureInPictureWindowControllerImpl::FromWebContents(
web_contents_impl());
@@ -262,9 +271,7 @@ void MediaWebContentsObserver::OnMediaPlaying(
return;
}
- // TODO(872066): check for |pip_player_| fully matching paused player.
- if (!web_contents()->IsBeingDestroyed() && pip_player_.has_value() &&
- pip_player_->render_frame_host == render_frame_host) {
+ if (!web_contents()->IsBeingDestroyed() && pip_player_ == id) {
PictureInPictureWindowControllerImpl* pip_controller =
PictureInPictureWindowControllerImpl::FromWebContents(
web_contents_impl());
@@ -349,13 +356,23 @@ void MediaWebContentsObserver::OnPictureInPictureModeEnded(
render_frame_host->GetRoutingID(), delegate_id, request_id));
}
+void MediaWebContentsObserver::OnSetPictureInPictureCustomControls(
+ RenderFrameHost* render_frame_host,
+ int delegate_id,
+ const std::vector<blink::PictureInPictureControlInfo>& controls) {
+ PictureInPictureWindowControllerImpl* pip_controller =
+ PictureInPictureWindowControllerImpl::FromWebContents(
+ web_contents_impl());
+ if (pip_controller)
+ pip_controller->SetPictureInPictureCustomControls(controls);
+}
+
void MediaWebContentsObserver::OnPictureInPictureSurfaceChanged(
RenderFrameHost* render_frame_host,
int delegate_id,
const viz::SurfaceId& surface_id,
const gfx::Size& natural_size) {
DCHECK(surface_id.is_valid());
- DCHECK(pip_player_);
pip_player_ = MediaPlayerId(render_frame_host, delegate_id);
@@ -515,7 +532,7 @@ void MediaWebContentsObserver::ExitPictureInPictureInternal() {
// Reset must happen after notifying the WebContents because it may interact
// with it.
- pip_player_.reset();
+ ResetPictureInPictureVideoMediaPlayerId();
UpdateVideoLock();
}
diff --git a/chromium/content/browser/media/media_web_contents_observer.h b/chromium/content/browser/media/media_web_contents_observer.h
index 67d25de6fd2..febe37fe409 100644
--- a/chromium/content/browser/media/media_web_contents_observer.h
+++ b/chromium/content/browser/media/media_web_contents_observer.h
@@ -23,6 +23,7 @@
namespace blink {
enum class WebFullscreenVideoStatus;
+struct PictureInPictureControlInfo;
} // namespace blink
namespace media {
@@ -73,12 +74,17 @@ class CONTENT_EXPORT MediaWebContentsObserver : public WebContentsObserver {
const base::Optional<MediaPlayerId>& GetPictureInPictureVideoMediaPlayerId()
const;
+ // Reset the MediaPlayerId of the picture in picture video when user closes
+ // Picture-in-Picture window manually.
+ void ResetPictureInPictureVideoMediaPlayerId();
+
// WebContentsObserver implementation.
void WebContentsDestroyed() override;
void RenderFrameDeleted(RenderFrameHost* render_frame_host) override;
bool OnMessageReceived(const IPC::Message& message,
RenderFrameHost* render_frame_host) override;
void OnVisibilityChanged(content::Visibility visibility) override;
+ void DidUpdateAudioMutingState(bool muted) override;
// TODO(zqzhang): this method is temporarily in MediaWebContentsObserver as
// the effectively fullscreen video code is also here. We need to consider
@@ -134,6 +140,10 @@ class CONTENT_EXPORT MediaWebContentsObserver : public WebContentsObserver {
void OnPictureInPictureModeEnded(RenderFrameHost* render_frame_host,
int delegate_id,
int request_id);
+ void OnSetPictureInPictureCustomControls(
+ RenderFrameHost* render_frame_host,
+ int delegate_id,
+ const std::vector<blink::PictureInPictureControlInfo>& controls);
void OnPictureInPictureSurfaceChanged(RenderFrameHost*,
int delegate_id,
const viz::SurfaceId&,
diff --git a/chromium/content/browser/media/session/audio_focus_delegate.h b/chromium/content/browser/media/session/audio_focus_delegate.h
index 5df555a56e5..ba23f16f875 100644
--- a/chromium/content/browser/media/session/audio_focus_delegate.h
+++ b/chromium/content/browser/media/session/audio_focus_delegate.h
@@ -7,6 +7,12 @@
#include "content/browser/media/session/audio_focus_manager.h"
+namespace media_session {
+namespace mojom {
+enum class AudioFocusType;
+} // namespace mojom
+} // namespace media_session
+
namespace content {
class MediaSessionImpl;
@@ -22,8 +28,11 @@ class AudioFocusDelegate {
virtual ~AudioFocusDelegate() = default;
virtual bool RequestAudioFocus(
- AudioFocusManager::AudioFocusType audio_focus_type) = 0;
+ media_session::mojom::AudioFocusType audio_focus_type) = 0;
virtual void AbandonAudioFocus() = 0;
+
+ // Retrieves the current |AudioFocusType| for the associated |MediaSession|.
+ virtual media_session::mojom::AudioFocusType GetCurrentFocusType() const = 0;
};
} // namespace content
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 603c5c9b6a2..211aad42013 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 "services/media_session/public/mojom/audio_focus.mojom.h"
using base::android::JavaParamRef;
@@ -30,13 +31,13 @@ void AudioFocusDelegateAndroid::Initialize() {
}
bool AudioFocusDelegateAndroid::RequestAudioFocus(
- AudioFocusManager::AudioFocusType audio_focus_type) {
+ media_session::mojom::AudioFocusType audio_focus_type) {
JNIEnv* env = base::android::AttachCurrentThread();
DCHECK(env);
return Java_AudioFocusDelegate_requestAudioFocus(
env, j_media_session_delegate_,
audio_focus_type ==
- AudioFocusManager::AudioFocusType::GainTransientMayDuck);
+ media_session::mojom::AudioFocusType::kGainTransientMayDuck);
}
void AudioFocusDelegateAndroid::AbandonAudioFocus() {
@@ -45,6 +46,16 @@ void AudioFocusDelegateAndroid::AbandonAudioFocus() {
Java_AudioFocusDelegate_abandonAudioFocus(env, j_media_session_delegate_);
}
+media_session::mojom::AudioFocusType
+AudioFocusDelegateAndroid::GetCurrentFocusType() const {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ DCHECK(env);
+ return Java_AudioFocusDelegate_isFocusTransient(env,
+ j_media_session_delegate_)
+ ? media_session::mojom::AudioFocusType::kGainTransientMayDuck
+ : media_session::mojom::AudioFocusType::kGain;
+}
+
void AudioFocusDelegateAndroid::OnSuspend(JNIEnv*,
const JavaParamRef<jobject>&) {
if (!media_session_->IsActive())
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 1c787004724..8c18679e42e 100644
--- a/chromium/content/browser/media/session/audio_focus_delegate_android.h
+++ b/chromium/content/browser/media/session/audio_focus_delegate_android.h
@@ -10,6 +10,12 @@
#include "base/android/scoped_java_ref.h"
#include "content/browser/media/session/audio_focus_delegate.h"
+namespace media_session {
+namespace mojom {
+enum class AudioFocusType;
+} // namespace mojom
+} // namespace media_session
+
namespace content {
// AudioFocusDelegateAndroid handles the audio focus at a system level on
@@ -22,8 +28,9 @@ class AudioFocusDelegateAndroid : public AudioFocusDelegate {
void Initialize();
bool RequestAudioFocus(
- AudioFocusManager::AudioFocusType audio_focus_type) override;
+ media_session::mojom::AudioFocusType audio_focus_type) override;
void AbandonAudioFocus() override;
+ media_session::mojom::AudioFocusType GetCurrentFocusType() const override;
// Called when the Android system requests the MediaSession to be suspended.
// Called by Java through JNI.
diff --git a/chromium/content/browser/media/session/audio_focus_delegate_default.cc b/chromium/content/browser/media/session/audio_focus_delegate_default.cc
index 586bbf361c1..eb7ec76aaf2 100644
--- a/chromium/content/browser/media/session/audio_focus_delegate_default.cc
+++ b/chromium/content/browser/media/session/audio_focus_delegate_default.cc
@@ -4,13 +4,13 @@
#include "content/browser/media/session/audio_focus_delegate.h"
-#include "base/command_line.h"
#include "content/browser/media/session/audio_focus_manager.h"
-#include "media/base/media_switches.h"
+#include "services/media_session/public/cpp/switches.h"
+#include "services/media_session/public/mojom/audio_focus.mojom.h"
namespace content {
-using AudioFocusType = AudioFocusManager::AudioFocusType;
+using media_session::mojom::AudioFocusType;
namespace {
@@ -22,13 +22,16 @@ class AudioFocusDelegateDefault : public AudioFocusDelegate {
~AudioFocusDelegateDefault() override;
// AudioFocusDelegate implementation.
- bool RequestAudioFocus(
- AudioFocusManager::AudioFocusType audio_focus_type) override;
+ bool RequestAudioFocus(AudioFocusType audio_focus_type) override;
void AbandonAudioFocus() override;
+ AudioFocusType GetCurrentFocusType() const override;
private:
// Weak pointer because |this| is owned by |media_session_|.
MediaSessionImpl* media_session_;
+
+ // The last requested AudioFocusType by the associated |media_session_|.
+ AudioFocusType audio_focus_type_if_disabled_;
};
} // anonymous namespace
@@ -40,11 +43,11 @@ AudioFocusDelegateDefault::AudioFocusDelegateDefault(
AudioFocusDelegateDefault::~AudioFocusDelegateDefault() = default;
bool AudioFocusDelegateDefault::RequestAudioFocus(
- AudioFocusManager::AudioFocusType audio_focus_type) {
- if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableAudioFocus)) {
+ AudioFocusType audio_focus_type) {
+ audio_focus_type_if_disabled_ = audio_focus_type;
+
+ if (!media_session::IsAudioFocusEnabled())
return true;
- }
AudioFocusManager::GetInstance()->RequestAudioFocus(media_session_,
audio_focus_type);
@@ -55,6 +58,15 @@ void AudioFocusDelegateDefault::AbandonAudioFocus() {
AudioFocusManager::GetInstance()->AbandonAudioFocus(media_session_);
}
+AudioFocusType AudioFocusDelegateDefault::GetCurrentFocusType() const {
+ if (media_session::IsAudioFocusEnabled()) {
+ return AudioFocusManager::GetInstance()->GetFocusTypeForSession(
+ media_session_);
+ }
+
+ return audio_focus_type_if_disabled_;
+}
+
// static
std::unique_ptr<AudioFocusDelegate> AudioFocusDelegate::Create(
MediaSessionImpl* media_session) {
diff --git a/chromium/content/browser/media/session/audio_focus_delegate_default_browsertest.cc b/chromium/content/browser/media/session/audio_focus_delegate_default_browsertest.cc
index ed4ec737d31..8d5e777f70a 100644
--- a/chromium/content/browser/media/session/audio_focus_delegate_default_browsertest.cc
+++ b/chromium/content/browser/media/session/audio_focus_delegate_default_browsertest.cc
@@ -8,14 +8,14 @@
#include "content/public/test/content_browser_test.h"
#include "content/shell/browser/shell.h"
#include "media/base/media_content_type.h"
-#include "media/base/media_switches.h"
+#include "services/media_session/public/cpp/switches.h"
namespace content {
class AudioFocusDelegateDefaultBrowserTest : public ContentBrowserTest {
protected:
void SetUpCommandLine(base::CommandLine* command_line) override {
- command_line->AppendSwitch(switches::kEnableAudioFocus);
+ command_line->AppendSwitch(media_session::switches::kEnableAudioFocus);
}
void Run(WebContents* start_contents, WebContents* interrupt_contents) {
diff --git a/chromium/content/browser/media/session/audio_focus_manager.cc b/chromium/content/browser/media/session/audio_focus_manager.cc
index 6a9e7215d5c..fbd8af4da47 100644
--- a/chromium/content/browser/media/session/audio_focus_manager.cc
+++ b/chromium/content/browser/media/session/audio_focus_manager.cc
@@ -4,11 +4,28 @@
#include "content/browser/media/session/audio_focus_manager.h"
+#include "content/browser/media/session/audio_focus_observer.h"
#include "content/browser/media/session/media_session_impl.h"
+#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_contents.h"
+#include "mojo/public/cpp/bindings/interface_request.h"
+#include "services/media_session/public/mojom/audio_focus.mojom.h"
namespace content {
+using media_session::mojom::AudioFocusType;
+
+namespace {
+
+media_session::mojom::MediaSessionPtr GetSessionMojoPtr(
+ MediaSessionImpl* session) {
+ media_session::mojom::MediaSessionPtr media_session_ptr;
+ session->BindToMojoRequest(mojo::MakeRequest(&media_session_ptr));
+ return media_session_ptr;
+}
+
+} // namespace
+
// static
AudioFocusManager* AudioFocusManager::GetInstance() {
return base::Singleton<AudioFocusManager>::get();
@@ -17,9 +34,9 @@ AudioFocusManager* AudioFocusManager::GetInstance() {
void AudioFocusManager::RequestAudioFocus(MediaSessionImpl* media_session,
AudioFocusType type) {
if (!audio_focus_stack_.empty() &&
- audio_focus_stack_.back() == media_session &&
- audio_focus_stack_.back()->audio_focus_type() == type &&
- audio_focus_stack_.back()->IsActive()) {
+ audio_focus_stack_.back().media_session == media_session &&
+ audio_focus_stack_.back().audio_focus_type == type &&
+ audio_focus_stack_.back().media_session->IsActive()) {
// Early returning if |media_session| is already on top (has focus) and is
// active.
return;
@@ -32,64 +49,125 @@ void AudioFocusManager::RequestAudioFocus(MediaSessionImpl* media_session,
// too much. Maybe it's better to do some abstraction and refactoring to clean
// up the relation between AudioFocusManager and MediaSessionImpl.
// See https://crbug.com/651069
- if (type == AudioFocusType::GainTransientMayDuck) {
- for (auto* old_session : audio_focus_stack_) {
- old_session->StartDucking();
+ if (type == AudioFocusType::kGainTransientMayDuck) {
+ for (auto& old_session : audio_focus_stack_) {
+ old_session.media_session->StartDucking();
}
} else {
- for (auto* old_session : audio_focus_stack_) {
- if (old_session->IsActive()) {
- if (old_session->HasPepper())
- old_session->StartDucking();
+ for (auto& old_session : audio_focus_stack_) {
+ if (old_session.media_session->IsActive()) {
+ if (old_session.media_session->HasPepper())
+ old_session.media_session->StartDucking();
else
- old_session->Suspend(MediaSessionImpl::SuspendType::SYSTEM);
+ old_session.media_session->Suspend(
+ MediaSessionImpl::SuspendType::SYSTEM);
}
}
}
- audio_focus_stack_.push_back(media_session);
- audio_focus_stack_.back()->StopDucking();
+ // Store the MediaSession and requested focus type.
+ audio_focus_stack_.emplace_back(media_session, type);
+ audio_focus_stack_.back().media_session->StopDucking();
+
+ // Notify observers that we were gained audio focus.
+ observers_.ForAllPtrs(
+ [media_session,
+ type](media_session::mojom::AudioFocusObserver* observer) {
+ observer->OnFocusGained(GetSessionMojoPtr(media_session), type);
+ });
}
void AudioFocusManager::AbandonAudioFocus(MediaSessionImpl* media_session) {
if (audio_focus_stack_.empty())
return;
- if (audio_focus_stack_.back() != media_session) {
+ if (audio_focus_stack_.back().media_session != media_session) {
MaybeRemoveFocusEntry(media_session);
return;
}
audio_focus_stack_.pop_back();
- if (audio_focus_stack_.empty())
+ if (audio_focus_stack_.empty()) {
+ // Notify observers that we lost audio focus.
+ observers_.ForAllPtrs(
+ [media_session](media_session::mojom::AudioFocusObserver* observer) {
+ observer->OnFocusLost(GetSessionMojoPtr(media_session));
+ });
return;
+ }
// Allow the top-most MediaSessionImpl having Pepper to unduck pepper even if
// it's
// not active.
for (auto iter = audio_focus_stack_.rbegin();
iter != audio_focus_stack_.rend(); ++iter) {
- if (!(*iter)->HasPepper())
+ if (!iter->media_session->HasPepper())
continue;
- MediaSessionImpl* pepper_session = *iter;
+ MediaSessionImpl* pepper_session = iter->media_session;
+ AudioFocusType focus_type = iter->audio_focus_type;
pepper_session->StopDucking();
MaybeRemoveFocusEntry(pepper_session);
- audio_focus_stack_.push_back(pepper_session);
+ audio_focus_stack_.emplace_back(pepper_session, focus_type);
return;
}
// Only try to unduck the new MediaSessionImpl on top. The session might be
// still
// inactive but it will not be resumed (so it doesn't surprise the user).
- audio_focus_stack_.back()->StopDucking();
+ audio_focus_stack_.back().media_session->StopDucking();
+
+ // Notify observers that we lost audio focus.
+ observers_.ForAllPtrs(
+ [media_session](media_session::mojom::AudioFocusObserver* observer) {
+ observer->OnFocusLost(GetSessionMojoPtr(media_session));
+ });
+}
+
+mojo::InterfacePtrSetElementId AudioFocusManager::AddObserver(
+ media_session::mojom::AudioFocusObserverPtr observer) {
+ return observers_.AddPtr(std::move(observer));
+}
+
+AudioFocusType AudioFocusManager::GetFocusTypeForSession(
+ MediaSessionImpl* media_session) const {
+ for (auto row : audio_focus_stack_) {
+ if (row.media_session == media_session)
+ return row.audio_focus_type;
+ }
+
+ NOTREACHED();
+ return AudioFocusType::kGain;
+}
+
+void AudioFocusManager::RemoveObserver(mojo::InterfacePtrSetElementId id) {
+ observers_.RemovePtr(id);
+}
+
+void AudioFocusManager::ResetForTesting() {
+ audio_focus_stack_.clear();
+ observers_.CloseAll();
+}
+
+void AudioFocusManager::FlushForTesting() {
+ observers_.FlushForTesting();
}
-AudioFocusManager::AudioFocusManager() = default;
+AudioFocusManager::AudioFocusManager() {
+ // Make sure we start AudioFocusManager on the browser UI thread. This is to
+ // ensure thread consistency for mojo::InterfaceSetPtr.
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+}
AudioFocusManager::~AudioFocusManager() = default;
void AudioFocusManager::MaybeRemoveFocusEntry(MediaSessionImpl* media_session) {
- audio_focus_stack_.remove(media_session);
+ for (auto iter = audio_focus_stack_.begin(); iter != audio_focus_stack_.end();
+ ++iter) {
+ if (iter->media_session == media_session) {
+ audio_focus_stack_.erase(iter);
+ break;
+ }
+ }
}
} // namespace content
diff --git a/chromium/content/browser/media/session/audio_focus_manager.h b/chromium/content/browser/media/session/audio_focus_manager.h
index df49b85fc1f..3bc2cc78253 100644
--- a/chromium/content/browser/media/session/audio_focus_manager.h
+++ b/chromium/content/browser/media/session/audio_focus_manager.h
@@ -11,6 +11,8 @@
#include "base/memory/singleton.h"
#include "content/common/content_export.h"
#include "content/public/browser/web_contents_observer.h"
+#include "mojo/public/cpp/bindings/interface_ptr_set.h"
+#include "services/media_session/public/mojom/audio_focus.mojom.h"
namespace content {
@@ -18,30 +20,55 @@ class MediaSessionImpl;
class CONTENT_EXPORT AudioFocusManager {
public:
- enum class AudioFocusType {
- Gain,
- GainTransientMayDuck,
- };
-
// Returns Chromium's internal AudioFocusManager.
static AudioFocusManager* GetInstance();
- void RequestAudioFocus(MediaSessionImpl* media_session, AudioFocusType type);
+ void RequestAudioFocus(MediaSessionImpl* media_session,
+ media_session::mojom::AudioFocusType type);
void AbandonAudioFocus(MediaSessionImpl* media_session);
+ media_session::mojom::AudioFocusType GetFocusTypeForSession(
+ MediaSessionImpl* media_session) const;
+
+ // Adds/removes audio focus observers.
+ mojo::InterfacePtrSetElementId AddObserver(
+ media_session::mojom::AudioFocusObserverPtr);
+ void RemoveObserver(mojo::InterfacePtrSetElementId);
+
private:
friend struct base::DefaultSingletonTraits<AudioFocusManager>;
friend class AudioFocusManagerTest;
+ // Media internals UI needs access to internal state.
+ friend class MediaInternalsAudioFocusTest;
+ friend class MediaInternals;
+
+ // Flush for testing will flush any pending messages to the observers.
+ void FlushForTesting();
+
+ // Reset for testing will clear any built up internal state.
+ void ResetForTesting();
+
AudioFocusManager();
~AudioFocusManager();
void MaybeRemoveFocusEntry(MediaSessionImpl* media_session);
- // Weak reference of managed MediaSessions. A MediaSession must abandon audio
- // foucs before its destruction.
- std::list<MediaSessionImpl*> audio_focus_stack_;
+ // Weak reference of managed observers. Observers are expected to remove
+ // themselves before being destroyed.
+ mojo::InterfacePtrSet<media_session::mojom::AudioFocusObserver> observers_;
+
+ // Weak reference of managed MediaSessions and their requested focus type.
+ // A MediaSession must abandon audio focus before its destruction.
+ struct StackRow {
+ StackRow(MediaSessionImpl* media_session,
+ media_session::mojom::AudioFocusType audio_focus_type)
+ : media_session(media_session), audio_focus_type(audio_focus_type) {}
+ MediaSessionImpl* media_session;
+ media_session::mojom::AudioFocusType audio_focus_type;
+ };
+ std::list<StackRow> audio_focus_stack_;
};
} // namespace content
diff --git a/chromium/content/browser/media/session/audio_focus_manager_unittest.cc b/chromium/content/browser/media/session/audio_focus_manager_unittest.cc
index 459ce5089f4..fc4a5974244 100644
--- a/chromium/content/browser/media/session/audio_focus_manager_unittest.cc
+++ b/chromium/content/browser/media/session/audio_focus_manager_unittest.cc
@@ -7,7 +7,9 @@
#include <memory>
#include "base/command_line.h"
+#include "base/optional.h"
#include "base/run_loop.h"
+#include "content/browser/media/session/audio_focus_observer.h"
#include "content/browser/media/session/media_session_impl.h"
#include "content/browser/media/session/media_session_player_observer.h"
#include "content/public/test/mock_render_process_host.h"
@@ -15,12 +17,36 @@
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/test/test_web_contents.h"
#include "media/base/media_content_type.h"
-#include "media/base/media_switches.h"
+#include "services/media_session/public/cpp/switches.h"
+#include "services/media_session/public/mojom/audio_focus.mojom.h"
namespace content {
+using media_session::mojom::AudioFocusType;
+using media_session::mojom::MediaSessionPtr;
+
namespace {
+class MockAudioFocusObserver : public AudioFocusObserver {
+ public:
+ MockAudioFocusObserver() { RegisterAudioFocusObserver(); }
+
+ void OnFocusGained(MediaSessionPtr session, AudioFocusType type) override {
+ EXPECT_TRUE(session.is_bound());
+ focus_gained_call_ = type;
+ focus_lost_call_ = false;
+ }
+
+ void OnFocusLost(MediaSessionPtr session) override {
+ EXPECT_TRUE(session.is_bound());
+ focus_lost_call_ = true;
+ focus_gained_call_.reset();
+ }
+
+ base::Optional<AudioFocusType> focus_gained_call_;
+ bool focus_lost_call_ = false;
+};
+
class MockMediaSessionPlayerObserver : public MediaSessionPlayerObserver {
public:
void OnSuspend(int player_id) override {}
@@ -34,7 +60,6 @@ class MockMediaSessionPlayerObserver : public MediaSessionPlayerObserver {
} // anonymous namespace
-using AudioFocusType = AudioFocusManager::AudioFocusType;
using SuspendType = MediaSession::SuspendType;
class AudioFocusManagerTest : public testing::Test {
@@ -43,12 +68,16 @@ class AudioFocusManagerTest : public testing::Test {
void SetUp() override {
base::CommandLine::ForCurrentProcess()->AppendSwitch(
- switches::kEnableAudioFocus);
+ media_session::switches::kEnableAudioFocus);
rph_factory_.reset(new MockRenderProcessHostFactory());
RenderProcessHostImpl::set_render_process_host_factory_for_testing(
rph_factory_.get());
browser_context_.reset(new TestBrowserContext());
pepper_observer_.reset(new MockMediaSessionPlayerObserver());
+
+ // AudioFocusManager is a singleton so we should make sure we reset any
+ // state in between tests.
+ AudioFocusManager::GetInstance()->ResetForTesting();
}
void TearDown() override {
@@ -61,29 +90,28 @@ class AudioFocusManagerTest : public testing::Test {
}
MediaSessionImpl* GetAudioFocusedSession() const {
- const auto& audio_focus_stack =
- AudioFocusManager::GetInstance()->audio_focus_stack_;
+ const AudioFocusManager* manager = AudioFocusManager::GetInstance();
+ const auto& audio_focus_stack = manager->audio_focus_stack_;
+
for (auto iter = audio_focus_stack.rbegin();
iter != audio_focus_stack.rend(); ++iter) {
- if ((*iter)->audio_focus_type() ==
- AudioFocusManager::AudioFocusType::Gain)
- return (*iter);
+ if ((*iter).audio_focus_type == AudioFocusType::kGain)
+ return (*iter).media_session;
}
return nullptr;
}
int GetTransientMaybeDuckCount() const {
+ const AudioFocusManager* manager = AudioFocusManager::GetInstance();
+ const auto& audio_focus_stack = manager->audio_focus_stack_;
int count = 0;
- const auto& audio_focus_stack =
- AudioFocusManager::GetInstance()->audio_focus_stack_;
+
for (auto iter = audio_focus_stack.rbegin();
iter != audio_focus_stack.rend(); ++iter) {
- if ((*iter)->audio_focus_type() ==
- AudioFocusManager::AudioFocusType::GainTransientMayDuck) {
- ++count;
- } else {
+ if ((*iter).audio_focus_type == AudioFocusType::kGainTransientMayDuck)
+ ++count;
+ else
break;
- }
}
return count;
@@ -94,7 +122,7 @@ class AudioFocusManagerTest : public testing::Test {
}
void RequestAudioFocus(MediaSessionImpl* session,
- AudioFocusManager::AudioFocusType audio_focus_type) {
+ AudioFocusType audio_focus_type) {
session->RequestSystemAudioFocus(audio_focus_type);
}
@@ -102,6 +130,10 @@ class AudioFocusManagerTest : public testing::Test {
session->AbandonSystemAudioFocusIfNeeded();
}
+ void FlushForTesting() {
+ AudioFocusManager::GetInstance()->FlushForTesting();
+ }
+
std::unique_ptr<WebContents> CreateWebContents() {
return TestWebContents::Create(browser_context_.get(),
SiteInstance::SiteInstance::Create(browser_context_.get()));
@@ -137,13 +169,13 @@ TEST_F(AudioFocusManagerTest, RequestAudioFocusGain_ReplaceFocusedEntry) {
ASSERT_EQ(nullptr, GetAudioFocusedSession());
- RequestAudioFocus(media_session_1, AudioFocusManager::AudioFocusType::Gain);
+ RequestAudioFocus(media_session_1, AudioFocusType::kGain);
ASSERT_EQ(media_session_1, GetAudioFocusedSession());
- RequestAudioFocus(media_session_2, AudioFocusManager::AudioFocusType::Gain);
+ RequestAudioFocus(media_session_2, AudioFocusType::kGain);
ASSERT_EQ(media_session_2, GetAudioFocusedSession());
- RequestAudioFocus(media_session_3, AudioFocusManager::AudioFocusType::Gain);
+ RequestAudioFocus(media_session_3, AudioFocusType::kGain);
ASSERT_EQ(media_session_3, GetAudioFocusedSession());
}
@@ -153,10 +185,10 @@ TEST_F(AudioFocusManagerTest, RequestAudioFocusGain_Duplicate) {
ASSERT_EQ(nullptr, GetAudioFocusedSession());
- RequestAudioFocus(media_session, AudioFocusManager::AudioFocusType::Gain);
+ RequestAudioFocus(media_session, AudioFocusType::kGain);
ASSERT_EQ(media_session, GetAudioFocusedSession());
- RequestAudioFocus(media_session, AudioFocusManager::AudioFocusType::Gain);
+ RequestAudioFocus(media_session, AudioFocusType::kGain);
ASSERT_EQ(media_session, GetAudioFocusedSession());
}
@@ -164,12 +196,11 @@ TEST_F(AudioFocusManagerTest, RequestAudioFocusGain_FromTransient) {
std::unique_ptr<WebContents> web_contents(CreateWebContents());
MediaSessionImpl* media_session = MediaSessionImpl::Get(web_contents.get());
- RequestAudioFocus(
- media_session, AudioFocusManager::AudioFocusType::GainTransientMayDuck);
+ RequestAudioFocus(media_session, AudioFocusType::kGainTransientMayDuck);
ASSERT_EQ(nullptr, GetAudioFocusedSession());
ASSERT_EQ(1, GetTransientMaybeDuckCount());
- RequestAudioFocus(media_session, AudioFocusManager::AudioFocusType::Gain);
+ RequestAudioFocus(media_session, AudioFocusType::kGain);
ASSERT_EQ(media_session, GetAudioFocusedSession());
ASSERT_EQ(0, GetTransientMaybeDuckCount());
}
@@ -178,12 +209,11 @@ TEST_F(AudioFocusManagerTest, RequestAudioFocusTransient_FromGain) {
std::unique_ptr<WebContents> web_contents(CreateWebContents());
MediaSessionImpl* media_session = MediaSessionImpl::Get(web_contents.get());
- RequestAudioFocus(media_session, AudioFocusManager::AudioFocusType::Gain);
+ RequestAudioFocus(media_session, AudioFocusType::kGain);
ASSERT_EQ(media_session, GetAudioFocusedSession());
ASSERT_EQ(0, GetTransientMaybeDuckCount());
- RequestAudioFocus(
- media_session, AudioFocusManager::AudioFocusType::GainTransientMayDuck);
+ RequestAudioFocus(media_session, AudioFocusType::kGainTransientMayDuck);
ASSERT_EQ(nullptr, GetAudioFocusedSession());
ASSERT_EQ(1, GetTransientMaybeDuckCount());
ASSERT_FALSE(IsSessionDucking(media_session));
@@ -198,17 +228,15 @@ TEST_F(AudioFocusManagerTest, RequestAudioFocusTransient_FromGainWhileDucking) {
MediaSessionImpl* media_session_2 =
MediaSessionImpl::Get(web_contents_2.get());
- RequestAudioFocus(media_session_1, AudioFocusManager::AudioFocusType::Gain);
+ RequestAudioFocus(media_session_1, AudioFocusType::kGain);
ASSERT_EQ(0, GetTransientMaybeDuckCount());
ASSERT_FALSE(IsSessionDucking(media_session_1));
- RequestAudioFocus(
- media_session_2, AudioFocusManager::AudioFocusType::GainTransientMayDuck);
+ RequestAudioFocus(media_session_2, AudioFocusType::kGainTransientMayDuck);
ASSERT_EQ(1, GetTransientMaybeDuckCount());
ASSERT_TRUE(IsSessionDucking(media_session_1));
- RequestAudioFocus(
- media_session_1, AudioFocusManager::AudioFocusType::GainTransientMayDuck);
+ RequestAudioFocus(media_session_1, AudioFocusType::kGainTransientMayDuck);
ASSERT_EQ(2, GetTransientMaybeDuckCount());
ASSERT_FALSE(IsSessionDucking(media_session_1));
}
@@ -217,7 +245,7 @@ TEST_F(AudioFocusManagerTest, AbandonAudioFocus_RemovesFocusedEntry) {
std::unique_ptr<WebContents> web_contents(CreateWebContents());
MediaSessionImpl* media_session = MediaSessionImpl::Get(web_contents.get());
- RequestAudioFocus(media_session, AudioFocusManager::AudioFocusType::Gain);
+ RequestAudioFocus(media_session, AudioFocusType::kGain);
ASSERT_EQ(media_session, GetAudioFocusedSession());
AbandonAudioFocus(media_session);
@@ -236,12 +264,17 @@ TEST_F(AudioFocusManagerTest, AbandonAudioFocus_RemovesTransientEntry) {
std::unique_ptr<WebContents> web_contents(CreateWebContents());
MediaSessionImpl* media_session = MediaSessionImpl::Get(web_contents.get());
- RequestAudioFocus(
- media_session, AudioFocusManager::AudioFocusType::GainTransientMayDuck);
+ RequestAudioFocus(media_session, AudioFocusType::kGainTransientMayDuck);
ASSERT_EQ(1, GetTransientMaybeDuckCount());
- AbandonAudioFocus(media_session);
- ASSERT_EQ(0, GetTransientMaybeDuckCount());
+ {
+ MockAudioFocusObserver observer;
+ AbandonAudioFocus(media_session);
+ FlushForTesting();
+
+ EXPECT_EQ(0, GetTransientMaybeDuckCount());
+ EXPECT_TRUE(observer.focus_lost_call_);
+ }
}
TEST_F(AudioFocusManagerTest, AbandonAudioFocus_WhileDuckingThenResume) {
@@ -253,12 +286,11 @@ TEST_F(AudioFocusManagerTest, AbandonAudioFocus_WhileDuckingThenResume) {
MediaSessionImpl* media_session_2 =
MediaSessionImpl::Get(web_contents_2.get());
- RequestAudioFocus(media_session_1, AudioFocusManager::AudioFocusType::Gain);
+ RequestAudioFocus(media_session_1, AudioFocusType::kGain);
ASSERT_EQ(0, GetTransientMaybeDuckCount());
ASSERT_FALSE(IsSessionDucking(media_session_1));
- RequestAudioFocus(
- media_session_2, AudioFocusManager::AudioFocusType::GainTransientMayDuck);
+ RequestAudioFocus(media_session_2, AudioFocusType::kGainTransientMayDuck);
ASSERT_EQ(1, GetTransientMaybeDuckCount());
ASSERT_TRUE(IsSessionDucking(media_session_1));
@@ -268,7 +300,7 @@ TEST_F(AudioFocusManagerTest, AbandonAudioFocus_WhileDuckingThenResume) {
AbandonAudioFocus(media_session_2);
ASSERT_EQ(0, GetTransientMaybeDuckCount());
- RequestAudioFocus(media_session_1, AudioFocusManager::AudioFocusType::Gain);
+ RequestAudioFocus(media_session_1, AudioFocusType::kGain);
ASSERT_FALSE(IsSessionDucking(media_session_1));
}
@@ -281,12 +313,11 @@ TEST_F(AudioFocusManagerTest, AbandonAudioFocus_StopsDucking) {
MediaSessionImpl* media_session_2 =
MediaSessionImpl::Get(web_contents_2.get());
- RequestAudioFocus(media_session_1, AudioFocusManager::AudioFocusType::Gain);
+ RequestAudioFocus(media_session_1, AudioFocusType::kGain);
ASSERT_EQ(0, GetTransientMaybeDuckCount());
ASSERT_FALSE(IsSessionDucking(media_session_1));
- RequestAudioFocus(
- media_session_2, AudioFocusManager::AudioFocusType::GainTransientMayDuck);
+ RequestAudioFocus(media_session_2, AudioFocusType::kGainTransientMayDuck);
ASSERT_EQ(1, GetTransientMaybeDuckCount());
ASSERT_TRUE(IsSessionDucking(media_session_1));
@@ -304,11 +335,10 @@ TEST_F(AudioFocusManagerTest, DuckWhilePlaying) {
MediaSessionImpl* media_session_2 =
MediaSessionImpl::Get(web_contents_2.get());
- RequestAudioFocus(media_session_1, AudioFocusManager::AudioFocusType::Gain);
+ RequestAudioFocus(media_session_1, AudioFocusType::kGain);
ASSERT_FALSE(IsSessionDucking(media_session_1));
- RequestAudioFocus(
- media_session_2, AudioFocusManager::AudioFocusType::GainTransientMayDuck);
+ RequestAudioFocus(media_session_2, AudioFocusType::kGainTransientMayDuck);
ASSERT_TRUE(IsSessionDucking(media_session_1));
}
@@ -321,10 +351,9 @@ TEST_F(AudioFocusManagerTest, GainSuspendsTransient) {
MediaSessionImpl* media_session_2 =
MediaSessionImpl::Get(web_contents_2.get());
- RequestAudioFocus(
- media_session_2, AudioFocusManager::AudioFocusType::GainTransientMayDuck);
+ RequestAudioFocus(media_session_2, AudioFocusType::kGainTransientMayDuck);
- RequestAudioFocus(media_session_1, AudioFocusManager::AudioFocusType::Gain);
+ RequestAudioFocus(media_session_1, AudioFocusType::kGain);
ASSERT_TRUE(media_session_2->IsSuspended());
}
@@ -341,15 +370,13 @@ TEST_F(AudioFocusManagerTest, DuckWithMultipleTransients) {
MediaSessionImpl* media_session_3 =
MediaSessionImpl::Get(web_contents_3.get());
- RequestAudioFocus(media_session_1, AudioFocusManager::AudioFocusType::Gain);
+ RequestAudioFocus(media_session_1, AudioFocusType::kGain);
ASSERT_FALSE(IsSessionDucking(media_session_1));
- RequestAudioFocus(
- media_session_2, AudioFocusManager::AudioFocusType::GainTransientMayDuck);
+ RequestAudioFocus(media_session_2, AudioFocusType::kGainTransientMayDuck);
ASSERT_TRUE(IsSessionDucking(media_session_1));
- RequestAudioFocus(
- media_session_3, AudioFocusManager::AudioFocusType::GainTransientMayDuck);
+ RequestAudioFocus(media_session_3, AudioFocusType::kGainTransientMayDuck);
ASSERT_TRUE(IsSessionDucking(media_session_1));
AbandonAudioFocus(media_session_2);
@@ -363,7 +390,7 @@ TEST_F(AudioFocusManagerTest, WebContentsDestroyed_ReleasesFocus) {
std::unique_ptr<WebContents> web_contents(CreateWebContents());
MediaSessionImpl* media_session = MediaSessionImpl::Get(web_contents.get());
- RequestAudioFocus(media_session, AudioFocusManager::AudioFocusType::Gain);
+ RequestAudioFocus(media_session, AudioFocusType::kGain);
ASSERT_EQ(media_session, GetAudioFocusedSession());
web_contents.reset();
@@ -374,8 +401,7 @@ TEST_F(AudioFocusManagerTest, WebContentsDestroyed_ReleasesTransients) {
std::unique_ptr<WebContents> web_contents(CreateWebContents());
MediaSessionImpl* media_session = MediaSessionImpl::Get(web_contents.get());
- RequestAudioFocus(
- media_session, AudioFocusManager::AudioFocusType::GainTransientMayDuck);
+ RequestAudioFocus(media_session, AudioFocusType::kGainTransientMayDuck);
ASSERT_EQ(1, GetTransientMaybeDuckCount());
web_contents.reset();
@@ -391,11 +417,10 @@ TEST_F(AudioFocusManagerTest, WebContentsDestroyed_StopsDucking) {
MediaSessionImpl* media_session_2 =
MediaSessionImpl::Get(web_contents_2.get());
- RequestAudioFocus(media_session_1, AudioFocusManager::AudioFocusType::Gain);
+ RequestAudioFocus(media_session_1, AudioFocusType::kGain);
ASSERT_FALSE(IsSessionDucking(media_session_1));
- RequestAudioFocus(
- media_session_2, AudioFocusManager::AudioFocusType::GainTransientMayDuck);
+ RequestAudioFocus(media_session_2, AudioFocusType::kGainTransientMayDuck);
ASSERT_TRUE(IsSessionDucking(media_session_1));
web_contents_2.reset();
@@ -426,8 +451,7 @@ TEST_F(AudioFocusManagerTest, GainDucksPepper) {
media_session_1->AddPlayer(
pepper_observer_.get(), 0, media::MediaContentType::Pepper);
- RequestAudioFocus(
- media_session_2, AudioFocusManager::AudioFocusType::Gain);
+ RequestAudioFocus(media_session_2, AudioFocusType::kGain);
ASSERT_EQ(media_session_2, GetAudioFocusedSession());
ASSERT_TRUE(media_session_1->IsActive());
@@ -450,10 +474,8 @@ TEST_F(AudioFocusManagerTest, AbandoningGainFocusRevokesTopMostPepperSession) {
media_session_1->AddPlayer(
pepper_observer_.get(), 0, media::MediaContentType::Pepper);
- RequestAudioFocus(
- media_session_2, AudioFocusManager::AudioFocusType::Gain);
- RequestAudioFocus(
- media_session_3, AudioFocusManager::AudioFocusType::Gain);
+ RequestAudioFocus(media_session_2, AudioFocusType::kGain);
+ RequestAudioFocus(media_session_3, AudioFocusType::kGain);
ASSERT_EQ(media_session_3, GetAudioFocusedSession());
ASSERT_TRUE(media_session_2->IsSuspended());
@@ -464,4 +486,65 @@ TEST_F(AudioFocusManagerTest, AbandoningGainFocusRevokesTopMostPepperSession) {
ASSERT_EQ(media_session_1, GetAudioFocusedSession());
}
+TEST_F(AudioFocusManagerTest, AudioFocusObserver_AbandonNoop) {
+ std::unique_ptr<WebContents> web_contents(CreateWebContents());
+ MediaSessionImpl* media_session = MediaSessionImpl::Get(web_contents.get());
+
+ {
+ MockAudioFocusObserver observer;
+ AbandonAudioFocus(media_session);
+ FlushForTesting();
+
+ EXPECT_EQ(nullptr, GetAudioFocusedSession());
+ EXPECT_FALSE(observer.focus_lost_call_);
+ }
+}
+
+TEST_F(AudioFocusManagerTest, AudioFocusObserver_RequestNoop) {
+ std::unique_ptr<WebContents> web_contents(CreateWebContents());
+ MediaSessionImpl* media_session = MediaSessionImpl::Get(web_contents.get());
+
+ {
+ MockAudioFocusObserver observer;
+ RequestAudioFocus(media_session, AudioFocusType::kGain);
+ FlushForTesting();
+
+ EXPECT_EQ(media_session, GetAudioFocusedSession());
+ EXPECT_EQ(AudioFocusType::kGain, observer.focus_gained_call_.value());
+ }
+
+ {
+ MockAudioFocusObserver observer;
+ RequestAudioFocus(media_session, AudioFocusType::kGain);
+ FlushForTesting();
+
+ EXPECT_EQ(media_session, GetAudioFocusedSession());
+ EXPECT_FALSE(observer.focus_gained_call_.has_value());
+ }
+}
+
+TEST_F(AudioFocusManagerTest, AudioFocusObserver_TransientMayDuck) {
+ std::unique_ptr<WebContents> web_contents(CreateWebContents());
+ MediaSessionImpl* media_session = MediaSessionImpl::Get(web_contents.get());
+
+ {
+ MockAudioFocusObserver observer;
+ RequestAudioFocus(media_session, AudioFocusType::kGainTransientMayDuck);
+ FlushForTesting();
+
+ EXPECT_EQ(1, GetTransientMaybeDuckCount());
+ EXPECT_EQ(AudioFocusType::kGainTransientMayDuck,
+ observer.focus_gained_call_.value());
+ }
+
+ {
+ MockAudioFocusObserver observer;
+ AbandonAudioFocus(media_session);
+ FlushForTesting();
+
+ EXPECT_EQ(0, GetTransientMaybeDuckCount());
+ EXPECT_TRUE(observer.focus_lost_call_);
+ }
+}
+
} // namespace content
diff --git a/chromium/content/browser/media/session/audio_focus_observer.cc b/chromium/content/browser/media/session/audio_focus_observer.cc
new file mode 100644
index 00000000000..b78c54c4b5f
--- /dev/null
+++ b/chromium/content/browser/media/session/audio_focus_observer.cc
@@ -0,0 +1,46 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/media/session/audio_focus_observer.h"
+
+#include "build/build_config.h"
+#include "content/browser/media/session/audio_focus_manager.h"
+#include "content/public/browser/browser_thread.h"
+#include "mojo/public/cpp/bindings/interface_request.h"
+
+namespace content {
+
+AudioFocusObserver::AudioFocusObserver() : binding_(this) {}
+
+void AudioFocusObserver::RegisterAudioFocusObserver() {
+ if (observer_id_.has_value())
+ return;
+
+#if !defined(OS_ANDROID)
+ // TODO(https://crbug.com/873320): Add support for Android.
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ media_session::mojom::AudioFocusObserverPtr observer;
+ binding_.Bind(mojo::MakeRequest(&observer));
+ observer_id_ =
+ AudioFocusManager::GetInstance()->AddObserver(std::move(observer));
+#endif
+}
+
+void AudioFocusObserver::UnregisterAudioFocusObserver() {
+ if (!observer_id_.has_value())
+ return;
+
+#if !defined(OS_ANDROID)
+ // TODO(https://crbug.com/873320): Add support for Android.
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ binding_.Close();
+ AudioFocusManager::GetInstance()->RemoveObserver(observer_id_.value());
+#endif
+
+ observer_id_.reset();
+}
+
+AudioFocusObserver::~AudioFocusObserver() = default;
+
+} // namespace content
diff --git a/chromium/content/browser/media/session/audio_focus_observer.h b/chromium/content/browser/media/session/audio_focus_observer.h
new file mode 100644
index 00000000000..c4eae2b9f56
--- /dev/null
+++ b/chromium/content/browser/media/session/audio_focus_observer.h
@@ -0,0 +1,47 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_MEDIA_SESSION_AUDIO_FOCUS_OBSERVER_H_
+#define CONTENT_BROWSER_MEDIA_SESSION_AUDIO_FOCUS_OBSERVER_H_
+
+#include "base/macros.h"
+#include "base/optional.h"
+#include "content/common/content_export.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/interface_ptr_set.h"
+#include "services/media_session/public/mojom/audio_focus.mojom.h"
+
+namespace content {
+
+// The observer for observing audio focus events. This will not work on Android
+// as it does not use the internal AudioFocusManager implementation.
+class CONTENT_EXPORT AudioFocusObserver
+ : public media_session::mojom::AudioFocusObserver {
+ public:
+ AudioFocusObserver();
+ ~AudioFocusObserver() override;
+
+ // The given media session gained audio focus with the specified type.
+ void OnFocusGained(::media_session::mojom::MediaSessionPtr,
+ media_session::mojom::AudioFocusType) override {}
+
+ // The given media session lost audio focus.
+ void OnFocusLost(::media_session::mojom::MediaSessionPtr) override {}
+
+ protected:
+ // Called by subclasses to (un-)register the observer with AudioFocusManager.
+ void RegisterAudioFocusObserver();
+ void UnregisterAudioFocusObserver();
+
+ private:
+ base::Optional<mojo::InterfacePtrSetElementId> observer_id_;
+
+ mojo::Binding<media_session::mojom::AudioFocusObserver> binding_;
+
+ DISALLOW_COPY_AND_ASSIGN(AudioFocusObserver);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MEDIA_SESSION_AUDIO_FOCUS_OBSERVER_H_
diff --git a/chromium/content/browser/media/session/media_session_android.cc b/chromium/content/browser/media/session/media_session_android.cc
index cd30af13b23..e110c52ea5e 100644
--- a/chromium/content/browser/media/session/media_session_android.cc
+++ b/chromium/content/browser/media/session/media_session_android.cc
@@ -12,6 +12,7 @@
#include "content/common/android/media_metadata_android.h"
#include "content/public/browser/media_session.h"
#include "jni/MediaSessionImpl_jni.h"
+#include "services/media_session/public/mojom/audio_focus.mojom.h"
namespace content {
@@ -167,7 +168,7 @@ void MediaSessionAndroid::RequestSystemAudioFocus(
const base::android::JavaParamRef<jobject>& j_obj) {
DCHECK(media_session());
static_cast<MediaSessionImpl*>(media_session())
- ->RequestSystemAudioFocus(AudioFocusManager::AudioFocusType::Gain);
+ ->RequestSystemAudioFocus(media_session::mojom::AudioFocusType::kGain);
}
WebContentsAndroid* MediaSessionAndroid::GetWebContentsAndroid() {
diff --git a/chromium/content/browser/media/session/media_session_browsertest.cc b/chromium/content/browser/media/session/media_session_browsertest.cc
index fb669cc671b..f89836e50a4 100644
--- a/chromium/content/browser/media/session/media_session_browsertest.cc
+++ b/chromium/content/browser/media/session/media_session_browsertest.cc
@@ -15,6 +15,7 @@
#include "content/public/test/content_browser_test_utils.h"
#include "content/shell/browser/shell.h"
#include "media/base/media_switches.h"
+#include "services/media_session/public/cpp/switches.h"
namespace content {
@@ -36,7 +37,7 @@ class MediaSessionBrowserTest : public ContentBrowserTest {
void EnableInternalMediaSesion() {
#if !defined(OS_ANDROID)
base::CommandLine::ForCurrentProcess()->AppendSwitch(
- switches::kEnableInternalMediaSession);
+ media_session::switches::kEnableInternalMediaSession);
#endif // !defined(OS_ANDROID)
}
@@ -176,6 +177,27 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, MultiplePlayersPlayPause) {
EXPECT_TRUE(IsPlaying(shell(), "long-audio"));
}
+IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, WebContents_Muted) {
+ EnableInternalMediaSesion();
+
+ NavigateToURL(shell(), GetTestUrl("media/session", "media-session.html"));
+
+ shell()->web_contents()->SetAudioMuted(true);
+ MediaSession* media_session = MediaSession::Get(shell()->web_contents());
+ ASSERT_NE(nullptr, media_session);
+
+ StartPlaybackAndWait(shell(), "long-video");
+ EXPECT_FALSE(media_session->IsControllable());
+
+ // Unmute the web contents and the player should be created.
+ shell()->web_contents()->SetAudioMuted(false);
+ EXPECT_TRUE(media_session->IsControllable());
+
+ // Now mute it again and the player should be removed.
+ shell()->web_contents()->SetAudioMuted(true);
+ EXPECT_FALSE(media_session->IsControllable());
+}
+
#if !defined(OS_ANDROID)
// On Android, System Audio Focus would break this test.
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, MultipleTabsPlayPause) {
diff --git a/chromium/content/browser/media/session/media_session_controller.cc b/chromium/content/browser/media/session/media_session_controller.cc
index 69df8daac0e..fa1a8a50405 100644
--- a/chromium/content/browser/media/session/media_session_controller.cc
+++ b/chromium/content/browser/media/session/media_session_controller.cc
@@ -32,6 +32,11 @@ bool MediaSessionController::Initialize(
bool has_audio,
bool is_remote,
media::MediaContentType media_content_type) {
+ // Store these as we will need them later.
+ is_remote_ = is_remote;
+ has_audio_ = has_audio;
+ media_content_type_ = media_content_type;
+
// Don't generate a new id if one has already been set.
if (!has_session_) {
// These objects are only created on the UI thread, so this is safe.
@@ -50,12 +55,13 @@ bool MediaSessionController::Initialize(
//
// TODO(dalecurtis): Delete sticky audio once we're no longer using WMPA and
// the BrowserMediaPlayerManagers. Tracked by http://crbug.com/580626
- has_audio = true;
+ has_audio_ = true;
}
// Don't bother with a MediaSession for remote players or without audio. If
// we already have a session from a previous call, release it.
- if (!has_audio || is_remote) {
+ if (!has_audio_ || is_remote ||
+ media_web_contents_observer_->web_contents()->IsAudioMuted()) {
if (has_session_) {
has_session_ = false;
media_session_->RemovePlayer(this, player_id_);
@@ -120,4 +126,19 @@ void MediaSessionController::OnPlaybackPaused() {
media_session_->OnPlayerPaused(this, player_id_);
}
+void MediaSessionController::WebContentsMutedStateChanged(bool muted) {
+ if (!has_audio_ || is_remote_)
+ return;
+
+ // We want to make sure we do not request audio focus on a muted tab as it
+ // would break user expectations by pausing/ducking other playbacks.
+ if (!muted && !has_session_) {
+ if (media_session_->AddPlayer(this, player_id_, media_content_type_))
+ has_session_ = true;
+ } else if (muted && has_session_) {
+ has_session_ = false;
+ media_session_->RemovePlayer(this, player_id_);
+ }
+}
+
} // namespace content
diff --git a/chromium/content/browser/media/session/media_session_controller.h b/chromium/content/browser/media/session/media_session_controller.h
index 3a9ea7cfcc0..cff0dc78c0e 100644
--- a/chromium/content/browser/media/session/media_session_controller.h
+++ b/chromium/content/browser/media/session/media_session_controller.h
@@ -10,10 +10,7 @@
#include "content/browser/media/session/media_session_player_observer.h"
#include "content/common/content_export.h"
#include "content/public/browser/web_contents_observer.h"
-
-namespace media {
-enum class MediaContentType;
-} // namespace media
+#include "media/base/media_content_type.h"
namespace content {
@@ -57,6 +54,9 @@ class CONTENT_EXPORT MediaSessionController
// Test helpers.
int get_player_id_for_testing() const { return player_id_; }
+ // Called when the WebContents is either muted or unmuted.
+ void WebContentsMutedStateChanged(bool muted);
+
private:
const WebContentsObserver::MediaPlayerId id_;
@@ -68,6 +68,10 @@ class CONTENT_EXPORT MediaSessionController
int player_id_ = 0;
bool has_session_ = false;
+ bool has_audio_ = false;
+ bool is_remote_ = false;
+ media::MediaContentType media_content_type_ =
+ media::MediaContentType::Persistent;
DISALLOW_COPY_AND_ASSIGN(MediaSessionController);
};
diff --git a/chromium/content/browser/media/session/media_session_controllers_manager.cc b/chromium/content/browser/media/session/media_session_controllers_manager.cc
index 33947c0d4b6..4607e46dc8b 100644
--- a/chromium/content/browser/media/session/media_session_controllers_manager.cc
+++ b/chromium/content/browser/media/session/media_session_controllers_manager.cc
@@ -4,28 +4,11 @@
#include "content/browser/media/session/media_session_controllers_manager.h"
-#include "base/command_line.h"
#include "content/browser/media/session/media_session_controller.h"
-#include "media/base/media_switches.h"
+#include "services/media_session/public/cpp/switches.h"
namespace content {
-namespace {
-
-bool IsMediaSessionEnabled() {
-// Media session is enabled on Android and Chrome OS to allow control of media
-// players as needed.
-#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
- return true;
-#else
- base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
- return command_line->HasSwitch(switches::kEnableInternalMediaSession) ||
- command_line->HasSwitch(switches::kEnableAudioFocus);
-#endif
-}
-
-} // anonymous namespace
-
MediaSessionControllersManager::MediaSessionControllersManager(
MediaWebContentsObserver* media_web_contents_observer)
: media_web_contents_observer_(media_web_contents_observer) {}
@@ -34,7 +17,7 @@ MediaSessionControllersManager::~MediaSessionControllersManager() = default;
void MediaSessionControllersManager::RenderFrameDeleted(
RenderFrameHost* render_frame_host) {
- if (!IsMediaSessionEnabled())
+ if (!media_session::IsMediaSessionEnabled())
return;
for (auto it = controllers_map_.begin(); it != controllers_map_.end();) {
@@ -50,7 +33,7 @@ bool MediaSessionControllersManager::RequestPlay(
bool has_audio,
bool is_remote,
media::MediaContentType media_content_type) {
- if (!IsMediaSessionEnabled())
+ if (!media_session::IsMediaSessionEnabled())
return true;
// Since we don't remove session instances on pause, there may be an existing
@@ -78,7 +61,7 @@ bool MediaSessionControllersManager::RequestPlay(
}
void MediaSessionControllersManager::OnPause(const MediaPlayerId& id) {
- if (!IsMediaSessionEnabled())
+ if (!media_session::IsMediaSessionEnabled())
return;
auto it = controllers_map_.find(id);
@@ -89,9 +72,17 @@ void MediaSessionControllersManager::OnPause(const MediaPlayerId& id) {
}
void MediaSessionControllersManager::OnEnd(const MediaPlayerId& id) {
- if (!IsMediaSessionEnabled())
+ if (!media_session::IsMediaSessionEnabled())
return;
controllers_map_.erase(id);
}
+void MediaSessionControllersManager::WebContentsMutedStateChanged(bool muted) {
+ if (!media_session::IsMediaSessionEnabled())
+ return;
+
+ for (auto& entry : controllers_map_)
+ entry.second->WebContentsMutedStateChanged(muted);
+}
+
} // namespace content
diff --git a/chromium/content/browser/media/session/media_session_controllers_manager.h b/chromium/content/browser/media/session/media_session_controllers_manager.h
index cf991cc3cb9..f15c96e11b5 100644
--- a/chromium/content/browser/media/session/media_session_controllers_manager.h
+++ b/chromium/content/browser/media/session/media_session_controllers_manager.h
@@ -54,6 +54,9 @@ class CONTENT_EXPORT MediaSessionControllersManager {
// Called when the given player |id| has ended.
void OnEnd(const MediaPlayerId& id);
+ // Called when the WebContents was muted or unmuted.
+ void WebContentsMutedStateChanged(bool muted);
+
private:
friend class MediaSessionControllersManagerTest;
diff --git a/chromium/content/browser/media/session/media_session_controllers_manager_unittest.cc b/chromium/content/browser/media/session/media_session_controllers_manager_unittest.cc
index e8e18e1f400..0c8afb247db 100644
--- a/chromium/content/browser/media/session/media_session_controllers_manager_unittest.cc
+++ b/chromium/content/browser/media/session/media_session_controllers_manager_unittest.cc
@@ -10,7 +10,7 @@
#include "content/test/test_render_view_host.h"
#include "content/test/test_web_contents.h"
#include "media/base/media_content_type.h"
-#include "media/base/media_switches.h"
+#include "services/media_session/public/cpp/switches.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -46,11 +46,11 @@ class MediaSessionControllersManagerTest
#if !defined(OS_ANDROID)
if (IsInternalMediaSessionEnabled()) {
base::CommandLine::ForCurrentProcess()->AppendSwitch(
- switches::kEnableInternalMediaSession);
+ media_session::switches::kEnableInternalMediaSession);
}
if (IsAudioFocusEnabled()) {
base::CommandLine::ForCurrentProcess()->AppendSwitch(
- switches::kEnableAudioFocus);
+ media_session::switches::kEnableAudioFocus);
}
#endif
diff --git a/chromium/content/browser/media/session/media_session_impl.cc b/chromium/content/browser/media/session/media_session_impl.cc
index a66c5d02e07..15bab907e47 100644
--- a/chromium/content/browser/media/session/media_session_impl.cc
+++ b/chromium/content/browser/media/session/media_session_impl.cc
@@ -5,8 +5,10 @@
#include "content/browser/media/session/media_session_impl.h"
#include <algorithm>
+#include <utility>
#include "base/numerics/ranges.h"
+#include "base/strings/string_util.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"
@@ -17,6 +19,7 @@
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/web_contents.h"
#include "media/base/media_content_type.h"
+#include "services/media_session/public/mojom/audio_focus.mojom.h"
#include "third_party/blink/public/platform/modules/mediasession/media_session.mojom.h"
#if defined(OS_ANDROID)
@@ -32,6 +35,12 @@ namespace {
const double kUnduckedVolumeMultiplier = 1.0;
const double kDefaultDuckingVolumeMultiplier = 0.2;
+const char kDebugInfoOwnerSeparator[] = " - ";
+const char kDebugInfoDucked[] = "Ducked";
+const char kDebugInfoActive[] = "Active";
+const char kDebugInfoInactive[] = "Inactive";
+const char kDebugInfoStateSeparator[] = " ";
+
using MapRenderFrameHostToDepth = std::map<RenderFrameHost*, size_t>;
size_t ComputeFrameDepth(RenderFrameHost* rfh,
@@ -72,13 +81,20 @@ MediaSessionUserAction MediaSessionActionToUserAction(
return MediaSessionUserAction::Count;
}
+// If the string is not empty then push it to the back of a vector.
+void MaybePushBackString(std::vector<std::string>& vector,
+ const std::string& str) {
+ if (!str.empty())
+ vector.push_back(str);
+}
+
} // anonymous namespace
+using media_session::mojom::AudioFocusType;
+
using MediaSessionSuspendedSource =
MediaSessionUmaHelper::MediaSessionSuspendedSource;
-DEFINE_WEB_CONTENTS_USER_DATA_KEY(MediaSessionImpl);
-
MediaSessionImpl::PlayerIdentifier::PlayerIdentifier(
MediaSessionPlayerObserver* observer,
int player_id)
@@ -195,23 +211,23 @@ bool MediaSessionImpl::AddPlayer(MediaSessionPlayerObserver* observer,
observer->OnSetVolumeMultiplier(player_id, GetVolumeMultiplier());
- AudioFocusManager::AudioFocusType required_audio_focus_type;
- if (media_content_type == media::MediaContentType::Persistent) {
- required_audio_focus_type = AudioFocusManager::AudioFocusType::Gain;
- } else {
- required_audio_focus_type =
- AudioFocusManager::AudioFocusType::GainTransientMayDuck;
- }
+ AudioFocusType required_audio_focus_type;
+ if (media_content_type == media::MediaContentType::Persistent)
+ required_audio_focus_type = AudioFocusType::kGain;
+ else
+ required_audio_focus_type = AudioFocusType::kGainTransientMayDuck;
// If the audio focus is already granted and is of type Content, there is
// nothing to do. If it is granted of type Transient the requested type is
// also transient, there is also nothing to do. Otherwise, the session needs
// to request audio focus again.
- if (audio_focus_state_ == State::ACTIVE &&
- (audio_focus_type_ == AudioFocusManager::AudioFocusType::Gain ||
- audio_focus_type_ == required_audio_focus_type)) {
- normal_players_.insert(PlayerIdentifier(observer, player_id));
- return true;
+ if (audio_focus_state_ == State::ACTIVE) {
+ AudioFocusType current_focus_type = delegate_->GetCurrentFocusType();
+ if (current_focus_type == AudioFocusType::kGain ||
+ current_focus_type == required_audio_focus_type) {
+ normal_players_.insert(PlayerIdentifier(observer, player_id));
+ return true;
+ }
}
State old_audio_focus_state = audio_focus_state_;
@@ -346,7 +362,7 @@ void MediaSessionImpl::Resume(SuspendType suspend_type) {
if (suspend_type != SuspendType::SYSTEM) {
// Request audio focus again in case we lost it because another app started
// playing while the playback was paused.
- State audio_focus_state = RequestSystemAudioFocus(audio_focus_type_)
+ State audio_focus_state = RequestSystemAudioFocus(desired_audio_focus_type_)
? State::ACTIVE
: State::INACTIVE;
SetAudioFocusState(audio_focus_state);
@@ -410,7 +426,7 @@ bool MediaSessionImpl::IsControllable() const {
// inactive. Also, the session will be uncontrollable if it contains one-shot
// players.
return audio_focus_state_ != State::INACTIVE &&
- audio_focus_type_ == AudioFocusManager::AudioFocusType::Gain &&
+ desired_audio_focus_type_ == AudioFocusType::kGain &&
one_shot_players_.empty();
}
@@ -560,8 +576,7 @@ void MediaSessionImpl::OnResumeInternal(SuspendType suspend_type) {
MediaSessionImpl::MediaSessionImpl(WebContents* web_contents)
: WebContentsObserver(web_contents),
audio_focus_state_(State::INACTIVE),
- audio_focus_type_(
- AudioFocusManager::AudioFocusType::GainTransientMayDuck),
+ desired_audio_focus_type_(AudioFocusType::kGainTransientMayDuck),
is_ducking_(false),
ducking_volume_multiplier_(kDefaultDuckingVolumeMultiplier),
routed_service_(nullptr) {
@@ -575,7 +590,7 @@ void MediaSessionImpl::Initialize() {
}
bool MediaSessionImpl::RequestSystemAudioFocus(
- AudioFocusManager::AudioFocusType audio_focus_type) {
+ AudioFocusType audio_focus_type) {
bool result = delegate_->RequestAudioFocus(audio_focus_type);
uma_helper_.RecordRequestAudioFocusResult(result);
@@ -586,10 +601,41 @@ bool MediaSessionImpl::RequestSystemAudioFocus(
// MediaSessionImpl must change its state & audio focus type AFTER requesting
// audio focus.
SetAudioFocusState(result ? State::ACTIVE : State::INACTIVE);
- audio_focus_type_ = audio_focus_type;
+ desired_audio_focus_type_ = audio_focus_type;
return result;
}
+const MediaSessionImpl::DebugInfo MediaSessionImpl::GetDebugInfo() {
+ MediaSessionImpl::DebugInfo debug_info;
+
+ // Convert the address of |this| to a string and use it as the name.
+ std::stringstream stream;
+ stream << this;
+ debug_info.name = stream.str();
+
+ // Add the title and the url to the owner.
+ std::vector<std::string> owner_parts;
+ MaybePushBackString(owner_parts,
+ base::UTF16ToUTF8(web_contents()->GetTitle()));
+ MaybePushBackString(owner_parts,
+ web_contents()->GetLastCommittedURL().spec());
+ debug_info.owner = base::JoinString(owner_parts, kDebugInfoOwnerSeparator);
+
+ // Add the ducking state to state.
+ std::vector<std::string> state_parts;
+ MaybePushBackString(state_parts,
+ IsActive() ? kDebugInfoActive : kDebugInfoInactive);
+ MaybePushBackString(state_parts, is_ducking_ ? kDebugInfoDucked : "");
+ debug_info.state = base::JoinString(state_parts, kDebugInfoStateSeparator);
+
+ return debug_info;
+}
+
+void MediaSessionImpl::BindToMojoRequest(
+ mojo::InterfaceRequest<media_session::mojom::MediaSession> request) {
+ bindings_.AddBinding(this, std::move(request));
+}
+
void MediaSessionImpl::AbandonSystemAudioFocusIfNeeded() {
if (audio_focus_state_ == State::INACTIVE || !normal_players_.empty() ||
!pepper_players_.empty() || !one_shot_players_.empty()) {
@@ -630,8 +676,7 @@ void MediaSessionImpl::SetAudioFocusState(State audio_focus_state) {
bool MediaSessionImpl::AddPepperPlayer(MediaSessionPlayerObserver* observer,
int player_id) {
- bool success =
- RequestSystemAudioFocus(AudioFocusManager::AudioFocusType::Gain);
+ bool success = RequestSystemAudioFocus(AudioFocusType::kGain);
DCHECK(success);
pepper_players_.insert(PlayerIdentifier(observer, player_id));
@@ -644,7 +689,7 @@ bool MediaSessionImpl::AddPepperPlayer(MediaSessionPlayerObserver* observer,
bool MediaSessionImpl::AddOneShotPlayer(MediaSessionPlayerObserver* observer,
int player_id) {
- if (!RequestSystemAudioFocus(AudioFocusManager::AudioFocusType::Gain))
+ if (!RequestSystemAudioFocus(AudioFocusType::kGain))
return false;
one_shot_players_.insert(PlayerIdentifier(observer, player_id));
diff --git a/chromium/content/browser/media/session/media_session_impl.h b/chromium/content/browser/media/session/media_session_impl.h
index 637acb6dfcf..42f85c71133 100644
--- a/chromium/content/browser/media/session/media_session_impl.h
+++ b/chromium/content/browser/media/session/media_session_impl.h
@@ -23,6 +23,9 @@
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_user_data.h"
#include "content/public/common/media_metadata.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
+#include "services/media_session/public/mojom/audio_focus.mojom.h"
#if defined(OS_ANDROID)
#include "base/android/scoped_java_ref.h"
@@ -34,6 +37,12 @@ namespace media {
enum class MediaContentType;
} // namespace media
+namespace media_session {
+namespace mojom {
+enum class AudioFocusType;
+} // namespace mojom
+} // namespace media_session
+
namespace content {
class AudioFocusDelegate;
@@ -161,12 +170,6 @@ class MediaSessionImpl : public MediaSession,
// Returns if the session is currently suspended.
CONTENT_EXPORT bool IsSuspended() const;
- // Returns the audio focus type. The type is updated everytime after the
- // session requests audio focus.
- CONTENT_EXPORT AudioFocusManager::AudioFocusType audio_focus_type() const {
- return audio_focus_type_;
- }
-
// Returns whether the session has Pepper instances.
bool HasPepper() const;
@@ -202,7 +205,24 @@ class MediaSessionImpl : public MediaSession,
// Requests audio focus to the AudioFocusDelegate.
// Returns whether the request was granted.
CONTENT_EXPORT bool RequestSystemAudioFocus(
- AudioFocusManager::AudioFocusType audio_focus_type);
+ media_session::mojom::AudioFocusType audio_focus_type);
+
+ // Returns debugging information to be displayed on chrome://media-internals.
+ struct DebugInfo {
+ // A unique name for the MediaSession.
+ std::string name;
+
+ // The title and URL of the owning WebContents.
+ std::string owner;
+
+ // State information stored in a string e.g. Ducked.
+ std::string state;
+ };
+ const DebugInfo GetDebugInfo();
+
+ // Creates a binding between |this| and |request|.
+ void BindToMojoRequest(
+ mojo::InterfaceRequest<media_session::mojom::MediaSession> request);
private:
friend class content::WebContentsUserData<MediaSessionImpl>;
@@ -212,6 +232,7 @@ class MediaSessionImpl : public MediaSession,
friend class content::MediaSessionImplServiceRoutingTest;
friend class content::MediaSessionImplStateObserver;
friend class content::MediaSessionServiceImplBrowserTest;
+ friend class MediaInternalsAudioFocusTest;
CONTENT_EXPORT void SetDelegateForTests(
std::unique_ptr<AudioFocusDelegate> delegate);
@@ -294,9 +315,12 @@ class MediaSessionImpl : public MediaSession,
PlayersMap pepper_players_;
PlayersMap one_shot_players_;
- State audio_focus_state_;
+ State audio_focus_state_ = State::INACTIVE;
MediaSession::SuspendType suspend_type_;
- AudioFocusManager::AudioFocusType audio_focus_type_;
+
+ // The |desired_audio_focus_type_| is the AudioFocusType we will request when
+ // we request system audio focus.
+ media_session::mojom::AudioFocusType desired_audio_focus_type_;
MediaSessionUmaHelper uma_helper_;
@@ -309,7 +333,7 @@ class MediaSessionImpl : public MediaSession,
base::CallbackList<void(State)> media_session_state_listeners_;
- base::ObserverList<MediaSessionObserver> observers_;
+ base::ObserverList<MediaSessionObserver>::Unchecked observers_;
#if defined(OS_ANDROID)
std::unique_ptr<MediaSessionAndroid> session_android_;
@@ -325,6 +349,9 @@ class MediaSessionImpl : public MediaSession,
// The currently routed service (non-owned pointer).
MediaSessionServiceImpl* routed_service_;
+ // Bindings for Mojo pointers to |this| held by media route providers.
+ mojo::BindingSet<media_session::mojom::MediaSession> bindings_;
+
DISALLOW_COPY_AND_ASSIGN(MediaSessionImpl);
};
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 f423db1ed37..a39d86d6a83 100644
--- a/chromium/content/browser/media/session/media_session_impl_browsertest.cc
+++ b/chromium/content/browser/media/session/media_session_impl_browsertest.cc
@@ -24,6 +24,7 @@
#include "content/public/test/content_browser_test.h"
#include "content/shell/browser/shell.h"
#include "media/base/media_content_type.h"
+#include "services/media_session/public/mojom/audio_focus.mojom.h"
#include "testing/gmock/include/gmock/gmock.h"
using content::WebContents;
@@ -35,6 +36,8 @@ using content::MediaSessionPlayerObserver;
using content::MediaSessionUmaHelper;
using content::MockMediaSessionPlayerObserver;
+using media_session::mojom::AudioFocusType;
+
using ::testing::Eq;
using ::testing::Expectation;
using ::testing::NiceMock;
@@ -48,13 +51,22 @@ const double kDifferentDuckingVolumeMultiplier = 0.018;
class MockAudioFocusDelegate : public AudioFocusDelegate {
public:
- MockAudioFocusDelegate() {
- ON_CALL(*this, RequestAudioFocus(_)).WillByDefault(::testing::Return(true));
- }
+ MockAudioFocusDelegate() {}
- MOCK_METHOD1(RequestAudioFocus,
- bool(content::AudioFocusManager::AudioFocusType));
MOCK_METHOD0(AbandonAudioFocus, void());
+
+ bool RequestAudioFocus(AudioFocusType audio_focus_type) {
+ audio_focus_type_ = audio_focus_type;
+ return true;
+ }
+
+ AudioFocusType GetCurrentFocusType() const {
+ DCHECK(audio_focus_type_.has_value());
+ return audio_focus_type_.value();
+ }
+
+ private:
+ base::Optional<AudioFocusType> audio_focus_type_;
};
class MockMediaSessionServiceImpl : public content::MediaSessionServiceImpl {
@@ -121,8 +133,8 @@ class MediaSessionImplBrowserTest : public content::ContentBrowserTest {
bool IsActive() { return media_session_->IsActive(); }
- content::AudioFocusManager::AudioFocusType GetSessionAudioFocusType() {
- return media_session_->audio_focus_type();
+ AudioFocusType GetSessionAudioFocusType() {
+ return mock_audio_focus_delegate_->GetCurrentFocusType();
}
bool IsControllable() { return media_session_->IsControllable(); }
@@ -356,8 +368,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
CanRequestFocusBeforePlayerCreation) {
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
- media_session_->RequestSystemAudioFocus(
- content::AudioFocusManager::AudioFocusType::Gain);
+ media_session_->RequestSystemAudioFocus(AudioFocusType::kGain);
EXPECT_TRUE(IsActive());
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
@@ -542,23 +553,19 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, AudioFocusType) {
// Starting a player with a given type should set the session to that type.
StartNewPlayer(player_observer.get(), media::MediaContentType::Transient);
- EXPECT_EQ(content::AudioFocusManager::AudioFocusType::GainTransientMayDuck,
- GetSessionAudioFocusType());
+ EXPECT_EQ(AudioFocusType::kGainTransientMayDuck, GetSessionAudioFocusType());
// Adding a player of the same type should have no effect on the type.
StartNewPlayer(player_observer.get(), media::MediaContentType::Transient);
- EXPECT_EQ(content::AudioFocusManager::AudioFocusType::GainTransientMayDuck,
- GetSessionAudioFocusType());
+ EXPECT_EQ(AudioFocusType::kGainTransientMayDuck, GetSessionAudioFocusType());
// Adding a player of Content type should override the current type.
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
- EXPECT_EQ(content::AudioFocusManager::AudioFocusType::Gain,
- GetSessionAudioFocusType());
+ EXPECT_EQ(AudioFocusType::kGain, GetSessionAudioFocusType());
// Adding a player of the Transient type should have no effect on the type.
StartNewPlayer(player_observer.get(), media::MediaContentType::Transient);
- EXPECT_EQ(content::AudioFocusManager::AudioFocusType::Gain,
- GetSessionAudioFocusType());
+ EXPECT_EQ(AudioFocusType::kGain, GetSessionAudioFocusType());
EXPECT_TRUE(player_observer->IsPlaying(0));
EXPECT_TRUE(player_observer->IsPlaying(1));
@@ -572,8 +579,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, AudioFocusType) {
EXPECT_FALSE(player_observer->IsPlaying(2));
EXPECT_FALSE(player_observer->IsPlaying(3));
- EXPECT_EQ(content::AudioFocusManager::AudioFocusType::Gain,
- GetSessionAudioFocusType());
+ EXPECT_EQ(AudioFocusType::kGain, GetSessionAudioFocusType());
SystemResume();
@@ -582,8 +588,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, AudioFocusType) {
EXPECT_TRUE(player_observer->IsPlaying(2));
EXPECT_TRUE(player_observer->IsPlaying(3));
- EXPECT_EQ(content::AudioFocusManager::AudioFocusType::Gain,
- GetSessionAudioFocusType());
+ EXPECT_EQ(AudioFocusType::kGain, GetSessionAudioFocusType());
}
IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, ControlsShowForContent) {
@@ -1075,17 +1080,12 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, ResumeSuspendFromSystem) {
IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, OneShotTakesGainFocus) {
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
- EXPECT_CALL(
- *mock_audio_focus_delegate(),
- RequestAudioFocus(content::AudioFocusManager::AudioFocusType::Gain))
- .Times(1);
- EXPECT_CALL(*mock_audio_focus_delegate(),
- RequestAudioFocus(::testing::Ne(
- content::AudioFocusManager::AudioFocusType::Gain)))
- .Times(0);
StartNewPlayer(player_observer.get(), media::MediaContentType::OneShot);
StartNewPlayer(player_observer.get(), media::MediaContentType::Transient);
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+
+ EXPECT_EQ(AudioFocusType::kGain,
+ mock_audio_focus_delegate()->GetCurrentFocusType());
}
IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, RemovingOneShotDropsFocus) {
diff --git a/chromium/content/browser/media/session/media_session_impl_visibility_browsertest.cc b/chromium/content/browser/media/session/media_session_impl_visibility_browsertest.cc
index 05bbdb6c355..d25f4fad6b8 100644
--- a/chromium/content/browser/media/session/media_session_impl_visibility_browsertest.cc
+++ b/chromium/content/browser/media/session/media_session_impl_visibility_browsertest.cc
@@ -20,6 +20,7 @@
#include "content/public/test/test_navigation_observer.h"
#include "content/shell/browser/shell.h"
#include "media/base/media_switches.h"
+#include "services/media_session/public/cpp/switches.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
@@ -107,7 +108,7 @@ class MediaSessionImplVisibilityBrowserTest
switches::kAutoplayPolicy,
switches::autoplay::kNoUserGestureRequiredPolicy);
#if !defined(OS_ANDROID)
- command_line->AppendSwitch(switches::kEnableAudioFocus);
+ command_line->AppendSwitch(media_session::switches::kEnableAudioFocus);
#endif // !defined(OS_ANDROID)
VisibilityTestData params = GetVisibilityTestData();
diff --git a/chromium/content/browser/media/session/pepper_playback_observer.cc b/chromium/content/browser/media/session/pepper_playback_observer.cc
index ab55c60796a..c8e7cd3d2a2 100644
--- a/chromium/content/browser/media/session/pepper_playback_observer.cc
+++ b/chromium/content/browser/media/session/pepper_playback_observer.cc
@@ -11,7 +11,7 @@
#include "content/common/frame_messages.h"
#include "ipc/ipc_message_macros.h"
#include "media/base/media_content_type.h"
-#include "media/base/media_switches.h"
+#include "services/media_session/public/cpp/switches.h"
namespace content {
@@ -75,8 +75,9 @@ void PepperPlaybackObserver::PepperStartsPlayback(
MediaSessionImpl::Get(contents_)->AddPlayer(
players_map_[id].get(), PepperPlayerDelegate::kPlayerId,
- media::IsAudioFocusDuckFlashEnabled() ? media::MediaContentType::Pepper
- : media::MediaContentType::OneShot);
+ media_session::IsAudioFocusDuckFlashEnabled()
+ ? media::MediaContentType::Pepper
+ : media::MediaContentType::OneShot);
}
void PepperPlaybackObserver::PepperStopsPlayback(
diff --git a/chromium/content/browser/media/session/pepper_player_delegate.cc b/chromium/content/browser/media/session/pepper_player_delegate.cc
index d3e23c458a5..a662cca2f2a 100644
--- a/chromium/content/browser/media/session/pepper_player_delegate.cc
+++ b/chromium/content/browser/media/session/pepper_player_delegate.cc
@@ -8,7 +8,7 @@
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/media/session/pepper_playback_observer.h"
#include "content/common/frame_messages.h"
-#include "media/base/media_switches.h"
+#include "services/media_session/public/cpp/switches.h"
namespace content {
@@ -28,7 +28,7 @@ PepperPlayerDelegate::PepperPlayerDelegate(
PepperPlayerDelegate::~PepperPlayerDelegate() = default;
void PepperPlayerDelegate::OnSuspend(int player_id) {
- if (!media::IsAudioFocusDuckFlashEnabled())
+ if (!media_session::IsAudioFocusDuckFlashEnabled())
return;
// Pepper player cannot be really suspended. Duck the volume instead.
@@ -37,7 +37,7 @@ void PepperPlayerDelegate::OnSuspend(int player_id) {
}
void PepperPlayerDelegate::OnResume(int player_id) {
- if (!media::IsAudioFocusDuckFlashEnabled())
+ if (!media_session::IsAudioFocusDuckFlashEnabled())
return;
DCHECK_EQ(player_id, kPlayerId);
@@ -56,7 +56,7 @@ void PepperPlayerDelegate::OnSeekBackward(int player_id,
void PepperPlayerDelegate::OnSetVolumeMultiplier(int player_id,
double volume_multiplier) {
- if (!media::IsAudioFocusDuckFlashEnabled())
+ if (!media_session::IsAudioFocusDuckFlashEnabled())
return;
DCHECK_EQ(player_id, kPlayerId);
diff --git a/chromium/content/browser/media/video_decoder_proxy.cc b/chromium/content/browser/media/video_decoder_proxy.cc
new file mode 100644
index 00000000000..ea252f0c806
--- /dev/null
+++ b/chromium/content/browser/media/video_decoder_proxy.cc
@@ -0,0 +1,96 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/media/video_decoder_proxy.h"
+
+#include "base/logging.h"
+#include "content/public/common/service_manager_connection.h"
+#include "media/mojo/interfaces/constants.mojom.h"
+#include "media/mojo/interfaces/media_service.mojom.h"
+#include "services/service_manager/public/cpp/connector.h"
+
+namespace content {
+
+VideoDecoderProxy::VideoDecoderProxy() {
+ DVLOG(1) << __func__;
+}
+
+VideoDecoderProxy::~VideoDecoderProxy() {
+ DVLOG(1) << __func__;
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+}
+
+void VideoDecoderProxy::Add(media::mojom::InterfaceFactoryRequest request) {
+ DVLOG(1) << __func__;
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ bindings_.AddBinding(this, std::move(request));
+}
+
+void VideoDecoderProxy::CreateAudioDecoder(
+ media::mojom::AudioDecoderRequest request) {}
+
+void VideoDecoderProxy::CreateVideoDecoder(
+ media::mojom::VideoDecoderRequest request) {
+ DVLOG(2) << __func__;
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ InterfaceFactory* factory = GetMediaInterfaceFactory();
+ if (factory)
+ factory->CreateVideoDecoder(std::move(request));
+}
+
+void VideoDecoderProxy::CreateRenderer(media::mojom::HostedRendererType type,
+ const std::string& type_specific_id,
+ media::mojom::RendererRequest request) {}
+
+void VideoDecoderProxy::CreateCdm(
+ const std::string& key_system,
+ media::mojom::ContentDecryptionModuleRequest request) {}
+
+void VideoDecoderProxy::CreateDecryptor(
+ int cdm_id,
+ media::mojom::DecryptorRequest request) {}
+
+void VideoDecoderProxy::CreateCdmProxy(const std::string& cdm_guid,
+ media::mojom::CdmProxyRequest request) {}
+
+media::mojom::InterfaceFactory* VideoDecoderProxy::GetMediaInterfaceFactory() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ if (!interface_factory_ptr_)
+ ConnectToMediaService();
+
+ return interface_factory_ptr_.get();
+}
+
+void VideoDecoderProxy::ConnectToMediaService() {
+ DVLOG(1) << __func__;
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(!interface_factory_ptr_);
+
+ media::mojom::MediaServicePtr media_service;
+ // TODO(slan): Use the BrowserContext Connector instead.
+ // See https://crbug.com/638950.
+ service_manager::Connector* connector =
+ ServiceManagerConnection::GetForProcess()->GetConnector();
+ connector->BindInterface(media::mojom::kMediaServiceName, &media_service);
+
+ // TODO(sandersd): Do we need to bind an empty |interfaces| implementation?
+ service_manager::mojom::InterfaceProviderPtr interfaces;
+ media_service->CreateInterfaceFactory(MakeRequest(&interface_factory_ptr_),
+ std::move(interfaces));
+
+ interface_factory_ptr_.set_connection_error_handler(
+ base::BindOnce(&VideoDecoderProxy::OnMediaServiceConnectionError,
+ base::Unretained(this)));
+}
+
+void VideoDecoderProxy::OnMediaServiceConnectionError() {
+ DVLOG(1) << __func__;
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ interface_factory_ptr_.reset();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/video_decoder_proxy.h b/chromium/content/browser/media/video_decoder_proxy.h
new file mode 100644
index 00000000000..35052a5d7fb
--- /dev/null
+++ b/chromium/content/browser/media/video_decoder_proxy.h
@@ -0,0 +1,58 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_MEDIA_VIDEO_DECODER_PROXY_H_
+#define CONTENT_BROWSER_MEDIA_VIDEO_DECODER_PROXY_H_
+
+#include <string>
+
+#include "base/macros.h"
+#include "base/threading/thread_checker.h"
+#include "media/mojo/interfaces/interface_factory.mojom.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
+
+namespace content {
+
+// This implements the media::mojom::InterfaceFactory interface for a
+// RenderProcessHostImpl. Unlike MediaInterfaceProxy, only
+// CreateVideoDecoder() is implemented. This allows WebRTC to create
+// MojoVideoDecoder instances without a RenderFrame.
+class VideoDecoderProxy : public media::mojom::InterfaceFactory {
+ public:
+ VideoDecoderProxy();
+ ~VideoDecoderProxy() final;
+
+ void Add(media::mojom::InterfaceFactoryRequest request);
+
+ // media::mojom::InterfaceFactory implementation.
+ void CreateAudioDecoder(media::mojom::AudioDecoderRequest request) final;
+ void CreateVideoDecoder(media::mojom::VideoDecoderRequest request) final;
+ void CreateRenderer(media::mojom::HostedRendererType type,
+ const std::string& type_specific_id,
+ media::mojom::RendererRequest request) final;
+ void CreateCdm(const std::string& key_system,
+ media::mojom::ContentDecryptionModuleRequest request) final;
+ void CreateDecryptor(int cdm_id,
+ media::mojom::DecryptorRequest request) final;
+ void CreateCdmProxy(const std::string& cdm_guid,
+ media::mojom::CdmProxyRequest request) final;
+
+ private:
+ media::mojom::InterfaceFactory* GetMediaInterfaceFactory();
+ void ConnectToMediaService();
+ void OnMediaServiceConnectionError();
+
+ // Connection to the remote media InterfaceFactory.
+ media::mojom::InterfaceFactoryPtr interface_factory_ptr_;
+
+ // Connections to the renderer.
+ mojo::BindingSet<media::mojom::InterfaceFactory> bindings_;
+
+ THREAD_CHECKER(thread_checker_);
+ DISALLOW_COPY_AND_ASSIGN(VideoDecoderProxy);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MEDIA_VIDEO_DECODER_PROXY_H_
diff --git a/chromium/content/browser/media/webaudio/OWNERS b/chromium/content/browser/media/webaudio/OWNERS
new file mode 100644
index 00000000000..5f297b8bf52
--- /dev/null
+++ b/chromium/content/browser/media/webaudio/OWNERS
@@ -0,0 +1,4 @@
+hongchan@chromium.org
+rtoy@chromium.org
+
+# COMPONENT: Blink>WebAudio \ No newline at end of file
diff --git a/chromium/content/browser/media/webaudio/audio_context_manager_browsertest.cc b/chromium/content/browser/media/webaudio/audio_context_manager_browsertest.cc
new file mode 100644
index 00000000000..9ab3e351ae6
--- /dev/null
+++ b/chromium/content/browser/media/webaudio/audio_context_manager_browsertest.cc
@@ -0,0 +1,75 @@
+// 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/web_contents_observer.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "content/shell/browser/shell.h"
+
+namespace content {
+
+namespace {
+// Test for audible playback message.
+class WaitForAudioContextAudible : WebContentsObserver {
+ public:
+ explicit WaitForAudioContextAudible(WebContents* web_contents)
+ : WebContentsObserver(web_contents) {
+ run_loop_.Run();
+ }
+
+ void AudioContextPlaybackStarted(const AudioContextId&) final {
+ // Stop the run loop when we get the message
+ run_loop_.Quit();
+ }
+
+ private:
+ base::RunLoop run_loop_;
+
+ DISALLOW_COPY_AND_ASSIGN(WaitForAudioContextAudible);
+};
+
+// Test for silent playback started (audible playback stopped).
+class WaitForAudioContextSilent : WebContentsObserver {
+ public:
+ explicit WaitForAudioContextSilent(WebContents* web_contents)
+ : WebContentsObserver(web_contents) {
+ run_loop_.Run();
+ }
+
+ void AudioContextPlaybackStopped(const AudioContextId&) final {
+ // Stop the run loop when we get the message
+ run_loop_.Quit();
+ }
+
+ private:
+ base::RunLoop run_loop_;
+
+ DISALLOW_COPY_AND_ASSIGN(WaitForAudioContextSilent);
+};
+
+} // namespace
+
+class AudioContextManagerTest : public ContentBrowserTest {};
+
+IN_PROC_BROWSER_TEST_F(AudioContextManagerTest, AudioContextPlaybackRecorded) {
+ NavigateToURL(shell(),
+ content::GetTestUrl("media/webaudio/", "playback-test.html"));
+
+ // Set gain to 1 to start audible audio and verify we got the
+ // playback started message.
+ {
+ ASSERT_TRUE(ExecuteScript(shell()->web_contents(), "gain.gain.value = 1;"));
+ WaitForAudioContextAudible wait(shell()->web_contents());
+ }
+
+ // Set gain to 0 to stop audible audio and verify we got the
+ // playback stopped message.
+ {
+ ASSERT_TRUE(ExecuteScript(shell()->web_contents(), "gain.gain.value = 0;"));
+ WaitForAudioContextSilent wait(shell()->web_contents());
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/webaudio/audio_context_manager_impl.cc b/chromium/content/browser/media/webaudio/audio_context_manager_impl.cc
new file mode 100644
index 00000000000..889ccb0026a
--- /dev/null
+++ b/chromium/content/browser/media/webaudio/audio_context_manager_impl.cc
@@ -0,0 +1,50 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/media/webaudio/audio_context_manager_impl.h"
+
+#include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/web_contents.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+
+namespace content {
+
+void AudioContextManagerImpl::Create(
+ RenderFrameHost* render_frame_host,
+ blink::mojom::AudioContextManagerRequest request) {
+ DCHECK(render_frame_host);
+
+ // The object is bound to the lifetime of |render_frame_host| and the mojo
+ // connection. See FrameServiceBase for details.
+ new AudioContextManagerImpl(render_frame_host, std::move(request));
+}
+
+AudioContextManagerImpl::AudioContextManagerImpl(
+ RenderFrameHost* render_frame_host,
+ blink::mojom::AudioContextManagerRequest request)
+ : FrameServiceBase(render_frame_host, std::move(request)),
+ render_frame_host_impl_(
+ static_cast<RenderFrameHostImpl*>(render_frame_host)) {
+ DCHECK(render_frame_host);
+}
+
+AudioContextManagerImpl::~AudioContextManagerImpl() = default;
+
+void AudioContextManagerImpl::AudioContextAudiblePlaybackStarted(
+ int32_t audio_context_id) {
+ // Notify observers that audible audio started playing from a WebAudio
+ // AudioContext.
+ render_frame_host_impl_->AudioContextPlaybackStarted(audio_context_id);
+}
+
+void AudioContextManagerImpl::AudioContextAudiblePlaybackStopped(
+ int32_t audio_context_id) {
+ // Notify observers that audible audio stopped playing from a WebAudio
+ // AudioContext.
+ render_frame_host_impl_->AudioContextPlaybackStopped(audio_context_id);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/webaudio/audio_context_manager_impl.h b/chromium/content/browser/media/webaudio/audio_context_manager_impl.h
new file mode 100644
index 00000000000..06d1c6b4220
--- /dev/null
+++ b/chromium/content/browser/media/webaudio/audio_context_manager_impl.h
@@ -0,0 +1,44 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_MEDIA_WEBAUDIO_AUDIO_CONTEXT_MANAGER_IMPL_H_
+#define CONTENT_BROWSER_MEDIA_WEBAUDIO_AUDIO_CONTEXT_MANAGER_IMPL_H_
+
+#include "content/common/content_export.h"
+#include "content/public/browser/frame_service_base.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "third_party/blink/public/mojom/webaudio/audio_context_manager.mojom.h"
+
+namespace content {
+
+class RenderFrameHost;
+class RenderFrameHostImpl;
+
+// Implements the mojo interface between WebAudio and the browser so that
+// WebAudio can report when audible sounds from an AudioContext starts and
+// stops.
+class CONTENT_EXPORT AudioContextManagerImpl final
+ : public content::FrameServiceBase<blink::mojom::AudioContextManager> {
+ public:
+ explicit AudioContextManagerImpl(
+ RenderFrameHost* render_frame_host,
+ blink::mojom::AudioContextManagerRequest request);
+ ~AudioContextManagerImpl() override;
+
+ static void Create(RenderFrameHost* render_frame_host,
+ blink::mojom::AudioContextManagerRequest request);
+
+ // Called when AudioContext starts or stops playing audible audio.
+ void AudioContextAudiblePlaybackStarted(int32_t audio_context_id) final;
+ void AudioContextAudiblePlaybackStopped(int32_t audio_context_id) final;
+
+ private:
+ RenderFrameHostImpl* const render_frame_host_impl_;
+
+ DISALLOW_COPY_AND_ASSIGN(AudioContextManagerImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MEDIA_WEBAUDIO_AUDIO_CONTEXT_MANAGER_IMPL_H_
diff --git a/chromium/content/browser/net/quota_policy_cookie_store.cc b/chromium/content/browser/net/quota_policy_cookie_store.cc
index 116ce029657..ecf284fd0d9 100644
--- a/chromium/content/browser/net/quota_policy_cookie_store.cc
+++ b/chromium/content/browser/net/quota_policy_cookie_store.cc
@@ -13,7 +13,7 @@
#include "base/files/file_util.h"
#include "base/memory/ref_counted.h"
#include "base/sequenced_task_runner.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/cookie_store_factory.h"
#include "net/cookies/canonical_cookie.h"
@@ -67,12 +67,14 @@ CookieStoreConfig::~CookieStoreConfig() {
}
std::unique_ptr<net::CookieStore> CreateCookieStore(
- const CookieStoreConfig& config) {
+ const CookieStoreConfig& config,
+ net::NetLog* net_log) {
std::unique_ptr<net::CookieMonster> cookie_monster;
if (config.path.empty()) {
// Empty path means in-memory store.
- cookie_monster.reset(new net::CookieMonster(nullptr));
+ cookie_monster = std::make_unique<net::CookieMonster>(
+ nullptr /* store */, nullptr /* channel_id_service */, net_log);
} else {
scoped_refptr<base::SequencedTaskRunner> client_task_runner =
config.client_task_runner;
@@ -86,7 +88,7 @@ std::unique_ptr<net::CookieStore> CreateCookieStore(
if (!background_task_runner.get()) {
background_task_runner = base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BACKGROUND,
+ {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::BLOCK_SHUTDOWN});
}
@@ -100,8 +102,8 @@ std::unique_ptr<net::CookieStore> CreateCookieStore(
sqlite_store.get(),
config.storage_policy.get());
- cookie_monster.reset(new net::CookieMonster(persistent_store,
- config.channel_id_service));
+ cookie_monster = std::make_unique<net::CookieMonster>(
+ persistent_store, config.channel_id_service, net_log);
if (config.persist_session_cookies)
cookie_monster->SetPersistSessionCookies(true);
}
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 2185402e450..e5189b1d7c9 100644
--- a/chromium/content/browser/net/quota_policy_cookie_store_unittest.cc
+++ b/chromium/content/browser/net/quota_policy_cookie_store_unittest.cc
@@ -10,11 +10,12 @@
#include "base/run_loop.h"
#include "base/sequenced_task_runner.h"
#include "base/synchronization/waitable_event.h"
-#include "base/task_scheduler/post_task.h"
-#include "base/task_scheduler/task_scheduler.h"
+#include "base/task/post_task.h"
+#include "base/task/task_scheduler/task_scheduler.h"
#include "base/time/time.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "net/cookies/cookie_util.h"
+#include "net/log/net_log_with_source.h"
#include "net/ssl/ssl_client_cert_type.h"
#include "net/test/cert_test_util.h"
#include "net/test/test_data_directory.h"
@@ -50,7 +51,8 @@ class QuotaPolicyCookieStoreTest : public testing::Test {
void Load(CanonicalCookieVector* cookies) {
EXPECT_FALSE(loaded_event_.IsSignaled());
store_->Load(base::Bind(&QuotaPolicyCookieStoreTest::OnLoaded,
- base::Unretained(this)));
+ base::Unretained(this)),
+ net::NetLogWithSource());
loaded_event_.Wait();
cookies->swap(cookies_);
}
diff --git a/chromium/content/browser/net/reporting_service_proxy.cc b/chromium/content/browser/net/reporting_service_proxy.cc
index 6f525514216..d207fa45341 100644
--- a/chromium/content/browser/net/reporting_service_proxy.cc
+++ b/chromium/content/browser/net/reporting_service_proxy.cc
@@ -105,6 +105,25 @@ class ReportingServiceProxyImpl : public blink::mojom::ReportingServiceProxy {
QueueReport(url, group, "csp", std::move(body));
}
+ void QueueFeaturePolicyViolationReport(
+ const GURL& url,
+ const std::string& policy,
+ 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("policy", policy);
+ body->SetString("message", message);
+ if (source_file)
+ body->SetString("sourceFile", *source_file);
+ if (line_number)
+ body->SetInteger("lineNumber", line_number);
+ if (column_number)
+ body->SetInteger("columnNumber", column_number);
+ QueueReport(url, "default", "feature-policy", std::move(body));
+ }
+
private:
void QueueReport(const GURL& url,
const std::string& group,
diff --git a/chromium/content/browser/network_service_browsertest.cc b/chromium/content/browser/network_service_browsertest.cc
index e8e70eb852f..25c031a14ea 100644
--- a/chromium/content/browser/network_service_browsertest.cc
+++ b/chromium/content/browser/network_service_browsertest.cc
@@ -126,20 +126,19 @@ class NetworkServiceBrowserTest : public ContentBrowserTest {
bool FetchResource(const GURL& url) {
if (!url.is_valid())
return false;
- std::string script(
+ std::string script = JsReplace(
"var xhr = new XMLHttpRequest();"
- "xhr.open('GET', '");
- script += url.spec() +
- "', true);"
- "xhr.onload = function (e) {"
- " if (xhr.readyState === 4) {"
- " window.domAutomationController.send(xhr.status === 200);"
- " }"
- "};"
- "xhr.onerror = function () {"
- " window.domAutomationController.send(false);"
- "};"
- "xhr.send(null)";
+ "xhr.open('GET', $1, true);"
+ "xhr.onload = function (e) {"
+ " if (xhr.readyState === 4) {"
+ " window.domAutomationController.send(xhr.status === 200);"
+ " }"
+ "};"
+ "xhr.onerror = function () {"
+ " window.domAutomationController.send(false);"
+ "};"
+ "xhr.send(null);",
+ url);
return ExecuteScript(script);
}
diff --git a/chromium/content/browser/network_service_client.cc b/chromium/content/browser/network_service_client.cc
index afeafe636a5..81a0655e94e 100644
--- a/chromium/content/browser/network_service_client.cc
+++ b/chromium/content/browser/network_service_client.cc
@@ -5,7 +5,8 @@
#include "content/browser/network_service_client.h"
#include "base/optional.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
+#include "content/browser/browsing_data/clear_site_data_handler.h"
#include "content/browser/devtools/devtools_url_loader_interceptor.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/ssl/ssl_client_auth_handler.h"
@@ -425,4 +426,51 @@ void NetworkServiceClient::OnCookieChange(int process_id,
process_id, routing_id, url, first_party_url, cookie, blocked_by_policy);
}
+void NetworkServiceClient::OnLoadingStateUpdate(
+ std::vector<network::mojom::LoadInfoPtr> infos,
+ OnLoadingStateUpdateCallback callback) {
+ auto rdh_infos = std::make_unique<ResourceDispatcherHostImpl::LoadInfoList>();
+
+ // TODO(jam): once ResourceDispatcherHost is gone remove the translation
+ // (other than adding the WebContents callback).
+ for (auto& info : infos) {
+ ResourceDispatcherHostImpl::LoadInfo load_info;
+ load_info.host = std::move(info->host);
+ load_info.load_state.state = static_cast<net::LoadState>(info->load_state);
+ load_info.load_state.param = std::move(info->state_param);
+ load_info.upload_position = info->upload_position;
+ load_info.upload_size = info->upload_size;
+ load_info.web_contents_getter =
+ info->process_id
+ ? base::BindRepeating(WebContentsImpl::FromRenderFrameHostID,
+ info->process_id, info->routing_id)
+ : base::BindRepeating(WebContents::FromFrameTreeNodeId,
+ info->routing_id);
+ rdh_infos->push_back(std::move(load_info));
+ }
+
+ auto* rdh = ResourceDispatcherHostImpl::Get();
+ ResourceDispatcherHostImpl::UpdateLoadStateOnUI(rdh->loader_delegate_,
+ std::move(rdh_infos));
+
+ 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) {
+ base::RepeatingCallback<WebContents*(void)> web_contents_getter =
+ process_id
+ ? base::BindRepeating(WebContentsImpl::FromRenderFrameHostID,
+ process_id, routing_id)
+ : base::BindRepeating(WebContents::FromFrameTreeNodeId, routing_id);
+
+ ClearSiteDataHandler::HandleHeader(std::move(web_contents_getter), url,
+ header_value, load_flags,
+ std::move(callback));
+}
+
} // namespace content
diff --git a/chromium/content/browser/network_service_client.h b/chromium/content/browser/network_service_client.h
index 68c0af0a499..1c0edbed8db 100644
--- a/chromium/content/browser/network_service_client.h
+++ b/chromium/content/browser/network_service_client.h
@@ -63,6 +63,14 @@ class CONTENT_EXPORT NetworkServiceClient
const GURL& first_party_url,
const net::CanonicalCookie& cookie,
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;
private:
mojo::Binding<network::mojom::NetworkServiceClient> binding_;
diff --git a/chromium/content/browser/network_service_instance.cc b/chromium/content/browser/network_service_instance.cc
index 374ac6da02d..905301ab321 100644
--- a/chromium/content/browser/network_service_instance.cc
+++ b/chromium/content/browser/network_service_instance.cc
@@ -10,8 +10,12 @@
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/service_manager_connection.h"
#include "content/public/common/service_names.mojom.h"
+#include "net/log/net_log_util.h"
#include "services/network/network_service.h"
#include "services/network/public/cpp/features.h"
+#include "services/network/public/cpp/network_connection_tracker.h"
+#include "services/network/public/cpp/network_switches.h"
+#include "services/network/public/mojom/network_change_manager.mojom.h"
#include "services/service_manager/public/cpp/connector.h"
namespace content {
@@ -19,6 +23,7 @@ namespace content {
namespace {
network::mojom::NetworkServicePtr* g_network_service_ptr = nullptr;
+network::NetworkConnectionTracker* g_network_connection_tracker;
network::NetworkService* g_network_service;
void CreateNetworkServiceOnIO(network::mojom::NetworkServiceRequest request) {
@@ -33,19 +38,32 @@ void CreateNetworkServiceOnIO(network::mojom::NetworkServiceRequest request) {
nullptr, std::move(request), GetContentClient()->browser()->GetNetLog());
}
+void BindNetworkChangeManagerRequest(
+ network::mojom::NetworkChangeManagerRequest request) {
+ GetNetworkService()->GetNetworkChangeManager(std::move(request));
+}
+
} // namespace
network::mojom::NetworkService* GetNetworkService() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ service_manager::Connector* connector =
+ base::FeatureList::IsEnabled(network::features::kNetworkService)
+ ? ServiceManagerConnection::GetForProcess()->GetConnector()
+ : nullptr;
+ return GetNetworkServiceFromConnector(connector);
+}
+CONTENT_EXPORT network::mojom::NetworkService* GetNetworkServiceFromConnector(
+ service_manager::Connector* connector) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (!g_network_service_ptr)
g_network_service_ptr = new network::mojom::NetworkServicePtr;
static NetworkServiceClient* g_client;
if (!g_network_service_ptr->is_bound() ||
g_network_service_ptr->encountered_error()) {
if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
- ServiceManagerConnection::GetForProcess()->GetConnector()->BindInterface(
- mojom::kNetworkServiceName, g_network_service_ptr);
+ connector->BindInterface(mojom::kNetworkServiceName,
+ g_network_service_ptr);
} else {
DCHECK(!g_network_service_ptr->is_bound());
BrowserThread::PostTask(
@@ -59,6 +77,25 @@ network::mojom::NetworkService* GetNetworkService() {
g_client = new NetworkServiceClient(mojo::MakeRequest(&client_ptr));
(*g_network_service_ptr)->SetClient(std::move(client_ptr));
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ const base::CommandLine* command_line =
+ base::CommandLine::ForCurrentProcess();
+ if (command_line->HasSwitch(network::switches::kLogNetLog)) {
+ base::FilePath log_path =
+ command_line->GetSwitchValuePath(network::switches::kLogNetLog);
+
+ base::DictionaryValue client_constants =
+ GetContentClient()->GetNetLogConstants();
+
+ base::File file(
+ log_path, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
+ LOG_IF(ERROR, !file.IsValid())
+ << "Failed opening: " << log_path.value();
+ (*g_network_service_ptr)
+ ->StartNetLog(std::move(file), std::move(client_constants));
+ }
+ }
+
GetContentClient()->browser()->OnNetworkServiceCreated(
g_network_service_ptr->get());
}
@@ -83,4 +120,18 @@ void FlushNetworkServiceInstanceForTesting() {
g_network_service_ptr->FlushForTesting();
}
+network::NetworkConnectionTracker* GetNetworkConnectionTracker() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ if (!g_network_connection_tracker) {
+ g_network_connection_tracker = new network::NetworkConnectionTracker(
+ base::BindRepeating(&BindNetworkChangeManagerRequest));
+ }
+ return g_network_connection_tracker;
+}
+
+void SetNetworkConnectionTrackerForTesting(
+ network::NetworkConnectionTracker* network_connection_tracker) {
+ g_network_connection_tracker = network_connection_tracker;
+}
+
} // namespace content
diff --git a/chromium/content/browser/network_service_restart_browsertest.cc b/chromium/content/browser/network_service_restart_browsertest.cc
index 96551970a99..a868b80d5c5 100644
--- a/chromium/content/browser/network_service_restart_browsertest.cc
+++ b/chromium/content/browser/network_service_restart_browsertest.cc
@@ -2,17 +2,19 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#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/frame_host/render_frame_host_impl.h"
+#include "content/browser/frame_host/render_frame_message_filter.h"
+#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/storage_partition_impl.h"
#include "content/browser/url_loader_factory_getter.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/network_service_instance.h"
-#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test_utils.h"
@@ -665,4 +667,42 @@ IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
EXPECT_FALSE(CheckContainsProcessID(network_usages, process_id2));
}
+// Make sure cookie access doesn't hang or fail after a network process crash.
+IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, Cookies) {
+ auto* web_contents = shell()->web_contents();
+ NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"));
+ EXPECT_TRUE(ExecuteScript(web_contents, "document.cookie = 'foo=bar';"));
+
+ std::string cookie;
+ EXPECT_TRUE(ExecuteScriptAndExtractString(
+ web_contents, "window.domAutomationController.send(document.cookie);",
+ &cookie));
+ EXPECT_EQ("foo=bar", cookie);
+
+ SimulateNetworkServiceCrash();
+
+ auto* process = web_contents->GetMainFrame()->GetProcess();
+ scoped_refptr<RenderFrameMessageFilter> filter(
+ static_cast<RenderProcessHostImpl*>(process)
+ ->render_frame_message_filter_for_testing());
+ // Need to use FlushAsyncForTesting instead of FlushForTesting because the IO
+ // thread doesn't support nested message loops.
+ base::RunLoop run_loop;
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::BindLambdaForTesting([&]() {
+ filter->GetCookieManager()->FlushAsyncForTesting(
+ run_loop.QuitClosure());
+ }));
+
+ // content_shell uses in-memory cookie database, so the value saved earlier
+ // won't persist across crashes. What matters is that new access works.
+ EXPECT_TRUE(ExecuteScript(web_contents, "document.cookie = 'foo=bar';"));
+
+ // This will hang without the fix.
+ EXPECT_TRUE(ExecuteScriptAndExtractString(
+ web_contents, "window.domAutomationController.send(document.cookie);",
+ &cookie));
+ EXPECT_EQ("foo=bar", cookie);
+}
+
} // namespace content
diff --git a/chromium/content/browser/notification_service_impl.h b/chromium/content/browser/notification_service_impl.h
index bd04f74cbe0..e74801f3cc1 100644
--- a/chromium/content/browser/notification_service_impl.h
+++ b/chromium/content/browser/notification_service_impl.h
@@ -34,7 +34,8 @@ class CONTENT_EXPORT NotificationServiceImpl : public NotificationService {
private:
friend class NotificationRegistrar;
- typedef base::ObserverList<NotificationObserver> NotificationObserverList;
+ typedef base::ObserverList<NotificationObserver>::Unchecked
+ NotificationObserverList;
typedef std::map<uintptr_t, NotificationObserverList*> NotificationSourceMap;
typedef std::map<int, NotificationSourceMap> NotificationObserverMap;
typedef std::map<int, int> NotificationObserverCount;
diff --git a/chromium/content/browser/notifications/OWNERS b/chromium/content/browser/notifications/OWNERS
index c172d4bfa29..0d5ed95cb0a 100644
--- a/chromium/content/browser/notifications/OWNERS
+++ b/chromium/content/browser/notifications/OWNERS
@@ -4,7 +4,6 @@
# //content/renderer/notifications/
# //content/test/mock_platform_notification_service.*
-awdf@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 cbcd2b5369f..73c5d6b436e 100644
--- a/chromium/content/browser/notifications/blink_notification_service_impl.cc
+++ b/chromium/content/browser/notifications/blink_notification_service_impl.cc
@@ -171,7 +171,8 @@ void BlinkNotificationServiceImpl::DisplayPersistentNotificationOnIOThread(
DisplayPersistentNotificationCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- // TODO(awdf): Necessary to validate resources here?
+ // TODO(https://crbug.com/870258): Validate resources are not too big (either
+ // here or in the mojo struct traits).
NotificationDatabaseData database_data;
database_data.origin = origin_.GetURL();
@@ -179,7 +180,8 @@ void BlinkNotificationServiceImpl::DisplayPersistentNotificationOnIOThread(
database_data.notification_data = platform_notification_data;
notification_context_->WriteNotificationData(
- next_persistent_notification_id, origin_.GetURL(), database_data,
+ next_persistent_notification_id, service_worker_registration_id,
+ origin_.GetURL(), database_data,
base::AdaptCallbackForRepeating(base::BindOnce(
&BlinkNotificationServiceImpl::
DisplayPersistentNotificationWithIdOnIOThread,
diff --git a/chromium/content/browser/notifications/notification_database.cc b/chromium/content/browser/notifications/notification_database.cc
index 28ff2f47881..bc54e5a090f 100644
--- a/chromium/content/browser/notifications/notification_database.cc
+++ b/chromium/content/browser/notifications/notification_database.cc
@@ -98,7 +98,7 @@ NotificationDatabase::Status DeserializedNotificationData(
// Updates the time of the last click on the notification, and the first if
// necessary.
-void UpdateNotificationClickTimestamps(NotificationDatabaseData* data) {
+void UpdateNotificationTimestamps(NotificationDatabaseData* data) {
base::TimeDelta delta = base::Time::Now() - data->creation_time_millis;
if (!data->time_until_first_click_millis.has_value())
data->time_until_first_click_millis = delta;
@@ -107,8 +107,9 @@ void UpdateNotificationClickTimestamps(NotificationDatabaseData* data) {
} // namespace
-NotificationDatabase::NotificationDatabase(const base::FilePath& path)
- : path_(path) {}
+NotificationDatabase::NotificationDatabase(const base::FilePath& path,
+ UkmCallback callback)
+ : path_(path), record_notification_to_ukm_callback_(std::move(callback)) {}
NotificationDatabase::~NotificationDatabase() {
DCHECK(sequence_checker_.CalledOnValidSequence());
@@ -182,18 +183,20 @@ NotificationDatabase::ReadNotificationDataAndRecordInteraction(
// Update the appropriate fields for UKM logging purposes.
switch (interaction) {
case PlatformNotificationContext::Interaction::CLOSED:
+ notification_database_data->closed_reason =
+ NotificationDatabaseData::ClosedReason::USER;
notification_database_data->time_until_close_millis =
base::Time::Now() - notification_database_data->creation_time_millis;
break;
case PlatformNotificationContext::Interaction::NONE:
- return status;
+ break;
case PlatformNotificationContext::Interaction::ACTION_BUTTON_CLICKED:
notification_database_data->num_action_button_clicks += 1;
- UpdateNotificationClickTimestamps(notification_database_data);
+ UpdateNotificationTimestamps(notification_database_data);
break;
case PlatformNotificationContext::Interaction::CLICKED:
notification_database_data->num_clicks += 1;
- UpdateNotificationClickTimestamps(notification_database_data);
+ UpdateNotificationTimestamps(notification_database_data);
break;
}
@@ -262,6 +265,13 @@ NotificationDatabase::Status NotificationDatabase::DeleteNotificationData(
DCHECK(!notification_id.empty());
DCHECK(origin.is_valid());
+ NotificationDatabaseData data;
+ Status status = ReadNotificationData(notification_id, origin, &data);
+ if (status == STATUS_OK && record_notification_to_ukm_callback_) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(record_notification_to_ukm_callback_, data));
+ }
std::string key = CreateDataKey(origin, notification_id);
return LevelDBStatusToNotificationDatabaseStatus(
db_->Delete(leveldb::WriteOptions(), key));
@@ -381,6 +391,13 @@ NotificationDatabase::DeleteAllNotificationDataInternal(
continue;
}
+ if (record_notification_to_ukm_callback_) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(record_notification_to_ukm_callback_,
+ notification_database_data));
+ }
+
batch.Delete(iter->key());
DCHECK(!notification_database_data.notification_id.empty());
diff --git a/chromium/content/browser/notifications/notification_database.h b/chromium/content/browser/notifications/notification_database.h
index 5237a8e323c..6ed4658d998 100644
--- a/chromium/content/browser/notifications/notification_database.h
+++ b/chromium/content/browser/notifications/notification_database.h
@@ -14,8 +14,8 @@
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/sequence_checker.h"
-#include "content/browser/notifications/platform_notification_context_impl.h"
#include "content/common/content_export.h"
+#include "content/public/browser/platform_notification_context.h"
class GURL;
@@ -23,7 +23,7 @@ namespace leveldb {
class DB;
class Env;
class FilterPolicy;
-}
+} // namespace leveldb
namespace content {
@@ -40,6 +40,9 @@ struct NotificationDatabaseData;
// file I/O. The same thread or task runner must be used for all method calls.
class CONTENT_EXPORT NotificationDatabase {
public:
+ using UkmCallback =
+ base::RepeatingCallback<void(const NotificationDatabaseData&)>;
+
// Result status codes for interations with the database. Will be used for
// UMA, so the assigned ids must remain stable.
enum Status {
@@ -69,7 +72,8 @@ class CONTENT_EXPORT NotificationDatabase {
STATUS_COUNT = 7
};
- explicit NotificationDatabase(const base::FilePath& path);
+ NotificationDatabase(const base::FilePath& path, UkmCallback callback);
+
~NotificationDatabase();
// Opens the database. If |path| is non-empty, it will be created on the given
@@ -212,6 +216,9 @@ class CONTENT_EXPORT NotificationDatabase {
base::SequenceChecker sequence_checker_;
+ // Callback to use for recording UKM metrics. Must be posted to the UI thread.
+ UkmCallback record_notification_to_ukm_callback_;
+
DISALLOW_COPY_AND_ASSIGN(NotificationDatabase);
};
diff --git a/chromium/content/browser/notifications/notification_database_data_conversions.cc b/chromium/content/browser/notifications/notification_database_data_conversions.cc
index 656108caa62..904963094eb 100644
--- a/chromium/content/browser/notifications/notification_database_data_conversions.cc
+++ b/chromium/content/browser/notifications/notification_database_data_conversions.cc
@@ -34,12 +34,19 @@ bool DeserializeNotificationDatabaseData(const std::string& input,
output->num_action_button_clicks = message.num_action_button_clicks();
output->creation_time_millis = base::Time::FromDeltaSinceWindowsEpoch(
base::TimeDelta::FromMicroseconds(message.creation_time_millis()));
- output->time_until_first_click_millis = base::TimeDelta::FromMilliseconds(
- message.time_until_first_click_millis());
- output->time_until_last_click_millis =
- base::TimeDelta::FromMilliseconds(message.time_until_last_click_millis());
- output->time_until_close_millis =
- base::TimeDelta::FromMilliseconds(message.time_until_close_millis());
+
+ if (message.has_time_until_close_millis()) {
+ output->time_until_close_millis =
+ base::TimeDelta::FromMilliseconds(message.time_until_close_millis());
+ }
+ if (message.has_time_until_first_click_millis()) {
+ output->time_until_first_click_millis = base::TimeDelta::FromMilliseconds(
+ message.time_until_first_click_millis());
+ }
+ if (message.has_time_until_last_click_millis()) {
+ output->time_until_last_click_millis = base::TimeDelta::FromMilliseconds(
+ message.time_until_last_click_millis());
+ }
switch (message.closed_reason()) {
case NotificationDatabaseDataProto::USER:
diff --git a/chromium/content/browser/notifications/notification_database_unittest.cc b/chromium/content/browser/notifications/notification_database_unittest.cc
index f6fdef1f358..fb0d6cb80fe 100644
--- a/chromium/content/browser/notifications/notification_database_unittest.cc
+++ b/chromium/content/browser/notifications/notification_database_unittest.cc
@@ -14,6 +14,7 @@
#include "base/strings/utf_string_conversions.h"
#include "content/public/browser/notification_database_data.h"
#include "content/public/common/platform_notification_data.h"
+#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/leveldatabase/src/include/leveldb/db.h"
#include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
@@ -39,15 +40,19 @@ const struct {
{"https://chrome.com", "foo" /* tag */, 0}};
class NotificationDatabaseTest : public ::testing::Test {
+ public:
+ NotificationDatabaseTest()
+ : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}
+
protected:
// Creates a new NotificationDatabase instance in memory.
NotificationDatabase* CreateDatabaseInMemory() {
- return new NotificationDatabase(base::FilePath());
+ return new NotificationDatabase(base::FilePath(), callback());
}
// Creates a new NotificationDatabase instance in |path|.
NotificationDatabase* CreateDatabaseOnFileSystem(const base::FilePath& path) {
- return new NotificationDatabase(path);
+ return new NotificationDatabase(path, callback());
}
// Creates a new notification for |service_worker_registration_id| belonging
@@ -108,6 +113,12 @@ class NotificationDatabaseTest : public ::testing::Test {
// Generates a random notification ID. The format of the ID is opaque.
std::string GenerateNotificationId() { return base::GenerateGUID(); }
+
+ NotificationDatabase::UkmCallback callback() { return callback_; }
+
+ TestBrowserThreadBundle thread_bundle_; // Must be first member.
+
+ NotificationDatabase::UkmCallback callback_;
};
TEST_F(NotificationDatabaseTest, OpenCloseMemory) {
diff --git a/chromium/content/browser/notifications/notification_event_dispatcher_impl.cc b/chromium/content/browser/notifications/notification_event_dispatcher_impl.cc
index 879ab76c96d..d8acb3229bf 100644
--- a/chromium/content/browser/notifications/notification_event_dispatcher_impl.cc
+++ b/chromium/content/browser/notifications/notification_event_dispatcher_impl.cc
@@ -13,11 +13,11 @@
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/service_worker/service_worker_storage.h"
-#include "content/common/platform_notification_param_traits.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/storage_partition.h"
+#include "content/public/common/persistent_notification_status.h"
#include "content/public/common/platform_notification_data.h"
namespace content {
@@ -58,13 +58,13 @@ void ServiceWorkerNotificationEventFinished(
<< blink::ServiceWorkerStatusToString(service_worker_status);
#endif
- PersistentNotificationStatus status = PERSISTENT_NOTIFICATION_STATUS_SUCCESS;
+ PersistentNotificationStatus status = PersistentNotificationStatus::kSuccess;
switch (service_worker_status) {
case blink::ServiceWorkerStatusCode::kOk:
// Success status was initialized above.
break;
case blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected:
- status = PERSISTENT_NOTIFICATION_STATUS_EVENT_WAITUNTIL_REJECTED;
+ status = PersistentNotificationStatus::kWaitUntilRejected;
break;
case blink::ServiceWorkerStatusCode::kErrorFailed:
case blink::ServiceWorkerStatusCode::kErrorAbort:
@@ -83,7 +83,8 @@ void ServiceWorkerNotificationEventFinished(
case blink::ServiceWorkerStatusCode::kErrorDiskCache:
case blink::ServiceWorkerStatusCode::kErrorRedundant:
case blink::ServiceWorkerStatusCode::kErrorDisallowed:
- status = PERSISTENT_NOTIFICATION_STATUS_SERVICE_WORKER_ERROR;
+ case blink::ServiceWorkerStatusCode::kErrorInvalidArguments:
+ status = PersistentNotificationStatus::kServiceWorkerError;
break;
}
NotificationEventFinished(dispatch_complete_callback, status);
@@ -115,10 +116,10 @@ void DispatchNotificationEventOnRegistration(
return;
}
- PersistentNotificationStatus status = PERSISTENT_NOTIFICATION_STATUS_SUCCESS;
+ PersistentNotificationStatus status = PersistentNotificationStatus::kSuccess;
switch (service_worker_status) {
case blink::ServiceWorkerStatusCode::kErrorNotFound:
- status = PERSISTENT_NOTIFICATION_STATUS_NO_SERVICE_WORKER;
+ status = PersistentNotificationStatus::kServiceWorkerMissing;
break;
case blink::ServiceWorkerStatusCode::kErrorFailed:
case blink::ServiceWorkerStatusCode::kErrorAbort:
@@ -137,7 +138,8 @@ void DispatchNotificationEventOnRegistration(
case blink::ServiceWorkerStatusCode::kErrorDiskCache:
case blink::ServiceWorkerStatusCode::kErrorRedundant:
case blink::ServiceWorkerStatusCode::kErrorDisallowed:
- status = PERSISTENT_NOTIFICATION_STATUS_SERVICE_WORKER_ERROR;
+ case blink::ServiceWorkerStatusCode::kErrorInvalidArguments:
+ status = PersistentNotificationStatus::kServiceWorkerError;
break;
case blink::ServiceWorkerStatusCode::kOk:
NOTREACHED();
@@ -170,7 +172,7 @@ void FindServiceWorkerRegistration(
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::BindOnce(dispatch_error_callback,
- PERSISTENT_NOTIFICATION_STATUS_DATABASE_ERROR));
+ PersistentNotificationStatus::kDatabaseError));
return;
}
@@ -260,10 +262,10 @@ void OnPersistentNotificationDataDeleted(
service_worker_status);
return;
}
- NotificationEventFinished(
- dispatch_complete_callback,
- success ? PERSISTENT_NOTIFICATION_STATUS_SUCCESS
- : PERSISTENT_NOTIFICATION_STATUS_DATABASE_ERROR);
+ NotificationEventFinished(dispatch_complete_callback,
+ success
+ ? PersistentNotificationStatus::kSuccess
+ : PersistentNotificationStatus::kDatabaseError);
}
// Called when the persistent notification close event has been handled
diff --git a/chromium/content/browser/notifications/notification_storage.cc b/chromium/content/browser/notifications/notification_storage.cc
new file mode 100644
index 00000000000..8c6053999e7
--- /dev/null
+++ b/chromium/content/browser/notifications/notification_storage.cc
@@ -0,0 +1,153 @@
+// 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/notifications/notification_storage.h"
+
+#include "base/metrics/histogram_macros.h"
+#include "base/time/time.h"
+#include "content/browser/notifications/notification_database_data_conversions.h"
+
+namespace content {
+
+namespace {
+
+// Schema is as follows:
+// KEY: NOTIFICATION_<|data.notification_id|>
+// VALUE: <serialized content::proto::NotificationDatabaseData>
+
+const char kNotificationPrefix[] = "NOTIFICATION_";
+
+// Create the key that will be used for the service worker database.
+std::string CreateDataKey(const std::string& notification_id) {
+ DCHECK(!notification_id.empty());
+ return kNotificationPrefix + notification_id;
+}
+
+// Updates the time of the last click on the notification, and the first if
+// necessary.
+void UpdateNotificationClickTimestamps(NotificationDatabaseData* data) {
+ base::TimeDelta delta = base::Time::Now() - data->creation_time_millis;
+ if (!data->time_until_first_click_millis.has_value())
+ data->time_until_first_click_millis = delta;
+ data->time_until_last_click_millis = delta;
+}
+
+} // namespace
+
+NotificationStorage::NotificationStorage(
+ scoped_refptr<ServiceWorkerContextWrapper> service_worker_context)
+ : service_worker_context_(std::move(service_worker_context)),
+ weak_ptr_factory_(this) {}
+
+NotificationStorage::~NotificationStorage() = default;
+
+void NotificationStorage::WriteNotificationData(
+ const NotificationDatabaseData& data,
+ const PlatformNotificationContext::WriteResultCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ std::string serialized_data;
+ if (!SerializeNotificationDatabaseData(data, &serialized_data)) {
+ DLOG(ERROR) << "Unable to serialize data for a notification belonging "
+ << "to: " << data.origin;
+ callback.Run(/* success= */ false, std::string());
+ return;
+ }
+
+ service_worker_context_->StoreRegistrationUserData(
+ data.service_worker_registration_id, data.origin,
+ {{CreateDataKey(data.notification_id), std::move(serialized_data)}},
+ base::BindOnce(&NotificationStorage::OnWriteComplete,
+ weak_ptr_factory_.GetWeakPtr(), data, callback));
+}
+
+void NotificationStorage::OnWriteComplete(
+ const NotificationDatabaseData& data,
+ const PlatformNotificationContext::WriteResultCallback& callback,
+ blink::ServiceWorkerStatusCode status) {
+ if (status == blink::ServiceWorkerStatusCode::kOk) {
+ callback.Run(/* success= */ true, data.notification_id);
+ } else {
+ callback.Run(/* success= */ false,
+ /* notification_id= */ std::string());
+ }
+}
+
+void NotificationStorage::ReadNotificationDataAndRecordInteraction(
+ int64_t service_worker_registration_id,
+ const std::string& notification_id,
+ PlatformNotificationContext::Interaction interaction,
+ const PlatformNotificationContext::ReadResultCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ service_worker_context_->GetRegistrationUserData(
+ service_worker_registration_id, {CreateDataKey(notification_id)},
+ base::BindOnce(&NotificationStorage::OnReadCompleteUpdateInteraction,
+ weak_ptr_factory_.GetWeakPtr(),
+ service_worker_registration_id, interaction, callback));
+}
+
+void NotificationStorage::OnReadCompleteUpdateInteraction(
+ int64_t service_worker_registration_id,
+ PlatformNotificationContext::Interaction interaction,
+ const PlatformNotificationContext::ReadResultCallback& callback,
+ const std::vector<std::string>& database_data,
+ blink::ServiceWorkerStatusCode status) {
+ if (status != blink::ServiceWorkerStatusCode::kOk || database_data.empty()) {
+ callback.Run(/* success= */ false, NotificationDatabaseData());
+ return;
+ }
+
+ auto data = std::make_unique<NotificationDatabaseData>();
+ if (!DeserializeNotificationDatabaseData(database_data[0], data.get())) {
+ DLOG(ERROR) << "Unable to deserialize data for a notification belonging "
+ << "to: " << data->origin;
+ callback.Run(/* success= */ false, NotificationDatabaseData());
+ return;
+ }
+
+ switch (interaction) {
+ case PlatformNotificationContext::Interaction::CLOSED:
+ data->time_until_close_millis =
+ base::Time::Now() - data->creation_time_millis;
+ break;
+ case PlatformNotificationContext::Interaction::NONE:
+ break;
+ case PlatformNotificationContext::Interaction::ACTION_BUTTON_CLICKED:
+ data->num_action_button_clicks += 1;
+ UpdateNotificationClickTimestamps(data.get());
+ break;
+ case PlatformNotificationContext::Interaction::CLICKED:
+ data->num_clicks += 1;
+ UpdateNotificationClickTimestamps(data.get());
+ break;
+ }
+ std::string serialized_data;
+ if (!SerializeNotificationDatabaseData(*data, &serialized_data)) {
+ DLOG(ERROR) << "Unable to serialize data for a notification belonging "
+ << "to: " << data->origin;
+ callback.Run(/* success= */ false, NotificationDatabaseData());
+ return;
+ }
+
+ GURL origin = data->origin;
+ std::string notification_id = data->notification_id;
+ service_worker_context_->StoreRegistrationUserData(
+ service_worker_registration_id, origin,
+ {{CreateDataKey(notification_id), std::move(serialized_data)}},
+ base::BindOnce(&NotificationStorage::OnInteractionUpdateComplete,
+ weak_ptr_factory_.GetWeakPtr(), std::move(data),
+ callback));
+}
+
+void NotificationStorage::OnInteractionUpdateComplete(
+ std::unique_ptr<NotificationDatabaseData> data,
+ const PlatformNotificationContext::ReadResultCallback& callback,
+ blink::ServiceWorkerStatusCode status) {
+ DCHECK(data);
+ if (status == blink::ServiceWorkerStatusCode::kOk)
+ callback.Run(/* success= */ true, *data);
+ else
+ callback.Run(/* success= */ false, NotificationDatabaseData());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/notifications/notification_storage.h b/chromium/content/browser/notifications/notification_storage.h
new file mode 100644
index 00000000000..1a24c48bb05
--- /dev/null
+++ b/chromium/content/browser/notifications/notification_storage.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_NOTIFICATIONS_NOTIFICATION_STORAGE_H_
+#define CONTENT_BROWSER_NOTIFICATIONS_NOTIFICATION_STORAGE_H_
+
+#include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "content/public/browser/platform_notification_context.h"
+#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
+
+namespace content {
+
+// The NotificationStorage class is a wrapper around persistent storage, the
+// Service Worker database, exposing APIs for read and write queries relating to
+// persistent notifications.
+class CONTENT_EXPORT NotificationStorage {
+ public:
+ explicit NotificationStorage(
+ scoped_refptr<ServiceWorkerContextWrapper> service_worker_context);
+ ~NotificationStorage();
+
+ void WriteNotificationData(
+ const NotificationDatabaseData& data,
+ const PlatformNotificationContext::WriteResultCallback& callback);
+
+ void ReadNotificationDataAndRecordInteraction(
+ int64_t service_worker_registration_id,
+ const std::string& notification_id,
+ PlatformNotificationContext::Interaction interaction,
+ const PlatformNotificationContext::ReadResultCallback& callback);
+
+ private:
+ void OnWriteComplete(
+ const NotificationDatabaseData& data,
+ const PlatformNotificationContext::WriteResultCallback& callback,
+ blink::ServiceWorkerStatusCode status);
+
+ void OnReadCompleteUpdateInteraction(
+ int64_t service_worker_registration_id,
+ PlatformNotificationContext::Interaction interaction,
+ const PlatformNotificationContext::ReadResultCallback& callback,
+ const std::vector<std::string>& database_data,
+ blink::ServiceWorkerStatusCode status);
+
+ void OnInteractionUpdateComplete(
+ std::unique_ptr<NotificationDatabaseData> data,
+ const PlatformNotificationContext::ReadResultCallback& callback,
+ blink::ServiceWorkerStatusCode status);
+
+ scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_;
+
+ base::WeakPtrFactory<NotificationStorage>
+ weak_ptr_factory_; // Must be last member.
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_NOTIFICATIONS_NOTIFICATION_STORAGE_H_
diff --git a/chromium/content/browser/notifications/notification_storage_unittest.cc b/chromium/content/browser/notifications/notification_storage_unittest.cc
new file mode 100644
index 00000000000..bb8a4e8b8e6
--- /dev/null
+++ b/chromium/content/browser/notifications/notification_storage_unittest.cc
@@ -0,0 +1,253 @@
+// 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/notifications/notification_storage.h"
+
+#include "base/bind.h"
+#include "base/guid.h"
+#include "base/run_loop.h"
+#include "content/browser/service_worker/embedded_worker_test_helper.h"
+#include "content/browser/service_worker/service_worker_registration.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"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
+#include "url/gurl.h"
+
+namespace content {
+
+class NotificationStorageTest : public ::testing::Test {
+ public:
+ NotificationStorageTest()
+ : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
+ origin_(GURL("https://example.com")),
+ success_(false),
+ service_worker_registration_id_(
+ blink::mojom::kInvalidServiceWorkerRegistrationId) {
+ helper_ = std::make_unique<EmbeddedWorkerTestHelper>(base::FilePath());
+ storage_ =
+ std::make_unique<NotificationStorage>(helper_->context_wrapper());
+ }
+
+ void DidRegisterServiceWorker(base::OnceClosure quit_closure,
+ blink::ServiceWorkerStatusCode status,
+ const std::string& status_message,
+ int64_t service_worker_registration_id) {
+ DCHECK(service_worker_registration_id_);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status) << status_message;
+
+ service_worker_registration_id_ = service_worker_registration_id;
+
+ std::move(quit_closure).Run();
+ }
+
+ void DidFindServiceWorkerRegistration(
+ scoped_refptr<ServiceWorkerRegistration>* out_service_worker_registration,
+ base::OnceClosure quit_closure,
+ blink::ServiceWorkerStatusCode status,
+ scoped_refptr<ServiceWorkerRegistration> service_worker_registration) {
+ DCHECK(out_service_worker_registration);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status)
+ << blink::ServiceWorkerStatusToString(status);
+
+ *out_service_worker_registration = service_worker_registration;
+
+ std::move(quit_closure).Run();
+ }
+
+ // Registers a Service Worker for the testing origin and returns its
+ // |service_worker_registration_id|. If registration failed, this will be
+ // blink::mojom::kInvalidServiceWorkerRegistrationId. The
+ // ServiceWorkerRegistration will be kept alive for the test's lifetime.
+ int64_t RegisterServiceWorker() {
+ GURL script_url = origin_;
+
+ {
+ blink::mojom::ServiceWorkerRegistrationOptions options;
+ options.scope = origin_;
+ base::RunLoop run_loop;
+ helper_->context()->RegisterServiceWorker(
+ script_url, options,
+ base::BindOnce(&NotificationStorageTest::DidRegisterServiceWorker,
+ base::Unretained(this), run_loop.QuitClosure()));
+ run_loop.Run();
+ }
+
+ if (service_worker_registration_id_ ==
+ blink::mojom::kInvalidServiceWorkerRegistrationId) {
+ ADD_FAILURE() << "Could not obtain a valid Service Worker registration";
+ return blink::mojom::kInvalidServiceWorkerRegistrationId;
+ }
+
+ scoped_refptr<ServiceWorkerRegistration> service_worker_registration;
+
+ {
+ base::RunLoop run_loop;
+ helper_->context()->storage()->FindRegistrationForId(
+ service_worker_registration_id_, origin_,
+ base::BindOnce(
+ &NotificationStorageTest::DidFindServiceWorkerRegistration,
+ base::Unretained(this), &service_worker_registration,
+ run_loop.QuitClosure()));
+ run_loop.Run();
+ }
+
+ // Wait for the worker to be activated.
+ thread_bundle_.RunUntilIdle();
+
+ if (!service_worker_registration) {
+ ADD_FAILURE() << "Could not find the new Service Worker registration.";
+ return blink::mojom::kInvalidServiceWorkerRegistrationId;
+ }
+
+ service_worker_registrations_.push_back(
+ std::move(service_worker_registration));
+
+ return service_worker_registration_id_;
+ }
+
+ void DidWriteNotificationDataSynchronous(base::OnceClosure quit_closure,
+ bool success,
+ const std::string& notification_id) {
+ success_ = success;
+ notification_id_ = notification_id;
+ std::move(quit_closure).Run();
+ }
+
+ void WriteNotificationDataSynchronous(const NotificationDatabaseData& data) {
+ base::RunLoop run_loop;
+ storage_->WriteNotificationData(
+ data, base::Bind(
+ &NotificationStorageTest::DidWriteNotificationDataSynchronous,
+ base::Unretained(this), run_loop.QuitClosure()));
+ run_loop.Run();
+ }
+
+ void DidReadNotificationDataAndRecordInteractionSynchronous(
+ base::OnceClosure quit_closure,
+ bool success,
+ const NotificationDatabaseData& data) {
+ success_ = success;
+ out_data_ = data;
+ std::move(quit_closure).Run();
+ }
+
+ NotificationDatabaseData ReadNotificationDataAndRecordInteractionSynchronous(
+ int64_t service_worker_registration_id,
+ const std::string& notification_id,
+ PlatformNotificationContext::Interaction interaction) {
+ base::RunLoop run_loop;
+ storage_->ReadNotificationDataAndRecordInteraction(
+ service_worker_registration_id, notification_id, interaction,
+ base::Bind(&NotificationStorageTest::
+ DidReadNotificationDataAndRecordInteractionSynchronous,
+ base::Unretained(this), run_loop.QuitClosure()));
+ run_loop.Run();
+ return out_data_;
+ }
+
+ // Generates a random notification ID. The format of the ID is opaque.
+ std::string GenerateNotificationId() { return base::GenerateGUID(); }
+
+ protected:
+ TestBrowserThreadBundle thread_bundle_; // Must be first member
+ std::unique_ptr<EmbeddedWorkerTestHelper> helper_;
+ GURL origin_;
+ TestBrowserContext browser_context_;
+ bool success_;
+ int64_t service_worker_registration_id_;
+ NotificationDatabaseData out_data_;
+
+ private:
+ std::unique_ptr<NotificationStorage> storage_;
+ std::string notification_id_;
+
+ // Vector of ServiceWorkerRegistration instances that have to be kept alive
+ // for the lifetime of this test.
+ std::vector<scoped_refptr<ServiceWorkerRegistration>>
+ service_worker_registrations_;
+};
+
+TEST_F(NotificationStorageTest, WriteReadNotification) {
+ NotificationDatabaseData data;
+ data.notification_id = GenerateNotificationId();
+ data.origin = origin_;
+ data.service_worker_registration_id = RegisterServiceWorker();
+ ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId,
+ data.service_worker_registration_id);
+ WriteNotificationDataSynchronous(data);
+ ASSERT_TRUE(success_);
+
+ NotificationDatabaseData read_data =
+ ReadNotificationDataAndRecordInteractionSynchronous(
+ data.service_worker_registration_id, data.notification_id,
+ PlatformNotificationContext::Interaction::NONE);
+ ASSERT_TRUE(success_);
+ EXPECT_EQ(data.origin, read_data.origin);
+ EXPECT_EQ(data.notification_id, read_data.notification_id);
+ EXPECT_EQ(data.service_worker_registration_id,
+ read_data.service_worker_registration_id);
+}
+
+TEST_F(NotificationStorageTest, ReadInvalidNotification) {
+ int64_t service_worker_registration_id = RegisterServiceWorker();
+ ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId,
+ service_worker_registration_id);
+ ReadNotificationDataAndRecordInteractionSynchronous(
+ service_worker_registration_id, "bad_id",
+ PlatformNotificationContext::Interaction::NONE);
+ ASSERT_FALSE(success_);
+}
+
+TEST_F(NotificationStorageTest, ReadAndUpdateInteraction) {
+ NotificationDatabaseData data, read_data;
+ data.notification_id = GenerateNotificationId();
+ data.origin = origin_;
+ data.service_worker_registration_id = RegisterServiceWorker();
+ ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId,
+ data.service_worker_registration_id);
+
+ WriteNotificationDataSynchronous(data);
+ ASSERT_TRUE(success_);
+
+ // Check that the time deltas have not yet been set.
+ EXPECT_FALSE(read_data.time_until_first_click_millis.has_value());
+ EXPECT_FALSE(read_data.time_until_last_click_millis.has_value());
+ EXPECT_FALSE(read_data.time_until_close_millis.has_value());
+
+ // Check that when a notification has an interaction, the appropriate field is
+ // updated on the read.
+ read_data = ReadNotificationDataAndRecordInteractionSynchronous(
+ data.service_worker_registration_id, data.notification_id,
+ PlatformNotificationContext::Interaction::CLICKED);
+ ASSERT_TRUE(success_);
+ EXPECT_EQ(1, read_data.num_clicks);
+
+ read_data = ReadNotificationDataAndRecordInteractionSynchronous(
+ data.service_worker_registration_id, data.notification_id,
+ PlatformNotificationContext::Interaction::ACTION_BUTTON_CLICKED);
+ ASSERT_TRUE(success_);
+ EXPECT_EQ(1, read_data.num_action_button_clicks);
+
+ read_data = ReadNotificationDataAndRecordInteractionSynchronous(
+ data.service_worker_registration_id, data.notification_id,
+ PlatformNotificationContext::Interaction::ACTION_BUTTON_CLICKED);
+ ASSERT_TRUE(success_);
+ EXPECT_EQ(2, read_data.num_action_button_clicks);
+
+ // Check that the click timestamps are correctly updated.
+ EXPECT_TRUE(read_data.time_until_first_click_millis.has_value());
+ EXPECT_TRUE(read_data.time_until_last_click_millis.has_value());
+
+ // Check that when a read with a CLOSED interaction occurs, the correct
+ // field is updated.
+ read_data = ReadNotificationDataAndRecordInteractionSynchronous(
+ data.service_worker_registration_id, data.notification_id,
+ PlatformNotificationContext::Interaction::CLOSED);
+ ASSERT_TRUE(success_);
+ EXPECT_EQ(true, read_data.time_until_close_millis.has_value());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/notifications/platform_notification_context_impl.cc b/chromium/content/browser/notifications/platform_notification_context_impl.cc
index 627e8dbd251..13ece81608b 100644
--- a/chromium/content/browser/notifications/platform_notification_context_impl.cc
+++ b/chromium/content/browser/notifications/platform_notification_context_impl.cc
@@ -8,7 +8,7 @@
#include "base/files/file_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/stl_util.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "content/browser/notifications/blink_notification_service_impl.h"
#include "content/browser/notifications/notification_database.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
@@ -66,6 +66,10 @@ void PlatformNotificationContextImpl::Initialize() {
browser_context_,
base::Bind(&PlatformNotificationContextImpl::DidGetNotificationsOnUI,
this));
+
+ ukm_callback_ = base::BindRepeating(
+ &PlatformNotificationService::RecordNotificationUkmEvent,
+ base::Unretained(service), browser_context_);
}
void PlatformNotificationContextImpl::DidGetNotificationsOnUI(
@@ -309,18 +313,20 @@ void PlatformNotificationContextImpl::
void PlatformNotificationContextImpl::WriteNotificationData(
int64_t persistent_notification_id,
+ int64_t service_worker_registration_id,
const GURL& origin,
const NotificationDatabaseData& database_data,
const WriteResultCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
LazyInitialize(
base::Bind(&PlatformNotificationContextImpl::DoWriteNotificationData,
- this, persistent_notification_id, origin, database_data,
- callback),
+ this, service_worker_registration_id,
+ persistent_notification_id, origin, database_data, callback),
base::Bind(callback, false /* success */, "" /* notification_id */));
}
void PlatformNotificationContextImpl::DoWriteNotificationData(
+ int64_t service_worker_registration_id,
int64_t persistent_notification_id,
const GURL& origin,
const NotificationDatabaseData& database_data,
@@ -472,7 +478,7 @@ void PlatformNotificationContextImpl::LazyInitialize(
if (!task_runner_) {
task_runner_ = base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BACKGROUND});
+ {base::MayBlock(), base::TaskPriority::BEST_EFFORT});
}
task_runner_->PostTask(
@@ -490,7 +496,7 @@ void PlatformNotificationContextImpl::OpenDatabase(
return;
}
- database_.reset(new NotificationDatabase(GetDatabasePath()));
+ database_.reset(new NotificationDatabase(GetDatabasePath(), ukm_callback_));
NotificationDatabase::Status status =
database_->Open(true /* create_if_missing */);
@@ -502,7 +508,7 @@ void PlatformNotificationContextImpl::OpenDatabase(
prune_database_on_open_ = false;
DestroyDatabase();
- database_.reset(new NotificationDatabase(GetDatabasePath()));
+ database_.reset(new NotificationDatabase(GetDatabasePath(), ukm_callback_));
status = database_->Open(true /* create_if_missing */);
// TODO(peter): Find the appropriate UMA to cover in regards to
@@ -513,7 +519,8 @@ void PlatformNotificationContextImpl::OpenDatabase(
// away the contents of the directory and try re-opening the database.
if (status == NotificationDatabase::STATUS_ERROR_CORRUPTED) {
if (DestroyDatabase()) {
- database_.reset(new NotificationDatabase(GetDatabasePath()));
+ database_.reset(
+ new NotificationDatabase(GetDatabasePath(), ukm_callback_));
status = database_->Open(true /* create_if_missing */);
UMA_HISTOGRAM_ENUMERATION(
diff --git a/chromium/content/browser/notifications/platform_notification_context_impl.h b/chromium/content/browser/notifications/platform_notification_context_impl.h
index 7ea92b62620..653f487b0b0 100644
--- a/chromium/content/browser/notifications/platform_notification_context_impl.h
+++ b/chromium/content/browser/notifications/platform_notification_context_impl.h
@@ -16,6 +16,7 @@
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "content/browser/notifications/notification_database.h"
#include "content/browser/notifications/notification_id_generator.h"
#include "content/browser/service_worker/service_worker_context_core_observer.h"
#include "content/common/content_export.h"
@@ -37,7 +38,6 @@ namespace content {
class BlinkNotificationServiceImpl;
class BrowserContext;
-class NotificationDatabase;
struct NotificationDatabaseData;
class ServiceWorkerContextWrapper;
@@ -84,6 +84,7 @@ class CONTENT_EXPORT PlatformNotificationContextImpl
Interaction interaction,
const ReadResultCallback& callback) override;
void WriteNotificationData(int64_t persistent_notification_id,
+ int64_t service_worker_registration_id,
const GURL& origin,
const NotificationDatabaseData& database_data,
const WriteResultCallback& callback) override;
@@ -166,6 +167,7 @@ class CONTENT_EXPORT PlatformNotificationContextImpl
// called on the |task_runner_| thread. |callback| will be invoked on the
// IO thread when the operation has completed.
void DoWriteNotificationData(int64_t persistent_notification_id,
+ int64_t service_worker_registration_id,
const GURL& origin,
const NotificationDatabaseData& database_data,
const WriteResultCallback& callback);
@@ -212,6 +214,8 @@ class CONTENT_EXPORT PlatformNotificationContextImpl
// removed when either this class is destroyed or the Mojo pipe disconnects.
std::vector<std::unique_ptr<BlinkNotificationServiceImpl>> services_;
+ NotificationDatabase::UkmCallback ukm_callback_;
+
DISALLOW_COPY_AND_ASSIGN(PlatformNotificationContextImpl);
};
diff --git a/chromium/content/browser/notifications/platform_notification_context_unittest.cc b/chromium/content/browser/notifications/platform_notification_context_unittest.cc
index ffe0ebb1681..1e566931611 100644
--- a/chromium/content/browser/notifications/platform_notification_context_unittest.cc
+++ b/chromium/content/browser/notifications/platform_notification_context_unittest.cc
@@ -101,13 +101,13 @@ class PlatformNotificationContextTest : public ::testing::Test {
protected:
// Creates a new PlatformNotificationContextImpl instance. When using this
// method, the underlying database will always be created in memory.
- PlatformNotificationContextImpl* CreatePlatformNotificationContext() {
- PlatformNotificationContextImpl* context =
- new PlatformNotificationContextImpl(base::FilePath(), &browser_context_,
- nullptr);
+ scoped_refptr<PlatformNotificationContextImpl>
+ CreatePlatformNotificationContext() {
+ auto context = base::MakeRefCounted<PlatformNotificationContextImpl>(
+ base::FilePath(), &browser_context_, nullptr);
context->Initialize();
- OverrideTaskRunnerForTesting(context);
+ OverrideTaskRunnerForTesting(context.get());
return context;
}
@@ -172,7 +172,8 @@ TEST_F(PlatformNotificationContextTest, WriteReadNotification) {
notification_database_data.origin = origin;
context->WriteNotificationData(
- next_persistent_notification_id(), origin, notification_database_data,
+ next_persistent_notification_id(), kFakeServiceWorkerRegistrationId,
+ origin, notification_database_data,
base::Bind(&PlatformNotificationContextTest::DidWriteNotificationData,
base::Unretained(this)));
@@ -213,7 +214,8 @@ TEST_F(PlatformNotificationContextTest, WriteReadReplacedNotification) {
// Write the first notification with the given |tag|.
context->WriteNotificationData(
- next_persistent_notification_id(), origin, notification_database_data,
+ next_persistent_notification_id(), kFakeServiceWorkerRegistrationId,
+ origin, notification_database_data,
base::Bind(&PlatformNotificationContextTest::DidWriteNotificationData,
base::Unretained(this)));
base::RunLoop().RunUntilIdle();
@@ -229,7 +231,8 @@ TEST_F(PlatformNotificationContextTest, WriteReadReplacedNotification) {
// Write the second notification with the given |tag|.
context->WriteNotificationData(
- next_persistent_notification_id(), origin, notification_database_data,
+ next_persistent_notification_id(), kFakeServiceWorkerRegistrationId,
+ origin, notification_database_data,
base::Bind(&PlatformNotificationContextTest::DidWriteNotificationData,
base::Unretained(this)));
@@ -283,7 +286,8 @@ TEST_F(PlatformNotificationContextTest, DeleteNotification) {
NotificationDatabaseData notification_database_data;
context->WriteNotificationData(
- next_persistent_notification_id(), origin, notification_database_data,
+ next_persistent_notification_id(), kFakeServiceWorkerRegistrationId,
+ origin, notification_database_data,
base::Bind(&PlatformNotificationContextTest::DidWriteNotificationData,
base::Unretained(this)));
@@ -351,7 +355,8 @@ TEST_F(PlatformNotificationContextTest, ServiceWorkerUnregistered) {
// Create a notification for that Service Worker registration.
notification_context->WriteNotificationData(
- next_persistent_notification_id(), origin, notification_database_data,
+ next_persistent_notification_id(), kFakeServiceWorkerRegistrationId,
+ origin, notification_database_data,
base::Bind(&PlatformNotificationContextTest::DidWriteNotificationData,
base::Unretained(this)));
@@ -390,7 +395,8 @@ TEST_F(PlatformNotificationContextTest, DestroyDatabaseOnStorageWiped) {
NotificationDatabaseData notification_database_data;
context->WriteNotificationData(
- next_persistent_notification_id(), origin, notification_database_data,
+ next_persistent_notification_id(), kFakeServiceWorkerRegistrationId,
+ origin, notification_database_data,
base::Bind(&PlatformNotificationContextTest::DidWriteNotificationData,
base::Unretained(this)));
@@ -483,7 +489,8 @@ TEST_F(PlatformNotificationContextTest, ReadAllServiceWorkerDataFilled) {
// test Service Worker Registration id.
for (int i = 0; i < 10; ++i) {
context->WriteNotificationData(
- next_persistent_notification_id(), origin, notification_database_data,
+ next_persistent_notification_id(), kFakeServiceWorkerRegistrationId,
+ origin, notification_database_data,
base::Bind(&PlatformNotificationContextTest::DidWriteNotificationData,
base::Unretained(this)));
@@ -527,7 +534,8 @@ TEST_F(PlatformNotificationContextTest, SynchronizeNotifications) {
content::NotificationResources notification_resources;
context->WriteNotificationData(
- next_persistent_notification_id(), origin, notification_database_data,
+ next_persistent_notification_id(), kFakeServiceWorkerRegistrationId,
+ origin, notification_database_data,
base::Bind(&PlatformNotificationContextTest::DidWriteNotificationData,
base::Unretained(this)));
diff --git a/chromium/content/browser/oop_browsertest.cc b/chromium/content/browser/oop_browsertest.cc
index 390c73409e9..eaf658ca213 100644
--- a/chromium/content/browser/oop_browsertest.cc
+++ b/chromium/content/browser/oop_browsertest.cc
@@ -38,7 +38,7 @@ class OOPBrowserTest : public ContentBrowserTest {
command_line->AppendSwitch(switches::kEnablePixelOutputInTests);
command_line->AppendSwitch(switches::kEnableOopRasterization);
- const bool use_gpu_in_tests = features::IsAshInBrowserProcess();
+ const bool use_gpu_in_tests = !features::IsUsingWindowService();
if (use_gpu_in_tests)
command_line->AppendSwitch(switches::kUseGpuInTests);
}
diff --git a/chromium/content/browser/payments/payment_app_browsertest.cc b/chromium/content/browser/payments/payment_app_browsertest.cc
index 0c837e8f51b..00e36951e35 100644
--- a/chromium/content/browser/payments/payment_app_browsertest.cc
+++ b/chromium/content/browser/payments/payment_app_browsertest.cc
@@ -17,8 +17,8 @@
#include "content/shell/browser/shell.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/mojom/payments/payment_app.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
-#include "third_party/blink/public/platform/modules/payments/payment_app.mojom.h"
namespace content {
namespace {
@@ -234,8 +234,16 @@ class PaymentAppBrowserTest : public ContentBrowserTest {
DISALLOW_COPY_AND_ASSIGN(PaymentAppBrowserTest);
};
+// TODO(crbug.com/869790) Flakes on linux-chromeos-dbg
+#if defined(OS_CHROMEOS) && !defined(NDEBUG)
+#define MAYBE_AbortPaymentWithInvalidRegistrationId \
+ DISABLED_AbortPaymentWithInvalidRegistrationId
+#else
+#define MAYBE_AbortPaymentWithInvalidRegistrationId \
+ AbortPaymentWithInvalidRegistrationId
+#endif
IN_PROC_BROWSER_TEST_F(PaymentAppBrowserTest,
- AbortPaymentWithInvalidRegistrationId) {
+ MAYBE_AbortPaymentWithInvalidRegistrationId) {
RegisterPaymentApp();
std::vector<int64_t> registrationIds = GetAllPaymentAppRegistrationIDs();
@@ -248,7 +256,13 @@ IN_PROC_BROWSER_TEST_F(PaymentAppBrowserTest,
ClearStoragePartitionData();
}
-IN_PROC_BROWSER_TEST_F(PaymentAppBrowserTest, AbortPayment) {
+// TODO(crbug.com/869790) Flakes on linux-chromeos-dbg
+#if defined(OS_CHROMEOS) && !defined(NDEBUG)
+#define MAYBE_AbortPayment DISABLED_AbortPayment
+#else
+#define MAYBE_AbortPayment AbortPayment
+#endif
+IN_PROC_BROWSER_TEST_F(PaymentAppBrowserTest, MAYBE_AbortPayment) {
RegisterPaymentApp();
std::vector<int64_t> registrationIds = GetAllPaymentAppRegistrationIDs();
@@ -260,7 +274,13 @@ IN_PROC_BROWSER_TEST_F(PaymentAppBrowserTest, AbortPayment) {
ClearStoragePartitionData();
}
-IN_PROC_BROWSER_TEST_F(PaymentAppBrowserTest, CanMakePayment) {
+// TODO(crbug.com/869790) Flakes on linux-chromeos-dbg
+#if defined(OS_CHROMEOS) && !defined(NDEBUG)
+#define MAYBE_CanMakePayment DISABLED_CanMakePayment
+#else
+#define MAYBE_CanMakePayment CanMakePayment
+#endif
+IN_PROC_BROWSER_TEST_F(PaymentAppBrowserTest, MAYBE_CanMakePayment) {
RegisterPaymentApp();
std::vector<int64_t> registrationIds = GetAllPaymentAppRegistrationIDs();
@@ -285,7 +305,15 @@ IN_PROC_BROWSER_TEST_F(PaymentAppBrowserTest, CanMakePayment) {
PopConsoleString() /* modifiers */);
}
-IN_PROC_BROWSER_TEST_F(PaymentAppBrowserTest, PaymentAppInvocationAndFailed) {
+// TODO(crbug.com/869790) Flakes on linux-chromeos-dbg
+#if defined(OS_CHROMEOS) && !defined(NDEBUG)
+#define MAYBE_PaymentAppInvocationAndFailed \
+ DISABLED_PaymentAppInvocationAndFailed
+#else
+#define MAYBE_PaymentAppInvocationAndFailed PaymentAppInvocationAndFailed
+#endif
+IN_PROC_BROWSER_TEST_F(PaymentAppBrowserTest,
+ MAYBE_PaymentAppInvocationAndFailed) {
RegisterPaymentApp();
std::vector<int64_t> registrationIds = GetAllPaymentAppRegistrationIDs();
@@ -301,7 +329,13 @@ IN_PROC_BROWSER_TEST_F(PaymentAppBrowserTest, PaymentAppInvocationAndFailed) {
ClearStoragePartitionData();
}
-IN_PROC_BROWSER_TEST_F(PaymentAppBrowserTest, PaymentAppInvocation) {
+// TODO(crbug.com/869790) Flakes on linux-chromeos-dbg
+#if defined(OS_CHROMEOS) && !defined(NDEBUG)
+#define MAYBE_PaymentAppInvocation DISABLED_PaymentAppInvocation
+#else
+#define MAYBE_PaymentAppInvocation PaymentAppInvocation
+#endif
+IN_PROC_BROWSER_TEST_F(PaymentAppBrowserTest, MAYBE_PaymentAppInvocation) {
RegisterPaymentApp();
std::vector<int64_t> registrationIds = GetAllPaymentAppRegistrationIDs();
@@ -336,7 +370,14 @@ IN_PROC_BROWSER_TEST_F(PaymentAppBrowserTest, PaymentAppInvocation) {
PopConsoleString() /* instrumentKey */);
}
-IN_PROC_BROWSER_TEST_F(PaymentAppBrowserTest, PaymentAppOpenWindowFailed) {
+// TODO(crbug.com/869790) Flakes on linux-chromeos-dbg
+#if defined(OS_CHROMEOS) && !defined(NDEBUG)
+#define MAYBE_PaymentAppOpenWindowFailed DISABLED_PaymentAppOpenWindowFailed
+#else
+#define MAYBE_PaymentAppOpenWindowFailed PaymentAppOpenWindowFailed
+#endif
+IN_PROC_BROWSER_TEST_F(PaymentAppBrowserTest,
+ MAYBE_PaymentAppOpenWindowFailed) {
RegisterPaymentApp();
std::vector<int64_t> registrationIds = GetAllPaymentAppRegistrationIDs();
diff --git a/chromium/content/browser/payments/payment_app_content_unittest_base.h b/chromium/content/browser/payments/payment_app_content_unittest_base.h
index 12a82842839..c09dd080903 100644
--- a/chromium/content/browser/payments/payment_app_content_unittest_base.h
+++ b/chromium/content/browser/payments/payment_app_content_unittest_base.h
@@ -13,7 +13,7 @@
#include "base/memory/ref_counted.h"
#include "content/browser/payments/payment_manager.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/modules/payments/payment_app.mojom.h"
+#include "third_party/blink/public/mojom/payments/payment_app.mojom.h"
#include "url/gurl.h"
namespace content {
diff --git a/chromium/content/browser/payments/payment_app_context_impl.h b/chromium/content/browser/payments/payment_app_context_impl.h
index 8c8ce926912..e79119e7f30 100644
--- a/chromium/content/browser/payments/payment_app_context_impl.h
+++ b/chromium/content/browser/payments/payment_app_context_impl.h
@@ -15,7 +15,7 @@
#include "content/browser/payments/payment_app_database.h"
#include "content/common/content_export.h"
#include "content/public/browser/browser_thread.h"
-#include "third_party/blink/public/platform/modules/payments/payment_app.mojom.h"
+#include "third_party/blink/public/mojom/payments/payment_app.mojom.h"
namespace content {
diff --git a/chromium/content/browser/payments/payment_app_database.cc b/chromium/content/browser/payments/payment_app_database.cc
index 924d36591cc..043c5b038e7 100644
--- a/chromium/content/browser/payments/payment_app_database.cc
+++ b/chromium/content/browser/payments/payment_app_database.cc
@@ -19,7 +19,7 @@
#include "content/public/browser/browser_thread.h"
#include "third_party/blink/public/common/manifest/manifest.h"
#include "third_party/skia/include/core/SkBitmap.h"
-#include "ui/gfx/image/image.h"
+#include "ui/gfx/codec/png_codec.h"
#include "url/gurl.h"
#include "url/origin.h"
@@ -106,12 +106,13 @@ std::unique_ptr<StoredPaymentApp> ToStoredPaymentApp(const std::string& input) {
if (!app_proto.icon().empty()) {
std::string icon_raw_data;
base::Base64Decode(app_proto.icon(), &icon_raw_data);
+ app->icon = std::make_unique<SkBitmap>();
// Note that the icon has been decoded to PNG raw data regardless of the
// original icon format that was downloaded.
- gfx::Image icon_image = gfx::Image::CreateFrom1xPNGBytes(
+ bool success = gfx::PNGCodec::Decode(
reinterpret_cast<const unsigned char*>(icon_raw_data.data()),
- icon_raw_data.size());
- app->icon = std::make_unique<SkBitmap>(icon_image.AsBitmap());
+ icon_raw_data.size(), app->icon.get());
+ DCHECK(success);
}
return app;
diff --git a/chromium/content/browser/payments/payment_app_database.h b/chromium/content/browser/payments/payment_app_database.h
index 07bb2e8c310..2652f8eca97 100644
--- a/chromium/content/browser/payments/payment_app_database.h
+++ b/chromium/content/browser/payments/payment_app_database.h
@@ -19,7 +19,7 @@
#include "content/public/browser/stored_payment_app.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
-#include "third_party/blink/public/platform/modules/payments/payment_app.mojom.h"
+#include "third_party/blink/public/mojom/payments/payment_app.mojom.h"
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 5ba89bcdda3..c1714b4cfe6 100644
--- a/chromium/content/browser/payments/payment_app_info_fetcher.cc
+++ b/chromium/content/browser/payments/payment_app_info_fetcher.cc
@@ -4,16 +4,19 @@
#include "content/browser/payments/payment_app_info_fetcher.h"
+#include <utility>
+
#include "base/base64.h"
#include "base/bind_helpers.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"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/global_routing_id.h"
#include "content/public/browser/manifest_icon_downloader.h"
#include "content/public/common/console_message_level.h"
#include "third_party/blink/public/common/manifest/manifest_icon_selector.h"
-#include "ui/gfx/image/image.h"
+#include "ui/gfx/codec/png_codec.h"
#include "url/origin.h"
namespace content {
@@ -28,7 +31,7 @@ void PaymentAppInfoFetcher::Start(
PaymentAppInfoFetchCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- std::unique_ptr<std::vector<std::pair<int, int>>> provider_hosts =
+ std::unique_ptr<std::vector<GlobalFrameRoutingId>> provider_hosts =
service_worker_context->GetProviderHostIds(context_url.GetOrigin());
BrowserThread::PostTask(
@@ -39,7 +42,7 @@ void PaymentAppInfoFetcher::Start(
void PaymentAppInfoFetcher::StartOnUI(
const GURL& context_url,
- const std::unique_ptr<std::vector<std::pair<int, int>>>& provider_hosts,
+ const std::unique_ptr<std::vector<GlobalFrameRoutingId>>& provider_hosts,
PaymentAppInfoFetchCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -70,7 +73,7 @@ PaymentAppInfoFetcher::SelfDeleteFetcher::~SelfDeleteFetcher() {
void PaymentAppInfoFetcher::SelfDeleteFetcher::Start(
const GURL& context_url,
- const std::unique_ptr<std::vector<std::pair<int, int>>>& provider_hosts) {
+ const std::unique_ptr<std::vector<GlobalFrameRoutingId>>& provider_hosts) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (provider_hosts->size() == 0U) {
@@ -81,7 +84,7 @@ void PaymentAppInfoFetcher::SelfDeleteFetcher::Start(
for (const auto& frame : *provider_hosts) {
// Find out the render frame host registering the payment app.
RenderFrameHostImpl* render_frame_host =
- RenderFrameHostImpl::FromID(frame.first, frame.second);
+ RenderFrameHostImpl::FromID(frame.child_id, frame.frame_routing_id);
if (!render_frame_host ||
context_url.spec().compare(
render_frame_host->GetLastCommittedURL().spec()) != 0) {
@@ -259,10 +262,12 @@ void PaymentAppInfoFetcher::SelfDeleteFetcher::OnIconFetched(
return;
}
- gfx::Image decoded_image = gfx::Image::CreateFrom1xBitmap(icon);
- scoped_refptr<base::RefCountedMemory> raw_data = decoded_image.As1xPNGBytes();
+ std::vector<unsigned char> bitmap_data;
+ bool success = gfx::PNGCodec::EncodeBGRASkBitmap(icon, false, &bitmap_data);
+ DCHECK(success);
base::Base64Encode(
- base::StringPiece(raw_data->front_as<char>(), raw_data->size()),
+ base::StringPiece(reinterpret_cast<const char*>(&bitmap_data[0]),
+ bitmap_data.size()),
&(fetched_payment_app_info_->icon));
RunCallbackAndDestroy();
}
diff --git a/chromium/content/browser/payments/payment_app_info_fetcher.h b/chromium/content/browser/payments/payment_app_info_fetcher.h
index 73dd74fcd45..756622eb5c7 100644
--- a/chromium/content/browser/payments/payment_app_info_fetcher.h
+++ b/chromium/content/browser/payments/payment_app_info_fetcher.h
@@ -10,6 +10,7 @@
#include "base/macros.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "content/public/browser/global_routing_id.h"
#include "content/public/browser/stored_payment_app.h"
#include "content/public/browser/web_contents_observer.h"
#include "third_party/blink/public/common/manifest/manifest.h"
@@ -41,7 +42,7 @@ class PaymentAppInfoFetcher {
// Only accessed on the UI thread.
static void StartOnUI(
const GURL& context_url,
- const std::unique_ptr<std::vector<std::pair<int, int>>>& provider_hosts,
+ const std::unique_ptr<std::vector<GlobalFrameRoutingId>>& provider_hosts,
PaymentAppInfoFetchCallback callback);
// Keeps track of the web contents.
@@ -59,7 +60,7 @@ class PaymentAppInfoFetcher {
~SelfDeleteFetcher();
void Start(const GURL& context_url,
- const std::unique_ptr<std::vector<std::pair<int, int>>>&
+ const std::unique_ptr<std::vector<GlobalFrameRoutingId>>&
provider_hosts);
private:
diff --git a/chromium/content/browser/payments/payment_app_provider_impl_unittest.cc b/chromium/content/browser/payments/payment_app_provider_impl_unittest.cc
index 4ed0f9bb1ad..42bf14809dc 100644
--- a/chromium/content/browser/payments/payment_app_provider_impl_unittest.cc
+++ b/chromium/content/browser/payments/payment_app_provider_impl_unittest.cc
@@ -15,7 +15,7 @@
#include "content/public/test/test_browser_context.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/modules/payments/payment_app.mojom.h"
+#include "third_party/blink/public/mojom/payments/payment_app.mojom.h"
#include "third_party/blink/public/platform/modules/permissions/permission_status.mojom.h"
#include "url/gurl.h"
diff --git a/chromium/content/browser/payments/payment_instrument_icon_fetcher.cc b/chromium/content/browser/payments/payment_instrument_icon_fetcher.cc
index 8ef0de4e991..3bb8cffa724 100644
--- a/chromium/content/browser/payments/payment_instrument_icon_fetcher.cc
+++ b/chromium/content/browser/payments/payment_instrument_icon_fetcher.cc
@@ -4,6 +4,8 @@
#include "content/browser/payments/payment_instrument_icon_fetcher.h"
+#include <utility>
+
#include "base/base64.h"
#include "base/bind_helpers.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
@@ -13,8 +15,7 @@
#include "content/public/browser/manifest_icon_downloader.h"
#include "third_party/blink/public/common/manifest/manifest_icon_selector.h"
#include "third_party/skia/include/core/SkBitmap.h"
-#include "ui/gfx/geometry/size.h"
-#include "ui/gfx/image/image.h"
+#include "ui/gfx/codec/png_codec.h"
namespace content {
namespace {
@@ -52,11 +53,13 @@ void OnIconFetched(
return;
}
- gfx::Image decoded_image = gfx::Image::CreateFrom1xBitmap(bitmap);
- scoped_refptr<base::RefCountedMemory> raw_data = decoded_image.As1xPNGBytes();
+ std::vector<unsigned char> bitmap_data;
+ bool success = gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, &bitmap_data);
+ DCHECK(success);
std::string encoded_data;
base::Base64Encode(
- base::StringPiece(raw_data->front_as<char>(), raw_data->size()),
+ base::StringPiece(reinterpret_cast<const char*>(&bitmap_data[0]),
+ bitmap_data.size()),
&encoded_data);
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
base::BindOnce(std::move(callback), encoded_data));
@@ -99,12 +102,12 @@ void DownloadBestMatchingIcon(
WebContents* GetWebContentsFromProviderHostIds(
const GURL& scope,
- std::unique_ptr<std::vector<std::pair<int, int>>> provider_hosts) {
+ std::unique_ptr<std::vector<GlobalFrameRoutingId>> provider_hosts) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
for (const auto& host : *provider_hosts) {
RenderFrameHostImpl* render_frame_host =
- RenderFrameHostImpl::FromID(host.first, host.second);
+ RenderFrameHostImpl::FromID(host.child_id, host.frame_routing_id);
if (!render_frame_host)
continue;
@@ -122,7 +125,7 @@ WebContents* GetWebContentsFromProviderHostIds(
void StartOnUI(
const GURL& scope,
- std::unique_ptr<std::vector<std::pair<int, int>>> provider_hosts,
+ std::unique_ptr<std::vector<GlobalFrameRoutingId>> provider_hosts,
const std::vector<blink::Manifest::ImageResource>& icons,
PaymentInstrumentIconFetcher::PaymentInstrumentIconFetcherCallback
callback) {
@@ -138,7 +141,7 @@ void StartOnUI(
// static
void PaymentInstrumentIconFetcher::Start(
const GURL& scope,
- std::unique_ptr<std::vector<std::pair<int, int>>> provider_hosts,
+ std::unique_ptr<std::vector<GlobalFrameRoutingId>> provider_hosts,
const std::vector<blink::Manifest::ImageResource>& icons,
PaymentInstrumentIconFetcherCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
diff --git a/chromium/content/browser/payments/payment_instrument_icon_fetcher.h b/chromium/content/browser/payments/payment_instrument_icon_fetcher.h
index c31d531fcc7..80dd3af3ba0 100644
--- a/chromium/content/browser/payments/payment_instrument_icon_fetcher.h
+++ b/chromium/content/browser/payments/payment_instrument_icon_fetcher.h
@@ -5,14 +5,16 @@
#ifndef CONTENT_BROWSER_PAYMENTS_PAYMENT_INSTRUMENT_ICON_FETCHER_H_
#define CONTENT_BROWSER_PAYMENTS_PAYMENT_INSTRUMENT_ICON_FETCHER_H_
+#include <memory>
#include <string>
#include <vector>
#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "content/public/browser/global_routing_id.h"
#include "third_party/blink/public/common/manifest/manifest.h"
-#include "third_party/blink/public/platform/modules/payments/payment_app.mojom.h"
+#include "third_party/blink/public/mojom/payments/payment_app.mojom.h"
namespace content {
@@ -24,7 +26,7 @@ class PaymentInstrumentIconFetcher {
// Should be called on IO thread.
static void Start(
const GURL& scope,
- std::unique_ptr<std::vector<std::pair<int, int>>> provider_hosts,
+ std::unique_ptr<std::vector<GlobalFrameRoutingId>> provider_hosts,
const std::vector<blink::Manifest::ImageResource>& icons,
PaymentInstrumentIconFetcherCallback callback);
diff --git a/chromium/content/browser/payments/payment_manager.h b/chromium/content/browser/payments/payment_manager.h
index 87a63ae300c..bb37eca5113 100644
--- a/chromium/content/browser/payments/payment_manager.h
+++ b/chromium/content/browser/payments/payment_manager.h
@@ -11,7 +11,7 @@
#include "base/memory/weak_ptr.h"
#include "content/common/content_export.h"
#include "mojo/public/cpp/bindings/binding.h"
-#include "third_party/blink/public/platform/modules/payments/payment_app.mojom.h"
+#include "third_party/blink/public/mojom/payments/payment_app.mojom.h"
#include "url/gurl.h"
namespace content {
diff --git a/chromium/content/browser/payments/payment_manager_unittest.cc b/chromium/content/browser/payments/payment_manager_unittest.cc
index b1320ce7ad5..6a19821a54c 100644
--- a/chromium/content/browser/payments/payment_manager_unittest.cc
+++ b/chromium/content/browser/payments/payment_manager_unittest.cc
@@ -8,7 +8,7 @@
#include "base/run_loop.h"
#include "content/browser/payments/payment_app_content_unittest_base.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/modules/payments/payment_app.mojom.h"
+#include "third_party/blink/public/mojom/payments/payment_app.mojom.h"
#include "url/gurl.h"
namespace content {
diff --git a/chromium/content/browser/permissions/permission_controller_impl.cc b/chromium/content/browser/permissions/permission_controller_impl.cc
index 75ccdf0efb4..b182e8de0bf 100644
--- a/chromium/content/browser/permissions/permission_controller_impl.cc
+++ b/chromium/content/browser/permissions/permission_controller_impl.cc
@@ -9,12 +9,27 @@
#include "content/common/content_export.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/permission_controller_delegate.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/web_contents.h"
#include "third_party/blink/public/platform/modules/permissions/permission_status.mojom.h"
class GURL;
namespace content {
+namespace {
+
+blink::mojom::PermissionStatus GetPermissionOverrideStatus(
+ const PermissionControllerImpl::PermissionOverrides& permission_overrides,
+ const PermissionType& permission) {
+ if (permission_overrides.find(permission) == permission_overrides.end())
+ return blink::mojom::PermissionStatus::DENIED;
+ return blink::mojom::PermissionStatus::GRANTED;
+}
+
+} // namespace
+
PermissionControllerImpl::PermissionControllerImpl(
BrowserContext* browser_context)
: browser_context_(browser_context) {}
@@ -26,7 +41,78 @@ PermissionControllerImpl* PermissionControllerImpl::FromBrowserContext(
BrowserContext::GetPermissionController(browser_context));
}
-PermissionControllerImpl::~PermissionControllerImpl() = default;
+struct PermissionControllerImpl::Subscription {
+ PermissionType permission;
+ GURL requesting_origin;
+ GURL embedding_origin;
+ int render_frame_id = -1;
+ int render_process_id = -1;
+ base::Callback<void(blink::mojom::PermissionStatus)> callback;
+ int delegate_subscription_id;
+};
+
+PermissionControllerImpl::~PermissionControllerImpl() {
+ // Ideally we need to unsubscribe from delegate subscriptions here,
+ // but browser_context_ is already destroyed by this point, so
+ // we can't fetch our delegate.
+}
+
+blink::mojom::PermissionStatus
+PermissionControllerImpl::GetSubscriptionCurrentValue(
+ const Subscription& subscription) {
+ // The RFH may be null if the request is for a worker.
+ content::RenderFrameHost* rfh = content::RenderFrameHost::FromID(
+ subscription.render_process_id, subscription.render_frame_id);
+ if (rfh) {
+ return GetPermissionStatusForFrame(subscription.permission, rfh,
+ subscription.requesting_origin);
+ }
+ return GetPermissionStatus(subscription.permission,
+ subscription.requesting_origin,
+ subscription.embedding_origin);
+}
+
+void PermissionControllerImpl::SetPermissionOverridesForDevTools(
+ const GURL& origin,
+ const PermissionOverrides& overrides) {
+ std::vector<base::Closure> callbacks;
+ for (SubscriptionsMap::iterator iter(&subscriptions_); !iter.IsAtEnd();
+ iter.Advance()) {
+ Subscription* subscription = iter.GetCurrentValue();
+ if (subscription->requesting_origin != origin)
+ continue;
+ blink::mojom::PermissionStatus current_value =
+ GetSubscriptionCurrentValue(*subscription);
+ blink::mojom::PermissionStatus new_value =
+ GetPermissionOverrideStatus(overrides, subscription->permission);
+ if (current_value != new_value)
+ callbacks.push_back(base::Bind(subscription->callback, new_value));
+ }
+ devtools_permission_overrides_[origin] = overrides;
+ for (const auto& callback : callbacks)
+ callback.Run();
+}
+
+void PermissionControllerImpl::ResetPermissionOverridesForDevTools() {
+ std::map<GURL, PermissionOverrides> old_overrides;
+ old_overrides.swap(devtools_permission_overrides_);
+ std::vector<base::Closure> callbacks;
+ for (SubscriptionsMap::iterator iter(&subscriptions_); !iter.IsAtEnd();
+ iter.Advance()) {
+ Subscription* subscription = iter.GetCurrentValue();
+ auto overrides_it = old_overrides.find(subscription->requesting_origin);
+ if (overrides_it == old_overrides.end())
+ continue;
+ blink::mojom::PermissionStatus current_value = GetPermissionOverrideStatus(
+ overrides_it->second, subscription->permission);
+ blink::mojom::PermissionStatus new_value =
+ GetSubscriptionCurrentValue(*subscription);
+ if (current_value != new_value)
+ callbacks.push_back(base::Bind(subscription->callback, new_value));
+ }
+ for (const auto& callback : callbacks)
+ callback.Run();
+}
int PermissionControllerImpl::RequestPermission(
PermissionType permission,
@@ -34,6 +120,12 @@ int PermissionControllerImpl::RequestPermission(
const GURL& requesting_origin,
bool user_gesture,
const base::Callback<void(blink::mojom::PermissionStatus)>& callback) {
+ auto it = devtools_permission_overrides_.find(requesting_origin.GetOrigin());
+ if (it != devtools_permission_overrides_.end()) {
+ callback.Run(GetPermissionOverrideStatus(it->second, permission));
+ return kNoPendingOperation;
+ }
+
PermissionControllerDelegate* delegate =
browser_context_->GetPermissionControllerDelegate();
if (!delegate) {
@@ -51,6 +143,15 @@ int PermissionControllerImpl::RequestPermissions(
bool user_gesture,
const base::Callback<
void(const std::vector<blink::mojom::PermissionStatus>&)>& callback) {
+ auto it = devtools_permission_overrides_.find(requesting_origin.GetOrigin());
+ if (it != devtools_permission_overrides_.end()) {
+ std::vector<blink::mojom::PermissionStatus> result;
+ for (auto& permission : permissions)
+ result.push_back(GetPermissionOverrideStatus(it->second, permission));
+ callback.Run(result);
+ return kNoPendingOperation;
+ }
+
PermissionControllerDelegate* delegate =
browser_context_->GetPermissionControllerDelegate();
if (!delegate) {
@@ -68,6 +169,10 @@ blink::mojom::PermissionStatus PermissionControllerImpl::GetPermissionStatus(
PermissionType permission,
const GURL& requesting_origin,
const GURL& embedding_origin) {
+ auto it = devtools_permission_overrides_.find(requesting_origin.GetOrigin());
+ if (it != devtools_permission_overrides_.end())
+ return GetPermissionOverrideStatus(it->second, permission);
+
PermissionControllerDelegate* delegate =
browser_context_->GetPermissionControllerDelegate();
if (!delegate)
@@ -81,6 +186,10 @@ PermissionControllerImpl::GetPermissionStatusForFrame(
PermissionType permission,
RenderFrameHost* render_frame_host,
const GURL& requesting_origin) {
+ auto it = devtools_permission_overrides_.find(requesting_origin.GetOrigin());
+ if (it != devtools_permission_overrides_.end())
+ return GetPermissionOverrideStatus(it->second, permission);
+
PermissionControllerDelegate* delegate =
browser_context_->GetPermissionControllerDelegate();
if (!delegate)
@@ -99,26 +208,67 @@ void PermissionControllerImpl::ResetPermission(PermissionType permission,
delegate->ResetPermission(permission, requesting_origin, embedding_origin);
}
+void PermissionControllerImpl::OnDelegatePermissionStatusChange(
+ Subscription* subscription,
+ blink::mojom::PermissionStatus status) {
+ auto overrides_it =
+ devtools_permission_overrides_.find(subscription->requesting_origin);
+ if (overrides_it == devtools_permission_overrides_.end())
+ subscription->callback.Run(status);
+}
+
int PermissionControllerImpl::SubscribePermissionStatusChange(
PermissionType permission,
+ RenderFrameHost* render_frame_host,
const GURL& requesting_origin,
- const GURL& embedding_origin,
const base::Callback<void(blink::mojom::PermissionStatus)>& callback) {
+ auto subscription = std::make_unique<Subscription>();
+ subscription->permission = permission;
+ subscription->callback = callback;
+ subscription->requesting_origin = requesting_origin;
+
+ // The RFH may be null if the request is for a worker.
+ if (render_frame_host) {
+ content::WebContents* web_contents =
+ content::WebContents::FromRenderFrameHost(render_frame_host);
+ subscription->embedding_origin =
+ web_contents->GetLastCommittedURL().GetOrigin();
+ subscription->render_frame_id = render_frame_host->GetRoutingID();
+ subscription->render_process_id = render_frame_host->GetProcess()->GetID();
+ } else {
+ subscription->embedding_origin = requesting_origin;
+ subscription->render_frame_id = -1;
+ subscription->render_process_id = -1;
+ }
+
PermissionControllerDelegate* delegate =
browser_context_->GetPermissionControllerDelegate();
- if (!delegate)
- return kNoPendingOperation;
- return delegate->SubscribePermissionStatusChange(
- permission, requesting_origin, embedding_origin, callback);
+ if (delegate) {
+ subscription->delegate_subscription_id =
+ delegate->SubscribePermissionStatusChange(
+ permission, render_frame_host, requesting_origin,
+ base::Bind(
+ &PermissionControllerImpl::OnDelegatePermissionStatusChange,
+ base::Unretained(this), subscription.get()));
+ } else {
+ subscription->delegate_subscription_id = kNoPendingOperation;
+ }
+ return subscriptions_.Add(std::move(subscription));
}
void PermissionControllerImpl::UnsubscribePermissionStatusChange(
int subscription_id) {
+ Subscription* subscription = subscriptions_.Lookup(subscription_id);
+ if (!subscription)
+ return;
PermissionControllerDelegate* delegate =
browser_context_->GetPermissionControllerDelegate();
- if (!delegate)
- return;
- delegate->UnsubscribePermissionStatusChange(subscription_id);
+ if (delegate &&
+ subscription->delegate_subscription_id != kNoPendingOperation) {
+ delegate->UnsubscribePermissionStatusChange(
+ subscription->delegate_subscription_id);
+ }
+ subscriptions_.Remove(subscription_id);
}
} // namespace content
diff --git a/chromium/content/browser/permissions/permission_controller_impl.h b/chromium/content/browser/permissions/permission_controller_impl.h
index 460f033513a..f6f0c2cec62 100644
--- a/chromium/content/browser/permissions/permission_controller_impl.h
+++ b/chromium/content/browser/permissions/permission_controller_impl.h
@@ -5,8 +5,10 @@
#ifndef CONTENT_BROWSER_PERMISSIONS_PERMISSION_CONTROLLER_IMPL_H_
#define CONTENT_BROWSER_PERMISSIONS_PERMISSION_CONTROLLER_IMPL_H_
+#include "base/containers/id_map.h"
#include "content/common/content_export.h"
#include "content/public/browser/permission_controller.h"
+#include "url/gurl.h"
namespace content {
@@ -23,6 +25,13 @@ class CONTENT_EXPORT PermissionControllerImpl : public PermissionController {
static PermissionControllerImpl* FromBrowserContext(
BrowserContext* browser_context);
+ using PermissionOverrides = std::set<PermissionType>;
+ // For the given |origin|, grant permissions that belong to |overrides|
+ // and reject all others.
+ void SetPermissionOverridesForDevTools(const GURL& origin,
+ const PermissionOverrides& overrides);
+ void ResetPermissionOverridesForDevTools();
+
// PermissionController implementation.
blink::mojom::PermissionStatus GetPermissionStatus(
PermissionType permission,
@@ -55,13 +64,23 @@ class CONTENT_EXPORT PermissionControllerImpl : public PermissionController {
int SubscribePermissionStatusChange(
PermissionType permission,
+ RenderFrameHost* render_frame_host,
const GURL& requesting_origin,
- const GURL& embedding_origin,
const base::Callback<void(blink::mojom::PermissionStatus)>& callback);
void UnsubscribePermissionStatusChange(int subscription_id);
private:
+ struct Subscription;
+ using SubscriptionsMap = base::IDMap<std::unique_ptr<Subscription>>;
+
+ blink::mojom::PermissionStatus GetSubscriptionCurrentValue(
+ const Subscription& subscription);
+ void OnDelegatePermissionStatusChange(Subscription* subscription,
+ blink::mojom::PermissionStatus status);
+
+ std::map<GURL, PermissionOverrides> devtools_permission_overrides_;
+ SubscriptionsMap subscriptions_;
BrowserContext* browser_context_;
DISALLOW_COPY_AND_ASSIGN(PermissionControllerImpl);
diff --git a/chromium/content/browser/permissions/permission_service_context.cc b/chromium/content/browser/permissions/permission_service_context.cc
index 05cd21bd9ec..e644dd07580 100644
--- a/chromium/content/browser/permissions/permission_service_context.cc
+++ b/chromium/content/browser/permissions/permission_service_context.cc
@@ -97,15 +97,10 @@ void PermissionServiceContext::CreateSubscription(
auto subscription =
std::make_unique<PermissionSubscription>(this, std::move(observer));
GURL requesting_origin(origin.Serialize());
- GURL embedding_origin = GetEmbeddingOrigin();
int subscription_id =
PermissionControllerImpl::FromBrowserContext(browser_context)
->SubscribePermissionStatusChange(
- permission_type, requesting_origin,
- // If the embedding_origin is empty, we'll use the |origin|
- // instead.
- embedding_origin.is_empty() ? requesting_origin
- : embedding_origin,
+ permission_type, render_frame_host_, requesting_origin,
base::Bind(&PermissionSubscription::OnPermissionStatusChanged,
base::Unretained(subscription.get())));
subscription->set_id(subscription_id);
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 2dfc189cf09..ba0270dd8d3 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
@@ -16,8 +16,6 @@
namespace content {
-DEFINE_WEB_CONTENTS_USER_DATA_KEY(PictureInPictureWindowControllerImpl);
-
// static
PictureInPictureWindowController*
PictureInPictureWindowController::GetOrCreateForWebContents(
@@ -48,7 +46,8 @@ PictureInPictureWindowControllerImpl::~PictureInPictureWindowControllerImpl() {
return;
initiator_->SetHasPictureInPictureVideo(false);
- OnLeavingPictureInPicture(true /* should_pause_video */);
+ OnLeavingPictureInPicture(true /* should_pause_video */,
+ true /* should_reset_pip_player */);
}
PictureInPictureWindowControllerImpl::PictureInPictureWindowControllerImpl(
@@ -82,18 +81,26 @@ void PictureInPictureWindowControllerImpl::ClickCustomControl(
media_player_id_->delegate_id, control_id));
}
-void PictureInPictureWindowControllerImpl::Close(bool should_pause_video) {
+void PictureInPictureWindowControllerImpl::SetPictureInPictureCustomControls(
+ const std::vector<blink::PictureInPictureControlInfo>& controls) {
+ DCHECK(window_);
+ window_->SetPictureInPictureCustomControls(controls);
+}
+
+void PictureInPictureWindowControllerImpl::Close(bool should_pause_video,
+ bool should_reset_pip_player) {
if (!window_ || !window_->IsVisible())
return;
window_->Hide();
- CloseInternal(should_pause_video);
+ CloseInternal(should_pause_video, should_reset_pip_player);
}
void PictureInPictureWindowControllerImpl::OnWindowDestroyed() {
window_ = nullptr;
embedder_ = nullptr;
- CloseInternal(true /* should_pause_video */);
+ CloseInternal(true /* should_pause_video */,
+ true /* should_reset_pip_player */);
}
void PictureInPictureWindowControllerImpl::EmbedSurface(
@@ -125,7 +132,7 @@ OverlayWindow* PictureInPictureWindowControllerImpl::GetWindowForTesting() {
}
void PictureInPictureWindowControllerImpl::UpdateLayerBounds() {
- if (window_ && window_->IsVisible()) {
+ if (media_player_id_.has_value() && window_ && window_->IsVisible()) {
media_web_contents_observer_->OnPictureInPictureWindowResize(
window_->GetBounds().size());
}
@@ -183,7 +190,8 @@ bool PictureInPictureWindowControllerImpl::TogglePlayPause() {
}
void PictureInPictureWindowControllerImpl::OnLeavingPictureInPicture(
- bool should_pause_video) {
+ bool should_pause_video,
+ bool should_reset_pip_player) {
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(
@@ -196,18 +204,21 @@ void PictureInPictureWindowControllerImpl::OnLeavingPictureInPicture(
new MediaPlayerDelegateMsg_EndPictureInPictureMode(
media_player_id_->render_frame_host->GetRoutingID(),
media_player_id_->delegate_id));
+ if (should_reset_pip_player)
+ media_web_contents_observer_->ResetPictureInPictureVideoMediaPlayerId();
}
}
void PictureInPictureWindowControllerImpl::CloseInternal(
- bool should_pause_video) {
+ bool should_pause_video,
+ bool should_reset_pip_player) {
if (initiator_->IsBeingDestroyed())
return;
surface_id_ = viz::SurfaceId();
initiator_->SetHasPictureInPictureVideo(false);
- OnLeavingPictureInPicture(should_pause_video);
+ OnLeavingPictureInPicture(should_pause_video, should_reset_pip_player);
}
void PictureInPictureWindowControllerImpl::EnsureWindow() {
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 7ce6d853fc4..a5c6499509e 100644
--- a/chromium/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.h
+++ b/chromium/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.h
@@ -35,10 +35,13 @@ class PictureInPictureWindowControllerImpl
// PictureInPictureWindowController:
CONTENT_EXPORT gfx::Size Show() override;
- CONTENT_EXPORT void Close(bool should_pause_video) override;
+ CONTENT_EXPORT void Close(bool should_pause_video,
+ bool should_reset_pip_player) override;
CONTENT_EXPORT void OnWindowDestroyed() override;
CONTENT_EXPORT void ClickCustomControl(
const std::string& control_id) override;
+ CONTENT_EXPORT void SetPictureInPictureCustomControls(
+ const std::vector<blink::PictureInPictureControlInfo>& controls) override;
CONTENT_EXPORT void EmbedSurface(const viz::SurfaceId& surface_id,
const gfx::Size& natural_size) override;
CONTENT_EXPORT OverlayWindow* GetWindowForTesting() override;
@@ -58,11 +61,12 @@ class PictureInPictureWindowControllerImpl
WebContents* initiator);
// Signal to the media player that |this| is leaving Picture-in-Picture mode.
- void OnLeavingPictureInPicture(bool should_pause_video);
+ void OnLeavingPictureInPicture(bool should_pause_video,
+ bool should_reset_pip_player);
// Internal method to set the states after the window was closed, whether via
// the system or Chromium.
- void CloseInternal(bool should_pause_video);
+ void CloseInternal(bool should_pause_video, bool should_reset_pip_player);
// Creates a new window if the previous one was destroyed. It can happen
// because of the system control of the window.
diff --git a/chromium/content/browser/plugin_data_remover_impl.cc b/chromium/content/browser/plugin_data_remover_impl.cc
index 9e6ef2a6610..fefc248ddbb 100644
--- a/chromium/content/browser/plugin_data_remover_impl.cc
+++ b/chromium/content/browser/plugin_data_remover_impl.cc
@@ -98,7 +98,7 @@ class PluginDataRemoverImpl::Context
base::FilePath plugin_path = plugins[0].path;
- PepperPluginInfo* pepper_info =
+ const PepperPluginInfo* pepper_info =
plugin_service->GetRegisteredPpapiPluginInfo(plugin_path);
if (!pepper_info) {
event_->Signal();
diff --git a/chromium/content/browser/plugin_service_impl.cc b/chromium/content/browser/plugin_service_impl.cc
index e4e5a87af7e..3a6480c7177 100644
--- a/chromium/content/browser/plugin_service_impl.cc
+++ b/chromium/content/browser/plugin_service_impl.cc
@@ -6,6 +6,7 @@
#include <stddef.h>
+#include <string>
#include <utility>
#include "base/bind.h"
@@ -18,8 +19,8 @@
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/waitable_event.h"
+#include "base/task/post_task.h"
#include "base/task_runner_util.h"
-#include "base/task_scheduler/post_task.h"
#include "base/threading/thread.h"
#include "build/build_config.h"
#include "content/browser/ppapi_plugin_process_host.h"
@@ -40,6 +41,7 @@
#include "content/public/common/content_switches.h"
#include "content/public/common/process_type.h"
#include "content/public/common/webplugininfo.h"
+#include "ppapi/shared_impl/ppapi_permissions.h"
#include "services/metrics/public/cpp/ukm_builders.h"
namespace content {
@@ -172,13 +174,28 @@ PpapiPluginProcessHost* PluginServiceImpl::FindOrStartPpapiPluginProcess(
}
// Validate that the plugin is actually registered.
- PepperPluginInfo* info = GetRegisteredPpapiPluginInfo(plugin_path);
+ const PepperPluginInfo* info = GetRegisteredPpapiPluginInfo(plugin_path);
if (!info) {
VLOG(1) << "Unable to find ppapi plugin registration for: "
<< plugin_path.MaybeAsASCII();
return nullptr;
}
+ // Flash has its own flavour of CORS, so CORB needs to allow all responses
+ // and rely on Flash to enforce same-origin policy. See also
+ // https://crbug.com/874515 and https://crbug.com/816318#c5.
+ //
+ // Note that ppapi::PERMISSION_FLASH is present not only in the Flash plugin.
+ // This permission is also present in plugins added from the cmdline and so
+ // will be also present for "PPAPI Tests" plugin used for
+ // OutOfProcessPPAPITest.URLLoaderTrusted and related tests.
+ //
+ // TODO(lukasza, laforge): https://crbug.com/702995: Remove the code below
+ // once Flash support is removed from Chromium (probably around 2020 - see
+ // https://www.chromium.org/flash-roadmap).
+ if (info->permissions & ppapi::PERMISSION_FLASH)
+ RenderProcessHostImpl::AddCorbExceptionForPlugin(render_process_id);
+
PpapiPluginProcessHost* plugin_host =
FindPpapiPluginProcess(plugin_path, profile_data_directory, origin_lock);
if (plugin_host)
@@ -224,12 +241,11 @@ PpapiPluginProcessHost* PluginServiceImpl::FindOrStartPpapiBrokerProcess(
return plugin_host;
// Validate that the plugin is actually registered.
- PepperPluginInfo* info = GetRegisteredPpapiPluginInfo(plugin_path);
+ const PepperPluginInfo* info = GetRegisteredPpapiPluginInfo(plugin_path);
if (!info)
return nullptr;
- // TODO(ddorwin): Uncomment once out of process is supported.
- // DCHECK(info->is_out_of_process);
+ DCHECK(info->is_out_of_process);
// This broker isn't loaded by any broker process, so create a new process.
return PpapiPluginProcessHost::CreateBrokerHost(*info);
@@ -317,11 +333,9 @@ bool PluginServiceImpl::GetPluginInfoByPath(const base::FilePath& plugin_path,
std::vector<WebPluginInfo> plugins;
PluginList::Singleton()->GetPluginsNoRefresh(&plugins);
- for (std::vector<WebPluginInfo>::iterator it = plugins.begin();
- it != plugins.end();
- ++it) {
- if (it->path == plugin_path) {
- *info = *it;
+ for (const WebPluginInfo& plugin : plugins) {
+ if (plugin.path == plugin_path) {
+ *info = plugin;
return true;
}
}
@@ -339,11 +353,11 @@ base::string16 PluginServiceImpl::GetPluginDisplayNameByPath(
#if defined(OS_MACOSX)
// Many plugins on the Mac have .plugin in the actual name, which looks
// terrible, so look for that and strip it off if present.
- const std::string kPluginExtension = ".plugin";
+ static const char kPluginExtension[] = ".plugin";
if (base::EndsWith(plugin_name, base::ASCIIToUTF16(kPluginExtension),
base::CompareCase::SENSITIVE))
- plugin_name.erase(plugin_name.length() - kPluginExtension.length());
-#endif // OS_MACOSX
+ plugin_name.erase(plugin_name.length() - strlen(kPluginExtension));
+#endif // defined(OS_MACOSX)
}
return plugin_name;
}
@@ -360,18 +374,18 @@ void PluginServiceImpl::GetPlugins(GetPluginsCallback callback) {
void PluginServiceImpl::RegisterPepperPlugins() {
ComputePepperPluginList(&ppapi_plugins_);
- for (size_t i = 0; i < ppapi_plugins_.size(); ++i) {
- RegisterInternalPlugin(ppapi_plugins_[i].ToWebPluginInfo(), true);
- }
+ for (const auto& plugin : ppapi_plugins_)
+ RegisterInternalPlugin(plugin.ToWebPluginInfo(), /*add_at_beginning=*/true);
}
// There should generally be very few plugins so a brute-force search is fine.
-PepperPluginInfo* PluginServiceImpl::GetRegisteredPpapiPluginInfo(
+const PepperPluginInfo* PluginServiceImpl::GetRegisteredPpapiPluginInfo(
const base::FilePath& plugin_path) {
- for (size_t i = 0; i < ppapi_plugins_.size(); ++i) {
- if (ppapi_plugins_[i].path == plugin_path)
- return &ppapi_plugins_[i];
+ for (auto& plugin : ppapi_plugins_) {
+ if (plugin.path == plugin_path)
+ return &plugin;
}
+
// We did not find the plugin in our list. But wait! the plugin can also
// be a latecomer, as it happens with pepper flash. This information
// can be obtained from the PluginList singleton and we can use it to
diff --git a/chromium/content/browser/plugin_service_impl.h b/chromium/content/browser/plugin_service_impl.h
index 4e11056a3dc..cb19abcd26b 100644
--- a/chromium/content/browser/plugin_service_impl.h
+++ b/chromium/content/browser/plugin_service_impl.h
@@ -35,14 +35,6 @@
#include "url/gurl.h"
#include "url/origin.h"
-#if defined(OS_WIN)
-#include "base/win/registry.h"
-#endif
-
-#if defined(OS_POSIX) && !defined(OS_OPENBSD) && !defined(OS_ANDROID)
-#include "base/files/file_path_watcher.h"
-#endif
-
namespace content {
class BrowserContext;
class PluginServiceFilter;
@@ -76,7 +68,7 @@ class CONTENT_EXPORT PluginServiceImpl : public PluginService {
base::string16 GetPluginDisplayNameByPath(
const base::FilePath& path) override;
void GetPlugins(GetPluginsCallback callback) override;
- PepperPluginInfo* GetRegisteredPpapiPluginInfo(
+ const PepperPluginInfo* GetRegisteredPpapiPluginInfo(
const base::FilePath& plugin_path) override;
void SetFilter(PluginServiceFilter* filter) override;
PluginServiceFilter* GetFilter() override;
@@ -139,10 +131,6 @@ class CONTENT_EXPORT PluginServiceImpl : public PluginService {
PluginServiceImpl();
~PluginServiceImpl() override;
-#if defined(OS_WIN)
- void OnKeyChanged(base::win::RegKey* key);
-#endif
-
// Returns the plugin process host corresponding to the plugin process that
// has been started by this service. Returns NULL if no process has been
// started.
@@ -155,9 +143,6 @@ class CONTENT_EXPORT PluginServiceImpl : public PluginService {
void RegisterPepperPlugins();
- // Loads the plugins synchronously in a thread pool.
- std::vector<WebPluginInfo> GetPluginsInternal();
-
std::vector<PepperPluginInfo> ppapi_plugins_;
int max_ppapi_processes_per_profile_ = kDefaultMaxPpapiProcessesPerProfile;
diff --git a/chromium/content/browser/plugin_service_impl_unittest.cc b/chromium/content/browser/plugin_service_impl_unittest.cc
index ed9ec8c472b..6156e81e944 100644
--- a/chromium/content/browser/plugin_service_impl_unittest.cc
+++ b/chromium/content/browser/plugin_service_impl_unittest.cc
@@ -8,7 +8,6 @@
#include "build/build_config.h"
#include "components/ukm/test_ukm_recorder.h"
-#include "components/ukm/ukm_source.h"
#include "content/browser/ppapi_plugin_process_host.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_thread.h"
@@ -18,6 +17,7 @@
#include "content/public/test/navigation_simulator.h"
#include "content/public/test/test_renderer_host.h"
#include "content/public/test/test_utils.h"
+#include "services/metrics/public/cpp/ukm_source.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
diff --git a/chromium/content/browser/pointer_lock_browsertest.cc b/chromium/content/browser/pointer_lock_browsertest.cc
index b4f10231ad3..d6eaf149a84 100644
--- a/chromium/content/browser/pointer_lock_browsertest.cc
+++ b/chromium/content/browser/pointer_lock_browsertest.cc
@@ -125,41 +125,27 @@ IN_PROC_BROWSER_TEST_F(PointerLockBrowserTest, PointerLock) {
FrameTreeNode* child = root->child_at(0);
// Request a pointer lock on the root frame's body.
- EXPECT_TRUE(ExecuteScript(root, "document.body.requestPointerLock()"));
+ EXPECT_TRUE(ExecJs(root, "document.body.requestPointerLock()"));
// Root frame should have been granted pointer lock.
- bool locked = false;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(root,
- "window.domAutomationController.send("
- "document.pointerLockElement == "
- "document.body);",
- &locked));
- EXPECT_TRUE(locked);
+ EXPECT_EQ(true, EvalJs(root, "document.pointerLockElement == document.body"));
// Request a pointer lock on the child frame's body.
- EXPECT_TRUE(ExecuteScript(child, "document.body.requestPointerLock()"));
+ EXPECT_TRUE(ExecJs(child, "document.body.requestPointerLock()"));
// Child frame should not be granted pointer lock since the root frame has it.
- EXPECT_TRUE(ExecuteScriptAndExtractBool(child,
- "window.domAutomationController.send("
- "document.pointerLockElement == "
- "document.body);",
- &locked));
- EXPECT_FALSE(locked);
+ EXPECT_EQ(false,
+ EvalJs(child, "document.pointerLockElement == document.body"));
// Release pointer lock on root frame.
- EXPECT_TRUE(ExecuteScript(root, "document.exitPointerLock()"));
+ EXPECT_TRUE(ExecJs(root, "document.exitPointerLock()"));
// Request a pointer lock on the child frame's body.
- EXPECT_TRUE(ExecuteScript(child, "document.body.requestPointerLock()"));
+ EXPECT_TRUE(ExecJs(child, "document.body.requestPointerLock()"));
// Child frame should have been granted pointer lock.
- EXPECT_TRUE(ExecuteScriptAndExtractBool(child,
- "window.domAutomationController.send("
- "document.pointerLockElement == "
- "document.body);",
- &locked));
- EXPECT_TRUE(locked);
+ EXPECT_EQ(true,
+ EvalJs(child, "document.pointerLockElement == document.body"));
}
IN_PROC_BROWSER_TEST_F(PointerLockBrowserTest, PointerLockEventRouting) {
@@ -179,19 +165,13 @@ IN_PROC_BROWSER_TEST_F(PointerLockBrowserTest, PointerLockEventRouting) {
WaitForHitTestDataOrChildSurfaceReady(child->current_frame_host());
// Request a pointer lock on the root frame's body.
- EXPECT_TRUE(ExecuteScript(root, "document.body.requestPointerLock()"));
+ EXPECT_TRUE(ExecJs(root, "document.body.requestPointerLock()"));
// Root frame should have been granted pointer lock.
- bool locked = false;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(root,
- "window.domAutomationController.send("
- "document.pointerLockElement == "
- "document.body);",
- &locked));
- EXPECT_TRUE(locked);
+ EXPECT_EQ(true, EvalJs(root, "document.pointerLockElement == document.body"));
// Add a mouse move event listener to the root frame.
- EXPECT_TRUE(ExecuteScript(
+ EXPECT_TRUE(ExecJs(
root,
"var x; var y; var mX; var mY; document.addEventListener('mousemove', "
"function(e) {x = e.x; y = e.y; mX = e.movementX; mY = e.movementY;});"));
@@ -208,36 +188,20 @@ IN_PROC_BROWSER_TEST_F(PointerLockBrowserTest, PointerLockEventRouting) {
MainThreadFrameObserver root_observer(root_view->GetRenderWidgetHost());
root_observer.Wait();
- int x, y, movementX, movementY;
- EXPECT_TRUE(ExecuteScriptAndExtractInt(
- root, "window.domAutomationController.send(x);", &x));
- EXPECT_TRUE(ExecuteScriptAndExtractInt(
- root, "window.domAutomationController.send(y);", &y));
- EXPECT_TRUE(ExecuteScriptAndExtractInt(
- root, "window.domAutomationController.send(mX);", &movementX));
- EXPECT_TRUE(ExecuteScriptAndExtractInt(
- root, "window.domAutomationController.send(mY);", &movementY));
- EXPECT_EQ(10, x);
- EXPECT_EQ(11, y);
- EXPECT_EQ(12, movementX);
- EXPECT_EQ(13, movementY);
+ EXPECT_EQ("[10,11,12,13]", EvalJs(root, "JSON.stringify([x,y,mX,mY])"));
// Release pointer lock on root frame.
- EXPECT_TRUE(ExecuteScript(root, "document.exitPointerLock()"));
+ EXPECT_TRUE(ExecJs(root, "document.exitPointerLock()"));
// Request a pointer lock on the child frame's body.
- EXPECT_TRUE(ExecuteScript(child, "document.body.requestPointerLock()"));
+ EXPECT_TRUE(ExecJs(child, "document.body.requestPointerLock()"));
// Child frame should have been granted pointer lock.
- EXPECT_TRUE(ExecuteScriptAndExtractBool(child,
- "window.domAutomationController.send("
- "document.pointerLockElement == "
- "document.body);",
- &locked));
- EXPECT_TRUE(locked);
+ EXPECT_EQ(true,
+ EvalJs(child, "document.pointerLockElement == document.body"));
// Add a mouse move event listener to the child frame.
- EXPECT_TRUE(ExecuteScript(
+ EXPECT_TRUE(ExecJs(
child,
"var x; var y; var mX; var mY; document.addEventListener('mousemove', "
"function(e) {x = e.x; y = e.y; mX = e.movementX; mY = e.movementY;});"));
@@ -259,18 +223,7 @@ IN_PROC_BROWSER_TEST_F(PointerLockBrowserTest, PointerLockEventRouting) {
MainThreadFrameObserver child_observer(child_view->GetRenderWidgetHost());
child_observer.Wait();
- EXPECT_TRUE(ExecuteScriptAndExtractInt(
- child, "window.domAutomationController.send(x);", &x));
- EXPECT_TRUE(ExecuteScriptAndExtractInt(
- child, "window.domAutomationController.send(y);", &y));
- EXPECT_TRUE(ExecuteScriptAndExtractInt(
- child, "window.domAutomationController.send(mX);", &movementX));
- EXPECT_TRUE(ExecuteScriptAndExtractInt(
- child, "window.domAutomationController.send(mY);", &movementY));
- EXPECT_EQ(14, x);
- EXPECT_EQ(15, y);
- EXPECT_EQ(16, movementX);
- EXPECT_EQ(17, movementY);
+ EXPECT_EQ("[14,15,16,17]", EvalJs(child, "JSON.stringify([x,y,mX,mY])"));
}
// Tests that the browser will not unlock the pointer if a RenderWidgetHostView
@@ -283,16 +236,10 @@ IN_PROC_BROWSER_TEST_F(PointerLockBrowserTest, PointerLockChildFrameDetached) {
FrameTreeNode* root = web_contents()->GetFrameTree()->root();
// Request a pointer lock on the root frame's body.
- EXPECT_TRUE(ExecuteScript(root, "document.body.requestPointerLock()"));
+ EXPECT_TRUE(ExecJs(root, "document.body.requestPointerLock()"));
// Root frame should have been granted pointer lock.
- bool locked = false;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(root,
- "window.domAutomationController.send("
- "document.pointerLockElement == "
- "document.body);",
- &locked));
- EXPECT_TRUE(locked);
+ EXPECT_EQ(true, EvalJs(root, "document.pointerLockElement == document.body"));
// Root (platform) RenderWidgetHostView should have the pointer locked.
EXPECT_TRUE(root->current_frame_host()->GetView()->IsMouseLocked());
@@ -300,7 +247,7 @@ IN_PROC_BROWSER_TEST_F(PointerLockBrowserTest, PointerLockChildFrameDetached) {
web_contents()->GetMouseLockWidget());
// Detach the child frame.
- EXPECT_TRUE(ExecuteScript(root, "document.querySelector('iframe').remove()"));
+ EXPECT_TRUE(ExecJs(root, "document.querySelector('iframe').remove()"));
// Root (platform) RenderWidgetHostView should still have the pointer locked.
EXPECT_TRUE(root->current_frame_host()->GetView()->IsMouseLocked());
@@ -333,21 +280,13 @@ IN_PROC_BROWSER_TEST_F(PointerLockBrowserTest,
"c.com", "/cross_site_iframe_factory.html?c(d)")));
// Request a pointer lock to the inner WebContents's document.body.
- std::string result;
- EXPECT_TRUE(ExecuteScriptAndExtractString(inner_contents->GetMainFrame(), R"(
- (new Promise((resolve, reject) => {
+ EXPECT_EQ("success", EvalJs(inner_contents->GetMainFrame(), R"(
+ new Promise((resolve, reject) => {
document.addEventListener('pointerlockchange', resolve);
document.addEventListener('pointerlockerror', reject);
- }).then(() => {
- window.domAutomationController.send(
- (document.pointerLockElement == document.body) ?
- "success" : "error");
- }).catch(error => {
- window.domAutomationController.send("" + error);
- }));
- document.body.requestPointerLock();)",
- &result));
- EXPECT_EQ("success", result);
+ document.body.requestPointerLock();
+ }).then(() => 'success');
+ )"));
// Root (platform) RenderWidgetHostView should have the pointer locked.
EXPECT_TRUE(root->current_frame_host()->GetView()->IsMouseLocked());
@@ -397,21 +336,15 @@ IN_PROC_BROWSER_TEST_F(PointerLockBrowserTest, PointerLockWheelEventRouting) {
WaitForHitTestDataOrChildSurfaceReady(child->current_frame_host());
// Request a pointer lock on the root frame's body.
- EXPECT_TRUE(ExecuteScript(root, "document.body.requestPointerLock()"));
+ EXPECT_TRUE(ExecJs(root, "document.body.requestPointerLock()"));
// Root frame should have been granted pointer lock.
- bool locked = false;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(root,
- "window.domAutomationController.send("
- "document.pointerLockElement == "
- "document.body);",
- &locked));
- EXPECT_TRUE(locked);
+ EXPECT_EQ(true, EvalJs(root, "document.pointerLockElement == document.body"));
// Add a mouse move wheel event listener to the root frame.
- EXPECT_TRUE(ExecuteScript(
+ EXPECT_TRUE(ExecJs(
root,
- "var x; var y; var mX; var mY; document.addEventListener('mousewheel', "
+ "var x; var y; var dX; var dY; document.addEventListener('mousewheel', "
"function(e) {x = e.x; y = e.y; dX = e.deltaX; dY = e.deltaY;});"));
MainThreadFrameObserver root_observer(root_view->GetRenderWidgetHost());
root_observer.Wait();
@@ -439,38 +372,22 @@ IN_PROC_BROWSER_TEST_F(PointerLockBrowserTest, PointerLockWheelEventRouting) {
// Make sure that the renderer handled the input event.
root_observer.Wait();
- int x, y, deltaX, deltaY;
- EXPECT_TRUE(ExecuteScriptAndExtractInt(
- root, "window.domAutomationController.send(x);", &x));
- EXPECT_TRUE(ExecuteScriptAndExtractInt(
- root, "window.domAutomationController.send(y);", &y));
- EXPECT_TRUE(ExecuteScriptAndExtractInt(
- root, "window.domAutomationController.send(dX);", &deltaX));
- EXPECT_TRUE(ExecuteScriptAndExtractInt(
- root, "window.domAutomationController.send(dY);", &deltaY));
- EXPECT_EQ(10, x);
- EXPECT_EQ(11, y);
- EXPECT_EQ(12, deltaX);
- EXPECT_EQ(13, deltaY);
+ EXPECT_EQ("[10,11,12,13]", EvalJs(root, "JSON.stringify([x, y, dX, dY])"));
// Release pointer lock on root frame.
- EXPECT_TRUE(ExecuteScript(root, "document.exitPointerLock()"));
+ EXPECT_TRUE(ExecJs(root, "document.exitPointerLock()"));
// Request a pointer lock on the child frame's body.
- EXPECT_TRUE(ExecuteScript(child, "document.body.requestPointerLock()"));
+ EXPECT_TRUE(ExecJs(child, "document.body.requestPointerLock()"));
// Child frame should have been granted pointer lock.
- EXPECT_TRUE(ExecuteScriptAndExtractBool(child,
- "window.domAutomationController.send("
- "document.pointerLockElement == "
- "document.body);",
- &locked));
- EXPECT_TRUE(locked);
+ EXPECT_EQ(true,
+ EvalJs(child, "document.pointerLockElement == document.body"));
// Add a mouse move event listener to the child frame.
- EXPECT_TRUE(ExecuteScript(
+ EXPECT_TRUE(ExecJs(
child,
- "var x; var y; var mX; var mY; document.addEventListener('mousewheel', "
+ "var x; var y; var dX; var dY; document.addEventListener('mousewheel', "
"function(e) {x = e.x; y = e.y; dX = e.deltaX; dY = e.deltaY;});"));
MainThreadFrameObserver child_observer(child_view->GetRenderWidgetHost());
child_observer.Wait();
@@ -492,18 +409,7 @@ IN_PROC_BROWSER_TEST_F(PointerLockBrowserTest, PointerLockWheelEventRouting) {
// Make sure that the renderer handled the input event.
child_observer.Wait();
- EXPECT_TRUE(ExecuteScriptAndExtractInt(
- child, "window.domAutomationController.send(x);", &x));
- EXPECT_TRUE(ExecuteScriptAndExtractInt(
- child, "window.domAutomationController.send(y);", &y));
- EXPECT_TRUE(ExecuteScriptAndExtractInt(
- child, "window.domAutomationController.send(dX);", &deltaX));
- EXPECT_TRUE(ExecuteScriptAndExtractInt(
- child, "window.domAutomationController.send(dY);", &deltaY));
- EXPECT_EQ(14, x);
- EXPECT_EQ(15, y);
- EXPECT_EQ(16, deltaX);
- EXPECT_EQ(17, deltaY);
+ EXPECT_EQ("[14,15,16,17]", EvalJs(child, "JSON.stringify([x, y, dX, dY])"));
}
IN_PROC_BROWSER_TEST_F(PointerLockBrowserTest, PointerLockWidgetHidden) {
@@ -519,16 +425,11 @@ IN_PROC_BROWSER_TEST_F(PointerLockBrowserTest, PointerLockWidgetHidden) {
WaitForHitTestDataOrChildSurfaceReady(child->current_frame_host());
// Request a pointer lock on the child frame's body.
- EXPECT_TRUE(ExecuteScript(child, "document.body.requestPointerLock()"));
+ EXPECT_TRUE(ExecJs(child, "document.body.requestPointerLock()"));
// Child frame should have been granted pointer lock.
- bool locked = false;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(child,
- "window.domAutomationController.send("
- "document.pointerLockElement == "
- "document.body);",
- &locked));
- EXPECT_TRUE(locked);
+ EXPECT_EQ(true,
+ EvalJs(child, "document.pointerLockElement == document.body"));
EXPECT_TRUE(child_view->IsMouseLocked());
EXPECT_EQ(child_view->host(), web_contents()->GetMouseLockWidget());
diff --git a/chromium/content/browser/portal/portal.cc b/chromium/content/browser/portal/portal.cc
new file mode 100644
index 00000000000..14430222d47
--- /dev/null
+++ b/chromium/content/browser/portal/portal.cc
@@ -0,0 +1,77 @@
+// 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/portal/portal.h"
+
+#include "base/feature_list.h"
+#include "base/memory/ptr_util.h"
+#include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/public/browser/navigation_controller.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/common/content_switches.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "third_party/blink/public/common/features.h"
+
+namespace content {
+
+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::~Portal() {}
+
+// static
+bool Portal::IsEnabled() {
+ return base::FeatureList::IsEnabled(blink::features::kPortals) ||
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableExperimentalWebPlatformFeatures);
+}
+
+// static
+Portal* Portal::Create(RenderFrameHostImpl* owner_render_frame_host,
+ blink::mojom::PortalRequest request) {
+ auto portal_ptr = base::WrapUnique(new Portal(owner_render_frame_host));
+ Portal* portal = portal_ptr.get();
+ portal->binding_ =
+ mojo::MakeStrongBinding(std::move(portal_ptr), std::move(request));
+ return portal;
+}
+
+// static
+std::unique_ptr<Portal> Portal::CreateForTesting(
+ RenderFrameHostImpl* owner_render_frame_host) {
+ return base::WrapUnique(new Portal(owner_render_frame_host));
+}
+
+void Portal::Init(
+ base::OnceCallback<void(const base::UnguessableToken&)> callback) {
+ std::move(callback).Run(portal_token_);
+ WebContents::CreateParams params(
+ WebContents::FromRenderFrameHost(owner_render_frame_host_)
+ ->GetBrowserContext());
+ portal_contents_ = WebContents::Create(params);
+}
+
+void Portal::Navigate(const GURL& url) {
+ NavigationController::LoadURLParams load_url_params(url);
+ portal_contents_->GetController().LoadURLWithParams(load_url_params);
+}
+
+void Portal::RenderFrameDeleted(RenderFrameHost* render_frame_host) {
+ if (render_frame_host == owner_render_frame_host_)
+ binding_->Close(); // Also deletes |this|.
+}
+
+WebContents* Portal::GetPortalContents() {
+ return portal_contents_.get();
+}
+
+void Portal::SetBindingForTesting(
+ mojo::StrongBindingPtr<blink::mojom::Portal> binding) {
+ binding_ = binding;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/portal/portal.h b/chromium/content/browser/portal/portal.h
new file mode 100644
index 00000000000..f894cb7d65c
--- /dev/null
+++ b/chromium/content/browser/portal/portal.h
@@ -0,0 +1,78 @@
+// 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_PORTAL_PORTAL_H_
+#define CONTENT_BROWSER_PORTAL_PORTAL_H_
+
+#include <memory>
+
+#include "content/common/content_export.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "third_party/blink/public/mojom/portal/portal.mojom.h"
+
+namespace content {
+
+class RenderFrameHostImpl;
+
+// A Portal provides a way to embed a WebContents inside a frame in another
+// WebContents. It also provides an API that the owning frame can interact with
+// the portal WebContents. The portal can be activated, where the portal
+// WebContents replaces the outer WebContents and inherit it as a new Portal.
+//
+// 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 WebContentsObserver {
+ public:
+ ~Portal() override;
+
+ static bool IsEnabled();
+
+ // Creates a Portal and binds it to the pipe specified in the |request|. This
+ // 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::PortalRequest request);
+
+ // Creates a portal without binding it to any pipe. Only used in tests.
+ static std::unique_ptr<Portal> CreateForTesting(
+ RenderFrameHostImpl* owner_render_frame_host);
+
+ // blink::mojom::Portal implementation.
+ void Init(base::OnceCallback<void(const base::UnguessableToken&)> callback)
+ override;
+ void Navigate(const GURL& url) override;
+
+ // WebContentsObserver overrides.
+ void RenderFrameDeleted(RenderFrameHost* render_frame_host) override;
+
+ // Returns the Portal's WebContents.
+ WebContents* GetPortalContents();
+
+ // Gets/sets the mojo binding. Only used in tests.
+ mojo::StrongBindingPtr<blink::mojom::Portal> GetBindingForTesting() {
+ return binding_;
+ }
+ void SetBindingForTesting(
+ mojo::StrongBindingPtr<blink::mojom::Portal> binding);
+
+ private:
+ explicit Portal(RenderFrameHostImpl* owner_render_frame_host);
+
+ RenderFrameHostImpl* owner_render_frame_host_;
+
+ // Uniquely identifies the portal, this token is used by the browser process
+ // to reference this portal when communicating with the renderer.
+ base::UnguessableToken portal_token_;
+
+ // WeakPtr to StrongBinding.
+ mojo::StrongBindingPtr<blink::mojom::Portal> binding_;
+
+ std::unique_ptr<WebContents> portal_contents_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_PORTAL_PORTAL_H_
diff --git a/chromium/content/browser/portal/portal_browsertest.cc b/chromium/content/browser/portal/portal_browsertest.cc
new file mode 100644
index 00000000000..a9a661e8b7b
--- /dev/null
+++ b/chromium/content/browser/portal/portal_browsertest.cc
@@ -0,0 +1,255 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/test/scoped_feature_list.h"
+#include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/browser/portal/portal.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/public/test/test_navigation_observer.h"
+#include "content/shell/browser/shell.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "net/dns/mock_host_resolver.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "third_party/blink/public/common/features.h"
+#include "third_party/blink/public/mojom/portal/portal.mojom.h"
+#include "url/url_constants.h"
+
+namespace content {
+
+// The PortalInterceptorForTesting can be used in tests to inspect Portal IPCs.
+class PortalInterceptorForTesting final
+ : public blink::mojom::PortalInterceptorForTesting {
+ public:
+ static PortalInterceptorForTesting* Create(
+ RenderFrameHostImpl* render_frame_host_impl,
+ blink::mojom::PortalRequest request);
+ static PortalInterceptorForTesting* From(content::Portal* portal);
+
+ void Init(InitCallback callback) override {
+ portal_->Init(std::move(callback));
+
+ // Init should be called only once.
+ ASSERT_FALSE(portal_initialized_);
+ portal_initialized_ = true;
+
+ if (run_loop_)
+ run_loop_->Quit();
+ }
+
+ void WaitForInit() {
+ if (portal_initialized_)
+ return;
+
+ base::RunLoop run_loop;
+ run_loop_ = &run_loop;
+ run_loop.Run();
+ run_loop_ = nullptr;
+ }
+
+ // Test getters.
+ content::Portal* GetPortal() { return portal_.get(); }
+ WebContents* GetPortalContents() { return portal_->GetPortalContents(); }
+
+ private:
+ PortalInterceptorForTesting(RenderFrameHostImpl* render_frame_host_impl)
+ : portal_(content::Portal::CreateForTesting(render_frame_host_impl)) {}
+
+ blink::mojom::Portal* GetForwardingInterface() override {
+ return portal_.get();
+ }
+
+ std::unique_ptr<content::Portal> portal_;
+ bool portal_initialized_ = false;
+ base::RunLoop* run_loop_ = nullptr;
+};
+
+// static
+PortalInterceptorForTesting* PortalInterceptorForTesting::Create(
+ RenderFrameHostImpl* render_frame_host_impl,
+ blink::mojom::PortalRequest request) {
+ auto test_portal_ptr =
+ base::WrapUnique(new PortalInterceptorForTesting(render_frame_host_impl));
+ PortalInterceptorForTesting* test_portal = test_portal_ptr.get();
+ test_portal->GetPortal()->SetBindingForTesting(
+ mojo::MakeStrongBinding(std::move(test_portal_ptr), std::move(request)));
+ return test_portal;
+}
+
+// static
+PortalInterceptorForTesting* PortalInterceptorForTesting::From(
+ content::Portal* portal) {
+ blink::mojom::Portal* impl = portal->GetBindingForTesting()->impl();
+ auto* interceptor = static_cast<PortalInterceptorForTesting*>(impl);
+ CHECK_NE(static_cast<blink::mojom::Portal*>(portal), impl);
+ CHECK_EQ(interceptor->GetPortal(), portal);
+ return interceptor;
+}
+
+// The PortalCreatedObserver observes portal creations on
+// |render_frame_host_impl|. This observer can be used to monitor for multiple
+// Portal creations on the same RenderFrameHost, by repeatedly calling
+// WaitUntilPortalCreated().
+//
+// The PortalCreatedObserver replaces the Portal interface in the
+// RenderFrameHosts' BinderRegistry, so when the observer is destroyed the
+// RenderFrameHost is left without an interface and attempts to create the
+// interface will fail.
+class PortalCreatedObserver {
+ public:
+ explicit PortalCreatedObserver(RenderFrameHostImpl* render_frame_host_impl)
+ : render_frame_host_impl_(render_frame_host_impl) {
+ service_manager::BinderRegistry& registry =
+ render_frame_host_impl->BinderRegistryForTesting();
+
+ registry.AddInterface(base::BindRepeating(
+ [](PortalCreatedObserver* observer,
+ RenderFrameHostImpl* render_frame_host_impl,
+ blink::mojom::PortalRequest request) {
+ observer->portal_ = PortalInterceptorForTesting::Create(
+ render_frame_host_impl, std::move(request))
+ ->GetPortal();
+ if (observer->run_loop_)
+ observer->run_loop_->Quit();
+ },
+ base::Unretained(this), base::Unretained(render_frame_host_impl)));
+ }
+
+ ~PortalCreatedObserver() {
+ service_manager::BinderRegistry& registry =
+ render_frame_host_impl_->BinderRegistryForTesting();
+
+ registry.RemoveInterface<Portal>();
+ }
+
+ Portal* WaitUntilPortalCreated() {
+ Portal* portal = portal_;
+ if (portal) {
+ portal_ = nullptr;
+ return portal;
+ }
+
+ base::RunLoop run_loop;
+ run_loop_ = &run_loop;
+ run_loop.Run();
+ run_loop_ = nullptr;
+
+ portal = portal_;
+ portal_ = nullptr;
+ return portal;
+ }
+
+ private:
+ RenderFrameHostImpl* render_frame_host_impl_;
+ base::RunLoop* run_loop_ = nullptr;
+ Portal* portal_ = nullptr;
+};
+
+class PortalBrowserTest : public ContentBrowserTest {
+ protected:
+ PortalBrowserTest() {}
+
+ void SetUp() override {
+ scoped_feature_list_.InitAndEnableFeature(blink::features::kPortals);
+ ContentBrowserTest::SetUp();
+ }
+
+ void SetUpOnMainThread() override {
+ host_resolver()->AddRule("*", "127.0.0.1");
+ ContentBrowserTest::SetUpOnMainThread();
+ ASSERT_TRUE(embedded_test_server()->Start());
+ }
+
+ private:
+ base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+// Tests that the renderer can create a Portal.
+IN_PROC_BROWSER_TEST_F(PortalBrowserTest, CreatePortal) {
+ 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();
+
+ PortalCreatedObserver portal_created_observer(main_frame);
+ EXPECT_TRUE(
+ ExecJs(main_frame,
+ "document.body.appendChild(document.createElement('portal'));"));
+ Portal* portal = portal_created_observer.WaitUntilPortalCreated();
+ EXPECT_NE(nullptr, portal);
+}
+
+// Tests the the renderer can navigate a Portal.
+IN_PROC_BROWSER_TEST_F(PortalBrowserTest, NavigatePortal) {
+ 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();
+
+ PortalCreatedObserver portal_created_observer(main_frame);
+
+ // Tests that a portal can navigate by setting its src before appending it to
+ // the DOM.
+ GURL a_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+ EXPECT_TRUE(
+ ExecJs(main_frame,
+ base::StringPrintf("var portal = document.createElement('portal');"
+ "portal.src = '%s';"
+ "document.body.appendChild(portal);",
+ a_url.spec().c_str())));
+
+ PortalInterceptorForTesting* portal_interceptor =
+ PortalInterceptorForTesting::From(
+ portal_created_observer.WaitUntilPortalCreated());
+ portal_interceptor->WaitForInit();
+ WebContents* portal_contents = portal_interceptor->GetPortalContents();
+ EXPECT_NE(nullptr, portal_contents);
+ EXPECT_NE(portal_contents->GetLastCommittedURL(), a_url);
+
+ // WaitForInit() above only waits for the Portal::Init call, which is when the
+ // Portal's WebContents is created. Portal::Navigate is a diffent IPC, so the
+ // portal should not have navigated yet, and we can observe the Portal's first
+ // navigation.
+ TestNavigationObserver navigation_observer(portal_contents);
+ navigation_observer.Wait();
+ EXPECT_EQ(navigation_observer.last_navigation_url(), a_url);
+ EXPECT_EQ(portal_contents->GetLastCommittedURL(), a_url);
+
+ // Tests that a portal can navigate by setting its src.
+ {
+ TestNavigationObserver navigation_observer(portal_contents);
+
+ GURL b_url(embedded_test_server()->GetURL("b.com", "/title1.html"));
+ EXPECT_TRUE(ExecJs(
+ main_frame,
+ base::StringPrintf("document.querySelector('portal').src = '%s';",
+ b_url.spec().c_str())));
+ navigation_observer.Wait();
+ EXPECT_EQ(navigation_observer.last_navigation_url(), b_url);
+ EXPECT_EQ(portal_contents->GetLastCommittedURL(), b_url);
+ }
+
+ // Tests that a portal can navigating by attribute.
+ {
+ TestNavigationObserver navigation_observer(portal_contents);
+
+ GURL c_url(embedded_test_server()->GetURL("c.com", "/title1.html"));
+ EXPECT_TRUE(ExecJs(
+ main_frame,
+ base::StringPrintf(
+ "document.querySelector('portal').setAttribute('src', '%s');",
+ c_url.spec().c_str())));
+ navigation_observer.Wait();
+ EXPECT_EQ(navigation_observer.last_navigation_url(), c_url);
+ EXPECT_EQ(portal_contents->GetLastCommittedURL(), c_url);
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/browser/portal/portal_unit_test.cc b/chromium/content/browser/portal/portal_unit_test.cc
new file mode 100644
index 00000000000..4f4aea46ada
--- /dev/null
+++ b/chromium/content/browser/portal/portal_unit_test.cc
@@ -0,0 +1,35 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/feature_list.h"
+#include "base/test/scoped_feature_list.h"
+#include "content/browser/portal/portal.h"
+#include "content/test/test_render_frame_host.h"
+#include "content/test/test_render_view_host.h"
+#include "content/test/test_web_contents.h"
+#include "services/service_manager/public/cpp/interface_provider.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/features.h"
+
+namespace content {
+
+class PortalUnitTest : public RenderViewHostImplTestHarness {
+ protected:
+ void SetUp() override {
+ scoped_feature_list_.InitAndEnableFeature(blink::features::kPortals);
+ RenderViewHostImplTestHarness::SetUp();
+ }
+
+ private:
+ base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+TEST_F(PortalUnitTest, InterfaceExists) {
+ ASSERT_TRUE(base::FeatureList::IsEnabled(blink::features::kPortals));
+
+ ASSERT_TRUE(contents()->GetMainFrame()->binder_registry().CanBindInterface(
+ blink::mojom::Portal::Name_));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/ppapi_plugin_process_host.cc b/chromium/content/browser/ppapi_plugin_process_host.cc
index 3cf4e5d1f53..1df1149921b 100644
--- a/chromium/content/browser/ppapi_plugin_process_host.cc
+++ b/chromium/content/browser/ppapi_plugin_process_host.cc
@@ -509,8 +509,8 @@ void PpapiPluginProcessHost::OnRendererPluginChannelCreated(
sent_requests_.pop();
const ChildProcessData& data = process_->GetData();
- client->OnPpapiChannelOpened(channel_handle, base::GetProcId(data.handle),
- data.id);
+ client->OnPpapiChannelOpened(channel_handle,
+ base::GetProcId(data.GetHandle()), data.id);
}
} // namespace content
diff --git a/chromium/content/browser/presentation/OWNERS b/chromium/content/browser/presentation/OWNERS
index 4c81ef2dbac..1a85e3fd162 100644
--- a/chromium/content/browser/presentation/OWNERS
+++ b/chromium/content/browser/presentation/OWNERS
@@ -1,9 +1,4 @@
# Presentation API OWNERS
-#
-# This file also covers ownership of the following directories:
-# //content/common/presentation/
-# //content/renderer/presentation/
-
imcheng@chromium.org
mfoltz@chromium.org
mlamouri@chromium.org
diff --git a/chromium/content/browser/presentation/presentation_service_impl.cc b/chromium/content/browser/presentation/presentation_service_impl.cc
index 321adbda8a1..7d2bd5d9a73 100644
--- a/chromium/content/browser/presentation/presentation_service_impl.cc
+++ b/chromium/content/browser/presentation/presentation_service_impl.cc
@@ -21,7 +21,6 @@
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/frame_navigate_params.h"
-#include "content/public/common/presentation_connection_message.h"
using blink::mojom::PresentationConnectionState;
using blink::mojom::PresentationError;
@@ -46,7 +45,7 @@ int GetNextRequestId() {
void InvokeNewPresentationCallbackWithError(
PresentationServiceImpl::NewPresentationCallback callback) {
std::move(callback).Run(
- PresentationInfoPtr(),
+ /** PresentationConnectionResultPtr */ nullptr,
PresentationError::New(
PresentationErrorType::PREVIOUS_START_IN_PROGRESS,
"There is already an unsettled Promise from a previous call "
@@ -211,7 +210,7 @@ void PresentationServiceImpl::StartPresentation(
DVLOG(2) << "StartPresentation";
if (!controller_delegate_) {
std::move(callback).Run(
- PresentationInfoPtr(),
+ /** PresentationConnectionResultPtr */ nullptr,
PresentationError::New(PresentationErrorType::NO_AVAILABLE_SCREENS,
"No screens found."));
return;
@@ -247,7 +246,7 @@ void PresentationServiceImpl::ReconnectPresentation(
DVLOG(2) << "ReconnectPresentation";
if (!controller_delegate_) {
std::move(callback).Run(
- PresentationInfoPtr(),
+ /** PresentationConnectionResultPtr */ nullptr,
PresentationError::New(PresentationErrorType::NO_PRESENTATION_FOUND,
"Error joining route: No matching route"));
return;
@@ -296,14 +295,15 @@ void PresentationServiceImpl::ListenForConnectionStateChange(
void PresentationServiceImpl::OnStartPresentationSucceeded(
int request_id,
- const PresentationInfo& presentation_info) {
+ blink::mojom::PresentationConnectionResultPtr result) {
if (request_id != start_presentation_request_id_)
return;
- CHECK(pending_start_presentation_cb_.get());
+ auto presentation_info = *result->presentation_info;
+ DCHECK(pending_start_presentation_cb_.get());
DCHECK(presentation_info.id.length() <= kMaxPresentationIdLength);
- pending_start_presentation_cb_->Run(PresentationInfo::New(presentation_info),
- PresentationErrorPtr());
+ pending_start_presentation_cb_->Run(std::move(result),
+ /** PresentationErrorPtr */ nullptr);
ListenForConnectionStateChange(presentation_info);
pending_start_presentation_cb_.reset();
start_presentation_request_id_ = kInvalidRequestId;
@@ -316,19 +316,19 @@ void PresentationServiceImpl::OnStartPresentationError(
return;
CHECK(pending_start_presentation_cb_.get());
- pending_start_presentation_cb_->Run(PresentationInfoPtr(),
- PresentationError::New(error));
+ pending_start_presentation_cb_->Run(
+ /** PresentationConnectionResultPtr */ nullptr,
+ PresentationError::New(error));
pending_start_presentation_cb_.reset();
start_presentation_request_id_ = kInvalidRequestId;
}
void PresentationServiceImpl::OnReconnectPresentationSucceeded(
int request_id,
- const PresentationInfo& presentation_info) {
- DCHECK(presentation_info.id.length() <= kMaxPresentationIdLength);
+ blink::mojom::PresentationConnectionResultPtr result) {
+ auto presentation_info = *result->presentation_info;
if (RunAndEraseReconnectPresentationMojoCallback(
- request_id, PresentationInfo::New(presentation_info),
- PresentationErrorPtr())) {
+ request_id, std::move(result), /** PresentationErrorPtr */ nullptr)) {
ListenForConnectionStateChange(presentation_info);
}
}
@@ -337,19 +337,20 @@ void PresentationServiceImpl::OnReconnectPresentationError(
int request_id,
const blink::mojom::PresentationError& error) {
RunAndEraseReconnectPresentationMojoCallback(
- request_id, PresentationInfoPtr(), PresentationError::New(error));
+ request_id, blink::mojom::PresentationConnectionResultPtr(),
+ PresentationError::New(error));
}
bool PresentationServiceImpl::RunAndEraseReconnectPresentationMojoCallback(
int request_id,
- PresentationInfoPtr presentation_info,
- PresentationErrorPtr error) {
+ blink::mojom::PresentationConnectionResultPtr result,
+ blink::mojom::PresentationErrorPtr error) {
auto it = pending_reconnect_presentation_cbs_.find(request_id);
if (it == pending_reconnect_presentation_cbs_.end())
return false;
DCHECK(it->second.get());
- it->second->Run(std::move(presentation_info), std::move(error));
+ it->second->Run(std::move(result), std::move(error));
pending_reconnect_presentation_cbs_.erase(it);
return true;
}
@@ -428,21 +429,7 @@ PresentationServiceImpl::GetPresentationServiceDelegate() {
: static_cast<PresentationServiceDelegate*>(controller_delegate_);
}
-void PresentationServiceImpl::SetPresentationConnection(
- PresentationInfoPtr presentation_info,
- blink::mojom::PresentationConnectionPtr controller_connection_ptr,
- blink::mojom::PresentationConnectionRequest receiver_connection_request) {
- DVLOG(2) << "SetPresentationConnection";
-
- if (!controller_delegate_)
- return;
-
- controller_delegate_->ConnectToPresentation(
- render_process_id_, render_frame_id_, *presentation_info,
- std::move(controller_connection_ptr),
- std::move(receiver_connection_request));
-}
-
+// TODO(btolsch): Convert to PresentationConnectionResultPtr.
void PresentationServiceImpl::OnReceiverConnectionAvailable(
PresentationInfoPtr presentation_info,
PresentationConnectionPtr controller_connection_ptr,
@@ -503,12 +490,14 @@ void PresentationServiceImpl::OnDelegateDestroyed() {
}
void PresentationServiceImpl::OnDefaultPresentationStarted(
- const PresentationInfo& connection) {
+ blink::mojom::PresentationConnectionResultPtr result) {
+ auto presentation_info = *result->presentation_info;
if (controller_)
- controller_->OnDefaultPresentationStarted(
- PresentationInfo::New(connection));
+ controller_->OnDefaultPresentationStarted(std::move(result));
- ListenForConnectionStateChange(connection);
+ // TODO(btolsch): Remove the state-change API in favor of direct
+ // PresentationConnection state use.
+ ListenForConnectionStateChange(presentation_info);
}
PresentationServiceImpl::ScreenAvailabilityListenerImpl::
@@ -543,7 +532,7 @@ PresentationServiceImpl::NewPresentationCallbackWrapper::
~NewPresentationCallbackWrapper() {
if (!callback_.is_null()) {
std::move(callback_).Run(
- PresentationInfoPtr(),
+ /** PresentationConnectionResultPtr */ nullptr,
PresentationError::New(
PresentationErrorType::PRESENTATION_REQUEST_CANCELLED,
"The frame is navigating or being destroyed."));
@@ -551,10 +540,10 @@ PresentationServiceImpl::NewPresentationCallbackWrapper::
}
void PresentationServiceImpl::NewPresentationCallbackWrapper::Run(
- PresentationInfoPtr presentation_info,
- PresentationErrorPtr error) {
+ blink::mojom::PresentationConnectionResultPtr result,
+ blink::mojom::PresentationErrorPtr error) {
DCHECK(!callback_.is_null());
- std::move(callback_).Run(std::move(presentation_info), std::move(error));
+ std::move(callback_).Run(std::move(result), std::move(error));
}
} // namespace content
diff --git a/chromium/content/browser/presentation/presentation_service_impl.h b/chromium/content/browser/presentation/presentation_service_impl.h
index 333d2ac479c..a9cc97e4a12 100644
--- a/chromium/content/browser/presentation/presentation_service_impl.h
+++ b/chromium/content/browser/presentation/presentation_service_impl.h
@@ -24,12 +24,11 @@
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/frame_navigate_params.h"
#include "mojo/public/cpp/bindings/binding.h"
-#include "third_party/blink/public/platform/modules/presentation/presentation.mojom.h"
+#include "third_party/blink/public/mojom/presentation/presentation.mojom.h"
#include "url/gurl.h"
namespace content {
-struct PresentationConnectionMessage;
class RenderFrameHost;
// Implementation of Mojo PresentationService.
@@ -45,7 +44,6 @@ class RenderFrameHost;
// Create()
// SetClient()
// StartPresentation()
-// SetPresentationConnection()
// ...
// TODO(crbug.com/749327): Split the controller and receiver logic into separate
// classes so that each is easier to reason about.
@@ -55,7 +53,7 @@ class CONTENT_EXPORT PresentationServiceImpl
public PresentationServiceDelegate::Observer {
public:
using NewPresentationCallback =
- base::OnceCallback<void(blink::mojom::PresentationInfoPtr,
+ base::OnceCallback<void(blink::mojom::PresentationConnectionResultPtr,
blink::mojom::PresentationErrorPtr)>;
// Creates a PresentationServiceImpl using the given RenderFrameHost.
@@ -85,11 +83,6 @@ class CONTENT_EXPORT PresentationServiceImpl
const std::string& presentation_id) override;
void Terminate(const GURL& presentation_url,
const std::string& presentation_id) override;
- void SetPresentationConnection(
- blink::mojom::PresentationInfoPtr presentation_info,
- blink::mojom::PresentationConnectionPtr controller_connection_ptr,
- blink::mojom::PresentationConnectionRequest receiver_connection_request)
- override;
private:
friend class PresentationServiceImplTest;
@@ -113,9 +106,6 @@ class CONTENT_EXPORT PresentationServiceImpl
// Maximum number of pending ReconnectPresentation requests at any given time.
static const int kMaxQueuedRequests = 10;
- using ConnectionMessagesCallback =
- base::OnceCallback<void(std::vector<PresentationConnectionMessage>)>;
-
// Listener implementation owned by PresentationServiceImpl. An instance of
// this is created when PresentationRequest.getAvailability() is resolved.
// The instance receives screen availability results from the embedder and
@@ -144,7 +134,7 @@ class CONTENT_EXPORT PresentationServiceImpl
explicit NewPresentationCallbackWrapper(NewPresentationCallback callback);
~NewPresentationCallbackWrapper();
- void Run(blink::mojom::PresentationInfoPtr presentation_info,
+ void Run(blink::mojom::PresentationConnectionResultPtr result,
blink::mojom::PresentationErrorPtr error);
private:
@@ -178,16 +168,16 @@ class CONTENT_EXPORT PresentationServiceImpl
// Passed to embedder's implementation of PresentationServiceDelegate for
// later invocation when default presentation has started.
void OnDefaultPresentationStarted(
- const blink::mojom::PresentationInfo& presentation_info);
+ blink::mojom::PresentationConnectionResultPtr result);
// Finds the callback from |pending_reconnect_presentation_cbs_| using
// |request_id|.
- // If it exists, invoke it with |presentation_info| and |error|, then erase it
+ // If it exists, invoke it with |result| and |error|, then erase it
// from |pending_reconnect_presentation_cbs_|. Returns true if the callback
// was found.
bool RunAndEraseReconnectPresentationMojoCallback(
int request_id,
- blink::mojom::PresentationInfoPtr presentation_info,
+ blink::mojom::PresentationConnectionResultPtr result,
blink::mojom::PresentationErrorPtr error);
// Removes all listeners and resets default presentation URL on this instance
@@ -199,12 +189,12 @@ class CONTENT_EXPORT PresentationServiceImpl
// invocation.
void OnStartPresentationSucceeded(
int request_id,
- const blink::mojom::PresentationInfo& presentation_info);
+ blink::mojom::PresentationConnectionResultPtr result);
void OnStartPresentationError(int request_id,
const blink::mojom::PresentationError& error);
void OnReconnectPresentationSucceeded(
int request_id,
- const blink::mojom::PresentationInfo& presentation_info);
+ blink::mojom::PresentationConnectionResultPtr result);
void OnReconnectPresentationError(
int request_id,
const blink::mojom::PresentationError& error);
@@ -214,12 +204,6 @@ class CONTENT_EXPORT PresentationServiceImpl
void ListenForConnectionStateChange(
const blink::mojom::PresentationInfo& connection);
- // Passed to embedder's implementation of PresentationServiceDelegate for
- // later invocation when connection messages arrive.
- void OnConnectionMessages(
- const blink::mojom::PresentationInfo& presentation_info,
- std::vector<content::PresentationConnectionMessage> messages);
-
// A callback registered to LocalPresentationManager when
// the PresentationServiceImpl for the presentation receiver is initialized.
// Calls |receiver_| to create a new PresentationConnection on receiver page.
diff --git a/chromium/content/browser/presentation/presentation_service_impl_unittest.cc b/chromium/content/browser/presentation/presentation_service_impl_unittest.cc
index a635d4413a8..51fd39f10ab 100644
--- a/chromium/content/browser/presentation/presentation_service_impl_unittest.cc
+++ b/chromium/content/browser/presentation/presentation_service_impl_unittest.cc
@@ -17,16 +17,24 @@
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/presentation_request.h"
#include "content/public/browser/presentation_service_delegate.h"
-#include "content/public/common/presentation_connection_message.h"
#include "content/test/test_render_frame_host.h"
#include "content/test/test_render_view_host.h"
#include "content/test/test_web_contents.h"
#include "mojo/public/cpp/bindings/interface_ptr.h"
#include "testing/gmock/include/gmock/gmock.h"
+using blink::mojom::PresentationConnection;
using blink::mojom::PresentationConnectionCloseReason;
+using blink::mojom::PresentationConnectionMessagePtr;
+using blink::mojom::PresentationConnectionPtr;
+using blink::mojom::PresentationConnectionPtrInfo;
+using blink::mojom::PresentationConnectionResult;
+using blink::mojom::PresentationConnectionResultPtr;
using blink::mojom::PresentationConnectionState;
+using blink::mojom::PresentationController;
+using blink::mojom::PresentationControllerPtr;
using blink::mojom::PresentationError;
+using blink::mojom::PresentationErrorPtr;
using blink::mojom::PresentationErrorType;
using blink::mojom::PresentationInfo;
using blink::mojom::PresentationInfoPtr;
@@ -52,6 +60,11 @@ MATCHER_P(InfoEquals, expected, "") {
return expected.url == arg.url && expected.id == arg.id;
}
+// Matches blink::mojom::PresentationInfoPtr.
+MATCHER_P(InfoPtrEquals, expected, "") {
+ return expected.url == arg->url && expected.id == arg->id;
+}
+
ACTION_TEMPLATE(SaveArgByMove,
HAS_1_TEMPLATE_PARAMS(int, k),
AND_1_VALUE_PARAMS(pointer)) {
@@ -73,7 +86,7 @@ class MockPresentationServiceDelegate
int render_frame_id,
PresentationServiceDelegate::Observer* observer));
MOCK_METHOD2(RemoveObserver,
- void(int render_process_id, int render_frame_id));
+ void(int render_process_id, int render_frame_id));
bool AddScreenAvailabilityListener(
int render_process_id,
@@ -88,41 +101,22 @@ class MockPresentationServiceDelegate
MOCK_METHOD0(AddScreenAvailabilityListener, bool());
MOCK_METHOD3(RemoveScreenAvailabilityListener,
- void(int render_process_id,
- int routing_id,
- PresentationScreenAvailabilityListener* listener));
- MOCK_METHOD2(Reset,
- void(int render_process_id,
- int routing_id));
+ void(int render_process_id,
+ int routing_id,
+ PresentationScreenAvailabilityListener* listener));
+ MOCK_METHOD2(Reset, void(int render_process_id, int routing_id));
MOCK_METHOD2(SetDefaultPresentationUrls,
void(const PresentationRequest& request,
DefaultPresentationConnectionCallback callback));
-
- // TODO(crbug.com/729950): Use MOCK_METHOD directly once GMock gets the
- // move-only type support.
- void StartPresentation(
- const PresentationRequest& request,
- PresentationConnectionCallback success_cb,
- PresentationConnectionErrorCallback error_cb) override {
- StartPresentationInternal(request, success_cb, error_cb);
- }
- MOCK_METHOD3(StartPresentationInternal,
+ MOCK_METHOD3(StartPresentation,
void(const PresentationRequest& request,
- PresentationConnectionCallback& success_cb,
- PresentationConnectionErrorCallback& error_cb));
- void ReconnectPresentation(
- const PresentationRequest& request,
- const std::string& presentation_id,
- PresentationConnectionCallback success_cb,
- PresentationConnectionErrorCallback error_cb) override {
- ReconnectPresentationInternal(request, presentation_id, success_cb,
- error_cb);
- }
- MOCK_METHOD4(ReconnectPresentationInternal,
+ PresentationConnectionCallback success_cb,
+ PresentationConnectionErrorCallback error_cb));
+ MOCK_METHOD4(ReconnectPresentation,
void(const PresentationRequest& request,
const std::string& presentation_id,
- PresentationConnectionCallback& success_cb,
- PresentationConnectionErrorCallback& error_cb));
+ PresentationConnectionCallback success_cb,
+ PresentationConnectionErrorCallback error_cb));
MOCK_METHOD3(CloseConnection,
void(int render_process_id,
int render_frame_id,
@@ -131,30 +125,17 @@ class MockPresentationServiceDelegate
void(int render_process_id,
int render_frame_id,
const std::string& presentation_id));
- MOCK_METHOD3(GetMediaController,
- std::unique_ptr<media::MediaController>(
+ MOCK_METHOD3(GetFlingingController,
+ std::unique_ptr<media::FlingingController>(
int render_process_id,
int render_frame_id,
const std::string& presentation_id));
-
- // PresentationConnectionMessage is move-only.
- // TODO(crbug.com/729950): Use MOCK_METHOD directly once GMock gets the
- // move-only type support.
- void SendMessage(int render_process_id,
- int render_frame_id,
- const PresentationInfo& presentation_info,
- PresentationConnectionMessage message,
- SendMessageCallback send_message_cb) {
- SendMessageInternal(render_process_id, render_frame_id, presentation_info,
- message, send_message_cb);
- }
- MOCK_METHOD5(SendMessageInternal,
+ MOCK_METHOD5(SendMessage,
void(int render_process_id,
int render_frame_id,
const PresentationInfo& presentation_info,
- const PresentationConnectionMessage& message,
+ PresentationConnectionMessagePtr message,
const SendMessageCallback& send_message_cb));
-
MOCK_METHOD4(
ListenForConnectionStateChange,
void(int render_process_id,
@@ -162,23 +143,6 @@ class MockPresentationServiceDelegate
const PresentationInfo& connection,
const PresentationConnectionStateChangedCallback& state_changed_cb));
- void ConnectToPresentation(
- int render_process_id,
- int render_frame_id,
- const PresentationInfo& presentation_info,
- PresentationConnectionPtr controller_conn_ptr,
- PresentationConnectionRequest receiver_conn_request) override {
- RegisterLocalPresentationConnectionRaw(render_process_id, render_frame_id,
- presentation_info,
- controller_conn_ptr.get());
- }
-
- MOCK_METHOD4(RegisterLocalPresentationConnectionRaw,
- void(int render_process_id,
- int render_frame_id,
- const PresentationInfo& presentation_info,
- blink::mojom::PresentationConnection* connection));
-
void set_screen_availability_listening_supported(bool value) {
screen_availability_listening_supported_ = value;
}
@@ -189,16 +153,10 @@ class MockPresentationServiceDelegate
class MockPresentationReceiver : public blink::mojom::PresentationReceiver {
public:
- void OnReceiverConnectionAvailable(
- PresentationInfoPtr info,
- blink::mojom::PresentationConnectionPtr controller_connection,
- blink::mojom::PresentationConnectionRequest receiver_connection_request)
- override {
- OnReceiverConnectionAvailable(*info);
- }
-
- MOCK_METHOD1(OnReceiverConnectionAvailable,
- void(const PresentationInfo& info));
+ MOCK_METHOD3(OnReceiverConnectionAvailable,
+ void(PresentationInfoPtr info,
+ PresentationConnectionPtr controller_connection,
+ PresentationConnectionRequest receiver_connection_request));
};
class MockReceiverPresentationServiceDelegate
@@ -215,16 +173,11 @@ class MockReceiverPresentationServiceDelegate
void(const ReceiverConnectionAvailableCallback&));
};
-class MockPresentationConnection : public blink::mojom::PresentationConnection {
+class MockPresentationConnection : public PresentationConnection {
public:
- // PresentationConnectionMessage is move-only.
- void OnMessage(PresentationConnectionMessage message,
- base::OnceCallback<void(bool)> send_message_cb) override {
- OnMessageInternal(message, send_message_cb);
- }
- MOCK_METHOD2(OnMessageInternal,
- void(const PresentationConnectionMessage& message,
- base::OnceCallback<void(bool)>& send_message_cb));
+ MOCK_METHOD2(OnMessage,
+ void(PresentationConnectionMessagePtr message,
+ base::OnceCallback<void(bool)> send_message_cb));
MOCK_METHOD1(DidChangeState, void(PresentationConnectionState state));
MOCK_METHOD0(RequestClose, void());
};
@@ -233,38 +186,19 @@ class MockPresentationController : public blink::mojom::PresentationController {
public:
MOCK_METHOD2(OnScreenAvailabilityUpdated,
void(const GURL& url, ScreenAvailability availability));
- void OnConnectionStateChanged(PresentationInfoPtr connection,
- PresentationConnectionState new_state) {
- OnConnectionStateChangedInternal(*connection, new_state);
- }
- MOCK_METHOD2(OnConnectionStateChangedInternal,
- void(const PresentationInfo& connection,
+ MOCK_METHOD2(OnConnectionStateChanged,
+ void(PresentationInfoPtr connection,
PresentationConnectionState new_state));
- void OnConnectionClosed(
- PresentationInfoPtr connection,
- blink::mojom::PresentationConnectionCloseReason reason,
- const std::string& message) {
- OnConnectionClosedInternal(*connection, reason, message);
- }
- MOCK_METHOD3(OnConnectionClosedInternal,
- void(const PresentationInfo& connection,
- blink::mojom::PresentationConnectionCloseReason reason,
+ MOCK_METHOD3(OnConnectionClosed,
+ void(PresentationInfoPtr connection,
+ PresentationConnectionCloseReason reason,
const std::string& message));
- // PresentationConnectionMessage is move-only.
- void OnConnectionMessagesReceived(
- PresentationInfoPtr presentation_info,
- std::vector<PresentationConnectionMessage> messages) {
- OnConnectionMessagesReceivedInternal(*presentation_info, messages);
- }
MOCK_METHOD2(
- OnConnectionMessagesReceivedInternal,
+ OnConnectionMessagesReceived,
void(const PresentationInfo& presentation_info,
- const std::vector<PresentationConnectionMessage>& messages));
- void OnDefaultPresentationStarted(PresentationInfoPtr presentation_info) {
- OnDefaultPresentationStartedInternal(*presentation_info);
- }
- MOCK_METHOD1(OnDefaultPresentationStartedInternal,
- void(const PresentationInfo& presentation_info));
+ const std::vector<PresentationConnectionMessagePtr>& messages));
+ MOCK_METHOD1(OnDefaultPresentationStarted,
+ void(PresentationConnectionResultPtr result));
};
class PresentationServiceImplTest : public RenderViewHostImplTestHarness {
@@ -286,10 +220,9 @@ class PresentationServiceImplTest : public RenderViewHostImplTestHarness {
service_impl_.reset(new PresentationServiceImpl(
render_frame_host, contents(), &mock_delegate_, nullptr));
- blink::mojom::PresentationControllerPtr controller_ptr;
- controller_binding_.reset(
- new mojo::Binding<blink::mojom::PresentationController>(
- &mock_controller_, mojo::MakeRequest(&controller_ptr)));
+ PresentationControllerPtr controller_ptr;
+ controller_binding_.reset(new mojo::Binding<PresentationController>(
+ &mock_controller_, mojo::MakeRequest(&controller_ptr)));
service_impl_->SetController(std::move(controller_ptr));
presentation_urls_.push_back(presentation_url1_);
@@ -318,8 +251,7 @@ class PresentationServiceImplTest : public RenderViewHostImplTestHarness {
if (!main_frame)
rfh = rfh_tester->AppendChild("subframe");
std::unique_ptr<NavigationHandle> navigation_handle =
- NavigationHandle::CreateNavigationHandleForTesting(
- GURL(), rfh, true);
+ NavigationHandle::CreateNavigationHandleForTesting(GURL(), rfh, true);
// Destructor calls DidFinishNavigation.
}
@@ -355,17 +287,17 @@ class PresentationServiceImplTest : public RenderViewHostImplTestHarness {
service_impl_->screen_availability_listeners_.end());
}
- void ExpectPresentationSuccess(PresentationInfoPtr info,
- blink::mojom::PresentationErrorPtr error) {
- EXPECT_FALSE(info.is_null());
- EXPECT_TRUE(error.is_null());
+ void ExpectPresentationSuccess(PresentationConnectionResultPtr result,
+ PresentationErrorPtr error) {
+ EXPECT_TRUE(result);
+ EXPECT_FALSE(error);
presentation_cb_was_run_ = true;
}
- void ExpectPresentationError(PresentationInfoPtr info,
- blink::mojom::PresentationErrorPtr error) {
- EXPECT_TRUE(info.is_null());
- EXPECT_FALSE(error.is_null());
+ void ExpectPresentationError(PresentationConnectionResultPtr result,
+ PresentationErrorPtr error) {
+ EXPECT_FALSE(result);
+ EXPECT_TRUE(error);
presentation_cb_was_run_ = true;
}
@@ -380,8 +312,7 @@ class PresentationServiceImplTest : public RenderViewHostImplTestHarness {
std::unique_ptr<PresentationServiceImpl> service_impl_;
MockPresentationController mock_controller_;
- std::unique_ptr<mojo::Binding<blink::mojom::PresentationController>>
- controller_binding_;
+ std::unique_ptr<mojo::Binding<PresentationController>> controller_binding_;
GURL presentation_url1_;
GURL presentation_url2_;
@@ -469,11 +400,24 @@ TEST_F(PresentationServiceImplTest, SetDefaultPresentationUrls) {
PresentationInfo presentation_info(presentation_url2_, kPresentationId);
- EXPECT_CALL(mock_controller_, OnDefaultPresentationStartedInternal(
- InfoEquals(presentation_info)));
+ EXPECT_CALL(mock_controller_, OnDefaultPresentationStarted(_))
+ .WillOnce([&presentation_info](PresentationConnectionResultPtr result) {
+ EXPECT_THAT(*result->presentation_info, InfoEquals(presentation_info));
+ });
EXPECT_CALL(mock_delegate_, ListenForConnectionStateChange(_, _, _, _));
- std::move(callback).Run(
- PresentationInfo(presentation_url2_, kPresentationId));
+
+ // Mojo requires we not send nullptr for the InterfacePtrInfo and
+ // InterfaceRequest in PresentationConnectionResult, but there's no reason to
+ // actually have them properly bound in the test. To get around this, we
+ // create mojo pipes but bind to a nullptr for the implementation.
+ PresentationConnectionPtrInfo receiver_ptr;
+ PresentationConnectionPtr controller_ptr;
+ auto request = mojo::MakeRequest(&controller_ptr);
+ mojo::Binding<PresentationConnection> binding(
+ /** impl */ nullptr, mojo::MakeRequest(&receiver_ptr));
+ std::move(callback).Run(PresentationConnectionResult::New(
+ blink::mojom::PresentationInfo::New(presentation_url2_, kPresentationId),
+ std::move(receiver_ptr), std::move(request)));
base::RunLoop().RunUntilIdle();
}
@@ -503,8 +447,8 @@ TEST_F(PresentationServiceImplTest, ListenForConnectionStateChange) {
.WillOnce(SaveArg<3>(&state_changed_cb));
service_impl_->ListenForConnectionStateChange(connection);
- EXPECT_CALL(mock_controller_, OnConnectionStateChangedInternal(
- InfoEquals(presentation_connection),
+ EXPECT_CALL(mock_controller_, OnConnectionStateChanged(
+ InfoPtrEquals(presentation_connection),
PresentationConnectionState::TERMINATED));
state_changed_cb.Run(PresentationConnectionStateChangeInfo(
PresentationConnectionState::TERMINATED));
@@ -526,10 +470,10 @@ TEST_F(PresentationServiceImplTest, ListenForConnectionClose) {
closed_info.close_reason = PresentationConnectionCloseReason::WENT_AWAY;
closed_info.message = "Foo";
- EXPECT_CALL(mock_controller_,
- OnConnectionClosedInternal(
- InfoEquals(presentation_connection),
- PresentationConnectionCloseReason::WENT_AWAY, "Foo"));
+ EXPECT_CALL(
+ mock_controller_,
+ OnConnectionClosed(InfoPtrEquals(presentation_connection),
+ PresentationConnectionCloseReason::WENT_AWAY, "Foo"));
state_changed_cb.Run(closed_info);
base::RunLoop().RunUntilIdle();
}
@@ -545,33 +489,41 @@ TEST_F(PresentationServiceImplTest, SetSameDefaultPresentationUrls) {
}
TEST_F(PresentationServiceImplTest, StartPresentationSuccess) {
- base::OnceCallback<void(const PresentationInfo&)> success_cb;
- EXPECT_CALL(mock_delegate_, StartPresentationInternal(_, _, _))
- .WillOnce(SaveArgByMove<1>(&success_cb));
+ PresentationConnectionCallback saved_success_cb;
+ EXPECT_CALL(mock_delegate_, StartPresentation(_, _, _))
+ .WillOnce([&saved_success_cb](const auto& request, auto success_cb,
+ auto error_cb) {
+ saved_success_cb = std::move(success_cb);
+ });
service_impl_->StartPresentation(presentation_urls_,
std::move(expect_presentation_success_cb_));
- EXPECT_FALSE(success_cb.is_null());
+ EXPECT_FALSE(saved_success_cb.is_null());
EXPECT_CALL(mock_delegate_, ListenForConnectionStateChange(_, _, _, _))
.Times(1);
- std::move(success_cb)
- .Run(PresentationInfo(presentation_url1_, kPresentationId));
+ std::move(saved_success_cb)
+ .Run(PresentationConnectionResult::New(
+ blink::mojom::PresentationInfo::New(presentation_url1_,
+ kPresentationId),
+ nullptr, nullptr));
ExpectPresentationCallbackWasRun();
}
TEST_F(PresentationServiceImplTest, StartPresentationError) {
- base::OnceCallback<void(const PresentationError&)> error_cb;
- EXPECT_CALL(mock_delegate_, StartPresentationInternal(_, _, _))
- .WillOnce(SaveArgByMove<2>(&error_cb));
+ base::OnceCallback<void(const PresentationError&)> saved_error_cb;
+ EXPECT_CALL(mock_delegate_, StartPresentation(_, _, _))
+ .WillOnce([&](const auto& request, auto success_cb, auto error_cb) {
+ saved_error_cb = std::move(error_cb);
+ });
service_impl_->StartPresentation(presentation_urls_,
std::move(expect_presentation_error_cb_));
- EXPECT_FALSE(error_cb.is_null());
- std::move(error_cb).Run(
- PresentationError(PresentationErrorType::UNKNOWN, "Error message"));
+ EXPECT_FALSE(saved_error_cb.is_null());
+ std::move(saved_error_cb)
+ .Run(PresentationError(PresentationErrorType::UNKNOWN, "Error message"));
ExpectPresentationCallbackWasRun();
}
TEST_F(PresentationServiceImplTest, StartPresentationInProgress) {
- EXPECT_CALL(mock_delegate_, StartPresentationInternal(_, _, _)).Times(1);
+ EXPECT_CALL(mock_delegate_, StartPresentation(_, _, _)).Times(1);
// Uninvoked callbacks must outlive |service_impl_| since they get invoked
// at |service_impl_|'s destruction.
service_impl_->StartPresentation(presentation_urls_, base::DoNothing());
@@ -584,32 +536,37 @@ TEST_F(PresentationServiceImplTest, StartPresentationInProgress) {
}
TEST_F(PresentationServiceImplTest, ReconnectPresentationSuccess) {
- base::OnceCallback<void(const PresentationInfo&)> success_cb;
- EXPECT_CALL(mock_delegate_,
- ReconnectPresentationInternal(_, kPresentationId, _, _))
- .WillOnce(SaveArgByMove<2>(&success_cb));
+ PresentationConnectionCallback saved_success_cb;
+ EXPECT_CALL(mock_delegate_, ReconnectPresentation(_, kPresentationId, _, _))
+ .WillOnce([&saved_success_cb](const auto& request, const auto& id,
+ auto success_cb, auto error_cb) {
+ saved_success_cb = std::move(success_cb);
+ });
service_impl_->ReconnectPresentation(
presentation_urls_, kPresentationId,
std::move(expect_presentation_success_cb_));
- EXPECT_FALSE(success_cb.is_null());
+ EXPECT_FALSE(saved_success_cb.is_null());
EXPECT_CALL(mock_delegate_, ListenForConnectionStateChange(_, _, _, _))
.Times(1);
- std::move(success_cb)
- .Run(PresentationInfo(presentation_url1_, kPresentationId));
+ std::move(saved_success_cb)
+ .Run(PresentationConnectionResult::New(
+ blink::mojom::PresentationInfo::New(presentation_url1_,
+ kPresentationId),
+ nullptr, nullptr));
ExpectPresentationCallbackWasRun();
}
TEST_F(PresentationServiceImplTest, ReconnectPresentationError) {
- base::OnceCallback<void(const PresentationError&)> error_cb;
- EXPECT_CALL(mock_delegate_,
- ReconnectPresentationInternal(_, kPresentationId, _, _))
- .WillOnce(SaveArgByMove<3>(&error_cb));
+ base::OnceCallback<void(const PresentationError&)> saved_error_cb;
+ EXPECT_CALL(mock_delegate_, ReconnectPresentation(_, kPresentationId, _, _))
+ .WillOnce([&](const auto& request, const std::string& id, auto success_cb,
+ auto error_cb) { saved_error_cb = std::move(error_cb); });
service_impl_->ReconnectPresentation(
presentation_urls_, kPresentationId,
std::move(expect_presentation_error_cb_));
- EXPECT_FALSE(error_cb.is_null());
- std::move(error_cb).Run(
- PresentationError(PresentationErrorType::UNKNOWN, "Error message"));
+ EXPECT_FALSE(saved_error_cb.is_null());
+ std::move(saved_error_cb)
+ .Run(PresentationError(PresentationErrorType::UNKNOWN, "Error message"));
ExpectPresentationCallbackWasRun();
}
@@ -618,7 +575,7 @@ TEST_F(PresentationServiceImplTest, MaxPendingReconnectPresentationRequests) {
const char* presentation_id = "presentationId%d";
int num_requests = PresentationServiceImpl::kMaxQueuedRequests;
int i = 0;
- EXPECT_CALL(mock_delegate_, ReconnectPresentationInternal(_, _, _, _))
+ EXPECT_CALL(mock_delegate_, ReconnectPresentation(_, _, _, _))
.Times(num_requests);
for (; i < num_requests; ++i) {
std::vector<GURL> urls = {GURL(base::StringPrintf(presentation_url, i))};
@@ -646,25 +603,6 @@ TEST_F(PresentationServiceImplTest, Terminate) {
service_impl_->Terminate(presentation_url1_, kPresentationId);
}
-TEST_F(PresentationServiceImplTest, SetPresentationConnection) {
- PresentationInfoPtr presentation_info =
- PresentationInfo::New(presentation_url1_, kPresentationId);
-
- blink::mojom::PresentationConnectionPtr connection;
- MockPresentationConnection mock_presentation_connection;
- mojo::Binding<blink::mojom::PresentationConnection> connection_binding(
- &mock_presentation_connection, mojo::MakeRequest(&connection));
- blink::mojom::PresentationConnectionPtr receiver_connection;
- auto request = mojo::MakeRequest(&receiver_connection);
-
- PresentationInfo expected(presentation_url1_, kPresentationId);
- EXPECT_CALL(mock_delegate_, RegisterLocalPresentationConnectionRaw(
- _, _, InfoEquals(expected), _));
-
- service_impl_->SetPresentationConnection(
- std::move(presentation_info), std::move(connection), std::move(request));
-}
-
TEST_F(PresentationServiceImplTest, ReceiverPresentationServiceDelegate) {
EXPECT_CALL(mock_receiver_delegate_, AddObserver(_, _, _)).Times(1);
@@ -687,14 +625,14 @@ TEST_F(PresentationServiceImplTest, ReceiverPresentationServiceDelegate) {
PresentationInfo expected(presentation_url1_, kPresentationId);
// Client gets notified of receiver connections.
- blink::mojom::PresentationConnectionPtr controller_connection;
+ PresentationConnectionPtr controller_connection;
MockPresentationConnection mock_presentation_connection;
- mojo::Binding<blink::mojom::PresentationConnection> connection_binding(
+ mojo::Binding<PresentationConnection> connection_binding(
&mock_presentation_connection, mojo::MakeRequest(&controller_connection));
- blink::mojom::PresentationConnectionPtr receiver_connection;
+ PresentationConnectionPtr receiver_connection;
EXPECT_CALL(mock_receiver,
- OnReceiverConnectionAvailable(InfoEquals(expected)))
+ OnReceiverConnectionAvailable(InfoPtrEquals(expected), _, _))
.Times(1);
callback.Run(PresentationInfo::New(expected),
std::move(controller_connection),
@@ -716,10 +654,9 @@ TEST_F(PresentationServiceImplTest, ReceiverDelegateOnSubFrame) {
RegisterReceiverConnectionAvailableCallback(_))
.Times(0);
- blink::mojom::PresentationControllerPtr controller_ptr;
- controller_binding_.reset(
- new mojo::Binding<blink::mojom::PresentationController>(
- &mock_controller_, mojo::MakeRequest(&controller_ptr)));
+ PresentationControllerPtr controller_ptr;
+ controller_binding_.reset(new mojo::Binding<PresentationController>(
+ &mock_controller_, mojo::MakeRequest(&controller_ptr)));
service_impl.controller_delegate_ = nullptr;
service_impl.SetController(std::move(controller_ptr));
diff --git a/chromium/content/browser/push_messaging/push_messaging_manager.cc b/chromium/content/browser/push_messaging/push_messaging_manager.cc
index bc6ee59fe0c..91018ad3310 100644
--- a/chromium/content/browser/push_messaging/push_messaging_manager.cc
+++ b/chromium/content/browser/push_messaging/push_messaging_manager.cc
@@ -13,6 +13,7 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/metrics/histogram_macros.h"
+#include "base/optional.h"
#include "base/strings/string_number_conversions.h"
#include "content/browser/permissions/permission_controller_impl.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
@@ -133,7 +134,7 @@ struct PushMessagingManager::RegisterData {
GURL requesting_origin;
int64_t service_worker_registration_id;
- std::string existing_subscription_id;
+ base::Optional<std::string> existing_subscription_id;
PushSubscriptionOptions options;
SubscribeCallback callback;
@@ -502,11 +503,12 @@ void PushMessagingManager::Core::DidRegister(
mojom::PushRegistrationStatus status) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- // TODO(nator): Handle the case where |push_subscription_id| and
+ // TODO(crbug.com/646721): Handle the case where |push_subscription_id| and
// |data.existing_subscription_id| are not the same. Right now we just
// override the old subscription ID and encryption information.
const bool subscription_changed =
- push_subscription_id != data.existing_subscription_id;
+ data.existing_subscription_id.has_value() &&
+ data.existing_subscription_id.value() != push_subscription_id;
if (status == mojom::PushRegistrationStatus::SUCCESS_FROM_PUSH_SERVICE) {
BrowserThread::PostTask(
@@ -806,7 +808,8 @@ void PushMessagingManager::DidGetSubscription(
case blink::ServiceWorkerStatusCode::kErrorScriptEvaluateFailed:
case blink::ServiceWorkerStatusCode::kErrorDiskCache:
case blink::ServiceWorkerStatusCode::kErrorRedundant:
- case blink::ServiceWorkerStatusCode::kErrorDisallowed: {
+ case blink::ServiceWorkerStatusCode::kErrorDisallowed:
+ case blink::ServiceWorkerStatusCode::kErrorInvalidArguments: {
NOTREACHED() << "Got unexpected error code: "
<< static_cast<uint32_t>(service_worker_status) << " "
<< blink::ServiceWorkerStatusToString(service_worker_status);
diff --git a/chromium/content/browser/push_messaging/push_messaging_router.cc b/chromium/content/browser/push_messaging/push_messaging_router.cc
index a648b5d11fa..697ca1fabf8 100644
--- a/chromium/content/browser/push_messaging/push_messaging_router.cc
+++ b/chromium/content/browser/push_messaging/push_messaging_router.cc
@@ -11,11 +11,9 @@
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/service_worker/service_worker_storage.h"
-#include "content/common/service_worker/service_worker_messages.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/storage_partition.h"
-#include "content/public/common/push_event_payload.h"
#include "content/public/common/push_messaging_status.mojom.h"
#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
@@ -39,7 +37,7 @@ void PushMessagingRouter::DeliverMessage(
BrowserContext* browser_context,
const GURL& origin,
int64_t service_worker_registration_id,
- const PushEventPayload& payload,
+ base::Optional<std::string> payload,
const DeliverMessageCallback& deliver_message_callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
StoragePartition* partition =
@@ -50,7 +48,7 @@ void PushMessagingRouter::DeliverMessage(
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(&PushMessagingRouter::FindServiceWorkerRegistration,
- origin, service_worker_registration_id, payload,
+ origin, service_worker_registration_id, std::move(payload),
deliver_message_callback, service_worker_context));
}
@@ -58,7 +56,7 @@ void PushMessagingRouter::DeliverMessage(
void PushMessagingRouter::FindServiceWorkerRegistration(
const GURL& origin,
int64_t service_worker_registration_id,
- const PushEventPayload& payload,
+ base::Optional<std::string> payload,
const DeliverMessageCallback& deliver_message_callback,
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -67,13 +65,13 @@ void PushMessagingRouter::FindServiceWorkerRegistration(
service_worker_context->FindReadyRegistrationForId(
service_worker_registration_id, origin,
base::BindOnce(
- &PushMessagingRouter::FindServiceWorkerRegistrationCallback, payload,
- deliver_message_callback));
+ &PushMessagingRouter::FindServiceWorkerRegistrationCallback,
+ std::move(payload), deliver_message_callback));
}
// static
void PushMessagingRouter::FindServiceWorkerRegistrationCallback(
- const PushEventPayload& payload,
+ base::Optional<std::string> payload,
const DeliverMessageCallback& deliver_message_callback,
blink::ServiceWorkerStatusCode service_worker_status,
scoped_refptr<ServiceWorkerRegistration> service_worker_registration) {
@@ -102,14 +100,14 @@ void PushMessagingRouter::FindServiceWorkerRegistrationCallback(
ServiceWorkerMetrics::EventType::PUSH,
base::BindOnce(&PushMessagingRouter::DeliverMessageToWorker,
base::WrapRefCounted(version), service_worker_registration,
- payload, deliver_message_callback));
+ std::move(payload), deliver_message_callback));
}
// static
void PushMessagingRouter::DeliverMessageToWorker(
const scoped_refptr<ServiceWorkerVersion>& service_worker,
const scoped_refptr<ServiceWorkerRegistration>& service_worker_registration,
- const PushEventPayload& payload,
+ base::Optional<std::string> payload,
const DeliverMessageCallback& deliver_message_callback,
blink::ServiceWorkerStatusCode start_worker_status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -168,6 +166,7 @@ void PushMessagingRouter::DeliverMessageEnd(
case blink::ServiceWorkerStatusCode::kErrorNetwork:
case blink::ServiceWorkerStatusCode::kErrorSecurity:
case blink::ServiceWorkerStatusCode::kErrorState:
+ case blink::ServiceWorkerStatusCode::kErrorInvalidArguments:
NOTREACHED() << "Got unexpected error code: "
<< static_cast<uint32_t>(service_worker_status) << " "
<< blink::ServiceWorkerStatusToString(service_worker_status);
diff --git a/chromium/content/browser/push_messaging/push_messaging_router.h b/chromium/content/browser/push_messaging/push_messaging_router.h
index 71bb530f425..773bed1ee05 100644
--- a/chromium/content/browser/push_messaging/push_messaging_router.h
+++ b/chromium/content/browser/push_messaging/push_messaging_router.h
@@ -10,6 +10,7 @@
#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/optional.h"
#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
#include "url/gurl.h"
@@ -20,7 +21,6 @@ enum class PushDeliveryStatus;
}
class BrowserContext;
-struct PushEventPayload;
class ServiceWorkerContextWrapper;
class ServiceWorkerRegistration;
class ServiceWorkerVersion;
@@ -37,7 +37,7 @@ class PushMessagingRouter {
BrowserContext* browser_context,
const GURL& origin,
int64_t service_worker_registration_id,
- const PushEventPayload& payload,
+ base::Optional<std::string> payload,
const DeliverMessageCallback& deliver_message_callback);
private:
@@ -46,7 +46,7 @@ class PushMessagingRouter {
static void FindServiceWorkerRegistration(
const GURL& origin,
int64_t service_worker_registration_id,
- const PushEventPayload& payload,
+ base::Optional<std::string> payload,
const DeliverMessageCallback& deliver_message_callback,
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context);
@@ -54,7 +54,7 @@ class PushMessagingRouter {
// |data| on the Service Worker identified by |service_worker_registration|.
// Must be called on the IO thread.
static void FindServiceWorkerRegistrationCallback(
- const PushEventPayload& payload,
+ base::Optional<std::string> payload,
const DeliverMessageCallback& deliver_message_callback,
blink::ServiceWorkerStatusCode service_worker_status,
scoped_refptr<ServiceWorkerRegistration> service_worker_registration);
@@ -65,7 +65,7 @@ class PushMessagingRouter {
const scoped_refptr<ServiceWorkerVersion>& service_worker,
const scoped_refptr<ServiceWorkerRegistration>&
service_worker_registration,
- const PushEventPayload& payload,
+ base::Optional<std::string> payload,
const DeliverMessageCallback& deliver_message_callback,
blink::ServiceWorkerStatusCode start_worker_status);
diff --git a/chromium/content/browser/renderer_host/DEPS b/chromium/content/browser/renderer_host/DEPS
index 8ac26e104a5..a38288a21c9 100644
--- a/chromium/content/browser/renderer_host/DEPS
+++ b/chromium/content/browser/renderer_host/DEPS
@@ -3,7 +3,7 @@ include_rules = [
"+components/viz/common",
"+components/viz/host",
"+components/viz/service",
- "+services/ui/public",
+ "+services/ws/public",
"+third_party/blink/public/platform/web_gesture_curve.h",
"+third_party/zlib",
"+ui/events/gestures/blink/web_gesture_curve_impl.h",
diff --git a/chromium/content/browser/renderer_host/browser_compositor_view_mac.h b/chromium/content/browser/renderer_host/browser_compositor_view_mac.h
index 46be85eea4b..7dc490ea560 100644
--- a/chromium/content/browser/renderer_host/browser_compositor_view_mac.h
+++ b/chromium/content/browser/renderer_host/browser_compositor_view_mac.h
@@ -13,10 +13,12 @@
#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
#include "components/viz/common/surfaces/scoped_surface_id_allocator.h"
#include "content/browser/renderer_host/delegated_frame_host.h"
+#include "content/public/common/screen_info.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/compositor_observer.h"
#include "ui/compositor/layer_observer.h"
#include "ui/display/display.h"
+#include "ui/gfx/ca_layer_params.h"
namespace ui {
class AcceleratedWidgetMacNSView;
@@ -30,7 +32,6 @@ class BrowserCompositorMacClient {
virtual SkColor BrowserCompositorMacGetGutterColor() const = 0;
virtual void BrowserCompositorMacOnBeginFrame(base::TimeTicks frame_time) = 0;
virtual void OnFrameTokenChanged(uint32_t frame_token) = 0;
- virtual void DidReceiveFirstFrameAfterNavigation() = 0;
virtual void DestroyCompositorForShutdown() = 0;
virtual bool SynchronizeVisualProperties(
const base::Optional<viz::LocalSurfaceId>&
@@ -136,7 +137,6 @@ class CONTENT_EXPORT BrowserCompositorMac : public DelegatedFrameHostClient,
void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info) override;
void OnBeginFrame(base::TimeTicks frame_time) override;
void OnFrameTokenChanged(uint32_t frame_token) override;
- void DidReceiveFirstFrameAfterNavigation() override;
base::WeakPtr<BrowserCompositorMac> GetWeakPtr() {
return weak_factory_.GetWeakPtr();
@@ -148,7 +148,7 @@ class CONTENT_EXPORT BrowserCompositorMac : public DelegatedFrameHostClient,
bool ForceNewSurfaceForTesting();
- ui::Compositor* GetCompositorForTesting() const;
+ ui::Compositor* GetCompositor() const;
private:
// ui::LayerObserver implementation:
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 92afcc77910..fb23caccdd1 100644
--- a/chromium/content/browser/renderer_host/browser_compositor_view_mac.mm
+++ b/chromium/content/browser/renderer_host/browser_compositor_view_mac.mm
@@ -60,9 +60,7 @@ BrowserCompositorMac::BrowserCompositorMac(
// content (otherwise this solid color will be flashed during navigation).
root_layer_->SetColor(SK_ColorTRANSPARENT);
delegated_frame_host_.reset(new DelegatedFrameHost(
- frame_sink_id, this,
- base::FeatureList::IsEnabled(features::kVizDisplayCompositor),
- true /* should_register_frame_sink_id */));
+ frame_sink_id, this, true /* should_register_frame_sink_id */));
SetRenderWidgetHostIsHidden(render_widget_host_is_hidden);
SetNSViewAttachedToWindow(false);
@@ -265,7 +263,7 @@ void BrowserCompositorMac::TransitionToState(State new_state) {
root_layer_->parent()->RemoveObserver(this);
root_layer_->parent()->Remove(root_layer_.get());
delegated_frame_host_->WasHidden();
- delegated_frame_host_->ResetCompositor();
+ delegated_frame_host_->DetachFromCompositor();
state_ = HasNoCompositor;
}
@@ -287,7 +285,8 @@ void BrowserCompositorMac::TransitionToState(State new_state) {
// Transition HasDetachedCompositor -> HasAttachedCompositor.
if (state_ == HasDetachedCompositor && new_state < HasDetachedCompositor) {
- delegated_frame_host_->SetCompositor(recyclable_compositor_->compositor());
+ delegated_frame_host_->AttachToCompositor(
+ recyclable_compositor_->compositor());
delegated_frame_host_->WasShown(GetRendererLocalSurfaceId(), dfh_size_dip_,
false /* record_presentation_time */);
@@ -308,7 +307,7 @@ void BrowserCompositorMac::TransitionToState(State new_state) {
// Marking the DelegatedFrameHost as removed from the window hierarchy is
// necessary to remove all connections to its old ui::Compositor.
delegated_frame_host_->WasHidden();
- delegated_frame_host_->ResetCompositor();
+ delegated_frame_host_->DetachFromCompositor();
state_ = HasDetachedCompositor;
}
@@ -327,7 +326,8 @@ void BrowserCompositorMac::TransitionToState(State new_state) {
DCHECK(parent_ui_layer_);
DCHECK(parent_ui_layer_->GetCompositor());
DCHECK(!root_layer_->parent());
- delegated_frame_host_->SetCompositor(parent_ui_layer_->GetCompositor());
+ delegated_frame_host_->AttachToCompositor(
+ parent_ui_layer_->GetCompositor());
delegated_frame_host_->WasShown(GetRendererLocalSurfaceId(), dfh_size_dip_,
false /* record_presentation_time */);
parent_ui_layer_->Add(root_layer_.get());
@@ -416,10 +416,6 @@ void BrowserCompositorMac::DidNavigate() {
is_first_navigation_ = false;
}
-void BrowserCompositorMac::DidReceiveFirstFrameAfterNavigation() {
- client_->DidReceiveFirstFrameAfterNavigation();
-}
-
bool BrowserCompositorMac::ShouldContinueToPauseForFrame() const {
if (state_ == UseParentLayerCompositor)
return false;
@@ -496,7 +492,9 @@ void BrowserCompositorMac::LayerDestroyed(ui::Layer* layer) {
SetParentUiLayer(nullptr);
}
-ui::Compositor* BrowserCompositorMac::GetCompositorForTesting() const {
+ui::Compositor* BrowserCompositorMac::GetCompositor() const {
+ if (parent_ui_layer_)
+ return parent_ui_layer_->GetCompositor();
if (recyclable_compositor_)
return recyclable_compositor_->compositor();
return nullptr;
diff --git a/chromium/content/browser/renderer_host/compositor_impl_android.cc b/chromium/content/browser/renderer_host/compositor_impl_android.cc
index 454ebcafa7a..ebfb4c19fb0 100644
--- a/chromium/content/browser/renderer_host/compositor_impl_android.cc
+++ b/chromium/content/browser/renderer_host/compositor_impl_android.cc
@@ -13,6 +13,7 @@
#include <utility>
#include <vector>
+#include "base/android/application_status_listener.h"
#include "base/android/jni_android.h"
#include "base/android/scoped_java_ref.h"
#include "base/auto_reset.h"
@@ -43,7 +44,6 @@
#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 "components/viz/common/gl_helper.h"
#include "components/viz/common/gpu/context_provider.h"
#include "components/viz/common/gpu/vulkan_in_process_context_provider.h"
#include "components/viz/common/quads/compositor_frame.h"
@@ -81,9 +81,9 @@
#include "gpu/vulkan/init/vulkan_factory.h"
#include "gpu/vulkan/vulkan_implementation.h"
#include "gpu/vulkan/vulkan_surface.h"
-#include "services/ui/public/cpp/gpu/context_provider_command_buffer.h"
#include "services/viz/privileged/interfaces/compositing/frame_sink_manager.mojom.h"
#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h"
+#include "services/ws/public/cpp/gpu/context_provider_command_buffer.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "third_party/khronos/GLES2/gl2ext.h"
#include "third_party/skia/include/core/SkMallocPixelRef.h"
@@ -104,6 +104,29 @@ namespace content {
namespace {
+// These functions are called based on application visibility status.
+void SendOnBackgroundedToGpuService() {
+ content::GpuProcessHost::CallOnIO(
+ content::GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
+ false /* force_create */,
+ base::BindRepeating([](content::GpuProcessHost* host) {
+ if (host) {
+ host->gpu_service()->OnBackgrounded();
+ }
+ }));
+}
+
+void SendOnForegroundedToGpuService() {
+ content::GpuProcessHost::CallOnIO(
+ content::GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
+ false /* force_create */,
+ base::BindRepeating([](content::GpuProcessHost* host) {
+ if (host) {
+ host->gpu_service()->OnForegrounded();
+ }
+ }));
+}
+
// The client_id used here should not conflict with the client_id generated
// from RenderWidgetHostImpl.
constexpr uint32_t kDefaultClientId = 0u;
@@ -161,13 +184,14 @@ class CompositorDependencies {
host_frame_sink_manager.SetConnectionLostCallback(base::BindRepeating(
[]() { CompositorDependencies::Get().CreateVizFrameSinkManager(); }));
- BrowserMainLoop::GetInstance()
- ->gpu_channel_establish_factory()
- ->EstablishGpuChannel(base::BindOnce(
- &CompositorDependencies::
- OnReadyToConnectVizFrameSinkManagerOnMainThread,
- base::Unretained(this), std::move(frame_sink_manager_request),
- frame_sink_manager_client.PassInterface()));
+ pending_connect_viz_on_main_thread_ = base::BindOnce(
+ &CompositorDependencies::
+ OnReadyToConnectVizFrameSinkManagerOnMainThread,
+ base::Unretained(this), std::move(frame_sink_manager_request),
+ frame_sink_manager_client.PassInterface());
+
+ // Will connect using the above callback if we are foreground.
+ TryEstablishVizConnectionIfNeeded();
}
SingleThreadTaskGraphRunner task_graph_runner;
@@ -190,7 +214,13 @@ class CompositorDependencies {
private:
friend class base::NoDestructor<CompositorDependencies>;
- CompositorDependencies() : frame_sink_id_allocator(kDefaultClientId) {
+ CompositorDependencies()
+ : frame_sink_id_allocator(kDefaultClientId),
+ app_listener_(base::BindRepeating(
+ &CompositorDependencies::OnApplicationStateChange,
+ base::Unretained(this))) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
bool enable_viz =
base::FeatureList::IsEnabled(features::kVizDisplayCompositor);
if (!enable_viz) {
@@ -203,6 +233,9 @@ class CompositorDependencies {
} else {
CreateVizFrameSinkManager();
}
+
+ // Ensure we're in the correct state at start up.
+ OnApplicationStateChange(app_listener_.GetState());
}
void OnReadyToConnectVizFrameSinkManagerOnMainThread(
@@ -234,10 +267,85 @@ class CompositorDependencies {
// GpuProcessHost::Get() can return null.
auto* gpu_process_host = GpuProcessHost::Get();
if (gpu_process_host) {
- gpu_process_host->ConnectFrameSinkManager(std::move(request),
- std::move(client));
+ gpu_process_host->gpu_host()->ConnectFrameSinkManager(std::move(request),
+ std::move(client));
+ }
+ }
+
+ void TryEstablishVizConnectionIfNeeded() {
+ // We don't connect to the viz process if backgrounded, as the OS may
+ // repeatedly kill the resulting process. Instead wait until we come to the
+ // foreground.
+ if (pending_connect_viz_on_main_thread_ && application_is_foreground_) {
+ BrowserMainLoop::GetInstance()
+ ->gpu_channel_establish_factory()
+ ->EstablishGpuChannel(std::move(pending_connect_viz_on_main_thread_));
+ }
+ }
+
+ void EnqueueLowEndBackgroundCleanup() {
+ if (base::SysInfo::IsLowEndDevice()) {
+ low_end_background_cleanup_task_.Reset(
+ base::BindOnce(&CompositorDependencies::DoLowEndBackgroundCleanup,
+ base::Unretained(this)));
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE, low_end_background_cleanup_task_.callback(),
+ base::TimeDelta::FromSeconds(5));
+ }
+ }
+
+ void DoLowEndBackgroundCleanup() {
+ // When we become visible, we immediately cancel the callback that runs this
+ // code. First, evict all unlocked frames, allowing resources to be
+ // reclaimed.
+ viz::FrameEvictionManager::GetInstance()->PurgeAllUnlockedFrames();
+
+ // 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 */,
+ base::BindRepeating([](content::GpuProcessHost* host) {
+ if (host) {
+ host->gpu_service()->OnBackgroundCleanup();
+ }
+ }));
+ }
+
+ // This callback function runs when application state changes. If application
+ // state is UNKNOWN, consider it as the app running as a conservative
+ // approach so that we don't send the gpu services to background.
+ void OnApplicationStateChange(
+ base::android::ApplicationState application_state) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ switch (application_state) {
+ case base::android::APPLICATION_STATE_UNKNOWN:
+ case base::android::APPLICATION_STATE_HAS_RUNNING_ACTIVITIES:
+ case base::android::APPLICATION_STATE_HAS_PAUSED_ACTIVITIES:
+ GpuDataManagerImpl::GetInstance()->SetApplicationVisible(true);
+ SendOnForegroundedToGpuService();
+ low_end_background_cleanup_task_.Cancel();
+ application_is_foreground_ = true;
+ TryEstablishVizConnectionIfNeeded();
+ break;
+ case base::android::APPLICATION_STATE_HAS_STOPPED_ACTIVITIES:
+ case base::android::APPLICATION_STATE_HAS_DESTROYED_ACTIVITIES:
+ GpuDataManagerImpl::GetInstance()->SetApplicationVisible(false);
+ SendOnBackgroundedToGpuService();
+ EnqueueLowEndBackgroundCleanup();
+ application_is_foreground_ = false;
}
}
+
+ // A task which runs cleanup tasks on low-end Android after a delay. Enqueued
+ // when we hide, canceled when we're shown.
+ base::CancelableOnceClosure low_end_background_cleanup_task_;
+
+ // An instance of Android AppListener.
+ base::android::ApplicationStatusListener app_listener_;
+ bool application_is_foreground_ = true;
+ gpu::GpuChannelEstablishedCallback pending_connect_viz_on_main_thread_;
};
const unsigned int kMaxDisplaySwapBuffers = 1U;
@@ -361,20 +469,20 @@ void CreateContextProviderAfterGpuChannelEstablished(
constexpr bool support_grcontext = false;
auto context_provider =
- base::MakeRefCounted<ui::ContextProviderCommandBuffer>(
+ base::MakeRefCounted<ws::ContextProviderCommandBuffer>(
std::move(gpu_channel_host), factory->GetGpuMemoryBufferManager(),
stream_id, stream_priority, handle,
GURL(std::string("chrome://gpu/Compositor::CreateContextProvider")),
automatic_flushes, support_locking, support_grcontext,
shared_memory_limits, attributes,
- ui::command_buffer_metrics::ContextType::UNKNOWN);
+ ws::command_buffer_metrics::ContextType::UNKNOWN);
callback.Run(std::move(context_provider));
}
class AndroidOutputSurface : public viz::OutputSurface {
public:
AndroidOutputSurface(
- scoped_refptr<ui::ContextProviderCommandBuffer> context_provider,
+ scoped_refptr<ws::ContextProviderCommandBuffer> context_provider,
base::RepeatingCallback<void(const gfx::Size&)> swap_buffers_callback)
: viz::OutputSurface(std::move(context_provider)),
swap_buffers_callback_(std::move(swap_buffers_callback)),
@@ -459,7 +567,7 @@ class AndroidOutputSurface : public viz::OutputSurface {
uint32_t GetFramebufferCopyTextureFormat() override {
auto* gl =
- static_cast<ui::ContextProviderCommandBuffer*>(context_provider());
+ static_cast<ws::ContextProviderCommandBuffer*>(context_provider());
return gl->GetCopyTextureInternalFormat();
}
@@ -467,8 +575,8 @@ class AndroidOutputSurface : public viz::OutputSurface {
private:
gpu::CommandBufferProxyImpl* GetCommandBufferProxy() {
- ui::ContextProviderCommandBuffer* provider_command_buffer =
- static_cast<ui::ContextProviderCommandBuffer*>(context_provider_.get());
+ ws::ContextProviderCommandBuffer* provider_command_buffer =
+ static_cast<ws::ContextProviderCommandBuffer*>(context_provider_.get());
gpu::CommandBufferProxyImpl* command_buffer_proxy =
provider_command_buffer->GetCommandBufferProxy();
DCHECK(command_buffer_proxy);
@@ -609,33 +717,6 @@ class VulkanOutputSurface : public viz::OutputSurface {
};
#endif
-// TODO(khushalsagar): These are being sent based on the CompositorImpl
-// visiblity which bakes in the assumption that there is a single CompositorImpl
-// instance per application, while the embedder could potentially create
-// multiple compositor instances. We should use the ApplicationStateListener to
-// send these notifications to the GPU instead. See crbug.com/859723.
-void SendOnBackgroundedToGpuService() {
- content::GpuProcessHost::CallOnIO(
- content::GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
- false /* force_create */,
- base::BindRepeating([](content::GpuProcessHost* host) {
- if (host) {
- host->gpu_service()->OnBackgrounded();
- }
- }));
-}
-
-void SendOnForegroundedToGpuService() {
- content::GpuProcessHost::CallOnIO(
- content::GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
- false /* force_create */,
- base::BindRepeating([](content::GpuProcessHost* host) {
- if (host) {
- host->gpu_service()->OnForegrounded();
- }
- }));
-}
-
static bool g_initialized = false;
} // anonymous namespace
@@ -703,9 +784,6 @@ CompositorImpl::CompositorImpl(CompositorClient* client,
enable_viz_(
base::FeatureList::IsEnabled(features::kVizDisplayCompositor)),
weak_factory_(this) {
- GetHostFrameSinkManager()->RegisterFrameSinkId(frame_sink_id_, this);
- GetHostFrameSinkManager()->SetFrameSinkDebugLabel(frame_sink_id_,
- "CompositorImpl");
DCHECK(client);
SetRootWindow(root_window);
@@ -720,7 +798,6 @@ CompositorImpl::~CompositorImpl() {
DetachRootWindow();
// Clean-up any surface references.
SetSurface(NULL);
- GetHostFrameSinkManager()->InvalidateFrameSinkId(frame_sink_id_);
}
void CompositorImpl::DetachRootWindow() {
@@ -858,38 +935,65 @@ void CompositorImpl::CreateLayerTreeHost() {
void CompositorImpl::SetVisible(bool visible) {
TRACE_EVENT1("cc", "CompositorImpl::SetVisible", "visible", visible);
+
if (!visible) {
DCHECK(host_->IsVisible());
+ // Tear down the display first, synchronously completing any pending
+ // draws/readbacks if poosible.
+ TearDownDisplayAndUnregisterRootFrameSink();
+ // Hide the LayerTreeHost and release its frame sink.
+ host_->SetVisible(false);
+ host_->ReleaseLayerTreeFrameSink();
+ has_layer_tree_frame_sink_ = false;
+ pending_frames_ = 0;
+ } else {
+ DCHECK(!host_->IsVisible());
+ RegisterRootFrameSink();
+ host_->SetVisible(true);
+ has_submitted_frame_since_became_visible_ = false;
+ if (layer_tree_frame_sink_request_pending_)
+ HandlePendingLayerTreeFrameSinkRequest();
+ }
+}
+void CompositorImpl::TearDownDisplayAndUnregisterRootFrameSink() {
+ if (enable_viz_) {
+ // Make a best effort to try to complete pending readbacks.
+ // TODO(crbug.com/637035): Consider doing this in a better way,
+ // ideally with the guarantee of readbacks completing.
+ if (display_private_ && HavePendingReadbacks()) {
+ // Note that while this is not a Sync IPC, the call to
+ // InvalidateFrameSinkId below will end up triggering a sync call to
+ // FrameSinkManager::DestroyCompositorFrameSink, as this is the root
+ // frame sink. Because |display_private_| is an associated interface to
+ // FrameSinkManager, this subsequent sync call will ensure ordered
+ // execution of this call.
+ display_private_->ForceImmediateDrawAndSwapIfPossible();
+ }
+
+ GetHostFrameSinkManager()->InvalidateFrameSinkId(frame_sink_id_);
+ display_private_.reset();
+ } else {
// Make a best effort to try to complete pending readbacks.
// TODO(crbug.com/637035): Consider doing this in a better way,
// ideally with the guarantee of readbacks completing.
- if (display_.get() && HavePendingReadbacks())
+ if (display_ && HavePendingReadbacks())
display_->ForceImmediateDrawAndSwapIfPossible();
- host_->SetVisible(false);
- host_->ReleaseLayerTreeFrameSink();
- has_layer_tree_frame_sink_ = false;
- pending_frames_ = 0;
if (display_) {
GetFrameSinkManager()->UnregisterBeginFrameSource(
root_window_->GetBeginFrameSource());
}
+
+ GetHostFrameSinkManager()->InvalidateFrameSinkId(frame_sink_id_);
display_.reset();
- GpuDataManagerImpl::GetInstance()->SetApplicationVisible(false);
- SendOnBackgroundedToGpuService();
- EnqueueLowEndBackgroundCleanup();
- } else {
- host_->SetVisible(true);
- has_submitted_frame_since_became_visible_ = false;
- if (layer_tree_frame_sink_request_pending_)
- HandlePendingLayerTreeFrameSinkRequest();
- GpuDataManagerImpl::GetInstance()->SetApplicationVisible(true);
- SendOnForegroundedToGpuService();
- low_end_background_cleanup_task_.Cancel();
}
- if (display_private_)
- display_private_->SetDisplayVisible(visible);
+}
+
+void CompositorImpl::RegisterRootFrameSink() {
+ GetHostFrameSinkManager()->RegisterFrameSinkId(frame_sink_id_, this);
+ GetHostFrameSinkManager()->SetFrameSinkDebugLabel(frame_sink_id_,
+ "CompositorImpl");
}
void CompositorImpl::SetWindowBounds(const gfx::Size& size) {
@@ -1011,10 +1115,8 @@ void CompositorImpl::OnGpuChannelEstablished(
return;
}
- // We don't need the context anymore if we are invisible. Additionally, we
- // should notify the channel that we are invisible.
+ // We don't need the context anymore if we are invisible.
if (!host_->IsVisible()) {
- SendOnBackgroundedToGpuService();
return;
}
@@ -1036,7 +1138,7 @@ void CompositorImpl::OnGpuChannelEstablished(
gpu::SurfaceHandle surface_handle =
enable_viz_ ? gpu::kNullSurfaceHandle : surface_handle_;
auto context_provider =
- base::MakeRefCounted<ui::ContextProviderCommandBuffer>(
+ base::MakeRefCounted<ws::ContextProviderCommandBuffer>(
std::move(gpu_channel_host), factory->GetGpuMemoryBufferManager(),
stream_id, stream_priority, surface_handle,
GURL(std::string("chrome://gpu/CompositorImpl::") +
@@ -1045,7 +1147,7 @@ void CompositorImpl::OnGpuChannelEstablished(
GetCompositorContextSharedMemoryLimits(root_window_),
GetCompositorContextAttributes(display_color_space_,
requires_alpha_channel_),
- ui::command_buffer_metrics::ContextType::BROWSER_COMPOSITOR);
+ ws::command_buffer_metrics::ContextType::BROWSER_COMPOSITOR);
auto result = context_provider->BindToCurrentThread();
LOG_IF(FATAL, result == gpu::ContextResult::kFatalFailure)
<< "Fatal error making Gpu context";
@@ -1232,44 +1334,26 @@ bool CompositorImpl::IsDrawingFirstVisibleFrame() const {
return !has_submitted_frame_since_became_visible_;
}
-void CompositorImpl::OnCompositorLockStateChanged(bool locked) {
- if (host_)
- host_->SetDeferCommits(locked);
-}
-
-void CompositorImpl::EnqueueLowEndBackgroundCleanup() {
- if (base::SysInfo::IsLowEndDevice()) {
- low_end_background_cleanup_task_.Reset(
- base::BindOnce(&CompositorImpl::DoLowEndBackgroundCleanup,
- weak_factory_.GetWeakPtr()));
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, low_end_background_cleanup_task_.callback(),
- base::TimeDelta::FromSeconds(5));
- }
-}
+void CompositorImpl::SetVSyncPaused(bool paused) {
+ // No action needed in non-Viz mode, as VSync is handled in WindowAndroid.
+ if (!enable_viz_)
+ return;
-void CompositorImpl::DoLowEndBackgroundCleanup() {
- // When we become visible, we immediately cancel the callback that runs this
- // code.
- DCHECK(!host_->IsVisible());
+ if (vsync_paused_ == paused)
+ return;
- // First, evict all unlocked frames, allowing resources to be reclaimed.
- viz::FrameEvictionManager::GetInstance()->PurgeAllUnlockedFrames();
+ vsync_paused_ = paused;
+ if (display_private_)
+ display_private_->SetVSyncPaused(paused);
+}
- // 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 */,
- base::BindRepeating([](content::GpuProcessHost* host) {
- if (host) {
- host->gpu_service()->OnBackgroundCleanup();
- }
- }));
+void CompositorImpl::OnCompositorLockStateChanged(bool locked) {
+ if (host_)
+ host_->SetDeferCommits(locked);
}
void CompositorImpl::InitializeVizLayerTreeFrameSink(
- scoped_refptr<ui::ContextProviderCommandBuffer> context_provider) {
+ scoped_refptr<ws::ContextProviderCommandBuffer> context_provider) {
DCHECK(enable_viz_);
pending_frames_ = 0;
@@ -1297,6 +1381,7 @@ void CompositorImpl::InitializeVizLayerTreeFrameSink(
viz::RendererSettings renderer_settings;
renderer_settings.allow_antialiasing = false;
renderer_settings.highp_threshold_min = 2048;
+ renderer_settings.requires_alpha_channel = requires_alpha_channel_;
root_params->frame_sink_id = frame_sink_id_;
root_params->widget = surface_handle_;
root_params->gpu_compositing = true;
@@ -1325,6 +1410,7 @@ void CompositorImpl::InitializeVizLayerTreeFrameSink(
host_->SetLayerTreeFrameSink(std::move(layer_tree_frame_sink));
display_private_->SetDisplayVisible(true);
display_private_->Resize(size_);
+ display_private_->SetVSyncPaused(vsync_paused_);
}
viz::LocalSurfaceId CompositorImpl::GenerateLocalSurfaceId() const {
diff --git a/chromium/content/browser/renderer_host/compositor_impl_android.h b/chromium/content/browser/renderer_host/compositor_impl_android.h
index ad8f0ea0358..465dee6734a 100644
--- a/chromium/content/browser/renderer_host/compositor_impl_android.h
+++ b/chromium/content/browser/renderer_host/compositor_impl_android.h
@@ -25,8 +25,8 @@
#include "gpu/command_buffer/common/capabilities.h"
#include "gpu/ipc/common/surface_handle.h"
#include "gpu/vulkan/buildflags.h"
-#include "services/ui/public/cpp/gpu/context_provider_command_buffer.h"
#include "services/viz/privileged/interfaces/compositing/display_private.mojom.h"
+#include "services/ws/public/cpp/gpu/context_provider_command_buffer.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "ui/android/resources/resource_manager_impl.h"
#include "ui/android/resources/ui_resource_provider.h"
@@ -148,6 +148,7 @@ class CONTENT_EXPORT CompositorImpl
ui::CompositorLockClient* client,
base::TimeDelta timeout) override;
bool IsDrawingFirstVisibleFrame() const override;
+ void SetVSyncPaused(bool paused) override;
// viz::HostFrameSinkClient implementation.
void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info) override {
@@ -189,9 +190,16 @@ class CONTENT_EXPORT CompositorImpl
// returns an empty surface.
viz::LocalSurfaceId GenerateLocalSurfaceId() const;
+ // Tears down the display for both Viz and non-Viz, unregistering the root
+ // frame sink ID in the process.
+ void TearDownDisplayAndUnregisterRootFrameSink();
+
+ // Registers the root frame sink ID.
+ void RegisterRootFrameSink();
+
// Viz specific functions:
void InitializeVizLayerTreeFrameSink(
- scoped_refptr<ui::ContextProviderCommandBuffer> context_provider);
+ scoped_refptr<ws::ContextProviderCommandBuffer> context_provider);
viz::FrameSinkId frame_sink_id_;
@@ -240,10 +248,6 @@ class CONTENT_EXPORT CompositorImpl
ui::CompositorLockManager lock_manager_;
bool has_submitted_frame_since_became_visible_ = false;
- // A task which runs cleanup tasks on low-end Android after a delay. Enqueued
- // when we hide, canceled when we're shown.
- base::CancelableOnceClosure low_end_background_cleanup_task_;
-
// If true, we are using surface synchronization.
const bool enable_surface_synchronization_;
@@ -253,6 +257,7 @@ class CONTENT_EXPORT CompositorImpl
// Viz-specific members for communicating with the display.
viz::mojom::DisplayPrivateAssociatedPtr display_private_;
std::unique_ptr<viz::HostDisplayClient> display_client_;
+ bool vsync_paused_ = false;
// Test-only. Called when we are notified of a swap.
base::RepeatingCallback<void(const gfx::Size&)>
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 a2b349b0a46..207c42dd823 100644
--- a/chromium/content/browser/renderer_host/compositor_impl_android_browsertest.cc
+++ b/chromium/content/browser/renderer_host/compositor_impl_android_browsertest.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/android/application_status_listener.h"
#include "base/base_switches.h"
#include "base/test/scoped_feature_list.h"
#include "components/viz/common/features.h"
@@ -198,6 +199,8 @@ IN_PROC_BROWSER_TEST_P(CompositorImplLowEndBrowserTest,
ContextLostRunLoop run_loop(context.get());
compositor->SetVisibleForTesting(false);
+ base::android::ApplicationStatusListener::NotifyApplicationStateChange(
+ base::android::APPLICATION_STATE_HAS_STOPPED_ACTIVITIES);
rwhva->OnRootWindowVisibilityChanged(false);
rwhva->Hide();
@@ -208,6 +211,8 @@ IN_PROC_BROWSER_TEST_P(CompositorImplLowEndBrowserTest,
// Become visible again:
compositor->SetVisibleForTesting(true);
+ base::android::ApplicationStatusListener::NotifyApplicationStateChange(
+ base::android::APPLICATION_STATE_HAS_RUNNING_ACTIVITIES);
rwhva->Show();
rwhva->OnRootWindowVisibilityChanged(true);
diff --git a/chromium/content/browser/renderer_host/cursor_manager.cc b/chromium/content/browser/renderer_host/cursor_manager.cc
index 724d64cd472..6d5ec95d2fd 100644
--- a/chromium/content/browser/renderer_host/cursor_manager.cc
+++ b/chromium/content/browser/renderer_host/cursor_manager.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 "cursor_manager.h"
+#include "content/browser/renderer_host/cursor_manager.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
diff --git a/chromium/content/browser/renderer_host/delegated_frame_host.cc b/chromium/content/browser/renderer_host/delegated_frame_host.cc
index 8b8bc279ccf..995ba36a5e1 100644
--- a/chromium/content/browser/renderer_host/delegated_frame_host.cc
+++ b/chromium/content/browser/renderer_host/delegated_frame_host.cc
@@ -15,6 +15,7 @@
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "cc/base/switches.h"
+#include "components/viz/common/features.h"
#include "components/viz/common/frame_sinks/copy_output_request.h"
#include "components/viz/common/quads/compositor_frame.h"
#include "components/viz/common/resources/single_release_callback.h"
@@ -37,22 +38,22 @@ namespace content {
DelegatedFrameHost::DelegatedFrameHost(const viz::FrameSinkId& frame_sink_id,
DelegatedFrameHostClient* client,
- bool enable_viz,
bool should_register_frame_sink_id)
: frame_sink_id_(frame_sink_id),
client_(client),
- enable_viz_(enable_viz),
+ enable_viz_(
+ base::FeatureList::IsEnabled(features::kVizDisplayCompositor)),
should_register_frame_sink_id_(should_register_frame_sink_id),
+ host_frame_sink_manager_(GetHostFrameSinkManager()),
frame_evictor_(std::make_unique<viz::FrameEvictor>(this)) {
ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
factory->GetContextFactory()->AddObserver(this);
- viz::HostFrameSinkManager* host_frame_sink_manager =
- factory->GetContextFactoryPrivate()->GetHostFrameSinkManager();
- host_frame_sink_manager->RegisterFrameSinkId(frame_sink_id_, this);
- host_frame_sink_manager->EnableSynchronizationReporting(
+ DCHECK(host_frame_sink_manager_);
+ host_frame_sink_manager_->RegisterFrameSinkId(frame_sink_id_, this);
+ host_frame_sink_manager_->EnableSynchronizationReporting(
frame_sink_id_, "Compositing.MainFrameSynchronization.Duration");
- host_frame_sink_manager->SetFrameSinkDebugLabel(frame_sink_id_,
- "DelegatedFrameHost");
+ host_frame_sink_manager_->SetFrameSinkDebugLabel(frame_sink_id_,
+ "DelegatedFrameHost");
CreateCompositorFrameSinkSupport();
}
@@ -62,10 +63,8 @@ DelegatedFrameHost::~DelegatedFrameHost() {
factory->GetContextFactory()->RemoveObserver(this);
ResetCompositorFrameSinkSupport();
-
- viz::HostFrameSinkManager* host_frame_sink_manager =
- factory->GetContextFactoryPrivate()->GetHostFrameSinkManager();
- host_frame_sink_manager->InvalidateFrameSinkId(frame_sink_id_);
+ DCHECK(host_frame_sink_manager_);
+ host_frame_sink_manager_->InvalidateFrameSinkId(frame_sink_id_);
}
void DelegatedFrameHost::WasShown(
@@ -142,15 +141,14 @@ void DelegatedFrameHost::ProcessCopyOutputRequest(
gfx::Vector2d(area.width(), area.height()),
gfx::Vector2d(result_selection.width(), result_selection.height()));
}
-
- GetHostFrameSinkManager()->RequestCopyOfOutput(
+ DCHECK(host_frame_sink_manager_);
+ host_frame_sink_manager_->RequestCopyOfOutput(
viz::SurfaceId(frame_sink_id_, pending_local_surface_id_),
std::move(request));
}
bool DelegatedFrameHost::CanCopyFromCompositingSurface() const {
- return (enable_viz_ || support_) && HasFallbackSurface() &&
- active_device_scale_factor_ != 0.f;
+ return HasFallbackSurface() && active_device_scale_factor_ != 0.f;
}
bool DelegatedFrameHost::TransformPointToLocalCoordSpaceLegacy(
@@ -170,19 +168,6 @@ bool DelegatedFrameHost::TransformPointToLocalCoordSpaceLegacy(
transformed_point);
}
-bool DelegatedFrameHost::TransformPointToCoordSpaceForView(
- const gfx::PointF& point,
- RenderWidgetHostViewBase* target_view,
- gfx::PointF* transformed_point,
- viz::EventSource source) {
- if (!HasFallbackSurface())
- return false;
-
- return target_view->TransformPointToLocalCoordSpace(
- point, viz::SurfaceId(frame_sink_id_, active_local_surface_id_),
- transformed_point, source);
-}
-
void DelegatedFrameHost::SetNeedsBeginFrames(bool needs_begin_frames) {
if (enable_viz_) {
NOTIMPLEMENTED();
@@ -334,41 +319,13 @@ void DelegatedFrameHost::OnBeginFramePausedChanged(bool paused) {
void DelegatedFrameHost::OnFirstSurfaceActivation(
const viz::SurfaceInfo& surface_info) {
- // If this is the first Surface created after navigation, notify |client_|.
- // If the Surface was created before navigation, drop it.
- uint32_t parent_sequence_number =
- surface_info.id().local_surface_id().parent_sequence_number();
- uint32_t latest_parent_sequence_number =
- pending_local_surface_id_.parent_sequence_number();
- // If |latest_parent_sequence_number| is less than
- // |first_parent_sequence_number_after_navigation_|, then the parent id has
- // wrapped around. Make sure that case is covered.
- if (parent_sequence_number >=
- first_parent_sequence_number_after_navigation_ ||
- (latest_parent_sequence_number <
- first_parent_sequence_number_after_navigation_ &&
- parent_sequence_number <= latest_parent_sequence_number)) {
- if (!received_frame_after_navigation_) {
- received_frame_after_navigation_ = true;
- client_->DidReceiveFirstFrameAfterNavigation();
- }
- } else {
- ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
- viz::HostFrameSinkManager* host_frame_sink_manager =
- factory->GetContextFactoryPrivate()->GetHostFrameSinkManager();
- host_frame_sink_manager->DropTemporaryReference(surface_info.id());
- return;
- }
-
// If there's no primary surface, then we don't wish to display content at
// this time (e.g. the view is hidden) and so we don't need a fallback
// surface either. Since we won't use the fallback surface, we drop the
// temporary reference here to save resources.
if (!HasPrimarySurface()) {
- ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
- viz::HostFrameSinkManager* host_frame_sink_manager =
- factory->GetContextFactoryPrivate()->GetHostFrameSinkManager();
- host_frame_sink_manager->DropTemporaryReference(surface_info.id());
+ DCHECK(host_frame_sink_manager_);
+ host_frame_sink_manager_->DropTemporaryReference(surface_info.id());
return;
}
@@ -401,14 +358,30 @@ void DelegatedFrameHost::OnBeginFrame(const viz::BeginFrameArgs& args) {
client_->OnBeginFrame(args.frame_time);
}
+void DelegatedFrameHost::ResetFallbackToFirstNavigationSurface() {
+ if (HasFallbackSurface()) {
+ client_->DelegatedFrameHostGetLayer()->SetFallbackSurfaceId(viz::SurfaceId(
+ frame_sink_id_, first_local_surface_id_after_navigation_));
+ }
+}
+
void DelegatedFrameHost::EvictDelegatedFrame() {
- // Replaces the SurfaceLayer with a SolidColorLayer.
- client_->DelegatedFrameHostGetLayer()->SetShowSolidColorContent();
+ // Reset fallback and primary surfaces.
+ if (HasFallbackSurface()) {
+ client_->DelegatedFrameHostGetLayer()->SetFallbackSurfaceId(
+ viz::SurfaceId());
+ }
+ if (HasPrimarySurface()) {
+ client_->DelegatedFrameHostGetLayer()->SetShowPrimarySurface(
+ viz::SurfaceId(), current_frame_size_in_dip_, GetGutterColor(),
+ cc::DeadlinePolicy::UseDefaultDeadline(), false);
+ }
if (!HasSavedFrame())
return;
std::vector<viz::SurfaceId> surface_ids = {GetCurrentSurfaceId()};
- GetHostFrameSinkManager()->EvictSurfaces(surface_ids);
+ DCHECK(host_frame_sink_manager_);
+ host_frame_sink_manager_->EvictSurfaces(surface_ids);
frame_evictor_->DiscardedFrame();
}
@@ -423,16 +396,12 @@ void DelegatedFrameHost::OnCompositingStarted(ui::Compositor* compositor,
void DelegatedFrameHost::OnCompositingEnded(ui::Compositor* compositor) {}
-void DelegatedFrameHost::OnCompositingLockStateChanged(
- ui::Compositor* compositor) {
-}
-
void DelegatedFrameHost::OnCompositingChildResizing(
ui::Compositor* compositor) {}
void DelegatedFrameHost::OnCompositingShuttingDown(ui::Compositor* compositor) {
DCHECK_EQ(compositor, compositor_);
- ResetCompositor();
+ DetachFromCompositor();
DCHECK(!compositor_);
}
@@ -457,23 +426,23 @@ void DelegatedFrameHost::OnLostVizProcess() {
////////////////////////////////////////////////////////////////////////////////
// DelegatedFrameHost, private:
-void DelegatedFrameHost::SetCompositor(ui::Compositor* compositor) {
+void DelegatedFrameHost::AttachToCompositor(ui::Compositor* compositor) {
DCHECK(!compositor_);
if (!compositor)
return;
compositor_ = compositor;
compositor_->AddObserver(this);
if (should_register_frame_sink_id_)
- compositor_->AddFrameSink(frame_sink_id_);
+ compositor_->AddChildFrameSink(frame_sink_id_);
}
-void DelegatedFrameHost::ResetCompositor() {
+void DelegatedFrameHost::DetachFromCompositor() {
if (!compositor_)
return;
if (compositor_->HasObserver(this))
compositor_->RemoveObserver(this);
if (should_register_frame_sink_id_)
- compositor_->RemoveFrameSink(frame_sink_id_);
+ compositor_->RemoveChildFrameSink(frame_sink_id_);
compositor_ = nullptr;
}
@@ -494,13 +463,11 @@ void DelegatedFrameHost::CreateCompositorFrameSinkSupport() {
DCHECK(!support_);
constexpr bool is_root = false;
constexpr bool needs_sync_points = true;
- ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
- support_ = factory->GetContextFactoryPrivate()
- ->GetHostFrameSinkManager()
- ->CreateCompositorFrameSinkSupport(this, frame_sink_id_,
- is_root, needs_sync_points);
+ DCHECK(host_frame_sink_manager_);
+ support_ = host_frame_sink_manager_->CreateCompositorFrameSinkSupport(
+ this, frame_sink_id_, is_root, needs_sync_points);
if (compositor_ && should_register_frame_sink_id_)
- compositor_->AddFrameSink(frame_sink_id_);
+ compositor_->AddChildFrameSink(frame_sink_id_);
if (needs_begin_frame_)
support_->SetNeedsBeginFrame(true);
}
@@ -509,13 +476,12 @@ void DelegatedFrameHost::ResetCompositorFrameSinkSupport() {
if (!support_)
return;
if (compositor_ && should_register_frame_sink_id_)
- compositor_->RemoveFrameSink(frame_sink_id_);
+ compositor_->RemoveChildFrameSink(frame_sink_id_);
support_.reset();
}
void DelegatedFrameHost::DidNavigate() {
- first_parent_sequence_number_after_navigation_ =
- pending_local_surface_id_.parent_sequence_number();
+ first_local_surface_id_after_navigation_ = pending_local_surface_id_;
received_frame_after_navigation_ = false;
}
@@ -525,9 +491,8 @@ bool DelegatedFrameHost::IsPrimarySurfaceEvicted() const {
}
void DelegatedFrameHost::WindowTitleChanged(const std::string& title) {
- auto* host_frame_sink_manager = GetHostFrameSinkManager();
- if (host_frame_sink_manager)
- host_frame_sink_manager->SetFrameSinkDebugLabel(frame_sink_id_, title);
+ if (host_frame_sink_manager_)
+ host_frame_sink_manager_->SetFrameSinkDebugLabel(frame_sink_id_, title);
}
void DelegatedFrameHost::TakeFallbackContentFrom(DelegatedFrameHost* other) {
diff --git a/chromium/content/browser/renderer_host/delegated_frame_host.h b/chromium/content/browser/renderer_host/delegated_frame_host.h
index d8f5261cc35..b223d4708b3 100644
--- a/chromium/content/browser/renderer_host/delegated_frame_host.h
+++ b/chromium/content/browser/renderer_host/delegated_frame_host.h
@@ -17,8 +17,6 @@
#include "components/viz/host/host_frame_sink_client.h"
#include "content/browser/compositor/image_transport_factory.h"
#include "content/browser/renderer_host/dip_util.h"
-#include "content/browser/renderer_host/render_widget_host_impl.h"
-#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/common/content_export.h"
#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h"
#include "services/viz/public/interfaces/hit_test/hit_test_region_list.mojom.h"
@@ -53,7 +51,6 @@ class CONTENT_EXPORT DelegatedFrameHostClient {
const viz::SurfaceInfo& surface_info) = 0;
virtual void OnBeginFrame(base::TimeTicks frame_time) = 0;
virtual void OnFrameTokenChanged(uint32_t frame_token) = 0;
- virtual void DidReceiveFirstFrameAfterNavigation() = 0;
};
// The DelegatedFrameHost is used to host all of the RenderWidgetHostView state
@@ -73,7 +70,6 @@ class CONTENT_EXPORT DelegatedFrameHost
// responsible for doing the appropriate [un]registration.
DelegatedFrameHost(const viz::FrameSinkId& frame_sink_id,
DelegatedFrameHostClient* client,
- bool enable_viz,
bool should_register_frame_sink_id);
~DelegatedFrameHost() override;
@@ -82,7 +78,6 @@ class CONTENT_EXPORT DelegatedFrameHost
void OnCompositingStarted(ui::Compositor* compositor,
base::TimeTicks start_time) override;
void OnCompositingEnded(ui::Compositor* compositor) override;
- void OnCompositingLockStateChanged(ui::Compositor* compositor) override;
void OnCompositingChildResizing(ui::Compositor* compositor) override;
void OnCompositingShuttingDown(ui::Compositor* compositor) override;
@@ -93,6 +88,8 @@ class CONTENT_EXPORT DelegatedFrameHost
// FrameEvictorClient implementation.
void EvictDelegatedFrame() override;
+ void ResetFallbackToFirstNavigationSurface();
+
// viz::mojom::CompositorFrameSinkClient implementation.
void DidReceiveCompositorFrameAck(
const std::vector<viz::ReturnedResource>& resources) override;
@@ -126,8 +123,8 @@ class CONTENT_EXPORT DelegatedFrameHost
const gfx::Size& dip_size,
cc::DeadlinePolicy deadline_policy);
bool HasSavedFrame() const;
- void SetCompositor(ui::Compositor* compositor);
- void ResetCompositor();
+ void AttachToCompositor(ui::Compositor* compositor);
+ void DetachFromCompositor();
// Note: |src_subrect| is specified in DIP dimensions while |output_size|
// expects pixels. If |src_subrect| is empty, the entire surface area is
// copied.
@@ -147,17 +144,6 @@ class CONTENT_EXPORT DelegatedFrameHost
const viz::SurfaceId& original_surface,
gfx::PointF* transformed_point);
- // Given a RenderWidgetHostViewBase that renders to a Surface that is
- // contained within this class' Surface, find the relative transform between
- // the Surfaces and apply it to a point. Returns false if a Surface has not
- // yet been created or if |target_view| is not a descendant RWHV from our
- // client.
- bool TransformPointToCoordSpaceForView(
- const gfx::PointF& point,
- RenderWidgetHostViewBase* target_view,
- gfx::PointF* transformed_point,
- viz::EventSource source = viz::EventSource::ANY);
-
void SetNeedsBeginFrames(bool needs_begin_frames);
void SetWantsAnimateOnlyBeginFrames();
void DidNotProduceFrame(const viz::BeginFrameAck& ack);
@@ -239,6 +225,8 @@ class CONTENT_EXPORT DelegatedFrameHost
// This is the last root background color from a swapped frame.
SkColor background_color_;
+ viz::HostFrameSinkManager* const host_frame_sink_manager_;
+
// State for rendering into a Surface.
std::unique_ptr<viz::CompositorFrameSinkSupport> support_;
@@ -249,7 +237,7 @@ class CONTENT_EXPORT DelegatedFrameHost
std::unique_ptr<viz::FrameEvictor> frame_evictor_;
- uint32_t first_parent_sequence_number_after_navigation_ = 0;
+ viz::LocalSurfaceId first_local_surface_id_after_navigation_;
bool received_frame_after_navigation_ = false;
std::vector<std::unique_ptr<viz::CopyOutputRequest>>
diff --git a/chromium/content/browser/renderer_host/delegated_frame_host_client_android.cc b/chromium/content/browser/renderer_host/delegated_frame_host_client_android.cc
new file mode 100644
index 00000000000..99604021dbd
--- /dev/null
+++ b/chromium/content/browser/renderer_host/delegated_frame_host_client_android.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/renderer_host/delegated_frame_host_client_android.h"
+
+#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "content/browser/renderer_host/render_widget_host_view_android.h"
+
+namespace content {
+
+DelegatedFrameHostClientAndroid::DelegatedFrameHostClientAndroid(
+ RenderWidgetHostViewAndroid* render_widget_host_view)
+ : render_widget_host_view_(render_widget_host_view) {}
+
+DelegatedFrameHostClientAndroid::~DelegatedFrameHostClientAndroid() {}
+
+void DelegatedFrameHostClientAndroid::SetBeginFrameSource(
+ viz::BeginFrameSource* begin_frame_source) {
+ render_widget_host_view_->SetBeginFrameSource(begin_frame_source);
+}
+
+void DelegatedFrameHostClientAndroid::DidReceiveCompositorFrameAck(
+ const std::vector<viz::ReturnedResource>& resources) {
+ render_widget_host_view_->DidReceiveCompositorFrameAck(resources);
+}
+
+void DelegatedFrameHostClientAndroid::DidPresentCompositorFrame(
+ uint32_t presentation_token,
+ const gfx::PresentationFeedback& feedback) {
+ render_widget_host_view_->DidPresentCompositorFrame(presentation_token,
+ feedback);
+}
+
+void DelegatedFrameHostClientAndroid::ReclaimResources(
+ const std::vector<viz::ReturnedResource>& resources) {
+ render_widget_host_view_->ReclaimResources(resources);
+}
+
+void DelegatedFrameHostClientAndroid::OnFrameTokenChanged(
+ uint32_t frame_token) {
+ render_widget_host_view_->OnFrameTokenChangedForView(frame_token);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/delegated_frame_host_client_android.h b/chromium/content/browser/renderer_host/delegated_frame_host_client_android.h
new file mode 100644
index 00000000000..967143a3fea
--- /dev/null
+++ b/chromium/content/browser/renderer_host/delegated_frame_host_client_android.h
@@ -0,0 +1,42 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_DELEGATED_FRAME_HOST_CLIENT_ANDROID_H_
+#define CONTENT_BROWSER_RENDERER_HOST_DELEGATED_FRAME_HOST_CLIENT_ANDROID_H_
+
+#include "base/macros.h"
+#include "content/common/content_export.h"
+#include "ui/android/delegated_frame_host_android.h"
+
+namespace content {
+
+class RenderWidgetHostViewAndroid;
+
+class CONTENT_EXPORT DelegatedFrameHostClientAndroid
+ : public ui::DelegatedFrameHostAndroid::Client {
+ public:
+ explicit DelegatedFrameHostClientAndroid(
+ RenderWidgetHostViewAndroid* render_widget_host_view);
+ ~DelegatedFrameHostClientAndroid() override;
+
+ private:
+ // DelegatedFrameHostAndroid::Client implementation.
+ void SetBeginFrameSource(viz::BeginFrameSource* begin_frame_source) override;
+ void DidPresentCompositorFrame(
+ uint32_t presentation_token,
+ const gfx::PresentationFeedback& feedback) override;
+ void DidReceiveCompositorFrameAck(
+ const std::vector<viz::ReturnedResource>& resources) override;
+ void ReclaimResources(
+ const std::vector<viz::ReturnedResource>& resources) override;
+ void OnFrameTokenChanged(uint32_t frame_token) override;
+
+ RenderWidgetHostViewAndroid* render_widget_host_view_;
+
+ DISALLOW_COPY_AND_ASSIGN(DelegatedFrameHostClientAndroid);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_DELEGATED_FRAME_HOST_CLIENT_ANDROID_H_
diff --git a/chromium/content/browser/renderer_host/delegated_frame_host_client_aura.cc b/chromium/content/browser/renderer_host/delegated_frame_host_client_aura.cc
index 4c83aa1b8d5..b3dc666da0f 100644
--- a/chromium/content/browser/renderer_host/delegated_frame_host_client_aura.cc
+++ b/chromium/content/browser/renderer_host/delegated_frame_host_client_aura.cc
@@ -21,19 +21,20 @@ DelegatedFrameHostClientAura::DelegatedFrameHostClientAura(
DelegatedFrameHostClientAura::~DelegatedFrameHostClientAura() {}
ui::Layer* DelegatedFrameHostClientAura::DelegatedFrameHostGetLayer() const {
- return render_widget_host_view_->window_->layer();
+ return render_widget_host_view_->window()->layer();
}
bool DelegatedFrameHostClientAura::DelegatedFrameHostIsVisible() const {
- return !render_widget_host_view_->host_->is_hidden();
+ return !render_widget_host_view_->host()->is_hidden();
}
SkColor DelegatedFrameHostClientAura::DelegatedFrameHostGetGutterColor() const {
// When making an element on the page fullscreen the element's background
// may not match the page's, so use black as the gutter color to avoid
// flashes of brighter colors during the transition.
- if (render_widget_host_view_->host_->delegate() &&
- render_widget_host_view_->host_->delegate()
+ if (render_widget_host_view_->host()->delegate() &&
+ render_widget_host_view_->host()
+ ->delegate()
->IsFullscreenForCurrentTab()) {
return SK_ColorBLACK;
}
@@ -53,8 +54,4 @@ void DelegatedFrameHostClientAura::OnFrameTokenChanged(uint32_t frame_token) {
render_widget_host_view_->OnFrameTokenChangedForView(frame_token);
}
-void DelegatedFrameHostClientAura::DidReceiveFirstFrameAfterNavigation() {
- render_widget_host_view_->host_->DidReceiveFirstFrameAfterNavigation();
-}
-
} // namespace content
diff --git a/chromium/content/browser/renderer_host/delegated_frame_host_client_aura.h b/chromium/content/browser/renderer_host/delegated_frame_host_client_aura.h
index 9a7964ddc24..3df3bbb637d 100644
--- a/chromium/content/browser/renderer_host/delegated_frame_host_client_aura.h
+++ b/chromium/content/browser/renderer_host/delegated_frame_host_client_aura.h
@@ -33,7 +33,6 @@ class CONTENT_EXPORT DelegatedFrameHostClientAura
void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info) override;
void OnBeginFrame(base::TimeTicks frame_time) override;
void OnFrameTokenChanged(uint32_t frame_token) override;
- void DidReceiveFirstFrameAfterNavigation() override;
private:
RenderWidgetHostViewAura* render_widget_host_view_;
diff --git a/chromium/content/browser/renderer_host/dwrite_font_proxy_message_filter_win.cc b/chromium/content/browser/renderer_host/dwrite_font_proxy_message_filter_win.cc
index 5fb0c0179d5..1302730229f 100644
--- a/chromium/content/browser/renderer_host/dwrite_font_proxy_message_filter_win.cc
+++ b/chromium/content/browser/renderer_host/dwrite_font_proxy_message_filter_win.cc
@@ -22,7 +22,7 @@
#include "base/strings/string16.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "mojo/public/cpp/bindings/callback_helpers.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "ui/gfx/win/direct_write.h"
diff --git a/chromium/content/browser/renderer_host/frame_connector_delegate.h b/chromium/content/browser/renderer_host/frame_connector_delegate.h
index 00a5e62ade0..d5f4343835f 100644
--- a/chromium/content/browser/renderer_host/frame_connector_delegate.h
+++ b/chromium/content/browser/renderer_host/frame_connector_delegate.h
@@ -15,7 +15,7 @@
#include "ui/gfx/geometry/rect.h"
#if defined(USE_AURA)
-#include "services/ui/public/interfaces/window_tree.mojom.h"
+#include "services/ws/public/mojom/window_tree.mojom.h"
#endif
namespace blink {
@@ -144,11 +144,6 @@ class CONTENT_EXPORT FrameConnectorDelegate {
gfx::PointF* transformed_point,
viz::EventSource source = viz::EventSource::ANY);
- // Pass acked touch events to the root view for gesture processing.
- virtual void ForwardProcessAckedTouchEvent(
- const TouchEventWithLatencyInfo& touch,
- InputEventAckState ack_result) {}
-
// Pass acked touchpad pinch gesture events to the root view for processing.
virtual void ForwardAckedTouchpadPinchGestureEvent(
const blink::WebGestureEvent& event,
@@ -183,6 +178,10 @@ class CONTENT_EXPORT FrameConnectorDelegate {
return compositor_visible_rect_;
}
+ // Returns whether the current view may be occluded or distorted (e.g, with
+ // CSS opacity or transform) in the parent view.
+ bool occluded_or_obscured() const { return occluded_or_obscured_; }
+
// Returns the viz::LocalSurfaceId propagated from the parent to be used by
// this child frame.
const viz::LocalSurfaceId& local_surface_id() const {
@@ -242,7 +241,7 @@ class CONTENT_EXPORT FrameConnectorDelegate {
// 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(
- ui::mojom::WindowTreeClientPtr window_tree_client) {}
+ ws::mojom::WindowTreeClientPtr window_tree_client) {}
#endif
// Called by RenderWidgetHostViewChildFrame when the child frame has updated
@@ -266,6 +265,8 @@ class CONTENT_EXPORT FrameConnectorDelegate {
gfx::Rect compositor_visible_rect_;
+ bool occluded_or_obscured_ = false;
+
ScreenInfo screen_info_;
gfx::Size local_frame_size_in_dip_;
gfx::Size local_frame_size_in_pixels_;
diff --git a/chromium/content/browser/renderer_host/input/autoscroll_browsertest.cc b/chromium/content/browser/renderer_host/input/autoscroll_browsertest.cc
new file mode 100644
index 00000000000..0b662c1fd05
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/autoscroll_browsertest.cc
@@ -0,0 +1,155 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/feature_list.h"
+#include "build/build_config.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 "third_party/blink/public/platform/web_input_event.h"
+#include "ui/events/base_event_utils.h"
+
+using blink::WebInputEvent;
+
+namespace {
+
+const std::string kAutoscrollDataURL = R"HTML(
+ <!DOCTYPE html>
+ <meta name='viewport' content='width=device-width'/>
+ <style>
+ html, body {
+ margin: 0;
+ }
+ .spacer { height: 10000px; }
+ </style>
+ <div class=spacer></div>
+ <script>
+ document.title='ready';
+ </script>)HTML";
+} // namespace
+
+namespace content {
+
+class AutoscrollBrowserTest : public ContentBrowserTest {
+ public:
+ AutoscrollBrowserTest() {}
+ ~AutoscrollBrowserTest() override {}
+
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ command_line->AppendSwitchASCII("--enable-blink-features",
+ "MiddleClickAutoscroll");
+ }
+
+ protected:
+ RenderWidgetHostImpl* GetWidgetHost() {
+ return RenderWidgetHostImpl::From(
+ shell()->web_contents()->GetRenderViewHost()->GetWidget());
+ }
+
+ void LoadURL(const std::string& page_data) {
+ const GURL data_url("data:text/html," + page_data);
+ NavigateToURL(shell(), data_url);
+
+ RenderWidgetHostImpl* host = GetWidgetHost();
+ host->GetView()->SetSize(gfx::Size(400, 400));
+
+ base::string16 ready_title(base::ASCIIToUTF16("ready"));
+ TitleWatcher watcher(shell()->web_contents(), ready_title);
+ ignore_result(watcher.WaitAndGetTitle());
+
+ MainThreadFrameObserver main_thread_sync(host);
+ main_thread_sync.Wait();
+ }
+
+ void SimulateMiddleClick(int x, int y, int modifiers) {
+ // Simulate and send middle click mouse down.
+ blink::WebMouseEvent down_event = SyntheticWebMouseEventBuilder::Build(
+ blink::WebInputEvent::kMouseDown, x, y, modifiers);
+ down_event.button = blink::WebMouseEvent::Button::kMiddle;
+ down_event.SetTimeStamp(ui::EventTimeForNow());
+ down_event.SetPositionInScreen(x, y);
+ GetWidgetHost()->ForwardMouseEvent(down_event);
+
+ // Simulate and send middle click mouse up.
+ blink::WebMouseEvent up_event = SyntheticWebMouseEventBuilder::Build(
+ blink::WebInputEvent::kMouseUp, x, y, modifiers);
+ up_event.button = blink::WebMouseEvent::Button::kMiddle;
+ up_event.SetTimeStamp(ui::EventTimeForNow());
+ up_event.SetPositionInScreen(x, y);
+ GetWidgetHost()->ForwardMouseEvent(up_event);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(AutoscrollBrowserTest);
+};
+
+// TODO(sahel): This test is flaky https://crbug.com/838769
+IN_PROC_BROWSER_TEST_F(AutoscrollBrowserTest, DISABLED_AutoscrollFling) {
+ LoadURL(kAutoscrollDataURL);
+
+ // Start autoscroll with middle click.
+ auto input_msg_watcher = std::make_unique<InputMsgWatcher>(
+ GetWidgetHost(), blink::WebInputEvent::kGestureScrollBegin);
+ SimulateMiddleClick(10, 10, blink::WebInputEvent::kNoModifiers);
+ input_msg_watcher->WaitForAck();
+
+ // The page should start scrolling with mouse move.
+ RenderFrameSubmissionObserver observer(
+ GetWidgetHost()->render_frame_metadata_provider());
+ blink::WebMouseEvent move_event = SyntheticWebMouseEventBuilder::Build(
+ blink::WebInputEvent::kMouseMove, 30, 30,
+ blink::WebInputEvent::kNoModifiers);
+ move_event.SetTimeStamp(ui::EventTimeForNow());
+ move_event.SetPositionInScreen(30, 30);
+ GetWidgetHost()->ForwardMouseEvent(move_event);
+ gfx::Vector2dF default_scroll_offset;
+ while (observer.LastRenderFrameMetadata()
+ .root_scroll_offset.value_or(default_scroll_offset)
+ .y() <= 0) {
+ observer.WaitForMetadataChange();
+ }
+}
+
+#if !defined(OS_ANDROID)
+#define MAYBE_WheelScrollingWorksAfterAutoscrollCancel \
+ WheelScrollingWorksAfterAutoscrollCancel
+#else
+#define MAYBE_WheelScrollingWorksAfterAutoscrollCancel \
+ DISABLED_WheelScrollingWorksAfterAutoscrollCancel
+#endif
+// Checks that wheel scrolling works after autoscroll cancelation.
+IN_PROC_BROWSER_TEST_F(AutoscrollBrowserTest,
+ MAYBE_WheelScrollingWorksAfterAutoscrollCancel) {
+ LoadURL(kAutoscrollDataURL);
+
+ // Start autoscroll with middle click.
+ auto input_msg_watcher = std::make_unique<InputMsgWatcher>(
+ GetWidgetHost(), blink::WebInputEvent::kGestureScrollBegin);
+ SimulateMiddleClick(10, 10, blink::WebInputEvent::kNoModifiers);
+ input_msg_watcher->WaitForAck();
+
+ // Without moving the mouse cancel the autoscroll fling with another click.
+ input_msg_watcher = std::make_unique<InputMsgWatcher>(
+ GetWidgetHost(), blink::WebInputEvent::kGestureScrollEnd);
+ SimulateMiddleClick(10, 10, blink::WebInputEvent::kNoModifiers);
+ input_msg_watcher->WaitForAck();
+
+ // The mouse wheel scrolling must work after autoscroll cancellation.
+ RenderFrameSubmissionObserver observer(
+ GetWidgetHost()->render_frame_metadata_provider());
+ blink::WebMouseWheelEvent wheel_event =
+ SyntheticWebMouseWheelEventBuilder::Build(10, 10, 0, -53, 0, true);
+ wheel_event.phase = blink::WebMouseWheelEvent::kPhaseBegan;
+ GetWidgetHost()->ForwardWheelEvent(wheel_event);
+ gfx::Vector2dF default_scroll_offset;
+ while (observer.LastRenderFrameMetadata()
+ .root_scroll_offset.value_or(default_scroll_offset)
+ .y() <= 0) {
+ observer.WaitForMetadataChange();
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/fling_browsertest.cc b/chromium/content/browser/renderer_host/input/fling_browsertest.cc
index b8371dc58c6..cba336b610d 100644
--- a/chromium/content/browser/renderer_host/input/fling_browsertest.cc
+++ b/chromium/content/browser/renderer_host/input/fling_browsertest.cc
@@ -2,13 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "build/build_config.h"
#include "content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
+#include "content/public/test/hit_test_region_observer.h"
#include "content/shell/browser/shell.h"
+#include "content/test/content_browser_test_utils_internal.h"
+#include "net/dns/mock_host_resolver.h"
#include "third_party/blink/public/platform/web_input_event.h"
#include "ui/events/base_event_utils.h"
@@ -51,16 +53,21 @@ class BrowserSideFlingBrowserTest : public ContentBrowserTest {
BrowserSideFlingBrowserTest() {}
~BrowserSideFlingBrowserTest() override {}
- void SetUpCommandLine(base::CommandLine* command_line) override {
- command_line->AppendSwitchASCII("--enable-blink-features",
- "MiddleClickAutoscroll");
- }
-
void OnSyntheticGestureCompleted(SyntheticGesture::Result result) {
EXPECT_EQ(SyntheticGesture::GESTURE_FINISHED, result);
run_loop_->Quit();
}
+ void SetUpOnMainThread() override {
+ host_resolver()->AddRule("*", "127.0.0.1");
+ SetupCrossSiteRedirector(embedded_test_server());
+ ASSERT_TRUE(embedded_test_server()->Start());
+ }
+
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ IsolateAllSitesForTesting(command_line);
+ }
+
protected:
RenderWidgetHostImpl* GetWidgetHost() {
return RenderWidgetHostImpl::From(
@@ -82,25 +89,151 @@ class BrowserSideFlingBrowserTest : public ContentBrowserTest {
main_thread_sync.Wait();
}
- void SimulateMiddleClick(int x, int y, int modifiers) {
- // Simulate and send middle click mouse down.
- blink::WebMouseEvent down_event = SyntheticWebMouseEventBuilder::Build(
- blink::WebInputEvent::kMouseDown, x, y, modifiers);
- down_event.button = blink::WebMouseEvent::Button::kMiddle;
- down_event.SetTimeStamp(ui::EventTimeForNow());
- down_event.SetPositionInScreen(x, y);
- GetWidgetHost()->ForwardMouseEvent(down_event);
-
- // Simulate and send middle click mouse up.
- blink::WebMouseEvent up_event = SyntheticWebMouseEventBuilder::Build(
- blink::WebInputEvent::kMouseUp, x, y, modifiers);
- up_event.button = blink::WebMouseEvent::Button::kMiddle;
- up_event.SetTimeStamp(ui::EventTimeForNow());
- up_event.SetPositionInScreen(x, y);
- GetWidgetHost()->ForwardMouseEvent(up_event);
+ void LoadPageWithOOPIF() {
+ // navigate main frame to URL.
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/frame_tree/page_with_positioned_frame.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ // Navigate oopif to URL.
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+ ASSERT_EQ(1U, root->child_count());
+ FrameTreeNode* iframe_node = root->child_at(0);
+ GURL iframe_url(embedded_test_server()->GetURL("b.com", "/tall_page.html"));
+ NavigateFrameToURL(iframe_node, iframe_url);
+
+ WaitForHitTestDataOrChildSurfaceReady(iframe_node->current_frame_host());
+ FrameTreeVisualizer visualizer;
+ ASSERT_EQ(
+ " Site A ------------ proxies for B\n"
+ " +--Site B ------- proxies for A\n"
+ "Where A = http://a.com/\n"
+ " B = http://b.com/",
+ visualizer.DepictFrameTree(root));
+
+ root_view_ = static_cast<RenderWidgetHostViewBase*>(
+ root->current_frame_host()->GetRenderWidgetHost()->GetView());
+ child_view_ = static_cast<RenderWidgetHostViewBase*>(
+ iframe_node->current_frame_host()->GetRenderWidgetHost()->GetView());
+ }
+
+ void SimulateTouchscreenFling(RenderWidgetHostImpl* render_widget_host) {
+ DCHECK(render_widget_host);
+ // Send a GSB to start scrolling sequence.
+ blink::WebGestureEvent gesture_scroll_begin(
+ blink::WebGestureEvent::kGestureScrollBegin,
+ blink::WebInputEvent::kNoModifiers, ui::EventTimeForNow());
+ gesture_scroll_begin.SetSourceDevice(blink::kWebGestureDeviceTouchscreen);
+ gesture_scroll_begin.data.scroll_begin.delta_hint_units =
+ blink::WebGestureEvent::ScrollUnits::kPrecisePixels;
+ gesture_scroll_begin.data.scroll_begin.delta_x_hint = 0.f;
+ gesture_scroll_begin.data.scroll_begin.delta_y_hint = -5.f;
+ const gfx::PointF scroll_location_in_widget(1, 1);
+ const gfx::PointF scroll_location_in_root =
+ child_view_ ? child_view_->TransformPointToRootCoordSpaceF(
+ scroll_location_in_widget)
+ : scroll_location_in_widget;
+ const gfx::PointF scroll_location_in_screen =
+ child_view_ ? scroll_location_in_root +
+ root_view_->GetViewBounds().OffsetFromOrigin()
+ : scroll_location_in_widget;
+ gesture_scroll_begin.SetPositionInWidget(scroll_location_in_widget);
+ gesture_scroll_begin.SetPositionInScreen(scroll_location_in_screen);
+ render_widget_host->ForwardGestureEvent(gesture_scroll_begin);
+
+ // Send a GFS.
+ blink::WebGestureEvent gesture_fling_start(
+ blink::WebGestureEvent::kGestureFlingStart,
+ blink::WebInputEvent::kNoModifiers, ui::EventTimeForNow());
+ gesture_fling_start.SetSourceDevice(blink::kWebGestureDeviceTouchscreen);
+ gesture_fling_start.data.fling_start.velocity_x = 0.f;
+ gesture_fling_start.data.fling_start.velocity_y = -2000.f;
+ gesture_fling_start.SetPositionInWidget(scroll_location_in_widget);
+ gesture_fling_start.SetPositionInScreen(scroll_location_in_screen);
+ render_widget_host->ForwardGestureEvent(gesture_fling_start);
+ }
+
+ void SimulateTouchpadFling(RenderWidgetHostImpl* render_widget_host) {
+ DCHECK(render_widget_host);
+ // Send a wheel event to start scrolling sequence.
+ auto input_msg_watcher = std::make_unique<InputMsgWatcher>(
+ GetWidgetHost(), blink::WebInputEvent::kMouseWheel);
+ blink::WebMouseWheelEvent wheel_event =
+ SyntheticWebMouseWheelEventBuilder::Build(10, 10, 0, -53, 0, true);
+ wheel_event.phase = blink::WebMouseWheelEvent::kPhaseBegan;
+ const gfx::PointF position_in_widget(1, 1);
+ const gfx::PointF position_in_root =
+ child_view_
+ ? child_view_->TransformPointToRootCoordSpaceF(position_in_widget)
+ : position_in_widget;
+ const gfx::PointF position_in_screen =
+ child_view_
+ ? position_in_root + root_view_->GetViewBounds().OffsetFromOrigin()
+ : position_in_widget;
+ wheel_event.SetPositionInWidget(position_in_widget);
+ wheel_event.SetPositionInScreen(position_in_screen);
+ render_widget_host->ForwardWheelEvent(wheel_event);
+ input_msg_watcher->WaitForAck();
+
+ // Send a GFS.
+ blink::WebGestureEvent gesture_fling_start(
+ blink::WebGestureEvent::kGestureFlingStart,
+ blink::WebInputEvent::kNoModifiers, ui::EventTimeForNow());
+ gesture_fling_start.SetSourceDevice(blink::kWebGestureDeviceTouchpad);
+ gesture_fling_start.data.fling_start.velocity_x = 0.f;
+ gesture_fling_start.data.fling_start.velocity_y = -2000.f;
+ gesture_fling_start.SetPositionInWidget(position_in_widget);
+ gesture_fling_start.SetPositionInScreen(position_in_screen);
+ render_widget_host->ForwardGestureEvent(gesture_fling_start);
+ }
+
+ void WaitForScroll() {
+ RenderFrameSubmissionObserver observer(
+ GetWidgetHost()->render_frame_metadata_provider());
+ gfx::Vector2dF default_scroll_offset;
+ // scrollTop > 0 is not enough since the first progressFling is called from
+ // FlingController::ProcessGestureFlingStart. Wait for scrollTop to exceed
+ // 100 pixels to make sure that ProgressFling has been called through
+ // FlingScheduler at least once.
+ while (observer.LastRenderFrameMetadata()
+ .root_scroll_offset.value_or(default_scroll_offset)
+ .y() <= 100) {
+ observer.WaitForMetadataChange();
+ }
+ }
+
+ void GiveItSomeTime() {
+ base::RunLoop run_loop;
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE, run_loop.QuitClosure(),
+ base::TimeDelta::FromMilliseconds(10));
+ run_loop.Run();
+ }
+
+ void WaitForChildScroll() {
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+ ASSERT_EQ(1U, root->child_count());
+ FrameTreeNode* iframe_node = root->child_at(0);
+ int scroll_top = EvalJs(iframe_node->current_frame_host(), "window.scrollY")
+ .ExtractDouble();
+ // scrollTop > 0 is not enough since the first progressFling is called from
+ // FlingController::ProcessGestureFlingStart. Wait for scrollTop to exceed
+ // 100 pixels to make sure that ProgressFling has been called through
+ // FlingScheduler at least once.
+ while (scroll_top < 100) {
+ GiveItSomeTime();
+ scroll_top = EvalJs(iframe_node->current_frame_host(), "window.scrollY")
+ .ExtractDouble();
+ }
}
std::unique_ptr<base::RunLoop> run_loop_;
+ RenderWidgetHostViewBase* child_view_ = nullptr;
+ RenderWidgetHostViewBase* root_view_ = nullptr;
private:
DISALLOW_COPY_AND_ASSIGN(BrowserSideFlingBrowserTest);
@@ -108,132 +241,24 @@ class BrowserSideFlingBrowserTest : public ContentBrowserTest {
IN_PROC_BROWSER_TEST_F(BrowserSideFlingBrowserTest, TouchscreenFling) {
LoadURL(kBrowserFlingDataURL);
-
- // Send a GSB to start scrolling sequence.
- blink::WebGestureEvent gesture_scroll_begin(
- blink::WebGestureEvent::kGestureScrollBegin,
- blink::WebInputEvent::kNoModifiers, ui::EventTimeForNow());
- gesture_scroll_begin.SetSourceDevice(blink::kWebGestureDeviceTouchscreen);
- gesture_scroll_begin.data.scroll_begin.delta_hint_units =
- blink::WebGestureEvent::ScrollUnits::kPrecisePixels;
- 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);
-
- // Send a GFS and wait for the page to scroll making sure that fling progress
- // has started.
- blink::WebGestureEvent gesture_fling_start(
- blink::WebGestureEvent::kGestureFlingStart,
- blink::WebInputEvent::kNoModifiers, ui::EventTimeForNow());
- gesture_fling_start.SetSourceDevice(blink::kWebGestureDeviceTouchscreen);
- gesture_fling_start.data.fling_start.velocity_x = 0.f;
- gesture_fling_start.data.fling_start.velocity_y = -2000.f;
- GetWidgetHost()->ForwardGestureEvent(gesture_fling_start);
- RenderFrameSubmissionObserver observer(
- GetWidgetHost()->render_frame_metadata_provider());
- gfx::Vector2dF default_scroll_offset;
- while (observer.LastRenderFrameMetadata()
- .root_scroll_offset.value_or(default_scroll_offset)
- .y() <= 0) {
- observer.WaitForMetadataChange();
- }
+ SimulateTouchscreenFling(GetWidgetHost());
+ WaitForScroll();
}
-
IN_PROC_BROWSER_TEST_F(BrowserSideFlingBrowserTest, TouchpadFling) {
LoadURL(kBrowserFlingDataURL);
-
- // Send a wheel event to start scrolling sequence.
- auto input_msg_watcher = std::make_unique<InputMsgWatcher>(
- GetWidgetHost(), blink::WebInputEvent::kMouseWheel);
- blink::WebMouseWheelEvent wheel_event =
- SyntheticWebMouseWheelEventBuilder::Build(10, 10, 0, -53, 0, true);
- wheel_event.phase = blink::WebMouseWheelEvent::kPhaseBegan;
- GetWidgetHost()->ForwardWheelEvent(wheel_event);
- input_msg_watcher->WaitForAck();
-
- // Send a GFS and wait for the page to scroll more than 60 pixels making sure
- // that fling progress has started.
- blink::WebGestureEvent gesture_fling_start(
- blink::WebGestureEvent::kGestureFlingStart,
- blink::WebInputEvent::kNoModifiers, ui::EventTimeForNow());
- gesture_fling_start.SetSourceDevice(blink::kWebGestureDeviceTouchpad);
- gesture_fling_start.data.fling_start.velocity_x = 0.f;
- gesture_fling_start.data.fling_start.velocity_y = -2000.f;
- GetWidgetHost()->ForwardGestureEvent(gesture_fling_start);
- RenderFrameSubmissionObserver observer(
- GetWidgetHost()->render_frame_metadata_provider());
- gfx::Vector2dF default_scroll_offset;
- while (observer.LastRenderFrameMetadata()
- .root_scroll_offset.value_or(default_scroll_offset)
- .y() <= 60) {
- observer.WaitForMetadataChange();
- }
+ SimulateTouchpadFling(GetWidgetHost());
+ WaitForScroll();
}
-// TODO(sahel): This test is flaky https://crbug.com/838769
-IN_PROC_BROWSER_TEST_F(BrowserSideFlingBrowserTest, DISABLED_AutoscrollFling) {
- LoadURL(kBrowserFlingDataURL);
-
- // Start autoscroll with middle click.
- auto input_msg_watcher = std::make_unique<InputMsgWatcher>(
- GetWidgetHost(), blink::WebInputEvent::kGestureScrollBegin);
- SimulateMiddleClick(10, 10, blink::WebInputEvent::kNoModifiers);
- input_msg_watcher->WaitForAck();
-
- // The page should start scrolling with mouse move.
- RenderFrameSubmissionObserver observer(
- GetWidgetHost()->render_frame_metadata_provider());
- blink::WebMouseEvent move_event = SyntheticWebMouseEventBuilder::Build(
- blink::WebInputEvent::kMouseMove, 30, 30,
- blink::WebInputEvent::kNoModifiers);
- move_event.SetTimeStamp(ui::EventTimeForNow());
- move_event.SetPositionInScreen(30, 30);
- GetWidgetHost()->ForwardMouseEvent(move_event);
- gfx::Vector2dF default_scroll_offset;
- while (observer.LastRenderFrameMetadata()
- .root_scroll_offset.value_or(default_scroll_offset)
- .y() <= 0) {
- observer.WaitForMetadataChange();
- }
+IN_PROC_BROWSER_TEST_F(BrowserSideFlingBrowserTest, TouchscreenFlingInOOPIF) {
+ LoadPageWithOOPIF();
+ SimulateTouchscreenFling(child_view_->host());
+ WaitForChildScroll();
}
-
-#if !defined(OS_ANDROID)
-#define MAYBE_WheelScrollingWorksAfterAutoscrollCancel \
- WheelScrollingWorksAfterAutoscrollCancel
-#else
-#define MAYBE_WheelScrollingWorksAfterAutoscrollCancel \
- DISABLED_WheelScrollingWorksAfterAutoscrollCancel
-#endif
-// Checks that wheel scrolling works after autoscroll cancelation.
-IN_PROC_BROWSER_TEST_F(BrowserSideFlingBrowserTest,
- MAYBE_WheelScrollingWorksAfterAutoscrollCancel) {
- LoadURL(kBrowserFlingDataURL);
-
- // Start autoscroll with middle click.
- auto input_msg_watcher = std::make_unique<InputMsgWatcher>(
- GetWidgetHost(), blink::WebInputEvent::kGestureScrollBegin);
- SimulateMiddleClick(10, 10, blink::WebInputEvent::kNoModifiers);
- input_msg_watcher->WaitForAck();
-
- // Without moving the mouse cancel the autoscroll fling with another click.
- input_msg_watcher = std::make_unique<InputMsgWatcher>(
- GetWidgetHost(), blink::WebInputEvent::kGestureScrollEnd);
- SimulateMiddleClick(10, 10, blink::WebInputEvent::kNoModifiers);
- input_msg_watcher->WaitForAck();
-
- // The mouse wheel scrolling must work after autoscroll cancellation.
- RenderFrameSubmissionObserver observer(
- GetWidgetHost()->render_frame_metadata_provider());
- blink::WebMouseWheelEvent wheel_event =
- SyntheticWebMouseWheelEventBuilder::Build(10, 10, 0, -53, 0, true);
- wheel_event.phase = blink::WebMouseWheelEvent::kPhaseBegan;
- GetWidgetHost()->ForwardWheelEvent(wheel_event);
- gfx::Vector2dF default_scroll_offset;
- while (observer.LastRenderFrameMetadata()
- .root_scroll_offset.value_or(default_scroll_offset)
- .y() <= 0) {
- observer.WaitForMetadataChange();
- }
+IN_PROC_BROWSER_TEST_F(BrowserSideFlingBrowserTest, TouchpadFlingInOOPIF) {
+ LoadPageWithOOPIF();
+ SimulateTouchscreenFling(child_view_->host());
+ WaitForChildScroll();
}
// Disabled on MacOS because it doesn't support touchscreen scroll.
diff --git a/chromium/content/browser/renderer_host/input/fling_controller.cc b/chromium/content/browser/renderer_host/input/fling_controller.cc
index ef40b4f664a..a82ea976947 100644
--- a/chromium/content/browser/renderer_host/input/fling_controller.cc
+++ b/chromium/content/browser/renderer_host/input/fling_controller.cc
@@ -16,12 +16,23 @@ using blink::WebInputEvent;
using blink::WebGestureEvent;
namespace {
+constexpr base::TimeDelta kFrameDelta =
+ base::TimeDelta::FromSecondsD(1.0 / 60.0);
+
// Maximum time between a fling event's timestamp and the first |Progress| call
// for the fling curve to use the fling timestamp as the initial animation time.
// Two frames allows a minor delay between event creation and the first
// progress.
constexpr base::TimeDelta kMaxMicrosecondsFromFlingTimestampToFirstProgress =
- base::TimeDelta::FromMicroseconds(33333);
+ base::TimeDelta::FromSecondsD(2.0 / 60.0);
+
+// Since the progress fling is called in ProcessGestureFlingStart right after
+// processing the GFS, it is possible to have a very small delta for the first
+// event. Don't send an event with deltas smaller than the
+// |kMinInertialScrollDelta| since the renderer ignores it and the fling gets
+// cancelled in FlingController::OnGestureEventAck due to an inertial GSU with
+// ack ignored.
+const float kMinInertialScrollDelta = 0.1f;
const char* kFlingTraceName = "FlingController::HandlingGestureFling";
} // namespace
@@ -177,7 +188,14 @@ void FlingController::ProcessGestureFlingStart(
current_fling_parameters_.velocity,
current_fling_parameters_.source_device,
current_fling_parameters_.modifiers);
- ScheduleFlingProgress();
+
+ // Wait for BeginFrame to call ProgressFling when
+ // SetNeedsBeginFrameForFlingProgress is used to progress flings instead of
+ // compositor animation observer (happens on Android WebView).
+ if (scheduler_client_->NeedsBeginFrameForFlingProgress())
+ ScheduleFlingProgress();
+ else
+ ProgressFling(base::TimeTicks::Now());
}
void FlingController::ScheduleFlingProgress() {
@@ -206,16 +224,34 @@ void FlingController::ProgressFling(base::TimeTicks current_time) {
}
if (!has_fling_animation_started_) {
- // Guard against invalid, future or sufficiently stale start times, as there
- // are no guarantees fling event and progress timestamps are compatible.
- if (current_fling_parameters_.start_time.is_null() ||
- current_time <= current_fling_parameters_.start_time ||
- current_time >= current_fling_parameters_.start_time +
- kMaxMicrosecondsFromFlingTimestampToFirstProgress) {
+ // Guard against invalid as there are no guarantees fling event and progress
+ // timestamps are compatible.
+ if (current_fling_parameters_.start_time.is_null()) {
current_fling_parameters_.start_time = current_time;
ScheduleFlingProgress();
return;
}
+
+ // If the first time that progressFling is called is more than two frames
+ // later than the fling start time, delay the fling start time to one frame
+ // prior to the current time. This makes sure that at least one progress
+ // event is sent while the fling is active even when the fling duration is
+ // short (samll velocity) and the time delta between its timestamp and its
+ // processing time is big (e.g. When a GFS gets bubbled from an oopif).
+ if (current_time >= current_fling_parameters_.start_time +
+ kMaxMicrosecondsFromFlingTimestampToFirstProgress) {
+ current_fling_parameters_.start_time = current_time - kFrameDelta;
+ }
+ }
+
+ // ProgressFling is called inside FlingScheduler::OnAnimationStep. Sometimes
+ // the first OnAnimationStep call has the time of the last frame before
+ // AddAnimationObserver call rather than time of the first frame after
+ // AddAnimationObserver call. Do not advance the fling when current_time is
+ // less than the GFS event timestamp.
+ if (current_time <= current_fling_parameters_.start_time) {
+ ScheduleFlingProgress();
+ return;
}
gfx::Vector2dF delta_to_scroll;
@@ -223,7 +259,8 @@ void FlingController::ProgressFling(base::TimeTicks current_time) {
(current_time - current_fling_parameters_.start_time).InSecondsF(),
current_fling_parameters_.velocity, delta_to_scroll);
if (fling_is_active) {
- if (delta_to_scroll != gfx::Vector2d()) {
+ if (std::abs(delta_to_scroll.x()) > kMinInertialScrollDelta ||
+ std::abs(delta_to_scroll.y()) > kMinInertialScrollDelta) {
GenerateAndSendFlingProgressEvents(delta_to_scroll);
has_fling_animation_started_ = true;
}
@@ -419,11 +456,6 @@ bool FlingController::FlingCancellationIsDeferred() const {
return fling_booster_ && fling_booster_->fling_cancellation_is_deferred();
}
-bool FlingController::TouchscreenFlingInProgress() const {
- return fling_in_progress_ && current_fling_parameters_.source_device ==
- blink::kWebGestureDeviceTouchscreen;
-}
-
gfx::Vector2dF FlingController::CurrentFlingVelocity() const {
return current_fling_parameters_.velocity;
}
diff --git a/chromium/content/browser/renderer_host/input/fling_controller.h b/chromium/content/browser/renderer_host/input/fling_controller.h
index 869e17b79e2..56e997187ca 100644
--- a/chromium/content/browser/renderer_host/input/fling_controller.h
+++ b/chromium/content/browser/renderer_host/input/fling_controller.h
@@ -46,6 +46,8 @@ class CONTENT_EXPORT FlingControllerSchedulerClient {
virtual void DidStopFlingingOnBrowser(
base::WeakPtr<FlingController> fling_controller) = 0;
+
+ virtual bool NeedsBeginFrameForFlingProgress() = 0;
};
class CONTENT_EXPORT FlingController {
@@ -99,8 +101,6 @@ class CONTENT_EXPORT FlingController {
bool FlingCancellationIsDeferred() const;
- bool TouchscreenFlingInProgress() const;
-
gfx::Vector2dF CurrentFlingVelocity() const;
// Returns the |TouchpadTapSuppressionController| instance.
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 9f658accb9f..3478d4eb08e 100644
--- a/chromium/content/browser/renderer_host/input/fling_controller_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/fling_controller_unittest.cc
@@ -6,6 +6,7 @@
#include "base/run_loop.h"
#include "base/test/scoped_task_environment.h"
+#include "build/build_config.h"
#include "content/browser/renderer_host/input/gesture_event_queue.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/events/base_event_utils.h"
@@ -32,14 +33,15 @@ class FakeFlingController : public FlingController {
bool FlingBoosted() const { return fling_booster_->fling_boosted(); }
};
-class FlingControllerTest : public testing::Test,
- public GestureEventQueueClient,
+class FlingControllerTest : public GestureEventQueueClient,
public FlingControllerEventSenderClient,
- public FlingControllerSchedulerClient {
+ public FlingControllerSchedulerClient,
+ public testing::TestWithParam<bool> {
public:
// testing::Test
FlingControllerTest()
- : scoped_task_environment_(
+ : needs_begin_frame_for_fling_progress_(GetParam()),
+ scoped_task_environment_(
base::test::ScopedTaskEnvironment::MainThreadType::UI) {}
~FlingControllerTest() override {}
@@ -62,9 +64,14 @@ class FlingControllerTest : public testing::Test,
void SendGeneratedWheelEvent(
const MouseWheelEventWithLatencyInfo& wheel_event) override {
last_sent_wheel_ = wheel_event.event;
+ first_wheel_event_sent_ = true;
+
+ if (wheel_event.event.momentum_phase == WebMouseWheelEvent::kPhaseEnded)
+ first_wheel_event_sent_ = false;
}
void SendGeneratedGestureScrollEvents(
const GestureEventWithLatencyInfo& gesture_event) override {
+ sent_scroll_gesture_count_++;
last_sent_gesture_ = gesture_event.event;
}
@@ -78,10 +85,14 @@ class FlingControllerTest : public testing::Test,
base::WeakPtr<FlingController> fling_controller) override {
notified_client_after_fling_stop_ = true;
}
+ bool NeedsBeginFrameForFlingProgress() override {
+ return needs_begin_frame_for_fling_progress_;
+ }
void SimulateFlingStart(blink::WebGestureDevice source_device,
const gfx::Vector2dF& velocity) {
scheduled_next_fling_progress_ = false;
+ sent_scroll_gesture_count_ = 0;
WebGestureEvent fling_start(WebInputEvent::kGestureFlingStart, 0,
base::TimeTicks::Now(), source_device);
fling_start.data.fling_start.velocity_x = velocity.x();
@@ -121,13 +132,19 @@ class FlingControllerTest : public testing::Test,
bool last_fling_cancel_filtered_;
bool scheduled_next_fling_progress_;
bool notified_client_after_fling_stop_;
+ bool first_wheel_event_sent_ = false;
+ int sent_scroll_gesture_count_ = 0;
private:
+ bool needs_begin_frame_for_fling_progress_;
base::test::ScopedTaskEnvironment scoped_task_environment_;
std::unique_ptr<GestureEventQueue> queue_;
+ DISALLOW_COPY_AND_ASSIGN(FlingControllerTest);
};
-TEST_F(FlingControllerTest,
+INSTANTIATE_TEST_CASE_P(, FlingControllerTest, testing::Bool());
+
+TEST_P(FlingControllerTest,
ControllerSendsWheelEndOnTouchpadFlingWithZeroVelocity) {
SimulateFlingStart(blink::kWebGestureDeviceTouchpad, gfx::Vector2dF());
// The controller doesn't start a fling and sends a wheel end event
@@ -138,7 +155,7 @@ TEST_F(FlingControllerTest,
EXPECT_EQ(0.f, last_sent_wheel_.delta_y);
}
-TEST_F(FlingControllerTest,
+TEST_P(FlingControllerTest,
ControllerSendsGSEOnTouchscreenFlingWithZeroVelocity) {
SimulateFlingStart(blink::kWebGestureDeviceTouchscreen, gfx::Vector2dF());
// The controller doesn't start a fling and sends a GSE immediately.
@@ -146,14 +163,25 @@ TEST_F(FlingControllerTest,
EXPECT_EQ(WebInputEvent::kGestureScrollEnd, last_sent_gesture_.GetType());
}
-TEST_F(FlingControllerTest, ControllerHandlesTouchpadGestureFling) {
+// TODO(https://crbug.com/836996): Timing-dependent flakes on some platforms.
+TEST_P(FlingControllerTest, DISABLED_ControllerHandlesTouchpadGestureFling) {
base::TimeTicks progress_time = base::TimeTicks::Now();
SimulateFlingStart(blink::kWebGestureDeviceTouchpad, gfx::Vector2dF(1000, 0));
EXPECT_TRUE(FlingInProgress());
- // The first wheel event must have momentum_phase == KPhaseBegan.
+ // Processing GFS will send the first fling prgoress event if the time delta
+ // between the timestamp of the GFS and the time that ProcessGestureFlingStart
+ // is called is large enough.
+ bool process_GFS_sent_first_event = first_wheel_event_sent_;
+
progress_time += base::TimeDelta::FromMilliseconds(17);
ProgressFling(progress_time);
- EXPECT_EQ(WebMouseWheelEvent::kPhaseBegan, last_sent_wheel_.momentum_phase);
+
+ if (!process_GFS_sent_first_event) {
+ EXPECT_EQ(WebMouseWheelEvent::kPhaseBegan, last_sent_wheel_.momentum_phase);
+ } else {
+ EXPECT_EQ(WebMouseWheelEvent::kPhaseChanged,
+ last_sent_wheel_.momentum_phase);
+ }
EXPECT_GT(last_sent_wheel_.delta_x, 0.f);
// The rest of the wheel events must have momentum_phase == KPhaseChanged.
@@ -176,7 +204,8 @@ TEST_F(FlingControllerTest, ControllerHandlesTouchpadGestureFling) {
EXPECT_EQ(0.f, last_sent_wheel_.delta_y);
}
-TEST_F(FlingControllerTest, ControllerHandlesTouchscreenGestureFling) {
+// TODO(https://crbug.com/836996): Timing-dependent flakes on some platforms.
+TEST_P(FlingControllerTest, DISABLED_ControllerHandlesTouchscreenGestureFling) {
base::TimeTicks progress_time = base::TimeTicks::Now();
SimulateFlingStart(blink::kWebGestureDeviceTouchscreen,
gfx::Vector2dF(1000, 0));
@@ -202,13 +231,25 @@ TEST_F(FlingControllerTest, ControllerHandlesTouchscreenGestureFling) {
EXPECT_EQ(WebInputEvent::kGestureScrollEnd, last_sent_gesture_.GetType());
}
-TEST_F(FlingControllerTest, ControllerSendsWheelEndWhenTouchpadFlingIsOver) {
+// TODO(https://crbug.com/836996): Timing-dependent flakes on some platforms.
+TEST_P(FlingControllerTest,
+ DISABLED_ControllerSendsWheelEndWhenTouchpadFlingIsOver) {
base::TimeTicks progress_time = base::TimeTicks::Now();
SimulateFlingStart(blink::kWebGestureDeviceTouchpad, gfx::Vector2dF(100, 0));
EXPECT_TRUE(FlingInProgress());
+ // Processing GFS will send the first fling prgoress event if the time delta
+ // between the timestamp of the GFS and the time that ProcessGestureFlingStart
+ // is called is large enough.
+ bool process_GFS_sent_first_event = first_wheel_event_sent_;
+
progress_time += base::TimeDelta::FromMilliseconds(17);
ProgressFling(progress_time);
- EXPECT_EQ(WebMouseWheelEvent::kPhaseBegan, last_sent_wheel_.momentum_phase);
+ if (!process_GFS_sent_first_event) {
+ EXPECT_EQ(WebMouseWheelEvent::kPhaseBegan, last_sent_wheel_.momentum_phase);
+ } else {
+ EXPECT_EQ(WebMouseWheelEvent::kPhaseChanged,
+ last_sent_wheel_.momentum_phase);
+ }
EXPECT_GT(last_sent_wheel_.delta_x, 0.f);
progress_time += base::TimeDelta::FromMilliseconds(17);
@@ -226,7 +267,9 @@ TEST_F(FlingControllerTest, ControllerSendsWheelEndWhenTouchpadFlingIsOver) {
EXPECT_EQ(0.f, last_sent_wheel_.delta_y);
}
-TEST_F(FlingControllerTest, ControllerSendsGSEWhenTouchscreenFlingIsOver) {
+// TODO(https://crbug.com/836996): Timing-dependent flakes on some platforms.
+TEST_P(FlingControllerTest,
+ DISABLED_ControllerSendsGSEWhenTouchscreenFlingIsOver) {
base::TimeTicks progress_time = base::TimeTicks::Now();
SimulateFlingStart(blink::kWebGestureDeviceTouchscreen,
gfx::Vector2dF(100, 0));
@@ -247,14 +290,25 @@ TEST_F(FlingControllerTest, ControllerSendsGSEWhenTouchscreenFlingIsOver) {
EXPECT_EQ(WebInputEvent::kGestureScrollEnd, last_sent_gesture_.GetType());
}
-TEST_F(FlingControllerTest,
- EarlyTouchpadFlingCancelationOnInertialGSUAckNotConsumed) {
+// TODO(https://crbug.com/836996): Timing-dependent flakes on some platforms.
+TEST_P(FlingControllerTest,
+ DISABLED_EarlyTouchpadFlingCancelationOnInertialGSUAckNotConsumed) {
base::TimeTicks progress_time = base::TimeTicks::Now();
SimulateFlingStart(blink::kWebGestureDeviceTouchpad, gfx::Vector2dF(1000, 0));
EXPECT_TRUE(FlingInProgress());
+ // Processing GFS will send the first fling prgoress event if the time delta
+ // between the timestamp of the GFS and the time that ProcessGestureFlingStart
+ // is called is large enough.
+ bool process_GFS_sent_first_event = first_wheel_event_sent_;
+
progress_time += base::TimeDelta::FromMilliseconds(17);
ProgressFling(progress_time);
- EXPECT_EQ(WebMouseWheelEvent::kPhaseBegan, last_sent_wheel_.momentum_phase);
+ if (!process_GFS_sent_first_event) {
+ EXPECT_EQ(WebMouseWheelEvent::kPhaseBegan, last_sent_wheel_.momentum_phase);
+ } else {
+ EXPECT_EQ(WebMouseWheelEvent::kPhaseChanged,
+ last_sent_wheel_.momentum_phase);
+ }
EXPECT_GT(last_sent_wheel_.delta_x, 0.f);
// A non-consumed GSU ack in inertial state cancels out the rest of the fling.
@@ -272,8 +326,9 @@ TEST_F(FlingControllerTest,
EXPECT_EQ(0.f, last_sent_wheel_.delta_y);
}
-TEST_F(FlingControllerTest,
- EarlyTouchscreenFlingCancelationOnInertialGSUAckNotConsumed) {
+// TODO(https://crbug.com/836996): Timing-dependent flakes on some platforms.
+TEST_P(FlingControllerTest,
+ DISABLED_EarlyTouchscreenFlingCancelationOnInertialGSUAckNotConsumed) {
base::TimeTicks progress_time = base::TimeTicks::Now();
SimulateFlingStart(blink::kWebGestureDeviceTouchscreen,
gfx::Vector2dF(1000, 0));
@@ -298,13 +353,24 @@ TEST_F(FlingControllerTest,
EXPECT_EQ(WebInputEvent::kGestureScrollEnd, last_sent_gesture_.GetType());
}
-TEST_F(FlingControllerTest, EarlyTouchpadFlingCancelationOnFlingStop) {
+// Flaky. https://crbug.com/836996.
+TEST_P(FlingControllerTest, DISABLED_EarlyTouchpadFlingCancelationOnFlingStop) {
base::TimeTicks progress_time = base::TimeTicks::Now();
SimulateFlingStart(blink::kWebGestureDeviceTouchpad, gfx::Vector2dF(1000, 0));
EXPECT_TRUE(FlingInProgress());
+ // Processing GFS will send the first fling prgoress event if the time delta
+ // between the timestamp of the GFS and the time that ProcessGestureFlingStart
+ // is called is large enough.
+ bool process_GFS_sent_first_event = first_wheel_event_sent_;
+
progress_time += base::TimeDelta::FromMilliseconds(17);
ProgressFling(progress_time);
- EXPECT_EQ(WebMouseWheelEvent::kPhaseBegan, last_sent_wheel_.momentum_phase);
+ if (!process_GFS_sent_first_event) {
+ EXPECT_EQ(WebMouseWheelEvent::kPhaseBegan, last_sent_wheel_.momentum_phase);
+ } else {
+ EXPECT_EQ(WebMouseWheelEvent::kPhaseChanged,
+ last_sent_wheel_.momentum_phase);
+ }
EXPECT_GT(last_sent_wheel_.delta_x, 0.f);
fling_controller_->StopFling();
@@ -314,7 +380,7 @@ TEST_F(FlingControllerTest, EarlyTouchpadFlingCancelationOnFlingStop) {
EXPECT_EQ(0.f, last_sent_wheel_.delta_y);
}
-TEST_F(FlingControllerTest, EarlyTouchscreenFlingCancelationOnFlingStop) {
+TEST_P(FlingControllerTest, EarlyTouchscreenFlingCancelationOnFlingStop) {
base::TimeTicks progress_time = base::TimeTicks::Now();
SimulateFlingStart(blink::kWebGestureDeviceTouchscreen,
gfx::Vector2dF(1000, 0));
@@ -333,7 +399,7 @@ TEST_F(FlingControllerTest, EarlyTouchscreenFlingCancelationOnFlingStop) {
EXPECT_EQ(WebInputEvent::kGestureScrollEnd, last_sent_gesture_.GetType());
}
-TEST_F(FlingControllerTest, GestureFlingCancelsFiltered) {
+TEST_P(FlingControllerTest, GestureFlingCancelsFiltered) {
// GFC without previous GFS is dropped.
SimulateFlingCancel(blink::kWebGestureDeviceTouchscreen);
EXPECT_TRUE(last_fling_cancel_filtered_);
@@ -352,7 +418,7 @@ TEST_F(FlingControllerTest, GestureFlingCancelsFiltered) {
}
// Flaky. https://crbug.com/836996.
-TEST_F(FlingControllerTest, DISABLED_GestureFlingNotCancelledBySmallTimeDelta) {
+TEST_P(FlingControllerTest, DISABLED_GestureFlingNotCancelledBySmallTimeDelta) {
base::TimeTicks progress_time = base::TimeTicks::Now();
SimulateFlingStart(blink::kWebGestureDeviceTouchscreen,
gfx::Vector2dF(1000, 0));
@@ -377,19 +443,20 @@ TEST_F(FlingControllerTest, DISABLED_GestureFlingNotCancelledBySmallTimeDelta) {
EXPECT_GT(last_sent_gesture_.data.scroll_update.delta_x, 0.f);
}
-TEST_F(FlingControllerTest, GestureFlingWithNegativeTimeDelta) {
+// TODO(https://crbug.com/836996): Timing-dependent flakes on some platforms.
+TEST_P(FlingControllerTest, DISABLED_GestureFlingWithNegativeTimeDelta) {
base::TimeTicks progress_time = base::TimeTicks::Now();
SimulateFlingStart(blink::kWebGestureDeviceTouchscreen,
gfx::Vector2dF(1000, 0));
EXPECT_TRUE(FlingInProgress());
+ int current_sent_scroll_gesture_count = sent_scroll_gesture_count_;
// If we get a negative time delta, that is, the Progress tick time happens
// before the fling's start time then we should *not* try progressing the
- // fling and instead reset the fling start time.
+ // fling.
progress_time -= base::TimeDelta::FromMilliseconds(5);
ProgressFling(progress_time);
- EXPECT_EQ(blink::kWebGestureDeviceUninitialized,
- last_sent_gesture_.SourceDevice());
+ EXPECT_EQ(current_sent_scroll_gesture_count, sent_scroll_gesture_count_);
// The rest of the progress flings must advance the fling normally.
progress_time += base::TimeDelta::FromMilliseconds(17);
@@ -402,14 +469,29 @@ TEST_F(FlingControllerTest, GestureFlingWithNegativeTimeDelta) {
EXPECT_GT(last_sent_gesture_.data.scroll_update.delta_x, 0.f);
}
-TEST_F(FlingControllerTest, ControllerBoostsTouchpadFling) {
+#if defined(OS_LINUX)
+#define MAYBE_ControllerBoostsTouchpadFling \
+ DISABLED_ControllerBoostsTouchpadFling
+#else
+#define MAYBE_ControllerBoostsTouchpadFling ControllerBoostsTouchpadFling
+#endif
+TEST_P(FlingControllerTest, MAYBE_ControllerBoostsTouchpadFling) {
base::TimeTicks progress_time = base::TimeTicks::Now();
SimulateFlingStart(blink::kWebGestureDeviceTouchpad, gfx::Vector2dF(1000, 0));
EXPECT_TRUE(FlingInProgress());
- // The first wheel event must have momentum_phase == KPhaseBegan.
+ // Processing GFS will send the first fling prgoress event if the time delta
+ // between the timestamp of the GFS and the time that ProcessGestureFlingStart
+ // is called is large enough.
+ bool process_GFS_sent_first_event = first_wheel_event_sent_;
+
progress_time += base::TimeDelta::FromMilliseconds(17);
ProgressFling(progress_time);
- EXPECT_EQ(WebMouseWheelEvent::kPhaseBegan, last_sent_wheel_.momentum_phase);
+ if (!process_GFS_sent_first_event) {
+ EXPECT_EQ(WebMouseWheelEvent::kPhaseBegan, last_sent_wheel_.momentum_phase);
+ } else {
+ EXPECT_EQ(WebMouseWheelEvent::kPhaseChanged,
+ last_sent_wheel_.momentum_phase);
+ }
EXPECT_GT(last_sent_wheel_.delta_x, 0.f);
// The rest of the wheel events must have momentum_phase == KPhaseChanged.
@@ -429,7 +511,7 @@ TEST_F(FlingControllerTest, ControllerBoostsTouchpadFling) {
EXPECT_TRUE(FlingBoosted());
}
-TEST_F(FlingControllerTest, ControllerBoostsTouchscreenFling) {
+TEST_P(FlingControllerTest, ControllerBoostsTouchscreenFling) {
base::TimeTicks progress_time = base::TimeTicks::Now();
SimulateFlingStart(blink::kWebGestureDeviceTouchscreen,
gfx::Vector2dF(1000, 0));
@@ -455,7 +537,7 @@ TEST_F(FlingControllerTest, ControllerBoostsTouchscreenFling) {
EXPECT_TRUE(FlingBoosted());
}
-TEST_F(FlingControllerTest, ControllerNotifiesTheClientAfterFlingStart) {
+TEST_P(FlingControllerTest, ControllerNotifiesTheClientAfterFlingStart) {
base::TimeTicks progress_time = base::TimeTicks::Now();
SimulateFlingStart(blink::kWebGestureDeviceTouchscreen,
gfx::Vector2dF(1000, 0));
@@ -475,7 +557,7 @@ TEST_F(FlingControllerTest, ControllerNotifiesTheClientAfterFlingStart) {
EXPECT_TRUE(notified_client_after_fling_stop_);
}
-TEST_F(FlingControllerTest, MiddleClickAutoScrollFling) {
+TEST_P(FlingControllerTest, MiddleClickAutoScrollFling) {
base::TimeTicks progress_time = base::TimeTicks::Now();
SimulateFlingStart(blink::kWebGestureDeviceSyntheticAutoscroll,
gfx::Vector2dF(1000, 0));
diff --git a/chromium/content/browser/renderer_host/input/fling_scheduler.cc b/chromium/content/browser/renderer_host/input/fling_scheduler.cc
index 63a6f7cca39..02772e70c89 100644
--- a/chromium/content/browser/renderer_host/input/fling_scheduler.cc
+++ b/chromium/content/browser/renderer_host/input/fling_scheduler.cc
@@ -52,6 +52,10 @@ void FlingScheduler::DidStopFlingingOnBrowser(
host_->DidStopFlinging();
}
+bool FlingScheduler::NeedsBeginFrameForFlingProgress() {
+ return !GetCompositor();
+}
+
void FlingScheduler::ProgressFlingOnBeginFrameIfneeded(
base::TimeTicks current_time) {
// No fling is active.
diff --git a/chromium/content/browser/renderer_host/input/fling_scheduler.h b/chromium/content/browser/renderer_host/input/fling_scheduler.h
index 634904e7b14..7e263503efd 100644
--- a/chromium/content/browser/renderer_host/input/fling_scheduler.h
+++ b/chromium/content/browser/renderer_host/input/fling_scheduler.h
@@ -28,6 +28,7 @@ class CONTENT_EXPORT FlingScheduler : public FlingSchedulerBase,
base::WeakPtr<FlingController> fling_controller) override;
void DidStopFlingingOnBrowser(
base::WeakPtr<FlingController> fling_controller) override;
+ bool NeedsBeginFrameForFlingProgress() override;
// FlingSchedulerBase
void ProgressFlingOnBeginFrameIfneeded(base::TimeTicks current_time) override;
diff --git a/chromium/content/browser/renderer_host/input/fling_scheduler_android.cc b/chromium/content/browser/renderer_host/input/fling_scheduler_android.cc
index c2e968437ea..28cb2dbb720 100644
--- a/chromium/content/browser/renderer_host/input/fling_scheduler_android.cc
+++ b/chromium/content/browser/renderer_host/input/fling_scheduler_android.cc
@@ -50,6 +50,14 @@ void FlingSchedulerAndroid::DidStopFlingingOnBrowser(
host_->DidStopFlinging();
}
+bool FlingSchedulerAndroid::NeedsBeginFrameForFlingProgress() {
+ ui::WindowAndroid* window = GetRootWindow();
+ // If the root window does not have a Compositor (happens on Android
+ // WebView), we'll never receive an OnAnimate call. In this case fall back
+ // to BeginFrames coming from the host.
+ return !window || !window->GetCompositor();
+}
+
void FlingSchedulerAndroid::ProgressFlingOnBeginFrameIfneeded(
base::TimeTicks current_time) {
// If a WindowAndroid is being observed, there is no need for BeginFrames
diff --git a/chromium/content/browser/renderer_host/input/fling_scheduler_android.h b/chromium/content/browser/renderer_host/input/fling_scheduler_android.h
index cbe1e6e119d..3b54e4e97d4 100644
--- a/chromium/content/browser/renderer_host/input/fling_scheduler_android.h
+++ b/chromium/content/browser/renderer_host/input/fling_scheduler_android.h
@@ -25,6 +25,7 @@ class CONTENT_EXPORT FlingSchedulerAndroid : public FlingSchedulerBase,
base::WeakPtr<FlingController> fling_controller) override;
void DidStopFlingingOnBrowser(
base::WeakPtr<FlingController> fling_controller) override;
+ bool NeedsBeginFrameForFlingProgress() override;
// FlingSchedulerBase
void ProgressFlingOnBeginFrameIfneeded(base::TimeTicks current_time) override;
diff --git a/chromium/content/browser/renderer_host/input/fling_scheduler_mac.mm b/chromium/content/browser/renderer_host/input/fling_scheduler_mac.mm
index f2ac740bea5..f10c5d161dd 100644
--- a/chromium/content/browser/renderer_host/input/fling_scheduler_mac.mm
+++ b/chromium/content/browser/renderer_host/input/fling_scheduler_mac.mm
@@ -5,6 +5,7 @@
#include "content/browser/renderer_host/input/fling_scheduler_mac.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "content/browser/renderer_host/render_widget_host_view_child_frame.h"
#include "content/browser/renderer_host/render_widget_host_view_mac.h"
#include "ui/compositor/compositor.h"
@@ -15,20 +16,20 @@ FlingSchedulerMac::FlingSchedulerMac(RenderWidgetHostImpl* host)
FlingSchedulerMac::~FlingSchedulerMac() = default;
ui::Compositor* FlingSchedulerMac::GetCompositor() {
- if (!host_->GetView())
+ RenderWidgetHostViewBase* view = host_->GetView();
+ if (!view)
return nullptr;
- // RWHV_child_frame doesn't have DelegatedFrameHost with ui::Compositor.
- if (host_->GetView()->IsRenderWidgetHostViewChildFrame())
- return nullptr;
+ if (view->IsRenderWidgetHostViewChildFrame()) {
+ view = view->GetRootView();
+ if (!view)
+ return nullptr;
+ }
- // TODO(sahel): Uncomment this once Viz is ready on Mac.
- // https://crbug.com/833985
- /* RenderWidgetHostViewMac* view =
- static_cast<RenderWidgetHostViewMac*>(host_->GetView());
- if (view->BrowserCompositor())
- return view->BrowserCompositor()->Compositor();
- } */
+ RenderWidgetHostViewMac* mac_view =
+ static_cast<RenderWidgetHostViewMac*>(view);
+ if (mac_view->BrowserCompositor())
+ return mac_view->BrowserCompositor()->GetCompositor();
return nullptr;
}
diff --git a/chromium/content/browser/renderer_host/input/gesture_event_queue.cc b/chromium/content/browser/renderer_host/input/gesture_event_queue.cc
index a9ff466e23a..93347d9c37e 100644
--- a/chromium/content/browser/renderer_host/input/gesture_event_queue.cc
+++ b/chromium/content/browser/renderer_host/input/gesture_event_queue.cc
@@ -94,9 +94,6 @@ bool GestureEventQueue::FlingCancellationIsDeferred() const {
return fling_controller_.FlingCancellationIsDeferred();
}
-bool GestureEventQueue::TouchscreenFlingInProgress() const {
- return fling_controller_.TouchscreenFlingInProgress();
-}
gfx::Vector2dF GestureEventQueue::CurrentFlingVelocity() const {
return fling_controller_.CurrentFlingVelocity();
}
diff --git a/chromium/content/browser/renderer_host/input/gesture_event_queue.h b/chromium/content/browser/renderer_host/input/gesture_event_queue.h
index f07f3cd6220..3dec354a48a 100644
--- a/chromium/content/browser/renderer_host/input/gesture_event_queue.h
+++ b/chromium/content/browser/renderer_host/input/gesture_event_queue.h
@@ -117,8 +117,6 @@ class CONTENT_EXPORT GestureEventQueue {
bool FlingCancellationIsDeferred() const;
- bool TouchscreenFlingInProgress() const;
-
gfx::Vector2dF CurrentFlingVelocity() const;
void set_debounce_interval_time_ms_for_testing(int interval_ms) {
diff --git a/chromium/content/browser/renderer_host/input/gesture_event_queue_unittest.cc b/chromium/content/browser/renderer_host/input/gesture_event_queue_unittest.cc
index a977b1921b5..34e5da173ee 100644
--- a/chromium/content/browser/renderer_host/input/gesture_event_queue_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/gesture_event_queue_unittest.cc
@@ -107,6 +107,7 @@ class GestureEventQueueTest : public testing::Test,
base::WeakPtr<FlingController> fling_controller) override {}
void DidStopFlingingOnBrowser(
base::WeakPtr<FlingController> fling_controller) override {}
+ bool NeedsBeginFrameForFlingProgress() override { return false; }
protected:
static GestureEventQueue::Config DefaultConfig() {
@@ -213,6 +214,9 @@ class GestureEventQueueTest : public testing::Test,
}
bool FlingInProgress() { return queue()->fling_in_progress_; }
+ bool FlingCancellationIsDeferred() {
+ return queue()->FlingCancellationIsDeferred();
+ }
bool WillIgnoreNextACK() {
return queue()->ignore_next_ack_;
@@ -1100,7 +1104,9 @@ TEST_F(GestureEventQueueTest, DebounceDropsDeferredEvents) {
// suppressed when tap suppression is enabled.
TEST_F(GestureEventQueueTest, TapGetsSuppressedAfterTapDownCancellsFling) {
SetUpForTapSuppression(400);
- SimulateGestureFlingStartEvent(0, -10, blink::kWebGestureDeviceTouchscreen);
+ // The velocity of the event must be large enough to make sure that the fling
+ // is still active when the tap down happens.
+ SimulateGestureFlingStartEvent(0, -1000, blink::kWebGestureDeviceTouchscreen);
EXPECT_TRUE(FlingInProgress());
// The fling start event is not sent to the renderer.
EXPECT_EQ(0U, GetAndResetSentGestureEventCount());
@@ -1111,7 +1117,7 @@ TEST_F(GestureEventQueueTest, TapGetsSuppressedAfterTapDownCancellsFling) {
// fling cancel event is not sent to the renderer.
SimulateGestureEvent(WebInputEvent::kGestureFlingCancel,
blink::kWebGestureDeviceTouchscreen);
- EXPECT_FALSE(FlingInProgress());
+ EXPECT_TRUE(FlingCancellationIsDeferred());
EXPECT_EQ(0U, GetAndResetSentGestureEventCount());
EXPECT_EQ(0U, GestureEventQueueSize());
RunUntilIdle();
diff --git a/chromium/content/browser/renderer_host/input/input_router_client.h b/chromium/content/browser/renderer_host/input/input_router_client.h
index e714ee3f9c3..01c2c1fa601 100644
--- a/chromium/content/browser/renderer_host/input/input_router_client.h
+++ b/chromium/content/browser/renderer_host/input/input_router_client.h
@@ -51,9 +51,6 @@ class CONTENT_EXPORT InputRouterClient {
// from the renderer.
virtual void OnSetWhiteListedTouchAction(cc::TouchAction touch_action) = 0;
- // Called when a renderer fling has terminated.
- virtual void DidStopFlinging() = 0;
-
// Called when a GSB has started scrolling a viewport.
virtual void DidStartScrollingViewport() = 0;
diff --git a/chromium/content/browser/renderer_host/input/input_router_impl.cc b/chromium/content/browser/renderer_host/input/input_router_impl.cc
index 788b74bd305..582b96fb30c 100644
--- a/chromium/content/browser/renderer_host/input/input_router_impl.cc
+++ b/chromium/content/browser/renderer_host/input/input_router_impl.cc
@@ -215,8 +215,7 @@ void InputRouterImpl::SetForceEnableZoom(bool enabled) {
}
base::Optional<cc::TouchAction> InputRouterImpl::AllowedTouchAction() {
- return touch_action_filter_.allowed_touch_action().value_or(
- cc::kTouchActionAuto);
+ return touch_action_filter_.allowed_touch_action();
}
void InputRouterImpl::BindHost(mojom::WidgetInputHandlerHostRequest request,
@@ -257,15 +256,6 @@ void InputRouterImpl::DidOverscroll(const ui::DidOverscrollParams& params) {
client_->DidOverscroll(fling_updated_params);
}
-void InputRouterImpl::DidStopFlinging() {
- DCHECK_GT(active_renderer_fling_count_, 0);
- // Note that we're only guaranteed to get a fling end notification from the
- // renderer, not from any other consumers. Consequently, the GestureEventQueue
- // cannot use this bookkeeping for logic like tap suppression.
- --active_renderer_fling_count_;
- client_->DidStopFlinging();
-}
-
void InputRouterImpl::DidStartScrollingViewport() {
client_->DidStartScrollingViewport();
}
@@ -349,14 +339,17 @@ void InputRouterImpl::OnTouchEventAck(const TouchEventWithLatencyInfo& event,
// in some cases we may filter out sending the touchstart - catch those here.
if (WebTouchEventTraits::IsTouchSequenceStart(event.event) &&
ack_result == INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS) {
+ touch_action_filter_.AppendToGestureSequenceForDebugging("T");
// Touch action must be auto when there is no consumer
touch_action_filter_.OnSetTouchAction(cc::kTouchActionAuto);
+ touch_action_filter_.SetActiveTouchInProgress(true);
UpdateTouchAckTimeoutEnabled();
}
disposition_handler_->OnTouchEventAck(event, ack_source, ack_result);
if (WebTouchEventTraits::IsTouchSequenceEnd(event.event)) {
touch_action_filter_.ReportAndResetTouchAction();
+ touch_action_filter_.SetActiveTouchInProgress(false);
UpdateTouchAckTimeoutEnabled();
}
}
@@ -372,10 +365,6 @@ void InputRouterImpl::OnFilteringTouchEvent(const WebTouchEvent& touch_event) {
output_stream_validator_.Validate(touch_event);
}
-bool InputRouterImpl::TouchscreenFlingInProgress() {
- return gesture_event_queue_.TouchscreenFlingInProgress();
-}
-
void InputRouterImpl::SendGestureEventImmediately(
const GestureEventWithLatencyInfo& gesture_event) {
mojom::WidgetInputHandler::DispatchEventCallback callback = base::BindOnce(
@@ -561,11 +550,6 @@ void InputRouterImpl::GestureEventHandled(
InputEventAckStateToString(state));
if (source != InputEventAckSource::BROWSER)
client_->DecrementInFlightEventCount(source);
- if (gesture_event.event.GetType() ==
- blink::WebInputEvent::kGestureFlingStart &&
- state == INPUT_EVENT_ACK_STATE_CONSUMED) {
- ++active_renderer_fling_count_;
- }
if (overscroll) {
DCHECK_EQ(WebInputEvent::kGestureScrollUpdate,
@@ -610,7 +594,13 @@ void InputRouterImpl::OnHasTouchEventHandlers(bool has_handlers) {
}
void InputRouterImpl::ForceSetTouchActionAuto() {
+ touch_action_filter_.AppendToGestureSequenceForDebugging("F");
touch_action_filter_.OnSetTouchAction(cc::kTouchActionAuto);
+ touch_action_filter_.SetActiveTouchInProgress(true);
+}
+
+void InputRouterImpl::OnHasTouchEventHandlersForTest(bool has_handlers) {
+ touch_action_filter_.OnHasTouchEventHandlers(has_handlers);
}
void InputRouterImpl::OnSetTouchAction(cc::TouchAction touch_action) {
@@ -622,7 +612,11 @@ void InputRouterImpl::OnSetTouchAction(cc::TouchAction touch_action) {
if (!touch_event_queue_.IsPendingAckTouchStart())
return;
+ touch_action_filter_.AppendToGestureSequenceForDebugging("S");
+ touch_action_filter_.AppendToGestureSequenceForDebugging(
+ std::to_string(touch_action).c_str());
touch_action_filter_.OnSetTouchAction(touch_action);
+ touch_action_filter_.SetActiveTouchInProgress(true);
// kTouchActionNone should disable the touch ack timeout.
UpdateTouchAckTimeoutEnabled();
diff --git a/chromium/content/browser/renderer_host/input/input_router_impl.h b/chromium/content/browser/renderer_host/input/input_router_impl.h
index 53605ce1286..9f2862155d0 100644
--- a/chromium/content/browser/renderer_host/input/input_router_impl.h
+++ b/chromium/content/browser/renderer_host/input/input_router_impl.h
@@ -93,7 +93,6 @@ class CONTENT_EXPORT InputRouterImpl : public InputRouter,
uint32_t unique_touch_event_id,
InputEventAckState state) override;
void DidOverscroll(const ui::DidOverscrollParams& params) override;
- void DidStopFlinging() override;
void ImeCancelComposition() override;
void DidStartScrollingViewport() override;
void ImeCompositionRangeChanged(
@@ -110,6 +109,8 @@ class CONTENT_EXPORT InputRouterImpl : public InputRouter,
// IPC::Listener
bool OnMessageReceived(const IPC::Message& message) override;
+ void OnHasTouchEventHandlersForTest(bool has_handlers);
+
private:
friend class InputRouterImplTest;
friend class MockRenderWidgetHost;
@@ -127,7 +128,6 @@ class CONTENT_EXPORT InputRouterImpl : public InputRouter,
InputEventAckSource ack_source,
InputEventAckState ack_result) override;
void OnFilteringTouchEvent(const blink::WebTouchEvent& touch_event) override;
- bool TouchscreenFlingInProgress() override;
// GestureEventFilterClient
void SendGestureEventImmediately(
diff --git a/chromium/content/browser/renderer_host/input/input_router_impl_unittest.cc b/chromium/content/browser/renderer_host/input/input_router_impl_unittest.cc
index 5ff4766f351..e06e5c15acb 100644
--- a/chromium/content/browser/renderer_host/input/input_router_impl_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/input_router_impl_unittest.cc
@@ -134,8 +134,6 @@ class MockInputRouterImplClient : public InputRouterImplClient {
input_router_client_.DidOverscroll(params);
}
- void DidStopFlinging() override { input_router_client_.DidStopFlinging(); }
-
void DidStartScrollingViewport() override {
input_router_client_.DidStartScrollingViewport();
}
@@ -292,8 +290,13 @@ class InputRouterImplTest : public testing::Test {
!gesture.data.fling_start.velocity_x &&
!gesture.data.fling_start.velocity_y) {
// Ensure non-zero touchscreen fling velocities, as the router will
- // validate against such.
- gesture.data.fling_start.velocity_x = 5.f;
+ // validate against such. The velocity should be large enough to make
+ // sure that the fling is still active while sending the GFC.
+ gesture.data.fling_start.velocity_x = 500.f;
+ } else if (gesture.GetType() == WebInputEvent::kGestureFlingCancel) {
+ // Set prevent boosting to make sure that the GFC cancels the active
+ // fling.
+ gesture.data.fling_cancel.prevent_boosting = true;
}
input_router_->SendGestureEvent(GestureEventWithLatencyInfo(gesture));
@@ -762,7 +765,13 @@ TEST_F(InputRouterImplTest, TouchTypesIgnoringAck) {
EXPECT_FALSE(HasPendingEvents());
}
-TEST_F(InputRouterImplTest, GestureTypesIgnoringAck) {
+// TODO(https://crbug.com/866946): Test is flaky on Fuchsia.
+#if defined(OS_FUCHSIA)
+#define MAYBE_GestureTypesIgnoringAck DISABLED_GestureTypesIgnoringAck
+#else
+#define MAYBE_GestureTypesIgnoringAck GestureTypesIgnoringAck
+#endif
+TEST_F(InputRouterImplTest, MAYBE_GestureTypesIgnoringAck) {
// We test every gesture type, ensuring that the stream of gestures is valid.
const WebInputEvent::Type eventTypes[] = {
WebInputEvent::kGestureTapDown, WebInputEvent::kGestureShowPress,
@@ -1233,6 +1242,9 @@ TEST_F(InputRouterImplTest, TouchActionResetBeforeEventReachesRenderer) {
// Ensure touch action is still none, as the next touch start hasn't been
// acked yet. ScrollBegin and ScrollEnd don't require acks.
+ SimulateGestureEvent(WebInputEvent::kGestureTapDown,
+ blink::kWebGestureDeviceTouchscreen);
+ EXPECT_EQ(1U, GetAndResetDispatchedMessages().size());
SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
blink::kWebGestureDeviceTouchscreen);
EXPECT_EQ(0U, GetAndResetDispatchedMessages().size());
@@ -1308,6 +1320,9 @@ TEST_F(InputRouterImplTest, TouchActionResetWhenTouchHasNoConsumer) {
// Ensure we have touch-action:none. ScrollBegin and ScrollEnd don't require
// acks.
+ SimulateGestureEvent(WebInputEvent::kGestureTapDown,
+ blink::kWebGestureDeviceTouchscreen);
+ EXPECT_EQ(1U, GetAndResetDispatchedMessages().size());
SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
blink::kWebGestureDeviceTouchscreen);
EXPECT_EQ(0U, GetAndResetDispatchedMessages().size());
@@ -1361,6 +1376,9 @@ TEST_F(InputRouterImplTest, TouchActionResetWhenTouchHandlerRemoved) {
dispatched_messages[1]->ToEvent()->CallCallback(
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_EQ(0U, GetAndResetDispatchedMessages().size());
+ SimulateGestureEvent(WebInputEvent::kGestureTapDown,
+ blink::kWebGestureDeviceTouchscreen);
+ EXPECT_EQ(1U, GetAndResetDispatchedMessages().size());
SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
blink::kWebGestureDeviceTouchscreen);
EXPECT_EQ(0U, GetAndResetDispatchedMessages().size());
@@ -1505,8 +1523,32 @@ TEST_F(InputRouterImplTest, DoubleTapGestureDependsOnFirstTap) {
EXPECT_EQ(0, client_->in_flight_event_count());
}
+class TouchpadPinchInputRouterImplTest
+ : public InputRouterImplTest,
+ public testing::WithParamInterface<bool> {
+ public:
+ TouchpadPinchInputRouterImplTest() : async_events_enabled_(GetParam()) {
+ if (async_events_enabled_) {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kTouchpadAsyncPinchEvents);
+ } else {
+ scoped_feature_list_.InitAndDisableFeature(
+ features::kTouchpadAsyncPinchEvents);
+ }
+ }
+ ~TouchpadPinchInputRouterImplTest() = default;
+
+ const bool async_events_enabled_;
+
+ private:
+ base::test::ScopedFeatureList scoped_feature_list_;
+ DISALLOW_COPY_AND_ASSIGN(TouchpadPinchInputRouterImplTest);
+};
+
+INSTANTIATE_TEST_CASE_P(, TouchpadPinchInputRouterImplTest, ::testing::Bool());
+
// Test that GesturePinchUpdate is handled specially for trackpad
-TEST_F(InputRouterImplTest, TouchpadPinchUpdate) {
+TEST_P(TouchpadPinchInputRouterImplTest, TouchpadPinchUpdate) {
// GesturePinchUpdate for trackpad sends synthetic wheel events.
// Note that the Touchscreen case is verified as NOT doing this as
// part of the ShowPressIsInOrder test.
@@ -1535,6 +1577,8 @@ TEST_F(InputRouterImplTest, TouchpadPinchUpdate) {
EXPECT_EQ(25, synthetic_wheel->PositionInScreen().y);
EXPECT_TRUE(synthetic_wheel->GetModifiers() &
blink::WebInputEvent::kControlKey);
+ EXPECT_EQ(blink::WebMouseWheelEvent::kPhaseBegan, synthetic_wheel->phase);
+ EXPECT_EQ(blink::WebInputEvent::kBlocking, synthetic_wheel->dispatch_type);
dispatched_messages[0]->ToEvent()->CallCallback(
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
@@ -1559,24 +1603,114 @@ TEST_F(InputRouterImplTest, TouchpadPinchUpdate) {
input_event = dispatched_messages[0]->ToEvent()->Event()->web_event.get();
ASSERT_EQ(WebInputEvent::kMouseWheel, input_event->GetType());
synthetic_wheel = static_cast<const WebMouseWheelEvent*>(input_event);
+ EXPECT_EQ(blink::WebMouseWheelEvent::kPhaseChanged, synthetic_wheel->phase);
+ if (async_events_enabled_) {
+ EXPECT_EQ(blink::WebInputEvent::kEventNonBlocking,
+ synthetic_wheel->dispatch_type);
+ } else {
+ EXPECT_EQ(blink::WebInputEvent::kBlocking, synthetic_wheel->dispatch_type);
+ }
- dispatched_messages[0]->ToEvent()->CallCallback(
- INPUT_EVENT_ACK_STATE_CONSUMED);
+ if (async_events_enabled_) {
+ dispatched_messages[0]->ToEvent()->CallCallback(
+ INPUT_EVENT_ACK_STATE_IGNORED);
+ } else {
+ dispatched_messages[0]->ToEvent()->CallCallback(
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ }
// Check that the correct HANDLED pinch event was received.
EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
EXPECT_EQ(WebInputEvent::kGesturePinchUpdate,
disposition_handler_->ack_event_type());
- EXPECT_EQ(INPUT_EVENT_ACK_STATE_CONSUMED, disposition_handler_->ack_state());
+ if (async_events_enabled_) {
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_IGNORED, disposition_handler_->ack_state());
+ } else {
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED,
+ disposition_handler_->ack_state());
+ }
EXPECT_FLOAT_EQ(
0.3f,
disposition_handler_->acked_gesture_event().data.pinch_update.scale);
SimulateGestureEvent(WebInputEvent::kGesturePinchEnd,
blink::kWebGestureDeviceTouchpad);
+ dispatched_messages = GetAndResetDispatchedMessages();
+ ASSERT_EQ(1U, dispatched_messages.size());
+ ASSERT_TRUE(dispatched_messages[0]->ToEvent());
+ input_event = dispatched_messages[0]->ToEvent()->Event()->web_event.get();
+ ASSERT_EQ(WebInputEvent::kMouseWheel, input_event->GetType());
+ synthetic_wheel = static_cast<const WebMouseWheelEvent*>(input_event);
+ EXPECT_EQ(blink::WebMouseWheelEvent::kPhaseEnded, synthetic_wheel->phase);
+ EXPECT_EQ(blink::WebInputEvent::kEventNonBlocking,
+ synthetic_wheel->dispatch_type);
+ dispatched_messages[0]->ToEvent()->CallCallback(
+ INPUT_EVENT_ACK_STATE_IGNORED);
+
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
+ EXPECT_EQ(WebInputEvent::kGesturePinchEnd,
+ disposition_handler_->ack_event_type());
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_IGNORED, disposition_handler_->ack_state());
+
+ // The first event is blocked. We should send following wheel events as
+ // blocking events.
+ SimulateGestureEvent(WebInputEvent::kGesturePinchBegin,
+ blink::kWebGestureDeviceTouchpad);
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
+ ASSERT_EQ(WebInputEvent::kGesturePinchBegin,
+ disposition_handler_->ack_event_type());
+
+ SimulateGesturePinchUpdateEvent(1.5f, 20, 25, 0,
+ blink::kWebGestureDeviceTouchpad);
+
+ // Verify we actually sent a special wheel event to the renderer.
+ dispatched_messages = GetAndResetDispatchedMessages();
+ ASSERT_EQ(1U, dispatched_messages.size());
+ ASSERT_TRUE(dispatched_messages[0]->ToEvent());
+ input_event = dispatched_messages[0]->ToEvent()->Event()->web_event.get();
+ ASSERT_EQ(WebInputEvent::kMouseWheel, input_event->GetType());
+ synthetic_wheel = static_cast<const WebMouseWheelEvent*>(input_event);
+ EXPECT_TRUE(synthetic_wheel->GetModifiers() &
+ blink::WebInputEvent::kControlKey);
+ EXPECT_EQ(blink::WebMouseWheelEvent::kPhaseBegan, synthetic_wheel->phase);
+ EXPECT_EQ(blink::WebInputEvent::kBlocking, synthetic_wheel->dispatch_type);
+
+ dispatched_messages[0]->ToEvent()->CallCallback(
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+
+ // Check that the correct handled pinch event was received.
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
+ ASSERT_EQ(WebInputEvent::kGesturePinchUpdate,
+ disposition_handler_->ack_event_type());
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_CONSUMED, disposition_handler_->ack_state());
+ EXPECT_EQ(
+ 1.5f,
+ disposition_handler_->acked_gesture_event().data.pinch_update.scale);
+ EXPECT_EQ(0, client_->in_flight_event_count());
+
+ // Second a second pinch event.
+ SimulateGesturePinchUpdateEvent(0.3f, 20, 25, 0,
+ blink::kWebGestureDeviceTouchpad);
+ dispatched_messages = GetAndResetDispatchedMessages();
+ ASSERT_EQ(1U, dispatched_messages.size());
+ ASSERT_TRUE(dispatched_messages[0]->ToEvent());
+ input_event = dispatched_messages[0]->ToEvent()->Event()->web_event.get();
+ ASSERT_EQ(WebInputEvent::kMouseWheel, input_event->GetType());
+ synthetic_wheel = static_cast<const WebMouseWheelEvent*>(input_event);
+ EXPECT_EQ(blink::WebMouseWheelEvent::kPhaseChanged, synthetic_wheel->phase);
+ EXPECT_EQ(blink::WebInputEvent::kBlocking, synthetic_wheel->dispatch_type);
+
+ dispatched_messages[0]->ToEvent()->CallCallback(
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+
+ // Check that the correct HANDLED pinch event was received.
EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
- ASSERT_EQ(WebInputEvent::kGesturePinchEnd,
+ EXPECT_EQ(WebInputEvent::kGesturePinchUpdate,
disposition_handler_->ack_event_type());
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_CONSUMED, disposition_handler_->ack_state());
+ EXPECT_FLOAT_EQ(
+ 0.3f,
+ disposition_handler_->acked_gesture_event().data.pinch_update.scale);
}
// Test proper handling of touchpad Gesture{Pinch,Scroll}Update sequences.
diff --git a/chromium/content/browser/renderer_host/input/mock_input_router_client.cc b/chromium/content/browser/renderer_host/input/mock_input_router_client.cc
index 33168e98cab..c3e8f83cce3 100644
--- a/chromium/content/browser/renderer_host/input/mock_input_router_client.cc
+++ b/chromium/content/browser/renderer_host/input/mock_input_router_client.cc
@@ -60,9 +60,6 @@ void MockInputRouterClient::OnSetWhiteListedTouchAction(
white_listed_touch_action_ = white_listed_touch_action;
}
-void MockInputRouterClient::DidStopFlinging() {
-}
-
void MockInputRouterClient::DidStartScrollingViewport() {}
void MockInputRouterClient::ForwardGestureEventWithLatencyInfo(
@@ -113,4 +110,8 @@ cc::TouchAction MockInputRouterClient::GetAndResetWhiteListedTouchAction() {
return white_listed_touch_action;
}
+bool MockInputRouterClient::NeedsBeginFrameForFlingProgress() {
+ return false;
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/mock_input_router_client.h b/chromium/content/browser/renderer_host/input/mock_input_router_client.h
index 8e161f5ff0e..508701de832 100644
--- a/chromium/content/browser/renderer_host/input/mock_input_router_client.h
+++ b/chromium/content/browser/renderer_host/input/mock_input_router_client.h
@@ -33,7 +33,6 @@ class MockInputRouterClient : public InputRouterClient,
void OnHasTouchEventHandlers(bool has_handlers) override;
void DidOverscroll(const ui::DidOverscrollParams& params) override;
void OnSetWhiteListedTouchAction(cc::TouchAction touch_action) override;
- void DidStopFlinging() override;
void DidStartScrollingViewport() override;
void ForwardWheelEventWithLatencyInfo(
const blink::WebMouseWheelEvent& wheel_event,
@@ -74,6 +73,7 @@ class MockInputRouterClient : public InputRouterClient,
base::WeakPtr<FlingController> fling_controller) override {}
void DidStopFlingingOnBrowser(
base::WeakPtr<FlingController> fling_controller) override {}
+ bool NeedsBeginFrameForFlingProgress() override;
private:
InputRouter* input_router_;
diff --git a/chromium/content/browser/renderer_host/input/motion_event_web.cc b/chromium/content/browser/renderer_host/input/motion_event_web.cc
index 7efdfac9ab5..38b3571379d 100644
--- a/chromium/content/browser/renderer_host/input/motion_event_web.cc
+++ b/chromium/content/browser/renderer_host/input/motion_event_web.cc
@@ -168,21 +168,27 @@ float MotionEventWeb::GetPressure(size_t pointer_index) const {
float MotionEventWeb::GetTiltX(size_t pointer_index) const {
DCHECK_LT(pointer_index, GetPointerCount());
- if (GetToolType(pointer_index) != ToolType::STYLUS)
- return 0.f;
-
return event_.touches[pointer_index].tilt_x;
}
float MotionEventWeb::GetTiltY(size_t pointer_index) const {
DCHECK_LT(pointer_index, GetPointerCount());
- if (GetToolType(pointer_index) != ToolType::STYLUS)
- return 0.f;
-
return event_.touches[pointer_index].tilt_y;
}
+float MotionEventWeb::GetTwist(size_t pointer_index) const {
+ DCHECK_LT(pointer_index, GetPointerCount());
+
+ return event_.touches[pointer_index].twist;
+}
+
+float MotionEventWeb::GetTangentialPressure(size_t pointer_index) const {
+ DCHECK_LT(pointer_index, GetPointerCount());
+
+ return event_.touches[pointer_index].tangential_pressure;
+}
+
base::TimeTicks MotionEventWeb::GetEventTime() const {
return event_.TimeStamp();
}
diff --git a/chromium/content/browser/renderer_host/input/motion_event_web.h b/chromium/content/browser/renderer_host/input/motion_event_web.h
index de4f1225f8c..31e26433dc0 100644
--- a/chromium/content/browser/renderer_host/input/motion_event_web.h
+++ b/chromium/content/browser/renderer_host/input/motion_event_web.h
@@ -37,6 +37,8 @@ class CONTENT_EXPORT MotionEventWeb : public ui::MotionEvent {
float GetPressure(size_t pointer_index) const override;
float GetTiltX(size_t pointer_index) const override;
float GetTiltY(size_t pointer_index) const override;
+ float GetTwist(size_t pointer_index) const override;
+ float GetTangentialPressure(size_t pointer_index) const override;
base::TimeTicks GetEventTime() const override;
ToolType GetToolType(size_t pointer_index) const override;
int GetButtonState() const override;
diff --git a/chromium/content/browser/renderer_host/input/motion_event_web_unittest.cc b/chromium/content/browser/renderer_host/input/motion_event_web_unittest.cc
index ddd36fee514..bf31318a931 100644
--- a/chromium/content/browser/renderer_host/input/motion_event_web_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/motion_event_web_unittest.cc
@@ -22,6 +22,8 @@ TEST(MotionEventWebTest, Constructor) {
const float orientations[] = {-pi, -2.f * pi / 3, -pi / 2};
const float tilts_x[] = {0.f, -180 / 4, -180 / 3};
const float tilts_y[] = {0.5f, 180 / 2, 180 / 3};
+ const float twists[] = {60, 160, 260};
+ const float tangential_pressures[] = {0.3f, 0.5f, 0.9f};
const MotionEvent::ToolType tool_types[] = {MotionEvent::ToolType::FINGER,
MotionEvent::ToolType::STYLUS,
MotionEvent::ToolType::MOUSE};
@@ -34,10 +36,14 @@ TEST(MotionEventWebTest, Constructor) {
const float tilt_x = tilts_x[i];
const float tilt_y = tilts_y[i];
const float orientation = orientations[i];
+ const float twist = twists[i];
+ const float tangential_pressure = tangential_pressures[i];
PointerProperties pp2;
pp2.orientation = orientation;
pp2.tilt_x = tilt_x;
pp2.tilt_y = tilt_y;
+ pp2.twist = twist;
+ pp2.tangential_pressure = tangential_pressure;
pp2.tool_type = tool_type;
size_t pointer_index = generic_event.PushPointer(pp2);
EXPECT_GT(pointer_index, 0u);
@@ -55,6 +61,9 @@ TEST(MotionEventWebTest, Constructor) {
<< " orientation=" << orientation;
EXPECT_NEAR(tilt_y, event.GetTiltY(pointer_index), 0.5)
<< " orientation=" << orientation;
+ EXPECT_EQ(twist, event.GetTwist(pointer_index));
+ EXPECT_EQ(tangential_pressure,
+ event.GetTangentialPressure(pointer_index));
} else {
EXPECT_EQ(0.f, event.GetTiltX(pointer_index));
EXPECT_EQ(0.f, event.GetTiltY(pointer_index));
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 702915772e4..db69b0d9fb3 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
@@ -6,6 +6,7 @@
#include "base/metrics/histogram_macros.h"
#include "base/trace_event/trace_event.h"
+#include "build/build_config.h"
#include "content/common/input/input_event_dispatch_type.h"
#include "content/public/common/content_features.h"
#include "ui/events/base_event_utils.h"
@@ -126,6 +127,7 @@ void MouseWheelEventQueue::ProcessMouseWheelAck(
event_sent_for_gesture_ack_->event.PositionInScreen());
scroll_update.resending_plugin_id = -1;
+#if !defined(OS_MACOSX)
// Swap X & Y if Shift is down and when there is no horizontal movement.
if ((event_sent_for_gesture_ack_->event.GetModifiers() &
WebInputEvent::kShiftKey) != 0 &&
@@ -134,7 +136,9 @@ void MouseWheelEventQueue::ProcessMouseWheelAck(
event_sent_for_gesture_ack_->event.delta_y;
scroll_update.data.scroll_update.delta_y =
event_sent_for_gesture_ack_->event.delta_x;
- } else {
+ } else
+#endif // OS_MACOSX
+ {
scroll_update.data.scroll_update.delta_x =
event_sent_for_gesture_ack_->event.delta_x;
scroll_update.data.scroll_update.delta_y =
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 b8f0067c4a8..51ca2edfd8c 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
@@ -15,6 +15,7 @@
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "build/build_config.h"
#include "content/browser/renderer_host/input/timeout_monitor.h"
#include "content/common/input/synthetic_web_input_event_builders.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -621,4 +622,29 @@ TEST_F(MouseWheelEventQueueTest, WheelScrollingWasLatchedHistogramCheck) {
histogram_tester.ExpectBucketCount(latching_histogram_name, 1, 1);
}
+#if defined(OS_MACOSX)
+TEST_F(MouseWheelEventQueueTest, DoNotSwapXYForShiftScroll) {
+ // Send an event with shift modifier, zero value for delta X, and no direction
+ // for |rails_mode|. Do not swap the scroll direction.
+ SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
+ kWheelScrollGlobalY, 0.0, 1.0, WebInputEvent::kShiftKey, false,
+ WebMouseWheelEvent::kPhaseBegan,
+ WebMouseWheelEvent::kPhaseNone, WebInputEvent::kRailsModeFree);
+ EXPECT_EQ(0U, queued_event_count());
+ EXPECT_TRUE(event_in_flight());
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+
+ // Receive an ACK for the mouse wheel event.
+ SendMouseWheelEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(0U, queued_event_count());
+ EXPECT_FALSE(event_in_flight());
+ EXPECT_EQ(WebInputEvent::kMouseWheel, acked_event().GetType());
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+
+ EXPECT_EQ(2U, all_sent_events().size());
+ EXPECT_EQ(0U, sent_gesture_event(1)->data.scroll_update.delta_x);
+ EXPECT_EQ(1U, sent_gesture_event(1)->data.scroll_update.delta_y);
+ EXPECT_EQ(2U, GetAndResetSentEventCount());
+}
+#endif
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/mouse_wheel_phase_handler.cc b/chromium/content/browser/renderer_host/input/mouse_wheel_phase_handler.cc
index a13243f3727..6056b1f2863 100644
--- a/chromium/content/browser/renderer_host/input/mouse_wheel_phase_handler.cc
+++ b/chromium/content/browser/renderer_host/input/mouse_wheel_phase_handler.cc
@@ -186,8 +186,9 @@ void MouseWheelPhaseHandler::ScheduleMouseWheelEndDispatching(
TRACE_EVENT_SCOPE_THREAD);
mouse_wheel_end_dispatch_timer_.Start(
FROM_HERE, timeout,
- base::Bind(&MouseWheelPhaseHandler::SendSyntheticWheelEventWithPhaseEnded,
- base::Unretained(this), should_route_event));
+ base::BindOnce(
+ &MouseWheelPhaseHandler::SendSyntheticWheelEventWithPhaseEnded,
+ base::Unretained(this), should_route_event));
}
bool MouseWheelPhaseHandler::IsWithinSlopRegion(
diff --git a/chromium/content/browser/renderer_host/input/mouse_wheel_rails_filter_mac.cc b/chromium/content/browser/renderer_host/input/mouse_wheel_rails_filter_mac.cc
index 78d9411c556..db224eef80f 100644
--- a/chromium/content/browser/renderer_host/input/mouse_wheel_rails_filter_mac.cc
+++ b/chromium/content/browser/renderer_host/input/mouse_wheel_rails_filter_mac.cc
@@ -17,6 +17,15 @@ MouseWheelRailsFilterMac::~MouseWheelRailsFilterMac() {
WebInputEvent::RailsMode MouseWheelRailsFilterMac::UpdateRailsMode(
const WebMouseWheelEvent& event) {
+ if (event.phase == WebMouseWheelEvent::kPhaseNone &&
+ event.momentum_phase == WebMouseWheelEvent::kPhaseNone) {
+ // We should only set the rails mode for trackpad wheel events. The AppKit
+ // documentation state that legacy mouse events (legacy mouse) do not have
+ // |phase| and |momentum_phase|.
+ // https://developer.apple.com/documentation/appkit/nsevent/1533550-phase.
+ return WebInputEvent::kRailsModeFree;
+ }
+
// A somewhat-arbitrary decay constant for hysteresis.
const float kDecayConstant = 0.8f;
diff --git a/chromium/content/browser/renderer_host/input/passthrough_touch_event_queue.h b/chromium/content/browser/renderer_host/input/passthrough_touch_event_queue.h
index bc5f7931272..65d881e9f48 100644
--- a/chromium/content/browser/renderer_host/input/passthrough_touch_event_queue.h
+++ b/chromium/content/browser/renderer_host/input/passthrough_touch_event_queue.h
@@ -33,8 +33,6 @@ class CONTENT_EXPORT PassthroughTouchEventQueueClient {
virtual void OnFilteringTouchEvent(
const blink::WebTouchEvent& touch_event) = 0;
-
- virtual bool TouchscreenFlingInProgress() = 0;
};
// A queue that processes a touch-event and forwards it on to the
diff --git a/chromium/content/browser/renderer_host/input/passthrough_touch_event_queue_unittest.cc b/chromium/content/browser/renderer_host/input/passthrough_touch_event_queue_unittest.cc
index 3f23c3a3ed1..718e02bf755 100644
--- a/chromium/content/browser/renderer_host/input/passthrough_touch_event_queue_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/passthrough_touch_event_queue_unittest.cc
@@ -94,8 +94,6 @@ class PassthroughTouchEventQueueTest : public testing::Test,
void OnFilteringTouchEvent(const blink::WebTouchEvent& touch_event) override {
}
- bool TouchscreenFlingInProgress() override { return false; }
-
protected:
void SetUpForTouchMoveSlopTesting(double slop_length_dips) {
slop_length_dips_ = slop_length_dips;
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 b174affcfc1..5cd15c4ff6e 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
@@ -9,13 +9,13 @@
#include "components/rappor/public/rappor_utils.h"
#include "components/rappor/test_rappor_service.h"
#include "components/ukm/test_ukm_recorder.h"
-#include "components/ukm/ukm_source.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/input/synthetic_web_input_event_builders.h"
#include "content/public/browser/native_web_keyboard_event.h"
#include "content/test/test_content_browser_client.h"
#include "content/test/test_render_view_host.h"
#include "content/test/test_web_contents.h"
+#include "services/metrics/public/cpp/ukm_source.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -1272,4 +1272,23 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, WheelDuringMultiFingerTouch) {
ElementsAre(Bucket(14, 1)));
}
+TEST_F(RenderWidgetHostLatencyTrackerTest, TouchpadPinchEvents) {
+ ui::LatencyInfo latency;
+ latency.set_trace_id(kTraceEventId);
+ latency.set_source_event_type(ui::SourceEventType::TOUCHPAD);
+ latency.AddLatencyNumberWithTimestamp(
+ ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT,
+ base::TimeTicks() + base::TimeDelta::FromMilliseconds(1), 1);
+ latency.AddLatencyNumberWithTimestamp(
+ ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
+ base::TimeTicks() + base::TimeDelta::FromMilliseconds(3), 1);
+ AddFakeComponentsWithTimeStamp(
+ *tracker(), &latency,
+ base::TimeTicks() + base::TimeDelta::FromMilliseconds(5));
+ viz_tracker()->OnGpuSwapBuffersCompleted(latency);
+
+ EXPECT_TRUE(HistogramSizeEq("Event.Latency.EventToRender.TouchpadPinch", 1));
+ EXPECT_TRUE(HistogramSizeEq("Event.Latency.EndToEnd.TouchpadPinch", 1));
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc b/chromium/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc
index 63a710082da..74d0eb047d9 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc
@@ -68,6 +68,7 @@ WebTouchPoint::State ToWebTouchPointState(
return WebTouchPoint::kStateReleased;
case SyntheticPointerActionParams::PointerActionType::IDLE:
return WebTouchPoint::kStateStationary;
+ case SyntheticPointerActionParams::PointerActionType::LEAVE:
case SyntheticPointerActionParams::PointerActionType::NOT_INITIALIZED:
NOTREACHED()
<< "Invalid SyntheticPointerActionParams::PointerActionType.";
@@ -86,6 +87,8 @@ WebInputEvent::Type ToWebMouseEventType(
return WebInputEvent::kMouseMove;
case SyntheticPointerActionParams::PointerActionType::RELEASE:
return WebInputEvent::kMouseUp;
+ case SyntheticPointerActionParams::PointerActionType::LEAVE:
+ return WebInputEvent::kMouseLeave;
case SyntheticPointerActionParams::PointerActionType::IDLE:
case SyntheticPointerActionParams::PointerActionType::NOT_INITIALIZED:
NOTREACHED()
@@ -188,7 +191,10 @@ class MockSyntheticGestureTarget : public SyntheticGestureTarget {
class MockMoveGestureTarget : public MockSyntheticGestureTarget {
public:
- MockMoveGestureTarget() : total_abs_move_distance_length_(0) {}
+ MockMoveGestureTarget()
+ : total_abs_move_distance_length_(0),
+ precise_scrolling_deltas_(false),
+ scroll_by_page_(false) {}
~MockMoveGestureTarget() override {}
gfx::Vector2dF start_to_end_distance() const {
@@ -197,10 +203,14 @@ class MockMoveGestureTarget : public MockSyntheticGestureTarget {
float total_abs_move_distance_length() const {
return total_abs_move_distance_length_;
}
+ bool precise_scrolling_deltas() const { return precise_scrolling_deltas_; }
+ bool scroll_by_page() const { return scroll_by_page_; }
protected:
gfx::Vector2dF start_to_end_distance_;
float total_abs_move_distance_length_;
+ bool precise_scrolling_deltas_;
+ bool scroll_by_page_;
};
class MockScrollMouseTarget : public MockMoveGestureTarget {
@@ -215,6 +225,8 @@ class MockScrollMouseTarget : public MockMoveGestureTarget {
gfx::Vector2dF delta(mouse_wheel_event.delta_x, mouse_wheel_event.delta_y);
start_to_end_distance_ += delta;
total_abs_move_distance_length_ += delta.Length();
+ precise_scrolling_deltas_ = mouse_wheel_event.has_precise_scrolling_deltas;
+ scroll_by_page_ = mouse_wheel_event.scroll_by_page;
}
};
@@ -256,6 +268,28 @@ class MockMoveTouchTarget : public MockMoveGestureTarget {
bool started_;
};
+class MockFlingGestureTarget : public MockMoveGestureTarget {
+ public:
+ MockFlingGestureTarget() : fling_velocity_x_(0), fling_velocity_y_(0) {}
+ ~MockFlingGestureTarget() override {}
+
+ void DispatchInputEventToPlatform(const WebInputEvent& event) override {
+ if (event.GetType() == WebInputEvent::kGestureFlingStart) {
+ const blink::WebGestureEvent& gesture_event =
+ static_cast<const blink::WebGestureEvent&>(event);
+ fling_velocity_x_ = gesture_event.data.fling_start.velocity_x;
+ fling_velocity_y_ = gesture_event.data.fling_start.velocity_y;
+ }
+ }
+
+ float fling_velocity_x() const { return fling_velocity_x_; }
+ float fling_velocity_y() const { return fling_velocity_y_; }
+
+ private:
+ float fling_velocity_x_;
+ float fling_velocity_y_;
+};
+
class MockDragMouseTarget : public MockMoveGestureTarget {
public:
MockDragMouseTarget() : started_(false) {}
@@ -534,16 +568,20 @@ class MockSyntheticTapMouseTarget : public MockSyntheticTapGestureTarget {
class MockSyntheticPointerActionTarget : public MockSyntheticGestureTarget {
public:
- MockSyntheticPointerActionTarget() : num_actions_dispatched_(0) {}
+ MockSyntheticPointerActionTarget() : num_dispatched_pointer_actions_(0) {}
~MockSyntheticPointerActionTarget() override {}
WebInputEvent::Type type() const { return type_; }
- int num_actions_dispatched() const { return num_actions_dispatched_; }
- void reset_num_actions_dispatched() { num_actions_dispatched_ = 0; }
+ int num_dispatched_pointer_actions() const {
+ return num_dispatched_pointer_actions_;
+ }
+ void reset_num_dispatched_pointer_actions() {
+ num_dispatched_pointer_actions_ = 0;
+ }
protected:
WebInputEvent::Type type_;
- int num_actions_dispatched_;
+ int num_dispatched_pointer_actions_;
};
class MockSyntheticPointerTouchActionTarget
@@ -559,25 +597,26 @@ class MockSyntheticPointerTouchActionTarget
for (size_t i = 0; i < WebTouchEvent::kTouchesLengthCap; ++i) {
if (WebTouchPointStateToEventType(touch_event.touches[i].state) != type_)
continue;
-
- indexes_[i] = touch_event.touches[i].id;
- positions_[i] = gfx::PointF(touch_event.touches[i].PositionInWidget());
- states_[i] = touch_event.touches[i].state;
+ indexes_[num_dispatched_pointer_actions_] = i;
+ positions_[num_dispatched_pointer_actions_] =
+ gfx::PointF(touch_event.touches[i].PositionInWidget());
+ states_[num_dispatched_pointer_actions_] = touch_event.touches[i].state;
+ num_dispatched_pointer_actions_++;
}
- num_actions_dispatched_++;
}
testing::AssertionResult SyntheticTouchActionDispatchedCorrectly(
const SyntheticPointerActionParams& param,
- int index) {
+ int index,
+ int touch_index) {
if (param.pointer_action_type() ==
SyntheticPointerActionParams::PointerActionType::PRESS ||
param.pointer_action_type() ==
SyntheticPointerActionParams::PointerActionType::MOVE) {
- if (indexes_[index] != param.index()) {
+ if (indexes_[index] != touch_index) {
return testing::AssertionFailure()
<< "Pointer index at index " << index << " was "
- << indexes_[index] << ", expected " << param.index() << ".";
+ << indexes_[index] << ", expected " << touch_index << ".";
}
if (positions_[index] != param.position()) {
@@ -598,13 +637,15 @@ class MockSyntheticPointerTouchActionTarget
}
testing::AssertionResult SyntheticTouchActionListDispatchedCorrectly(
- const std::vector<SyntheticPointerActionParams>& params_list) {
+ const std::vector<SyntheticPointerActionParams>& params_list,
+ int start_index,
+ int index_array[]) {
testing::AssertionResult result = testing::AssertionSuccess();
for (size_t i = 0; i < params_list.size(); ++i) {
if (params_list[i].pointer_action_type() !=
SyntheticPointerActionParams::PointerActionType::IDLE)
result = SyntheticTouchActionDispatchedCorrectly(
- params_list[i], params_list[i].index());
+ params_list[i], start_index + i, index_array[i]);
if (result == testing::AssertionFailure())
return result;
}
@@ -630,7 +671,7 @@ class MockSyntheticPointerMouseActionTarget
position_ = gfx::PointF(mouse_event.PositionInWidget());
clickCount_ = mouse_event.click_count;
button_ = mouse_event.button;
- num_actions_dispatched_++;
+ num_dispatched_pointer_actions_++;
}
testing::AssertionResult SyntheticMouseActionDispatchedCorrectly(
@@ -1179,6 +1220,73 @@ TEST_F(SyntheticGestureControllerTest, MultiScrollGestureMouseHorizontal) {
scroll_target->start_to_end_distance().x());
}
+TEST_F(SyntheticGestureControllerTest, SingleScrollGestureTouchpadSwipe) {
+ CreateControllerAndTarget<MockFlingGestureTarget>();
+
+ SyntheticSmoothMoveGestureParams params;
+ params.input_type = SyntheticSmoothMoveGestureParams::MOUSE_WHEEL_INPUT;
+ params.start_point.SetPoint(39, 86);
+ params.distances.push_back(gfx::Vector2d(0, -132));
+ params.fling_velocity_x = 800;
+ params.fling_velocity_y = -1000;
+ params.prevent_fling = false;
+
+ std::unique_ptr<SyntheticSmoothMoveGesture> gesture(
+ new SyntheticSmoothMoveGesture(params));
+ QueueSyntheticGesture(std::move(gesture));
+ FlushInputUntilComplete();
+
+ MockFlingGestureTarget* swipe_target =
+ static_cast<MockFlingGestureTarget*>(target_);
+ EXPECT_EQ(1, num_success_);
+ EXPECT_EQ(0, num_failure_);
+ EXPECT_EQ(params.fling_velocity_x, swipe_target->fling_velocity_x());
+ EXPECT_EQ(params.fling_velocity_y, swipe_target->fling_velocity_y());
+}
+
+TEST_F(SyntheticGestureControllerTest, SingleScrollGestureMousePreciseScroll) {
+ CreateControllerAndTarget<MockScrollMouseTarget>();
+
+ SyntheticSmoothMoveGestureParams params;
+ params.input_type = SyntheticSmoothMoveGestureParams::MOUSE_WHEEL_INPUT;
+ params.start_point.SetPoint(39, 86);
+ params.distances.push_back(gfx::Vector2d(0, -132));
+ params.precise_scrolling_deltas = true;
+
+ std::unique_ptr<SyntheticSmoothMoveGesture> gesture(
+ new SyntheticSmoothMoveGesture(params));
+ QueueSyntheticGesture(std::move(gesture));
+ FlushInputUntilComplete();
+
+ MockMoveGestureTarget* scroll_target =
+ static_cast<MockMoveGestureTarget*>(target_);
+ EXPECT_EQ(1, num_success_);
+ EXPECT_EQ(0, num_failure_);
+ EXPECT_EQ(params.precise_scrolling_deltas,
+ scroll_target->precise_scrolling_deltas());
+}
+
+TEST_F(SyntheticGestureControllerTest, SingleScrollGestureMouseScrollByPage) {
+ CreateControllerAndTarget<MockScrollMouseTarget>();
+
+ SyntheticSmoothMoveGestureParams params;
+ params.input_type = SyntheticSmoothMoveGestureParams::MOUSE_WHEEL_INPUT;
+ params.start_point.SetPoint(39, 86);
+ params.distances.push_back(gfx::Vector2d(0, -132));
+ params.scroll_by_page = true;
+
+ std::unique_ptr<SyntheticSmoothMoveGesture> gesture(
+ new SyntheticSmoothMoveGesture(params));
+ QueueSyntheticGesture(std::move(gesture));
+ FlushInputUntilComplete();
+
+ MockMoveGestureTarget* scroll_target =
+ static_cast<MockMoveGestureTarget*>(target_);
+ EXPECT_EQ(1, num_success_);
+ EXPECT_EQ(0, num_failure_);
+ EXPECT_EQ(params.scroll_by_page, scroll_target->scroll_by_page());
+}
+
void CheckIsWithinRangeMulti(float scroll_distance,
int target_distance,
SyntheticGestureTarget* target) {
@@ -1666,11 +1774,12 @@ TEST_F(SyntheticGestureControllerTest, PointerTouchAction) {
MockSyntheticPointerTouchActionTarget* pointer_touch_target =
static_cast<MockSyntheticPointerTouchActionTarget*>(target_);
+ int index_array[2] = {0, 1};
EXPECT_EQ(1, num_success_);
EXPECT_EQ(0, num_failure_);
- EXPECT_EQ(pointer_touch_target->num_actions_dispatched(), 2);
+ EXPECT_EQ(pointer_touch_target->num_dispatched_pointer_actions(), 2);
EXPECT_TRUE(pointer_touch_target->SyntheticTouchActionListDispatchedCorrectly(
- param_list));
+ param_list, 0, index_array));
// Second, send a touch release for finger 0, a touch move for finger 1.
param0.set_pointer_action_type(
@@ -1684,14 +1793,15 @@ TEST_F(SyntheticGestureControllerTest, PointerTouchAction) {
params.PushPointerActionParamsList(param_list);
gesture.reset(new SyntheticPointerAction(params));
QueueSyntheticGesture(std::move(gesture));
- pointer_touch_target->reset_num_actions_dispatched();
+ pointer_touch_target->reset_num_dispatched_pointer_actions();
FlushInputUntilComplete();
+ index_array[1] = 0;
EXPECT_EQ(2, num_success_);
EXPECT_EQ(0, num_failure_);
- EXPECT_EQ(pointer_touch_target->num_actions_dispatched(), 4);
+ EXPECT_EQ(pointer_touch_target->num_dispatched_pointer_actions(), 4);
EXPECT_TRUE(pointer_touch_target->SyntheticTouchActionListDispatchedCorrectly(
- param_list));
+ param_list, 2, index_array));
// Third, send a touch release for finger 1.
param1.set_pointer_action_type(
@@ -1701,14 +1811,14 @@ TEST_F(SyntheticGestureControllerTest, PointerTouchAction) {
params.PushPointerActionParamsList(param_list);
gesture.reset(new SyntheticPointerAction(params));
QueueSyntheticGesture(std::move(gesture));
- pointer_touch_target->reset_num_actions_dispatched();
+ pointer_touch_target->reset_num_dispatched_pointer_actions();
FlushInputUntilComplete();
EXPECT_EQ(3, num_success_);
EXPECT_EQ(0, num_failure_);
- EXPECT_EQ(pointer_touch_target->num_actions_dispatched(), 5);
+ EXPECT_EQ(pointer_touch_target->num_dispatched_pointer_actions(), 5);
EXPECT_TRUE(pointer_touch_target->SyntheticTouchActionListDispatchedCorrectly(
- param_list));
+ param_list, 4, index_array));
}
TEST_F(SyntheticGestureControllerTest, PointerMouseAction) {
@@ -1732,7 +1842,7 @@ TEST_F(SyntheticGestureControllerTest, PointerMouseAction) {
static_cast<MockSyntheticPointerMouseActionTarget*>(target_);
EXPECT_EQ(1, num_success_);
EXPECT_EQ(0, num_failure_);
- EXPECT_EQ(pointer_mouse_target->num_actions_dispatched(), 1);
+ EXPECT_EQ(pointer_mouse_target->num_dispatched_pointer_actions(), 1);
EXPECT_TRUE(
pointer_mouse_target->SyntheticMouseActionDispatchedCorrectly(param, 0));
@@ -1743,12 +1853,12 @@ TEST_F(SyntheticGestureControllerTest, PointerMouseAction) {
params.PushPointerActionParams(param);
gesture.reset(new SyntheticPointerAction(params));
QueueSyntheticGesture(std::move(gesture));
- pointer_mouse_target->reset_num_actions_dispatched();
+ pointer_mouse_target->reset_num_dispatched_pointer_actions();
FlushInputUntilComplete();
EXPECT_EQ(2, num_success_);
EXPECT_EQ(0, num_failure_);
- EXPECT_EQ(pointer_mouse_target->num_actions_dispatched(), 2);
+ EXPECT_EQ(pointer_mouse_target->num_dispatched_pointer_actions(), 2);
EXPECT_TRUE(
pointer_mouse_target->SyntheticMouseActionDispatchedCorrectly(param, 1));
@@ -1759,12 +1869,12 @@ TEST_F(SyntheticGestureControllerTest, PointerMouseAction) {
params.PushPointerActionParams(param);
gesture.reset(new SyntheticPointerAction(params));
QueueSyntheticGesture(std::move(gesture));
- pointer_mouse_target->reset_num_actions_dispatched();
+ pointer_mouse_target->reset_num_dispatched_pointer_actions();
FlushInputUntilComplete();
EXPECT_EQ(3, num_success_);
EXPECT_EQ(0, num_failure_);
- EXPECT_EQ(pointer_mouse_target->num_actions_dispatched(), 3);
+ EXPECT_EQ(pointer_mouse_target->num_dispatched_pointer_actions(), 3);
EXPECT_TRUE(
pointer_mouse_target->SyntheticMouseActionDispatchedCorrectly(param, 1));
@@ -1774,14 +1884,102 @@ TEST_F(SyntheticGestureControllerTest, PointerMouseAction) {
params.PushPointerActionParams(param);
gesture.reset(new SyntheticPointerAction(params));
QueueSyntheticGesture(std::move(gesture));
- pointer_mouse_target->reset_num_actions_dispatched();
+ pointer_mouse_target->reset_num_dispatched_pointer_actions();
FlushInputUntilComplete();
EXPECT_EQ(4, num_success_);
EXPECT_EQ(0, num_failure_);
- EXPECT_EQ(pointer_mouse_target->num_actions_dispatched(), 4);
+ EXPECT_EQ(pointer_mouse_target->num_dispatched_pointer_actions(), 4);
EXPECT_TRUE(
pointer_mouse_target->SyntheticMouseActionDispatchedCorrectly(param, 1));
}
+TEST_F(SyntheticGestureControllerTest, PointerPenAction) {
+ CreateControllerAndTarget<MockSyntheticPointerMouseActionTarget>();
+
+ // First, send a pen move.
+ SyntheticPointerActionListParams::ParamList param_list;
+ SyntheticPointerActionParams param = SyntheticPointerActionParams(
+ SyntheticPointerActionParams::PointerActionType::MOVE);
+
+ param.set_position(gfx::PointF(54, 89));
+ SyntheticPointerActionListParams params;
+ params.PushPointerActionParams(param);
+ params.gesture_source_type = SyntheticGestureParams::PEN_INPUT;
+ std::unique_ptr<SyntheticPointerAction> gesture(
+ new SyntheticPointerAction(params));
+ QueueSyntheticGesture(std::move(gesture));
+ FlushInputUntilComplete();
+
+ MockSyntheticPointerMouseActionTarget* pointer_pen_target =
+ static_cast<MockSyntheticPointerMouseActionTarget*>(target_);
+ EXPECT_EQ(1, num_success_);
+ EXPECT_EQ(0, num_failure_);
+ EXPECT_EQ(pointer_pen_target->num_dispatched_pointer_actions(), 1);
+ EXPECT_TRUE(
+ pointer_pen_target->SyntheticMouseActionDispatchedCorrectly(param, 0));
+
+ // Second, send a pen press.
+ param.set_pointer_action_type(
+ SyntheticPointerActionParams::PointerActionType::PRESS);
+ param.set_position(gfx::PointF(183, 239));
+ params.PushPointerActionParams(param);
+ gesture.reset(new SyntheticPointerAction(params));
+ QueueSyntheticGesture(std::move(gesture));
+ pointer_pen_target->reset_num_dispatched_pointer_actions();
+ FlushInputUntilComplete();
+
+ EXPECT_EQ(2, num_success_);
+ EXPECT_EQ(0, num_failure_);
+ EXPECT_EQ(pointer_pen_target->num_dispatched_pointer_actions(), 2);
+ EXPECT_TRUE(
+ pointer_pen_target->SyntheticMouseActionDispatchedCorrectly(param, 1));
+
+ // Third, send a pen move.
+ param.set_pointer_action_type(
+ SyntheticPointerActionParams::PointerActionType::MOVE);
+ param.set_position(gfx::PointF(254, 279));
+ params.PushPointerActionParams(param);
+ gesture.reset(new SyntheticPointerAction(params));
+ QueueSyntheticGesture(std::move(gesture));
+ pointer_pen_target->reset_num_dispatched_pointer_actions();
+ FlushInputUntilComplete();
+
+ EXPECT_EQ(3, num_success_);
+ EXPECT_EQ(0, num_failure_);
+ EXPECT_EQ(pointer_pen_target->num_dispatched_pointer_actions(), 3);
+ EXPECT_TRUE(
+ pointer_pen_target->SyntheticMouseActionDispatchedCorrectly(param, 1));
+
+ // Fourth, send a pen release.
+ param.set_pointer_action_type(
+ SyntheticPointerActionParams::PointerActionType::RELEASE);
+ params.PushPointerActionParams(param);
+ gesture.reset(new SyntheticPointerAction(params));
+ QueueSyntheticGesture(std::move(gesture));
+ pointer_pen_target->reset_num_dispatched_pointer_actions();
+ FlushInputUntilComplete();
+
+ EXPECT_EQ(4, num_success_);
+ EXPECT_EQ(0, num_failure_);
+ EXPECT_EQ(pointer_pen_target->num_dispatched_pointer_actions(), 4);
+ EXPECT_TRUE(
+ pointer_pen_target->SyntheticMouseActionDispatchedCorrectly(param, 1));
+
+ // Fifth, send a pen leave.
+ param.set_pointer_action_type(
+ SyntheticPointerActionParams::PointerActionType::LEAVE);
+ params.PushPointerActionParams(param);
+ gesture.reset(new SyntheticPointerAction(params));
+ QueueSyntheticGesture(std::move(gesture));
+ pointer_pen_target->reset_num_dispatched_pointer_actions();
+ FlushInputUntilComplete();
+
+ EXPECT_EQ(5, num_success_);
+ EXPECT_EQ(0, num_failure_);
+ EXPECT_EQ(pointer_pen_target->num_dispatched_pointer_actions(), 5);
+ EXPECT_TRUE(
+ pointer_pen_target->SyntheticMouseActionDispatchedCorrectly(param, 0));
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/synthetic_gesture_target_aura.cc b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_aura.cc
index c9b4679a367..f66e36f7a46 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_gesture_target_aura.cc
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_aura.cc
@@ -81,9 +81,16 @@ void SyntheticGestureTargetAura::DispatchWebMouseWheelEventToPlatform(
return;
}
base::TimeTicks timestamp = web_wheel.TimeStamp();
+ int modifiers = ui::EF_NONE;
+ if (web_wheel.has_precise_scrolling_deltas)
+ modifiers |= ui::EF_PRECISION_SCROLLING_DELTA;
+
+ if (web_wheel.scroll_by_page)
+ modifiers |= ui::EF_SCROLL_BY_PAGE;
+
ui::MouseWheelEvent wheel_event(
gfx::Vector2d(web_wheel.delta_x, web_wheel.delta_y), gfx::Point(),
- gfx::Point(), timestamp, ui::EF_NONE, ui::EF_NONE);
+ gfx::Point(), timestamp, modifiers, ui::EF_NONE);
gfx::PointF location(web_wheel.PositionInWidget().x * device_scale_factor_,
web_wheel.PositionInWidget().y * device_scale_factor_);
wheel_event.set_location_f(location);
@@ -101,25 +108,44 @@ void SyntheticGestureTargetAura::DispatchWebMouseWheelEventToPlatform(
void SyntheticGestureTargetAura::DispatchWebGestureEventToPlatform(
const blink::WebGestureEvent& web_gesture,
const ui::LatencyInfo& latency_info) {
- DCHECK(blink::WebInputEvent::IsPinchGestureEventType(web_gesture.GetType()));
+ DCHECK(blink::WebInputEvent::IsPinchGestureEventType(web_gesture.GetType()) ||
+ blink::WebInputEvent::IsFlingGestureEventType(web_gesture.GetType()));
ui::EventType event_type = ui::WebEventTypeToEventType(web_gesture.GetType());
int flags = ui::WebEventModifiersToEventFlags(web_gesture.GetModifiers());
+ aura::Window* window = GetWindow();
+ aura::EventInjector injector;
- ui::GestureEventDetails pinch_details(event_type);
- pinch_details.set_device_type(ui::GestureDeviceType::DEVICE_TOUCHPAD);
- if (event_type == ui::ET_GESTURE_PINCH_UPDATE)
- pinch_details.set_scale(web_gesture.data.pinch_update.scale);
+ if (blink::WebInputEvent::IsPinchGestureEventType(web_gesture.GetType())) {
+ ui::GestureEventDetails pinch_details(event_type);
+ pinch_details.set_device_type(ui::GestureDeviceType::DEVICE_TOUCHPAD);
+ if (event_type == ui::ET_GESTURE_PINCH_UPDATE)
+ pinch_details.set_scale(web_gesture.data.pinch_update.scale);
- ui::GestureEvent pinch_event(
- web_gesture.PositionInWidget().x * device_scale_factor_,
- web_gesture.PositionInWidget().y * device_scale_factor_, flags,
- ui::EventTimeForNow(), pinch_details);
+ ui::GestureEvent pinch_event(
+ web_gesture.PositionInWidget().x * device_scale_factor_,
+ web_gesture.PositionInWidget().y * device_scale_factor_, flags,
+ ui::EventTimeForNow(), pinch_details);
- aura::Window* window = GetWindow();
- pinch_event.ConvertLocationToTarget(window, window->GetRootWindow());
+ pinch_event.ConvertLocationToTarget(window, window->GetRootWindow());
- aura::EventInjector injector;
- injector.Inject(window->GetHost(), &pinch_event);
+ injector.Inject(window->GetHost(), &pinch_event);
+ return;
+ }
+
+ ui::EventMomentumPhase momentum_phase =
+ web_gesture.GetType() == blink::WebInputEvent::kGestureFlingStart
+ ? ui::EventMomentumPhase::BEGAN
+ : ui::EventMomentumPhase::END;
+ gfx::PointF location(web_gesture.PositionInWidget().x * device_scale_factor_,
+ web_gesture.PositionInWidget().y * device_scale_factor_);
+ ui::ScrollEvent scroll_event(event_type, gfx::Point(), ui::EventTimeForNow(),
+ flags, web_gesture.data.fling_start.velocity_x,
+ web_gesture.data.fling_start.velocity_y, 0, 0, 2,
+ momentum_phase, ui::ScrollEventPhase::kNone);
+ scroll_event.set_location_f(location);
+ scroll_event.set_root_location_f(location);
+ scroll_event.ConvertLocationToTarget(window, window->GetRootWindow());
+ injector.Inject(window->GetHost(), &scroll_event);
}
void SyntheticGestureTargetAura::DispatchWebMouseEventToPlatform(
diff --git a/chromium/content/browser/renderer_host/input/synthetic_gesture_target_base.cc b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_base.cc
index c238c21add2..f700f10e947 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_gesture_target_base.cc
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_base.cc
@@ -99,6 +99,19 @@ void SyntheticGestureTargetBase::DispatchInputEventToPlatform(
return;
}
DispatchWebGestureEventToPlatform(web_pinch, latency_info);
+ } else if (WebInputEvent::IsFlingGestureEventType(event.GetType())) {
+ const WebGestureEvent& web_fling =
+ static_cast<const WebGestureEvent&>(event);
+ // Touchscreen swipe should be injected as touch events.
+ DCHECK_EQ(blink::kWebGestureDeviceTouchpad, web_fling.SourceDevice());
+ if (event.GetType() == WebInputEvent::kGestureFlingStart &&
+ !PointIsWithinContents(web_fling.PositionInWidget().x,
+ web_fling.PositionInWidget().y)) {
+ LOG(WARNING)
+ << "Fling coordinates are not within content bounds on FlingStart.";
+ return;
+ }
+ DispatchWebGestureEventToPlatform(web_fling, latency_info);
} else {
NOTREACHED();
}
diff --git a/chromium/content/browser/renderer_host/input/synthetic_mouse_driver.cc b/chromium/content/browser/renderer_host/input/synthetic_mouse_driver.cc
index 2547e5d210c..4a48a9684bc 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_mouse_driver.cc
+++ b/chromium/content/browser/renderer_host/input/synthetic_mouse_driver.cc
@@ -66,6 +66,10 @@ void SyntheticMouseDriver::Release(
(~SyntheticPointerActionParams::GetWebMouseEventModifier(button));
}
+void SyntheticMouseDriver::Leave(int index) {
+ NOTIMPLEMENTED();
+}
+
bool SyntheticMouseDriver::UserInputCheck(
const SyntheticPointerActionParams& params) const {
if (params.index() != 0)
@@ -85,12 +89,17 @@ bool SyntheticMouseDriver::UserInputCheck(
}
if (params.pointer_action_type() ==
- SyntheticPointerActionParams::PointerActionType::RELEASE &&
- mouse_event_.click_count <= 0) {
- return false;
+ SyntheticPointerActionParams::PointerActionType::RELEASE) {
+ if (mouse_event_.click_count <= 0)
+ return false;
+
+ int modifiers =
+ SyntheticPointerActionParams::GetWebMouseEventModifier(params.button());
+ if (!(last_modifiers_ & modifiers))
+ return false;
}
return true;
}
-} // namespace content
+} // namespace content \ No newline at end of file
diff --git a/chromium/content/browser/renderer_host/input/synthetic_mouse_driver.h b/chromium/content/browser/renderer_host/input/synthetic_mouse_driver.h
index a314788e78e..341d167134c 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_mouse_driver.h
+++ b/chromium/content/browser/renderer_host/input/synthetic_mouse_driver.h
@@ -29,16 +29,16 @@ class CONTENT_EXPORT SyntheticMouseDriver : public SyntheticPointerDriver {
void Release(int index = 0,
SyntheticPointerActionParams::Button button =
SyntheticPointerActionParams::Button::LEFT) override;
+ void Leave(int index = 0) override;
bool UserInputCheck(
const SyntheticPointerActionParams& params) const override;
protected:
blink::WebMouseEvent mouse_event_;
-
- private:
unsigned last_modifiers_;
+ private:
DISALLOW_COPY_AND_ASSIGN(SyntheticMouseDriver);
};
diff --git a/chromium/content/browser/renderer_host/input/synthetic_pen_driver.cc b/chromium/content/browser/renderer_host/input/synthetic_pen_driver.cc
index 0d6f85a6e9b..697ee995f5e 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_pen_driver.cc
+++ b/chromium/content/browser/renderer_host/input/synthetic_pen_driver.cc
@@ -12,4 +12,12 @@ SyntheticPenDriver::SyntheticPenDriver() : SyntheticMouseDriver() {
SyntheticPenDriver::~SyntheticPenDriver() {}
-} // namespace content
+void SyntheticPenDriver::Leave(int index) {
+ DCHECK_EQ(index, 0);
+ mouse_event_ = SyntheticWebMouseEventBuilder::Build(
+ blink::WebInputEvent::kMouseLeave, mouse_event_.PositionInWidget().x,
+ mouse_event_.PositionInWidget().y, last_modifiers_,
+ mouse_event_.pointer_type);
+}
+
+} // namespace content \ No newline at end of file
diff --git a/chromium/content/browser/renderer_host/input/synthetic_pen_driver.h b/chromium/content/browser/renderer_host/input/synthetic_pen_driver.h
index d6ece9f0532..428aaba96d6 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_pen_driver.h
+++ b/chromium/content/browser/renderer_host/input/synthetic_pen_driver.h
@@ -16,6 +16,8 @@ class CONTENT_EXPORT SyntheticPenDriver : public SyntheticMouseDriver {
SyntheticPenDriver();
~SyntheticPenDriver() override;
+ void Leave(int index = 0) override;
+
private:
DISALLOW_COPY_AND_ASSIGN(SyntheticPenDriver);
};
diff --git a/chromium/content/browser/renderer_host/input/synthetic_pointer_action.cc b/chromium/content/browser/renderer_host/input/synthetic_pointer_action.cc
index bc0526b5fee..65dccb01a30 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_pointer_action.cc
+++ b/chromium/content/browser/renderer_host/input/synthetic_pointer_action.cc
@@ -74,6 +74,9 @@ SyntheticPointerAction::ForwardTouchOrMouseInputEvents(
case SyntheticPointerActionParams::PointerActionType::RELEASE:
synthetic_pointer_driver_->Release(param.index(), param.button());
break;
+ case SyntheticPointerActionParams::PointerActionType::LEAVE:
+ synthetic_pointer_driver_->Leave(param.index());
+ break;
case SyntheticPointerActionParams::PointerActionType::IDLE:
break;
case SyntheticPointerActionParams::PointerActionType::NOT_INITIALIZED:
diff --git a/chromium/content/browser/renderer_host/input/synthetic_pointer_action_unittest.cc b/chromium/content/browser/renderer_host/input/synthetic_pointer_action_unittest.cc
index c4d45f9d825..8f480dd77dc 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_pointer_action_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/synthetic_pointer_action_unittest.cc
@@ -32,6 +32,7 @@ WebTouchPoint::State ToWebTouchPointState(
return WebTouchPoint::kStateReleased;
case SyntheticPointerActionParams::PointerActionType::IDLE:
return WebTouchPoint::kStateStationary;
+ case SyntheticPointerActionParams::PointerActionType::LEAVE:
case SyntheticPointerActionParams::PointerActionType::NOT_INITIALIZED:
NOTREACHED()
<< "Invalid SyntheticPointerActionParams::PointerActionType.";
@@ -50,6 +51,8 @@ WebInputEvent::Type ToWebMouseEventType(
return WebInputEvent::kMouseMove;
case SyntheticPointerActionParams::PointerActionType::RELEASE:
return WebInputEvent::kMouseUp;
+ case SyntheticPointerActionParams::PointerActionType::LEAVE:
+ return WebInputEvent::kMouseLeave;
case SyntheticPointerActionParams::PointerActionType::IDLE:
case SyntheticPointerActionParams::PointerActionType::NOT_INITIALIZED:
NOTREACHED()
@@ -115,7 +118,8 @@ class MockSyntheticPointerActionTarget : public SyntheticGestureTarget {
class MockSyntheticPointerTouchActionTarget
: public MockSyntheticPointerActionTarget {
public:
- MockSyntheticPointerTouchActionTarget() {}
+ MockSyntheticPointerTouchActionTarget()
+ : num_dispatched_pointer_actions_(0) {}
~MockSyntheticPointerTouchActionTarget() override {}
void DispatchInputEventToPlatform(const WebInputEvent& event) override {
@@ -125,16 +129,18 @@ class MockSyntheticPointerTouchActionTarget
for (size_t i = 0; i < WebTouchEvent::kTouchesLengthCap; ++i) {
if (WebTouchPointStateToEventType(touch_event.touches[i].state) != type_)
continue;
-
- indexes_[i] = touch_event.touches[i].id;
- positions_[i] = gfx::PointF(touch_event.touches[i].PositionInWidget());
- states_[i] = touch_event.touches[i].state;
+ indexes_[num_dispatched_pointer_actions_] = i;
+ positions_[num_dispatched_pointer_actions_] =
+ gfx::PointF(touch_event.touches[i].PositionInWidget());
+ states_[num_dispatched_pointer_actions_] = touch_event.touches[i].state;
+ num_dispatched_pointer_actions_++;
}
}
testing::AssertionResult SyntheticTouchActionDispatchedCorrectly(
const SyntheticPointerActionParams& param,
- int index) {
+ int index,
+ int touch_index) {
if (param.pointer_action_type() ==
SyntheticPointerActionParams::PointerActionType::PRESS ||
param.pointer_action_type() ==
@@ -163,13 +169,16 @@ class MockSyntheticPointerTouchActionTarget
}
testing::AssertionResult SyntheticTouchActionListDispatchedCorrectly(
- const std::vector<SyntheticPointerActionParams>& params_list) {
+ const std::vector<SyntheticPointerActionParams>& params_list,
+ int index_array[]) {
testing::AssertionResult result = testing::AssertionSuccess();
+ num_dispatched_pointer_actions_ = 0;
+ int result_index = 0;
for (size_t i = 0; i < params_list.size(); ++i) {
if (params_list[i].pointer_action_type() !=
SyntheticPointerActionParams::PointerActionType::IDLE)
result = SyntheticTouchActionDispatchedCorrectly(
- params_list[i], params_list[i].index());
+ params_list[i], result_index++, index_array[i]);
if (result == testing::AssertionFailure())
return result;
}
@@ -182,6 +191,7 @@ class MockSyntheticPointerTouchActionTarget
}
private:
+ int num_dispatched_pointer_actions_;
gfx::PointF positions_[WebTouchEvent::kTouchesLengthCap];
int indexes_[WebTouchEvent::kTouchesLengthCap];
WebTouchPoint::State states_[WebTouchEvent::kTouchesLengthCap];
@@ -381,11 +391,12 @@ TEST_F(SyntheticPointerActionTest, PointerTouchAction) {
ForwardSyntheticPointerAction();
MockSyntheticPointerTouchActionTarget* pointer_touch_target =
static_cast<MockSyntheticPointerTouchActionTarget*>(target_.get());
+ int index_array[2] = {0, 1};
EXPECT_EQ(1, num_success_);
EXPECT_EQ(0, num_failure_);
EXPECT_EQ(pointer_touch_target->type(), WebInputEvent::kTouchStart);
EXPECT_TRUE(pointer_touch_target->SyntheticTouchActionListDispatchedCorrectly(
- param_list1));
+ param_list1, index_array));
ForwardSyntheticPointerAction();
EXPECT_EQ(2, num_success_);
@@ -393,21 +404,22 @@ TEST_F(SyntheticPointerActionTest, PointerTouchAction) {
// The type of the SyntheticWebTouchEvent is the action of the last finger.
EXPECT_EQ(pointer_touch_target->type(), WebInputEvent::kTouchStart);
EXPECT_TRUE(pointer_touch_target->SyntheticTouchActionListDispatchedCorrectly(
- param_list2));
+ param_list2, index_array));
ForwardSyntheticPointerAction();
EXPECT_EQ(3, num_success_);
EXPECT_EQ(0, num_failure_);
EXPECT_EQ(pointer_touch_target->type(), WebInputEvent::kTouchMove);
EXPECT_TRUE(pointer_touch_target->SyntheticTouchActionListDispatchedCorrectly(
- param_list3));
+ param_list3, index_array));
ForwardSyntheticPointerAction();
+ index_array[1] = 0;
EXPECT_EQ(4, num_success_);
EXPECT_EQ(0, num_failure_);
EXPECT_EQ(pointer_touch_target->type(), WebInputEvent::kTouchEnd);
EXPECT_TRUE(pointer_touch_target->SyntheticTouchActionListDispatchedCorrectly(
- param_list4));
+ param_list4, index_array));
}
TEST_F(SyntheticPointerActionTest, PointerTouchActionsMultiPressRelease) {
@@ -450,11 +462,12 @@ TEST_F(SyntheticPointerActionTest, PointerTouchActionsMultiPressRelease) {
ForwardSyntheticPointerAction();
MockSyntheticPointerTouchActionTarget* pointer_touch_target =
static_cast<MockSyntheticPointerTouchActionTarget*>(target_.get());
+ int index_array[2] = {0, 1};
EXPECT_EQ(count_success++, num_success_);
EXPECT_EQ(0, num_failure_);
EXPECT_EQ(pointer_touch_target->type(), WebInputEvent::kTouchStart);
EXPECT_TRUE(pointer_touch_target->SyntheticTouchActionListDispatchedCorrectly(
- param_list1));
+ param_list1, index_array));
for (int index = 1; index < 4; ++index) {
ForwardSyntheticPointerAction();
@@ -464,7 +477,7 @@ TEST_F(SyntheticPointerActionTest, PointerTouchActionsMultiPressRelease) {
EXPECT_EQ(pointer_touch_target->type(), WebInputEvent::kTouchStart);
EXPECT_TRUE(
pointer_touch_target->SyntheticTouchActionListDispatchedCorrectly(
- param_list2));
+ param_list2, index_array));
ForwardSyntheticPointerAction();
EXPECT_EQ(count_success++, num_success_);
@@ -473,7 +486,7 @@ TEST_F(SyntheticPointerActionTest, PointerTouchActionsMultiPressRelease) {
EXPECT_EQ(pointer_touch_target->type(), WebInputEvent::kTouchEnd);
EXPECT_TRUE(
pointer_touch_target->SyntheticTouchActionListDispatchedCorrectly(
- param_list3));
+ param_list3, index_array));
}
}
@@ -517,8 +530,8 @@ TEST_F(SyntheticPointerActionTest, PointerTouchActionTypeInvalid) {
EXPECT_EQ(1, num_success_);
EXPECT_EQ(2, num_failure_);
EXPECT_EQ(pointer_touch_target->type(), WebInputEvent::kTouchStart);
- EXPECT_TRUE(
- pointer_touch_target->SyntheticTouchActionDispatchedCorrectly(param, 0));
+ EXPECT_TRUE(pointer_touch_target->SyntheticTouchActionDispatchedCorrectly(
+ param, 0, 0));
// Cannot send a touch press again without releasing the finger.
ForwardSyntheticPointerAction();
@@ -702,6 +715,11 @@ TEST_F(SyntheticPointerActionTest, PointerPenAction) {
SyntheticPointerActionParams param3 = SyntheticPointerActionParams(
SyntheticPointerActionParams::PointerActionType::RELEASE);
params_.PushPointerActionParams(param3);
+
+ // Send a pen leave.
+ SyntheticPointerActionParams param4 = SyntheticPointerActionParams(
+ SyntheticPointerActionParams::PointerActionType::LEAVE);
+ params_.PushPointerActionParams(param4);
pointer_action_.reset(new SyntheticPointerAction(params_));
ForwardSyntheticPointerAction();
@@ -725,6 +743,13 @@ TEST_F(SyntheticPointerActionTest, PointerPenAction) {
EXPECT_EQ(0, num_failure_);
EXPECT_TRUE(pointer_pen_target->SyntheticMouseActionDispatchedCorrectly(
param3, 1, buttons, SyntheticGestureParams::PEN_INPUT));
+
+ ForwardSyntheticPointerAction();
+ EXPECT_EQ(4, num_success_);
+ EXPECT_EQ(0, num_failure_);
+ buttons.pop_back();
+ EXPECT_TRUE(pointer_pen_target->SyntheticMouseActionDispatchedCorrectly(
+ param4, 0, buttons, SyntheticGestureParams::PEN_INPUT));
}
TEST_F(SyntheticPointerActionTest, EmptyParams) {
diff --git a/chromium/content/browser/renderer_host/input/synthetic_pointer_driver.h b/chromium/content/browser/renderer_host/input/synthetic_pointer_driver.h
index 8ca1163b4e9..4325654257e 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_pointer_driver.h
+++ b/chromium/content/browser/renderer_host/input/synthetic_pointer_driver.h
@@ -37,6 +37,7 @@ class CONTENT_EXPORT SyntheticPointerDriver {
virtual void Release(int index = 0,
SyntheticPointerActionParams::Button button =
SyntheticPointerActionParams::Button::LEFT) = 0;
+ virtual void Leave(int index = 0) = 0;
// Check if the user inputs in the SyntheticPointerActionParams can generate
// a valid sequence of pointer actions.
diff --git a/chromium/content/browser/renderer_host/input/synthetic_smooth_move_gesture.cc b/chromium/content/browser/renderer_host/input/synthetic_smooth_move_gesture.cc
index ea2c5eca311..11325e371a7 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_smooth_move_gesture.cc
+++ b/chromium/content/browser/renderer_host/input/synthetic_smooth_move_gesture.cc
@@ -29,8 +29,12 @@ const int kDefaultSpeedInPixelsPerSec = 800;
SyntheticSmoothMoveGestureParams::SyntheticSmoothMoveGestureParams()
: speed_in_pixels_s(kDefaultSpeedInPixelsPerSec),
+ fling_velocity_x(0),
+ fling_velocity_y(0),
prevent_fling(true),
- add_slop(true) {}
+ add_slop(true),
+ precise_scrolling_deltas(false),
+ scroll_by_page(false) {}
SyntheticSmoothMoveGestureParams::SyntheticSmoothMoveGestureParams(
const SyntheticSmoothMoveGestureParams& other) = default;
@@ -185,10 +189,18 @@ void SyntheticSmoothMoveGesture::ForwardMouseWheelInputEvents(
ComputeNextMoveSegment();
} else {
state_ = DONE;
- // Forward a wheel event with phase ended and zero deltas.
- ForwardMouseWheelEvent(target, gfx::Vector2d(),
- blink::WebMouseWheelEvent::kPhaseEnded,
- event_timestamp);
+
+ // Start flinging on the swipe action.
+ if (!params_.prevent_fling && (params_.fling_velocity_x != 0 ||
+ params_.fling_velocity_y != 0)) {
+ ForwardFlingGestureEvent(
+ target, blink::WebGestureEvent::kGestureFlingStart);
+ } else {
+ // Forward a wheel event with phase ended and zero deltas.
+ ForwardMouseWheelEvent(target, gfx::Vector2d(),
+ blink::WebMouseWheelEvent::kPhaseEnded,
+ event_timestamp);
+ }
needs_scroll_begin_ = true;
}
}
@@ -258,8 +270,9 @@ void SyntheticSmoothMoveGesture::ForwardMouseWheelEvent(
const blink::WebMouseWheelEvent::Phase phase,
const base::TimeTicks& timestamp) const {
blink::WebMouseWheelEvent mouse_wheel_event =
- SyntheticWebMouseWheelEventBuilder::Build(0, 0, delta.x(), delta.y(), 0,
- false);
+ SyntheticWebMouseWheelEventBuilder::Build(
+ 0, 0, delta.x(), delta.y(), 0, params_.precise_scrolling_deltas,
+ params_.scroll_by_page);
mouse_wheel_event.SetPositionInWidget(
current_move_segment_start_position_.x(),
@@ -271,6 +284,18 @@ void SyntheticSmoothMoveGesture::ForwardMouseWheelEvent(
target->DispatchInputEventToPlatform(mouse_wheel_event);
}
+void SyntheticSmoothMoveGesture::ForwardFlingGestureEvent(
+ SyntheticGestureTarget* target,
+ const blink::WebInputEvent::Type type) const {
+ blink::WebGestureEvent fling_gesture_event =
+ SyntheticWebGestureEventBuilder::Build(type,
+ blink::kWebGestureDeviceTouchpad);
+ fling_gesture_event.data.fling_start.velocity_x = params_.fling_velocity_x;
+ fling_gesture_event.data.fling_start.velocity_y = params_.fling_velocity_y;
+ fling_gesture_event.SetPositionInWidget(current_move_segment_start_position_);
+ target->DispatchInputEventToPlatform(fling_gesture_event);
+}
+
void SyntheticSmoothMoveGesture::PressPoint(SyntheticGestureTarget* target,
const base::TimeTicks& timestamp) {
DCHECK_EQ(current_move_segment_, 0);
diff --git a/chromium/content/browser/renderer_host/input/synthetic_smooth_move_gesture.h b/chromium/content/browser/renderer_host/input/synthetic_smooth_move_gesture.h
index 353336c1f5c..353b10d30a7 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_smooth_move_gesture.h
+++ b/chromium/content/browser/renderer_host/input/synthetic_smooth_move_gesture.h
@@ -34,8 +34,12 @@ class CONTENT_EXPORT SyntheticSmoothMoveGestureParams {
gfx::PointF start_point;
std::vector<gfx::Vector2dF> distances;
int speed_in_pixels_s;
+ int fling_velocity_x;
+ int fling_velocity_y;
bool prevent_fling;
bool add_slop;
+ bool precise_scrolling_deltas;
+ bool scroll_by_page;
};
// This class is used as helper class for simulation of scroll and drag.
@@ -77,6 +81,9 @@ class CONTENT_EXPORT SyntheticSmoothMoveGesture : public SyntheticGesture {
const blink::WebMouseWheelEvent::Phase phase,
const base::TimeTicks& timestamp) const;
+ void ForwardFlingGestureEvent(SyntheticGestureTarget* target,
+ const blink::WebInputEvent::Type type) const;
+
void PressPoint(SyntheticGestureTarget* target,
const base::TimeTicks& timestamp);
void MovePoint(SyntheticGestureTarget* target,
diff --git a/chromium/content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.cc b/chromium/content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.cc
index de5265912ca..977fe39a806 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.cc
+++ b/chromium/content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.cc
@@ -45,9 +45,13 @@ bool SyntheticSmoothScrollGesture::InitializeMoveGesture(
move_params.start_point = params_.anchor;
move_params.distances = params_.distances;
move_params.speed_in_pixels_s = params_.speed_in_pixels_s;
+ move_params.fling_velocity_x = params_.fling_velocity_x;
+ move_params.fling_velocity_y = params_.fling_velocity_y;
move_params.prevent_fling = params_.prevent_fling;
move_params.input_type = GetInputSourceType(gesture_type);
move_params.add_slop = true;
+ move_params.precise_scrolling_deltas = params_.precise_scrolling_deltas;
+ move_params.scroll_by_page = params_.scroll_by_page;
move_gesture_.reset(new SyntheticSmoothMoveGesture(move_params));
return true;
}
diff --git a/chromium/content/browser/renderer_host/input/synthetic_touch_driver.cc b/chromium/content/browser/renderer_host/input/synthetic_touch_driver.cc
index a8e14a2aff0..c16c6e00c9c 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_touch_driver.cc
+++ b/chromium/content/browser/renderer_host/input/synthetic_touch_driver.cc
@@ -25,6 +25,7 @@ void SyntheticTouchDriver::DispatchEvent(SyntheticGestureTarget* target,
if (touch_event_.GetType() != blink::WebInputEvent::kUndefined)
target->DispatchInputEventToPlatform(touch_event_);
touch_event_.ResetPoints();
+ ResetIndexMap();
}
void SyntheticTouchDriver::Press(float x,
@@ -52,6 +53,10 @@ void SyntheticTouchDriver::Release(
index_map_[index] = -1;
}
+void SyntheticTouchDriver::Leave(int index) {
+ NOTIMPLEMENTED();
+}
+
bool SyntheticTouchDriver::UserInputCheck(
const SyntheticPointerActionParams& params) const {
if (params.index() < 0 ||
@@ -84,4 +89,26 @@ bool SyntheticTouchDriver::UserInputCheck(
return true;
}
+void SyntheticTouchDriver::ResetIndexMap() {
+ unsigned free_index = 0;
+ for (unsigned int i = 0; i < blink::WebTouchEvent::kTouchesLengthCap; ++i) {
+ if (free_index >= touch_event_.touches_length)
+ break;
+ if (touch_event_.touches[i].state !=
+ blink::WebTouchPoint::kStateUndefined) {
+ touch_event_.touches[free_index] = touch_event_.touches[i];
+ int index = GetIndexFromMap(i);
+ index_map_[index] = free_index;
+ free_index++;
+ }
+ }
+}
+
+int SyntheticTouchDriver::GetIndexFromMap(int value) const {
+ int index = std::find(index_map_.begin(), index_map_.end(), value) -
+ index_map_.begin();
+ DCHECK(index >= 0 && index < blink::WebTouchEvent::kTouchesLengthCap);
+ return index;
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/synthetic_touch_driver.h b/chromium/content/browser/renderer_host/input/synthetic_touch_driver.h
index 95470f378bf..3f8102a212d 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_touch_driver.h
+++ b/chromium/content/browser/renderer_host/input/synthetic_touch_driver.h
@@ -31,6 +31,7 @@ class CONTENT_EXPORT SyntheticTouchDriver : public SyntheticPointerDriver {
void Release(int index,
SyntheticPointerActionParams::Button button =
SyntheticPointerActionParams::Button::LEFT) override;
+ void Leave(int index) override;
bool UserInputCheck(
const SyntheticPointerActionParams& params) const override;
@@ -38,6 +39,9 @@ class CONTENT_EXPORT SyntheticTouchDriver : public SyntheticPointerDriver {
private:
using IndexMap = std::array<int, blink::WebTouchEvent::kTouchesLengthCap>;
+ void ResetIndexMap();
+ int GetIndexFromMap(int value) const;
+
SyntheticWebTouchEvent touch_event_;
IndexMap index_map_;
diff --git a/chromium/content/browser/renderer_host/input/touch_action_filter.cc b/chromium/content/browser/renderer_host/input/touch_action_filter.cc
index 16e30e8e392..8a35a81229d 100644
--- a/chromium/content/browser/renderer_host/input/touch_action_filter.cc
+++ b/chromium/content/browser/renderer_host/input/touch_action_filter.cc
@@ -6,6 +6,7 @@
#include <math.h>
+#include "base/debug/crash_logging.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "third_party/blink/public/platform/web_gesture_event.h"
@@ -38,7 +39,11 @@ TouchActionFilter::TouchActionFilter()
: suppress_manipulation_events_(false),
drop_current_tap_ending_event_(false),
allow_current_double_tap_event_(true),
- force_enable_zoom_(false) {}
+ force_enable_zoom_(false) {
+ ResetTouchAction();
+}
+
+TouchActionFilter::~TouchActionFilter() {}
FilterGestureEventResult TouchActionFilter::FilterGestureEvent(
WebGestureEvent* gesture_event) {
@@ -50,11 +55,22 @@ FilterGestureEventResult TouchActionFilter::FilterGestureEvent(
switch (gesture_event->GetType()) {
case WebInputEvent::kGestureScrollBegin: {
DCHECK(!suppress_manipulation_events_);
- DCHECK(!touchscreen_scroll_in_progress_);
- touchscreen_scroll_in_progress_ = true;
- // TODO(https://crbug.com/851644): Make sure the value is properly set.
- if (!scrolling_touch_action_.has_value())
+ // In VR or virtual keyboard (https://crbug.com/880701),
+ // GestureScrollBegin could come without GestureTapDown.
+ if (!gesture_sequence_in_progress_) {
+ gesture_sequence_in_progress_ = true;
+ if (!scrolling_touch_action_.has_value())
+ SetTouchAction(cc::kTouchActionAuto);
+ }
+ gesture_sequence_.append("B");
+ if (!scrolling_touch_action_.has_value()) {
+ static auto* crash_key = base::debug::AllocateCrashKeyString(
+ "scrollbegin-gestures", base::debug::CrashKeySize::Size256);
+ base::debug::SetCrashKeyString(crash_key, gesture_sequence_);
+ gesture_sequence_.clear();
+ // https://crbug.com/869375, temporary fix to prevent crash.
SetTouchAction(cc::kTouchActionAuto);
+ }
suppress_manipulation_events_ =
ShouldSuppressManipulation(*gesture_event);
return suppress_manipulation_events_
@@ -66,6 +82,7 @@ FilterGestureEventResult TouchActionFilter::FilterGestureEvent(
if (suppress_manipulation_events_)
return FilterGestureEventResult::kFilterGestureEventFiltered;
+ gesture_sequence_.append("U");
// Scrolls restricted to a specific axis shouldn't permit movement
// in the perpendicular axis.
//
@@ -74,6 +91,14 @@ FilterGestureEventResult TouchActionFilter::FilterGestureEvent(
// two-finger scrolling but a "touch-action: pan-x pinch-zoom" region
// doesn't.
// TODO(mustaq): Add it to spec?
+ if (!scrolling_touch_action_.has_value()) {
+ static auto* crash_key = base::debug::AllocateCrashKeyString(
+ "scrollupdate-gestures", base::debug::CrashKeySize::Size256);
+ base::debug::SetCrashKeyString(crash_key, gesture_sequence_);
+ gesture_sequence_.clear();
+ // https://crbug.com/869375, temporary fix to prevent crash.
+ SetTouchAction(cc::kTouchActionAuto);
+ }
if (IsYAxisActionDisallowed(scrolling_touch_action_.value())) {
gesture_event->data.scroll_update.delta_y = 0;
gesture_event->data.scroll_update.velocity_y = 0;
@@ -91,8 +116,8 @@ FilterGestureEventResult TouchActionFilter::FilterGestureEvent(
break;
case WebInputEvent::kGestureScrollEnd:
- DCHECK(touchscreen_scroll_in_progress_);
- touchscreen_scroll_in_progress_ = false;
+ gesture_sequence_.clear();
+ gesture_sequence_in_progress_ = false;
ReportGestureEventFiltered(suppress_manipulation_events_);
return FilterManipulationEventAndResetState()
? FilterGestureEventResult::kFilterGestureEventFiltered
@@ -101,6 +126,7 @@ FilterGestureEventResult TouchActionFilter::FilterGestureEvent(
case WebInputEvent::kGesturePinchBegin:
case WebInputEvent::kGesturePinchUpdate:
case WebInputEvent::kGesturePinchEnd:
+ gesture_sequence_.append("P");
ReportGestureEventFiltered(suppress_manipulation_events_);
return suppress_manipulation_events_
? FilterGestureEventResult::kFilterGestureEventFiltered
@@ -109,6 +135,8 @@ FilterGestureEventResult TouchActionFilter::FilterGestureEvent(
// The double tap gesture is a tap ending event. If a double tap gesture is
// filtered out, replace it with a tap event.
case WebInputEvent::kGestureDoubleTap:
+ gesture_sequence_in_progress_ = false;
+ gesture_sequence_.append("D");
DCHECK_EQ(1, gesture_event->data.tap.tap_count);
if (!allow_current_double_tap_event_)
gesture_event->SetType(WebInputEvent::kGestureTap);
@@ -117,10 +145,16 @@ FilterGestureEventResult TouchActionFilter::FilterGestureEvent(
// If double tap is disabled, there's no reason for the tap delay.
case WebInputEvent::kGestureTapUnconfirmed: {
+ gesture_sequence_.append("C");
DCHECK_EQ(1, gesture_event->data.tap.tap_count);
- // TODO(https://crbug.com/851644): Make sure the value is properly set.
- if (!scrolling_touch_action_.has_value())
+ if (!scrolling_touch_action_.has_value()) {
+ static auto* crash_key = base::debug::AllocateCrashKeyString(
+ "tapunconfirmed-gestures", base::debug::CrashKeySize::Size256);
+ base::debug::SetCrashKeyString(crash_key, gesture_sequence_);
+ gesture_sequence_.clear();
+ // https://crbug.com/869375, temporary fix to prevent crash.
SetTouchAction(cc::kTouchActionAuto);
+ }
allow_current_double_tap_event_ = (scrolling_touch_action_.value() &
cc::kTouchActionDoubleTapZoom) != 0;
if (!allow_current_double_tap_event_) {
@@ -131,7 +165,16 @@ FilterGestureEventResult TouchActionFilter::FilterGestureEvent(
}
case WebInputEvent::kGestureTap:
+ gesture_sequence_in_progress_ = false;
+ gesture_sequence_.append("A");
+ if (drop_current_tap_ending_event_) {
+ drop_current_tap_ending_event_ = false;
+ return FilterGestureEventResult::kFilterGestureEventFiltered;
+ }
+ break;
+
case WebInputEvent::kGestureTapCancel:
+ gesture_sequence_.append("K");
if (drop_current_tap_ending_event_) {
drop_current_tap_ending_event_ = false;
return FilterGestureEventResult::kFilterGestureEventFiltered;
@@ -139,19 +182,24 @@ FilterGestureEventResult TouchActionFilter::FilterGestureEvent(
break;
case WebInputEvent::kGestureTapDown:
+ gesture_sequence_in_progress_ = true;
// If the gesture is hitting a region that has a non-blocking (such as a
// passive) event listener.
if (gesture_event->is_source_touch_event_set_non_blocking)
SetTouchAction(cc::kTouchActionAuto);
scrolling_touch_action_ = allowed_touch_action_;
- // TODO(https://crbug.com/851644): The value may not set in the case when
- // the gesture event is flushed due to touch ack time out after the finger
- // is lifted up. Make sure the value is properly set.
- if (!scrolling_touch_action_.has_value())
- SetTouchAction(cc::kTouchActionAuto);
+ if (scrolling_touch_action_.has_value())
+ gesture_sequence_.append("O1");
+ else
+ gesture_sequence_.append("O2");
DCHECK(!drop_current_tap_ending_event_);
break;
+ case WebInputEvent::kGestureLongTap:
+ case WebInputEvent::kGestureTwoFingerTap:
+ gesture_sequence_in_progress_ = false;
+ break;
+
default:
// Gesture events unrelated to touch actions (panning/zooming) are left
// alone.
@@ -200,13 +248,22 @@ void TouchActionFilter::OnSetTouchAction(cc::TouchAction touch_action) {
scrolling_touch_action_ = allowed_touch_action_;
}
+void TouchActionFilter::SetActiveTouchInProgress(
+ bool active_touch_in_progress) {
+ active_touch_in_progress_ = active_touch_in_progress;
+}
+
void TouchActionFilter::ReportAndResetTouchAction() {
+ if (has_touch_event_handler_)
+ gesture_sequence_.append("R1");
+ else
+ gesture_sequence_.append("R0");
ReportTouchAction();
ResetTouchAction();
}
void TouchActionFilter::ReportTouchAction() {
- // TODO(https://crbug.com/851644): make sure the value is properly set.
+ // https://crbug.com/869375, temporary fix to prevent crash.
if (!scrolling_touch_action_.has_value())
SetTouchAction(cc::kTouchActionAuto);
// Report the effective touch action computed by blink such as
@@ -214,6 +271,10 @@ void TouchActionFilter::ReportTouchAction() {
// Since |cc::kTouchActionAuto| is equivalent to |cc::kTouchActionMax|, we
// must add one to the upper bound to be able to visualize the number of
// times |cc::kTouchActionAuto| is hit.
+ // https://crbug.com/879511, remove this temporary fix.
+ if (!scrolling_touch_action_.has_value())
+ return;
+
UMA_HISTOGRAM_ENUMERATION("TouchAction.EffectiveTouchAction",
scrolling_touch_action_.value(),
cc::kTouchActionMax + 1);
@@ -228,6 +289,10 @@ void TouchActionFilter::ReportTouchAction() {
}
}
+void TouchActionFilter::AppendToGestureSequenceForDebugging(const char* str) {
+ gesture_sequence_.append(str);
+}
+
void TouchActionFilter::ResetTouchAction() {
// Note that resetting the action mid-sequence is tolerated. Gestures that had
// their begin event(s) suppressed will be suppressed until the next
@@ -303,13 +368,18 @@ void TouchActionFilter::OnHasTouchEventHandlers(bool has_handlers) {
if (has_handlers && has_touch_event_handler_ == has_handlers)
return;
has_touch_event_handler_ = has_handlers;
- ResetTouchAction();
- // If a page has a touch event handler, this function can be called twice with
- // has_handlers = false first and then true later. When it is true, we need to
- // reset the |scrolling_touch_action_|. However, we do not want to reset it if
- // there is an active scroll in progress.
- if (has_touch_event_handler_ && !touchscreen_scroll_in_progress_)
- scrolling_touch_action_.reset();
+ if (has_touch_event_handler_)
+ gesture_sequence_.append("L1");
+ else
+ gesture_sequence_.append("L0");
+ // We have set the associated touch action if the touch start already happened
+ // or there is a gesture in progress. In these cases, we should not reset the
+ // associated touch action.
+ if (!gesture_sequence_in_progress_ && !active_touch_in_progress_) {
+ ResetTouchAction();
+ if (has_touch_event_handler_)
+ scrolling_touch_action_.reset();
+ }
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/touch_action_filter.h b/chromium/content/browser/renderer_host/input/touch_action_filter.h
index d1167ae83d6..2d157fbebe9 100644
--- a/chromium/content/browser/renderer_host/input/touch_action_filter.h
+++ b/chromium/content/browser/renderer_host/input/touch_action_filter.h
@@ -9,6 +9,7 @@
#include "base/optional.h"
#include "cc/input/touch_action.h"
#include "content/common/content_export.h"
+#include "third_party/blink/public/platform/web_input_event.h"
namespace blink {
class WebGestureEvent;
@@ -30,6 +31,7 @@ enum class FilterGestureEventResult {
class CONTENT_EXPORT TouchActionFilter {
public:
TouchActionFilter();
+ ~TouchActionFilter();
// Returns kFilterGestureEventFiltered if the supplied gesture event should be
// dropped based on the current touch-action state. Otherwise returns
@@ -65,6 +67,11 @@ class CONTENT_EXPORT TouchActionFilter {
void OnHasTouchEventHandlers(bool has_handlers);
+ void SetActiveTouchInProgress(bool active_touch_in_progress);
+
+ // Debugging only.
+ void AppendToGestureSequenceForDebugging(const char* str);
+
private:
friend class MockRenderWidgetHost;
friend class TouchActionFilterTest;
@@ -91,13 +98,17 @@ class CONTENT_EXPORT TouchActionFilter {
bool force_enable_zoom_;
// Indicates whether this page has touch event handler or not. Set by
- // InputRouterImpl::OnHasTouchEventHandler.
- // TODO(https://crbug.com/850238): default to true or make it Optional.
+ // InputRouterImpl::OnHasTouchEventHandlers. Default to false because one
+ // could not scroll anyways when there is no content, and this is consistent
+ // with the default state committed after DocumentLoader::DidCommitNavigation.
bool has_touch_event_handler_ = false;
- // True if an active touch scroll gesture is in progress. i.e. after GSB and
+ // True if an active gesture sequence is in progress. i.e. after GTD and
// before GSE.
- bool touchscreen_scroll_in_progress_ = false;
+ bool gesture_sequence_in_progress_ = false;
+
+ // True at touch start and false at touch end.
+ bool active_touch_in_progress_ = false;
// What touch actions are currently permitted.
base::Optional<cc::TouchAction> allowed_touch_action_;
@@ -111,6 +122,9 @@ class CONTENT_EXPORT TouchActionFilter {
// Whitelisted touch action received from the compositor.
base::Optional<cc::TouchAction> white_listed_touch_action_;
+ // Debugging only.
+ std::string gesture_sequence_;
+
DISALLOW_COPY_AND_ASSIGN(TouchActionFilter);
};
diff --git a/chromium/content/browser/renderer_host/input/touch_action_filter_unittest.cc b/chromium/content/browser/renderer_host/input/touch_action_filter_unittest.cc
index 9a5d4a8c41c..95d48e39153 100644
--- a/chromium/content/browser/renderer_host/input/touch_action_filter_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/touch_action_filter_unittest.cc
@@ -22,7 +22,7 @@ const blink::WebGestureDevice kSourceDevice =
class TouchActionFilterTest : public testing::Test {
public:
- TouchActionFilterTest(){};
+ TouchActionFilterTest() { filter_.OnHasTouchEventHandlers(true); }
~TouchActionFilterTest() override {}
protected:
@@ -36,6 +36,8 @@ class TouchActionFilterTest : public testing::Test {
float dy,
float expected_dx,
float expected_dy) {
+ WebGestureEvent tap_down = SyntheticWebGestureEventBuilder::Build(
+ WebInputEvent::kGestureTapDown, kSourceDevice);
WebGestureEvent scroll_end = SyntheticWebGestureEventBuilder::Build(
WebInputEvent::kGestureScrollEnd, kSourceDevice);
@@ -47,6 +49,8 @@ class TouchActionFilterTest : public testing::Test {
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(0, 0,
kSourceDevice);
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventAllowed);
@@ -69,6 +73,8 @@ class TouchActionFilterTest : public testing::Test {
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(scroll_x, scroll_y,
kSourceDevice);
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventAllowed);
@@ -104,6 +110,8 @@ class TouchActionFilterTest : public testing::Test {
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(scroll_y, scroll_x,
kSourceDevice);
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventFiltered);
@@ -123,6 +131,8 @@ class TouchActionFilterTest : public testing::Test {
void PanTestForUnidirectionalTouchAction(cc::TouchAction action,
float scroll_x,
float scroll_y) {
+ WebGestureEvent tap_down = SyntheticWebGestureEventBuilder::Build(
+ WebInputEvent::kGestureTapDown, kSourceDevice);
WebGestureEvent scroll_end = SyntheticWebGestureEventBuilder::Build(
WebInputEvent::kGestureScrollEnd, kSourceDevice);
@@ -133,6 +143,8 @@ class TouchActionFilterTest : public testing::Test {
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(scroll_x, scroll_y,
kSourceDevice);
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventAllowed);
@@ -153,6 +165,8 @@ class TouchActionFilterTest : public testing::Test {
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(
-scroll_x, -scroll_y, kSourceDevice);
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventFiltered);
@@ -173,6 +187,8 @@ class TouchActionFilterTest : public testing::Test {
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(
-scroll_x - scroll_y, -scroll_x - scroll_y, kSourceDevice);
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventFiltered);
@@ -200,12 +216,12 @@ TEST_F(TouchActionFilterTest, SimpleFilter) {
kSourceDevice);
WebGestureEvent scroll_end = SyntheticWebGestureEventBuilder::Build(
WebInputEvent::kGestureScrollEnd, kSourceDevice);
- WebGestureEvent tap = SyntheticWebGestureEventBuilder::Build(
- WebInputEvent::kGestureTap, kSourceDevice);
// cc::kTouchActionAuto doesn't cause any filtering.
filter_.ResetTouchAction();
filter_.OnSetTouchAction(cc::kTouchActionAuto);
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update),
@@ -220,8 +236,6 @@ TEST_F(TouchActionFilterTest, SimpleFilter) {
filter_.OnSetTouchAction(cc::kTouchActionNone);
EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter_.FilterGestureEvent(&tap),
- FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventFiltered);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update),
@@ -236,6 +250,8 @@ TEST_F(TouchActionFilterTest, SimpleFilter) {
// When a new touch sequence begins, the state is reset.
filter_.ResetTouchAction();
filter_.OnSetTouchAction(cc::kTouchActionAuto);
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update),
@@ -246,6 +262,8 @@ TEST_F(TouchActionFilterTest, SimpleFilter) {
// Setting touch action doesn't impact any in-progress gestures.
filter_.ResetTouchAction();
filter_.OnSetTouchAction(cc::kTouchActionAuto);
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventAllowed);
filter_.OnSetTouchAction(cc::kTouchActionNone);
@@ -257,6 +275,8 @@ TEST_F(TouchActionFilterTest, SimpleFilter) {
// And the state is still cleared for the next gesture.
filter_.ResetTouchAction();
filter_.OnSetTouchAction(cc::kTouchActionAuto);
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
@@ -265,6 +285,8 @@ TEST_F(TouchActionFilterTest, SimpleFilter) {
// Changing the touch action during a gesture has no effect.
filter_.ResetTouchAction();
filter_.OnSetTouchAction(cc::kTouchActionNone);
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventFiltered);
filter_.OnSetTouchAction(cc::kTouchActionAuto);
@@ -339,6 +361,8 @@ TEST_F(TouchActionFilterTest, PanY) {
TEST_F(TouchActionFilterTest, PanXY) {
const float kDX = 5;
const float kDY = 10;
+ WebGestureEvent tap_down = SyntheticWebGestureEventBuilder::Build(
+ WebInputEvent::kGestureTapDown, kSourceDevice);
WebGestureEvent scroll_end = SyntheticWebGestureEventBuilder::Build(
WebInputEvent::kGestureScrollEnd, kSourceDevice);
@@ -348,6 +372,8 @@ TEST_F(TouchActionFilterTest, PanXY) {
filter_.OnSetTouchAction(cc::kTouchActionPan);
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(-7, 6, kSourceDevice);
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventAllowed);
@@ -369,6 +395,8 @@ TEST_F(TouchActionFilterTest, PanXY) {
filter_.OnSetTouchAction(cc::kTouchActionPan);
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(-6, 7, kSourceDevice);
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventAllowed);
@@ -391,6 +419,8 @@ TEST_F(TouchActionFilterTest, PanXY) {
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(-6, 7, kSourceDevice,
2);
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventFiltered);
@@ -420,6 +450,8 @@ TEST_F(TouchActionFilterTest, BitMath) {
}
TEST_F(TouchActionFilterTest, MultiTouch) {
+ WebGestureEvent tap_down = SyntheticWebGestureEventBuilder::Build(
+ WebInputEvent::kGestureTapDown, kSourceDevice);
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(2, 3, kSourceDevice);
const float kDeltaX = 5;
@@ -434,6 +466,8 @@ TEST_F(TouchActionFilterTest, MultiTouch) {
filter_.ResetTouchAction();
filter_.OnSetTouchAction(cc::kTouchActionNone);
filter_.OnSetTouchAction(cc::kTouchActionAuto);
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventFiltered);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update),
@@ -450,6 +484,8 @@ TEST_F(TouchActionFilterTest, MultiTouch) {
filter_.OnSetTouchAction(cc::kTouchActionPanX);
filter_.OnSetTouchAction(cc::kTouchActionPanY);
filter_.OnSetTouchAction(cc::kTouchActionPan);
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventFiltered);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update),
@@ -461,8 +497,11 @@ TEST_F(TouchActionFilterTest, MultiTouch) {
class TouchActionFilterPinchTest : public testing::Test {
public:
void RunTest(bool force_enable_zoom) {
+ filter_.OnHasTouchEventHandlers(true);
filter_.SetForceEnableZoom(force_enable_zoom);
+ WebGestureEvent tap_down = SyntheticWebGestureEventBuilder::Build(
+ WebInputEvent::kGestureTapDown, kSourceDevice);
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(2, 3, kSourceDevice,
2);
@@ -479,6 +518,8 @@ class TouchActionFilterPinchTest : public testing::Test {
// Pinch is allowed with touch-action: auto.
filter_.ResetTouchAction();
filter_.OnSetTouchAction(cc::kTouchActionAuto);
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&pinch_begin),
@@ -493,6 +534,8 @@ class TouchActionFilterPinchTest : public testing::Test {
// Pinch is not allowed with touch-action: none.
filter_.ResetTouchAction();
filter_.OnSetTouchAction(cc::kTouchActionNone);
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventFiltered);
EXPECT_EQ(filter_.FilterGestureEvent(&pinch_begin),
@@ -514,6 +557,8 @@ class TouchActionFilterPinchTest : public testing::Test {
// enable zoom.
filter_.ResetTouchAction();
filter_.OnSetTouchAction(cc::kTouchActionPan);
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_NE(filter_.FilterGestureEvent(&scroll_begin),
force_enable_zoom
? FilterGestureEventResult::kFilterGestureEventFiltered
@@ -538,6 +583,8 @@ class TouchActionFilterPinchTest : public testing::Test {
// Pinch is allowed with touch-action: manipulation.
filter_.ResetTouchAction();
filter_.OnSetTouchAction(cc::kTouchActionManipulation);
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&pinch_begin),
@@ -552,6 +599,8 @@ class TouchActionFilterPinchTest : public testing::Test {
// Pinch state is automatically reset at the end of a scroll.
filter_.ResetTouchAction();
filter_.OnSetTouchAction(cc::kTouchActionAuto);
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&pinch_begin),
@@ -566,6 +615,8 @@ class TouchActionFilterPinchTest : public testing::Test {
// Pinching is only computed at GestureScrollBegin time.
filter_.ResetTouchAction();
filter_.OnSetTouchAction(cc::kTouchActionAuto);
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&pinch_begin),
@@ -595,6 +646,8 @@ class TouchActionFilterPinchTest : public testing::Test {
// gestures since it is computed in GestureScrollBegin.
filter_.ResetTouchAction();
filter_.OnSetTouchAction(cc::kTouchActionAuto);
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&pinch_begin),
@@ -616,6 +669,8 @@ class TouchActionFilterPinchTest : public testing::Test {
// Scrolling is allowed when two fingers are down.
filter_.ResetTouchAction();
filter_.OnSetTouchAction(cc::kTouchActionPinchZoom);
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&pinch_begin),
@@ -632,6 +687,8 @@ class TouchActionFilterPinchTest : public testing::Test {
scroll_begin.data.scroll_begin.pointer_count = 1;
filter_.ResetTouchAction();
filter_.OnSetTouchAction(cc::kTouchActionPinchZoom);
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventFiltered);
EXPECT_EQ(filter_.FilterGestureEvent(&pinch_begin),
@@ -772,6 +829,8 @@ TEST_F(TouchActionFilterTest, TouchActionResetsOnResetTouchAction) {
filter_.ResetTouchAction();
filter_.OnSetTouchAction(cc::kTouchActionNone);
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventFiltered);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
@@ -786,11 +845,16 @@ TEST_F(TouchActionFilterTest, TouchActionResetsOnResetTouchAction) {
filter_.ResetTouchAction();
filter_.OnSetTouchAction(cc::kTouchActionAuto);
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventAllowed);
}
TEST_F(TouchActionFilterTest, TouchActionResetMidSequence) {
+ filter_.OnHasTouchEventHandlers(true);
+ WebGestureEvent tap_down = SyntheticWebGestureEventBuilder::Build(
+ WebInputEvent::kGestureTapDown, kSourceDevice);
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(2, 3, kSourceDevice);
WebGestureEvent pinch_begin = SyntheticWebGestureEventBuilder::Build(
@@ -804,6 +868,8 @@ TEST_F(TouchActionFilterTest, TouchActionResetMidSequence) {
WebInputEvent::kGestureScrollEnd, kSourceDevice);
filter_.OnSetTouchAction(cc::kTouchActionNone);
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventFiltered);
EXPECT_EQ(filter_.FilterGestureEvent(&pinch_begin),
@@ -871,25 +937,203 @@ TEST_F(TouchActionFilterTest, TouchActionNotResetWithinGestureSequence) {
filter_.ReportAndResetTouchAction();
EXPECT_FALSE(filter_.allowed_touch_action().has_value());
EXPECT_EQ(cc::kTouchActionPanY, ScrollingTouchAction().value());
+ // In fling or fling boosting case, we will see ScrollUpdate after the touch
+ // end.
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventAllowed);
// The |allowed_touch_action_| should have been reset, but not the
// |scrolling_touch_action_|.
EXPECT_FALSE(filter_.allowed_touch_action().has_value());
EXPECT_EQ(cc::kTouchActionPanY, ScrollingTouchAction().value());
+}
+
+// The following 3 tests ensures that when the IPC message
+// OnHasTouchEventHandlers is received in the middle of a gesture sequence, the
+// touch action is not reset.
+TEST_F(TouchActionFilterTest, OnHasTouchEventHandlersReceivedDuringTap) {
+ filter_.OnHasTouchEventHandlers(false);
+
+ WebGestureEvent tap_down = SyntheticWebGestureEventBuilder::Build(
+ WebInputEvent::kGestureTapDown, kSourceDevice);
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ filter_.OnHasTouchEventHandlers(true);
+ EXPECT_TRUE(ScrollingTouchAction().has_value());
+
+ filter_.OnSetTouchAction(cc::kTouchActionPan);
+ // Simulate a simple tap gesture.
+ WebGestureEvent tap = SyntheticWebGestureEventBuilder::Build(
+ WebInputEvent::kGestureTap, kSourceDevice);
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ // Gesture tap indicates that there is no scroll in progress, so this should
+ // reset the |allowed_touch_action_|.
+ filter_.ResetTouchAction();
+ EXPECT_FALSE(filter_.allowed_touch_action().has_value());
+}
- // In the fling boosting case, we won't get a TapDown after the previous GSE.
+TEST_F(TouchActionFilterTest, OnHasTouchEventHandlersReceivedDuringDoubleTap) {
+ filter_.OnHasTouchEventHandlers(false);
+
+ WebGestureEvent tap_down = SyntheticWebGestureEventBuilder::Build(
+ WebInputEvent::kGestureTapDown, kSourceDevice);
+ WebGestureEvent tap_cancel = SyntheticWebGestureEventBuilder::Build(
+ WebInputEvent::kGestureTapCancel, kSourceDevice);
+ WebGestureEvent double_tap = SyntheticWebGestureEventBuilder::Build(
+ WebInputEvent::kGestureDoubleTap, kSourceDevice);
+
+ // Simulate a double tap gesture: GTD-->GTC-->GTD-->GTC-->GDT.
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(ScrollingTouchAction().value(), cc::kTouchActionAuto);
+ filter_.OnHasTouchEventHandlers(true);
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_cancel),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_TRUE(ScrollingTouchAction().has_value());
+ filter_.OnSetTouchAction(cc::kTouchActionPan);
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(ScrollingTouchAction().value(), cc::kTouchActionPan);
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_cancel),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter_.FilterGestureEvent(&double_tap),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+}
+
+TEST_F(TouchActionFilterTest, OnHasTouchEventHandlersReceivedDuringScroll) {
+ filter_.OnHasTouchEventHandlers(false);
+
+ WebGestureEvent tap_down = SyntheticWebGestureEventBuilder::Build(
+ WebInputEvent::kGestureTapDown, kSourceDevice);
+ WebGestureEvent tap_cancel = SyntheticWebGestureEventBuilder::Build(
+ WebInputEvent::kGestureTapCancel, kSourceDevice);
+ WebGestureEvent scroll_begin =
+ SyntheticWebGestureEventBuilder::BuildScrollBegin(5, 0, kSourceDevice);
+ WebGestureEvent scroll_update =
+ SyntheticWebGestureEventBuilder::BuildScrollUpdate(5, 0, 0,
+ kSourceDevice);
+ WebGestureEvent scroll_end = SyntheticWebGestureEventBuilder::Build(
+ WebInputEvent::kGestureScrollEnd, kSourceDevice);
+
+ // Simulate a gesture scroll: GTD-->GTC-->GSB-->GSU-->GSE.
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_cancel),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ filter_.OnHasTouchEventHandlers(true);
+ filter_.OnSetTouchAction(cc::kTouchActionPan);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(ScrollingTouchAction().value(), cc::kTouchActionPan);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update),
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventAllowed);
+}
+
+// If OnHasTouchEventHandlers IPC is received after LongTap or TwoFingerTap,
+// the touch action should be reset.
+TEST_F(TouchActionFilterTest,
+ OnHasTouchEventHandlersReceivedAfterLongTapOrTwoFingerTap) {
+ filter_.OnHasTouchEventHandlers(false);
+ WebGestureEvent tap_down = SyntheticWebGestureEventBuilder::Build(
+ WebInputEvent::kGestureTapDown, kSourceDevice);
+ WebGestureEvent tap_cancel = SyntheticWebGestureEventBuilder::Build(
+ WebInputEvent::kGestureTapCancel, kSourceDevice);
+ WebGestureEvent long_tap = SyntheticWebGestureEventBuilder::Build(
+ WebInputEvent::kGestureLongTap, kSourceDevice);
EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_TRUE(filter_.allowed_touch_action().has_value());
- EXPECT_TRUE(ScrollingTouchAction().has_value());
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_cancel),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter_.FilterGestureEvent(&long_tap),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(ScrollingTouchAction().value(), cc::kTouchActionAuto);
+
+ filter_.OnHasTouchEventHandlers(true);
+ EXPECT_FALSE(ScrollingTouchAction().has_value());
+
+ filter_.OnHasTouchEventHandlers(false);
+ WebGestureEvent two_finger_tap = SyntheticWebGestureEventBuilder::Build(
+ WebInputEvent::kGestureTwoFingerTap, kSourceDevice);
+
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_cancel),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter_.FilterGestureEvent(&two_finger_tap),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(ScrollingTouchAction().value(), cc::kTouchActionAuto);
+
+ filter_.OnHasTouchEventHandlers(true);
+ EXPECT_FALSE(ScrollingTouchAction().has_value());
+}
+
+TEST_F(TouchActionFilterTest, OnHasTouchEventHandlersReceivedAfterTouchStart) {
+ filter_.OnHasTouchEventHandlers(true);
+ EXPECT_FALSE(ScrollingTouchAction().has_value());
+ EXPECT_FALSE(filter_.allowed_touch_action().has_value());
+
+ // Receive a touch start ack, set the touch action.
+ filter_.OnSetTouchAction(cc::kTouchActionPanY);
+ filter_.SetActiveTouchInProgress(true);
+ filter_.OnHasTouchEventHandlers(false);
+ EXPECT_EQ(ScrollingTouchAction().value(), cc::kTouchActionPanY);
+ EXPECT_EQ(filter_.allowed_touch_action().value(), cc::kTouchActionPanY);
+ filter_.OnHasTouchEventHandlers(true);
+ EXPECT_EQ(ScrollingTouchAction().value(), cc::kTouchActionPanY);
+ EXPECT_EQ(filter_.allowed_touch_action().value(), cc::kTouchActionPanY);
+}
+
+// If the renderer is busy, the gesture event might have come before the
+// OnHasTouchEventHanlders IPC is received. In this case, we should allow all
+// the gestures.
+TEST_F(TouchActionFilterTest, GestureArrivesBeforeHasHandlerSet) {
+ WebGestureEvent tap_down = SyntheticWebGestureEventBuilder::Build(
+ WebInputEvent::kGestureTapDown, kSourceDevice);
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+}
+
+TEST_F(TouchActionFilterTest, ResetBeforeHasHandlerSet) {
+ // This should not crash, and should set touch action to auto.
+ filter_.ResetTouchAction();
+ WebGestureEvent tap_down = SyntheticWebGestureEventBuilder::Build(
+ WebInputEvent::kGestureTapDown, kSourceDevice);
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+}
+
+// Having a gesture scroll begin without tap down should set touch action to
+// Auto.
+TEST_F(TouchActionFilterTest, ScrollBeginWithoutTapDown) {
+ filter_.OnHasTouchEventHandlers(true);
+ EXPECT_FALSE(ScrollingTouchAction().has_value());
+ EXPECT_FALSE(filter_.allowed_touch_action().has_value());
+
+ WebGestureEvent scroll_begin =
+ SyntheticWebGestureEventBuilder::BuildScrollBegin(5, 0, kSourceDevice);
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(ScrollingTouchAction().value(), cc::kTouchActionAuto);
+ EXPECT_EQ(filter_.allowed_touch_action().value(), cc::kTouchActionAuto);
+}
+
+TEST_F(TouchActionFilterTest, ScrollBeginWithoutTapDownWithKnownTouchAction) {
+ filter_.OnHasTouchEventHandlers(true);
+ EXPECT_FALSE(ScrollingTouchAction().has_value());
+ EXPECT_FALSE(filter_.allowed_touch_action().has_value());
+
+ filter_.OnSetTouchAction(cc::kTouchActionPan);
+ WebGestureEvent scroll_begin =
+ SyntheticWebGestureEventBuilder::BuildScrollBegin(5, 0, kSourceDevice);
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(ScrollingTouchAction().value(), cc::kTouchActionPan);
+ EXPECT_EQ(filter_.allowed_touch_action().value(), cc::kTouchActionPan);
}
TEST_F(TouchActionFilterTest, TouchpadScroll) {
diff --git a/chromium/content/browser/renderer_host/input/touch_emulator.cc b/chromium/content/browser/renderer_host/input/touch_emulator.cc
index bb6fb67ff9f..e5cfa600cf5 100644
--- a/chromium/content/browser/renderer_host/input/touch_emulator.cc
+++ b/chromium/content/browser/renderer_host/input/touch_emulator.cc
@@ -363,14 +363,7 @@ void TouchEmulator::OnGestureEvent(const ui::GestureEventData& gesture) {
WebGestureEvent gesture_event =
ui::CreateWebGestureEventFromGestureEventData(gesture);
- if (!gesture_event.unique_touch_event_id) {
- // TODO(wjmaclean): Find out why the local GestureProvider puts id=0 on
- // kGestureShowPress. This is a problem for RWHIER as it will cause it to
- // attempt to re-target the event. There must be a nicer solution than
- // setting the id to -1.
- DCHECK(gesture_event.GetType() == blink::WebInputEvent::kGestureShowPress);
- gesture_event.unique_touch_event_id = -1;
- }
+ DCHECK(gesture_event.unique_touch_event_id);
switch (gesture_event.GetType()) {
case WebInputEvent::kUndefined:
@@ -528,11 +521,12 @@ void TouchEmulator::ScrollEnd(const WebGestureEvent& event) {
WebGestureEvent TouchEmulator::GetPinchGestureEvent(
WebInputEvent::Type type,
- const WebInputEvent& original_event) {
+ const WebGestureEvent& original_event) {
WebGestureEvent event(type, ModifiersWithoutMouseButtons(original_event),
original_event.TimeStamp(),
blink::kWebGestureDeviceTouchscreen);
event.SetPositionInWidget(pinch_anchor_);
+ event.unique_touch_event_id = original_event.unique_touch_event_id;
return event;
}
diff --git a/chromium/content/browser/renderer_host/input/touch_emulator.h b/chromium/content/browser/renderer_host/input/touch_emulator.h
index 3ff06e2158b..55fabad3b55 100644
--- a/chromium/content/browser/renderer_host/input/touch_emulator.h
+++ b/chromium/content/browser/renderer_host/input/touch_emulator.h
@@ -105,7 +105,7 @@ class CONTENT_EXPORT TouchEmulator : public ui::GestureProviderClient {
const gfx::PointF& pos_in_root);
blink::WebGestureEvent GetPinchGestureEvent(
blink::WebInputEvent::Type type,
- const blink::WebInputEvent& original_event);
+ const blink::WebGestureEvent& original_event);
// The following methods generate and pass gesture events to the renderer.
void PinchBegin(const blink::WebGestureEvent& event);
diff --git a/chromium/content/browser/renderer_host/input/touch_input_browsertest.cc b/chromium/content/browser/renderer_host/input/touch_input_browsertest.cc
index f223edca1d7..ddab75b7c0a 100644
--- a/chromium/content/browser/renderer_host/input/touch_input_browsertest.cc
+++ b/chromium/content/browser/renderer_host/input/touch_input_browsertest.cc
@@ -10,6 +10,7 @@
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
+#include "components/viz/common/features.h"
#include "content/browser/gpu/compositor_util.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
@@ -22,6 +23,7 @@
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
+#include "content/public/test/hit_test_region_observer.h"
#include "content/shell/browser/shell.h"
#include "third_party/blink/public/platform/web_input_event.h"
#include "ui/latency/latency_info.h"
@@ -30,13 +32,6 @@ using blink::WebInputEvent;
namespace {
-void GiveItSomeTime() {
- base::RunLoop run_loop;
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, run_loop.QuitClosure(), base::TimeDelta::FromMilliseconds(10));
- run_loop.Run();
-}
-
const char kTouchEventDataURL[] =
"data:text/html;charset=utf-8,"
#if defined(OS_ANDROID)
@@ -113,11 +108,23 @@ class TouchInputBrowserTest : public ContentBrowserTest {
NavigateToURL(shell(), data_url);
RenderWidgetHostImpl* host = GetWidgetHost();
+ // Wait to confirm a frame was generated from the navigation.
+ RenderFrameSubmissionObserver frame_observer(
+ host->render_frame_metadata_provider());
+ frame_observer.WaitForMetadataChange();
+
+#if !defined(OS_ANDROID)
+ // On non-Android, set a size for the view, and wait for a new frame to be
+ // generated at that size. On Android the size is specified in
+ // kTouchEventDataURL.
host->GetView()->SetSize(gfx::Size(400, 400));
+ frame_observer.WaitForAnyFrameSubmission();
+#endif
- // The page is loaded in the renderer, wait for a new frame to arrive.
- while (!host->RequestRepaintForTesting())
- GiveItSomeTime();
+ if (features::IsVizHitTestingEnabled()) {
+ HitTestRegionObserver observer(host->GetFrameSinkId());
+ observer.WaitForHitTestData();
+ }
}
void SetUpCommandLine(base::CommandLine* cmd) override {
@@ -126,13 +133,7 @@ class TouchInputBrowserTest : public ContentBrowserTest {
}
};
-#if defined(OS_MACOSX)
-// TODO(ccameron): Failing on mac: crbug.com/346363
-#define MAYBE_TouchNoHandler DISABLED_TouchNoHandler
-#else
-#define MAYBE_TouchNoHandler TouchNoHandler
-#endif
-IN_PROC_BROWSER_TEST_F(TouchInputBrowserTest, MAYBE_TouchNoHandler) {
+IN_PROC_BROWSER_TEST_F(TouchInputBrowserTest, TouchNoHandler) {
LoadURL();
SyntheticWebTouchEvent touch;
@@ -150,13 +151,7 @@ IN_PROC_BROWSER_TEST_F(TouchInputBrowserTest, MAYBE_TouchNoHandler) {
SendTouchEvent(&touch);
}
-#if defined(OS_CHROMEOS)
-// crbug.com/514456
-#define MAYBE_TouchHandlerNoConsume DISABLED_TouchHandlerNoConsume
-#else
-#define MAYBE_TouchHandlerNoConsume TouchHandlerNoConsume
-#endif
-IN_PROC_BROWSER_TEST_F(TouchInputBrowserTest, MAYBE_TouchHandlerNoConsume) {
+IN_PROC_BROWSER_TEST_F(TouchInputBrowserTest, TouchHandlerNoConsume) {
LoadURL();
SyntheticWebTouchEvent touch;
@@ -173,13 +168,7 @@ IN_PROC_BROWSER_TEST_F(TouchInputBrowserTest, MAYBE_TouchHandlerNoConsume) {
filter->WaitForAck();
}
-#if defined(OS_CHROMEOS)
-// crbug.com/514456
-#define MAYBE_TouchHandlerConsume DISABLED_TouchHandlerConsume
-#else
-#define MAYBE_TouchHandlerConsume TouchHandlerConsume
-#endif
-IN_PROC_BROWSER_TEST_F(TouchInputBrowserTest, MAYBE_TouchHandlerConsume) {
+IN_PROC_BROWSER_TEST_F(TouchInputBrowserTest, TouchHandlerConsume) {
LoadURL();
SyntheticWebTouchEvent touch;
@@ -196,16 +185,7 @@ IN_PROC_BROWSER_TEST_F(TouchInputBrowserTest, MAYBE_TouchHandlerConsume) {
filter->WaitForAck();
}
-#if defined(OS_CHROMEOS)
-// crbug.com/514456
-#define MAYBE_MultiPointTouchPress DISABLED_MultiPointTouchPress
-#elif defined(OS_MACOSX)
-// TODO(ccameron): Failing on mac: crbug.com/346363
-#define MAYBE_MultiPointTouchPress DISABLED_MultiPointTouchPress
-#else
-#define MAYBE_MultiPointTouchPress MultiPointTouchPress
-#endif
-IN_PROC_BROWSER_TEST_F(TouchInputBrowserTest, MAYBE_MultiPointTouchPress) {
+IN_PROC_BROWSER_TEST_F(TouchInputBrowserTest, MultiPointTouchPress) {
LoadURL();
SyntheticWebTouchEvent touch;
diff --git a/chromium/content/browser/renderer_host/input/touch_selection_controller_client_aura.h b/chromium/content/browser/renderer_host/input/touch_selection_controller_client_aura.h
index a18886536d5..572c56b0e69 100644
--- a/chromium/content/browser/renderer_host/input/touch_selection_controller_client_aura.h
+++ b/chromium/content/browser/renderer_host/input/touch_selection_controller_client_aura.h
@@ -122,7 +122,7 @@ class CONTENT_EXPORT TouchSelectionControllerClientAura
gfx::SelectionBound manager_selection_start_;
gfx::SelectionBound manager_selection_end_;
- base::ObserverList<TouchSelectionControllerClientManager::Observer>
+ base::ObserverList<TouchSelectionControllerClientManager::Observer>::Unchecked
observers_;
base::RetainingOneShotTimer quick_menu_timer_;
diff --git a/chromium/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc b/chromium/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc
index d8350f38862..86f8645c735 100644
--- a/chromium/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc
+++ b/chromium/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc
@@ -682,8 +682,6 @@ IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraTest,
rwhva->selection_controller()->active_status());
EXPECT_FALSE(ui::TouchSelectionMenuRunner::GetInstance()->IsRunning());
- ui::test::EventGeneratorDelegate* generator_delegate =
- ui::test::EventGenerator::default_delegate;
gfx::NativeView native_view = rwhva->GetNativeView();
ui::test::EventGenerator generator(native_view->GetRootWindow());
@@ -694,7 +692,7 @@ IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraTest,
gfx::PointF point_f;
ASSERT_TRUE(GetPointInsideTextfield(&point_f));
gfx::Point point = gfx::ToRoundedPoint(point_f);
- generator_delegate->ConvertPointFromTarget(native_view, &point);
+ generator.delegate()->ConvertPointFromTarget(native_view, &point);
generator.GestureTapAt(point);
selection_controller_client()->Wait();
@@ -707,7 +705,7 @@ IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraTest,
// Tap on the insertion handle; the quick menu should appear.
gfx::Point handle_center = gfx::ToRoundedPoint(
rwhva->selection_controller()->GetStartHandleRect().CenterPoint());
- generator_delegate->ConvertPointFromTarget(native_view, &handle_center);
+ generator.delegate()->ConvertPointFromTarget(native_view, &handle_center);
generator.GestureTapAt(handle_center);
EXPECT_TRUE(ui::TouchSelectionMenuRunner::GetInstance()->IsRunning());
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 9cea813f8d8..b839bddccbf 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
@@ -55,7 +55,7 @@ class TouchSelectionControllerClientManagerAndroid
float page_scale_factor_;
gfx::SelectionBound manager_selection_start_;
gfx::SelectionBound manager_selection_end_;
- base::ObserverList<TouchSelectionControllerClientManager::Observer>
+ base::ObserverList<TouchSelectionControllerClientManager::Observer>::Unchecked
observers_;
DISALLOW_COPY_AND_ASSIGN(TouchSelectionControllerClientManagerAndroid);
diff --git a/chromium/content/browser/renderer_host/input/touchpad_pinch_browsertest.cc b/chromium/content/browser/renderer_host/input/touchpad_pinch_browsertest.cc
index 7111ab6ae9c..9d60505dcb8 100644
--- a/chromium/content/browser/renderer_host/input/touchpad_pinch_browsertest.cc
+++ b/chromium/content/browser/renderer_host/input/touchpad_pinch_browsertest.cc
@@ -3,8 +3,10 @@
// found in the LICENSE file.
#include "base/run_loop.h"
+#include "base/test/scoped_feature_list.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/public/browser/web_contents.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"
@@ -55,9 +57,18 @@ const char kTouchpadPinchDataURL[] =
namespace content {
-class TouchpadPinchBrowserTest : public ContentBrowserTest {
+class TouchpadPinchBrowserTest : public ContentBrowserTest,
+ public testing::WithParamInterface<bool> {
public:
- TouchpadPinchBrowserTest() = default;
+ TouchpadPinchBrowserTest() {
+ if (GetParam()) {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kTouchpadAsyncPinchEvents);
+ } else {
+ scoped_feature_list_.InitAndDisableFeature(
+ features::kTouchpadAsyncPinchEvents);
+ }
+ }
~TouchpadPinchBrowserTest() override = default;
protected:
@@ -78,10 +89,16 @@ class TouchpadPinchBrowserTest : public ContentBrowserTest {
MainThreadFrameObserver observer(GetRenderWidgetHost());
observer.Wait();
}
+
+ private:
+ base::test::ScopedFeatureList scoped_feature_list_;
+ DISALLOW_COPY_AND_ASSIGN(TouchpadPinchBrowserTest);
};
+INSTANTIATE_TEST_CASE_P(, TouchpadPinchBrowserTest, testing::Bool());
+
// Performing a touchpad pinch gesture should change the page scale.
-IN_PROC_BROWSER_TEST_F(TouchpadPinchBrowserTest,
+IN_PROC_BROWSER_TEST_P(TouchpadPinchBrowserTest,
TouchpadPinchChangesPageScale) {
LoadURL();
@@ -98,7 +115,7 @@ IN_PROC_BROWSER_TEST_F(TouchpadPinchBrowserTest,
// We should offer synthetic wheel events to the page when a touchpad pinch
// is performed.
-IN_PROC_BROWSER_TEST_F(TouchpadPinchBrowserTest, WheelListenerAllowingPinch) {
+IN_PROC_BROWSER_TEST_P(TouchpadPinchBrowserTest, WheelListenerAllowingPinch) {
LoadURL();
ASSERT_TRUE(
content::ExecuteScript(shell()->web_contents(), "setListener(false);"));
@@ -129,7 +146,7 @@ IN_PROC_BROWSER_TEST_F(TouchpadPinchBrowserTest, WheelListenerAllowingPinch) {
// If the synthetic wheel event for a touchpad pinch is canceled, we should not
// change the page scale.
-IN_PROC_BROWSER_TEST_F(TouchpadPinchBrowserTest, WheelListenerPreventingPinch) {
+IN_PROC_BROWSER_TEST_P(TouchpadPinchBrowserTest, WheelListenerPreventingPinch) {
LoadURL();
// Perform an initial pinch so we can figure out the page scale we're
diff --git a/chromium/content/browser/renderer_host/input/touchpad_pinch_event_queue.cc b/chromium/content/browser/renderer_host/input/touchpad_pinch_event_queue.cc
index f0279ae7225..fa6ca271fa9 100644
--- a/chromium/content/browser/renderer_host/input/touchpad_pinch_event_queue.cc
+++ b/chromium/content/browser/renderer_host/input/touchpad_pinch_event_queue.cc
@@ -5,6 +5,7 @@
#include "content/browser/renderer_host/input/touchpad_pinch_event_queue.h"
#include "base/trace_event/trace_event.h"
+#include "content/public/common/content_features.h"
#include "third_party/blink/public/platform/web_mouse_wheel_event.h"
#include "ui/events/base_event_utils.h"
#include "ui/events/blink/blink_event_util.h"
@@ -15,8 +16,29 @@ namespace content {
namespace {
blink::WebMouseWheelEvent CreateSyntheticWheelFromTouchpadPinchEvent(
- const blink::WebGestureEvent& pinch_event) {
- DCHECK_EQ(blink::WebInputEvent::kGesturePinchUpdate, pinch_event.GetType());
+ const blink::WebGestureEvent& pinch_event,
+ blink::WebMouseWheelEvent::Phase phase,
+ bool cancelable) {
+ DCHECK(pinch_event.GetType() == blink::WebInputEvent::kGesturePinchUpdate ||
+ pinch_event.GetType() == blink::WebInputEvent::kGesturePinchEnd);
+ float delta_y = 0.0f;
+ float wheel_ticks_y = 0.0f;
+
+ // The function to convert scales to deltaY values is designed to be
+ // compatible with websites existing use of wheel events, and with existing
+ // Windows trackpad behavior. In particular, we want:
+ // - deltas should accumulate via addition: f(s1*s2)==f(s1)+f(s2)
+ // - deltas should invert via negation: f(1/s) == -f(s)
+ // - zoom in should be positive: f(s) > 0 iff s > 1
+ // - magnitude roughly matches wheels: f(2) > 25 && f(2) < 100
+ // - a formula that's relatively easy to use from JavaScript
+ // Note that 'wheel' event deltaY values have their sign inverted. So to
+ // convert a wheel deltaY back to a scale use Math.exp(-deltaY/100).
+ if (pinch_event.GetType() == blink::WebInputEvent::kGesturePinchUpdate) {
+ DCHECK_GT(pinch_event.data.pinch_update.scale, 0);
+ delta_y = 100.0f * log(pinch_event.data.pinch_update.scale);
+ wheel_ticks_y = pinch_event.data.pinch_update.scale > 1 ? 1 : -1;
+ }
// For pinch gesture events, similar to ctrl+wheel zooming, allow content to
// prevent the browser from zooming by sending fake wheel events with the ctrl
@@ -29,22 +51,18 @@ blink::WebMouseWheelEvent CreateSyntheticWheelFromTouchpadPinchEvent(
wheel_event.SetPositionInWidget(pinch_event.PositionInWidget());
wheel_event.SetPositionInScreen(pinch_event.PositionInScreen());
wheel_event.delta_x = 0;
+ wheel_event.delta_y = delta_y;
- // The function to convert scales to deltaY values is designed to be
- // compatible with websites existing use of wheel events, and with existing
- // Windows trackpad behavior. In particular, we want:
- // - deltas should accumulate via addition: f(s1*s2)==f(s1)+f(s2)
- // - deltas should invert via negation: f(1/s) == -f(s)
- // - zoom in should be positive: f(s) > 0 iff s > 1
- // - magnitude roughly matches wheels: f(2) > 25 && f(2) < 100
- // - a formula that's relatively easy to use from JavaScript
- // Note that 'wheel' event deltaY values have their sign inverted. So to
- // convert a wheel deltaY back to a scale use Math.exp(-deltaY/100).
- DCHECK_GT(pinch_event.data.pinch_update.scale, 0);
- wheel_event.delta_y = 100.0f * log(pinch_event.data.pinch_update.scale);
wheel_event.has_precise_scrolling_deltas = true;
+
+ wheel_event.phase = phase;
wheel_event.wheel_ticks_x = 0;
- wheel_event.wheel_ticks_y = pinch_event.data.pinch_update.scale > 1 ? 1 : -1;
+ wheel_event.wheel_ticks_y = wheel_ticks_y;
+
+ if (cancelable)
+ wheel_event.dispatch_type = blink::WebInputEvent::kBlocking;
+ else
+ wheel_event.dispatch_type = blink::WebInputEvent::kEventNonBlocking;
return wheel_event;
}
@@ -71,7 +89,9 @@ class QueuedTouchpadPinchEvent : public GestureEventWithLatencyInfo {
TouchpadPinchEventQueue::TouchpadPinchEventQueue(
TouchpadPinchEventQueueClient* client)
- : client_(client) {
+ : touchpad_async_pinch_events_(
+ base::FeatureList::IsEnabled(features::kTouchpadAsyncPinchEvents)),
+ client_(client) {
DCHECK(client_);
}
@@ -110,6 +130,11 @@ void TouchpadPinchEventQueue::ProcessMouseWheelAck(
if (!pinch_event_awaiting_ack_)
return;
+ if (pinch_event_awaiting_ack_->event.GetType() ==
+ blink::WebInputEvent::kGesturePinchUpdate &&
+ !first_event_prevented_.has_value())
+ first_event_prevented_ = (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED);
+
pinch_event_awaiting_ack_->latency.AddNewLatencyFrom(latency_info);
client_->OnGestureEventForPinchAck(*pinch_event_awaiting_ack_, ack_source,
ack_result);
@@ -129,15 +154,7 @@ void TouchpadPinchEventQueue::TryForwardNextEventToRenderer() {
pinch_queue_.pop_front();
if (pinch_event_awaiting_ack_->event.GetType() ==
- blink::WebInputEvent::kGesturePinchBegin ||
- pinch_event_awaiting_ack_->event.GetType() ==
- blink::WebInputEvent::kGesturePinchEnd) {
- // Wheel event listeners are given individual events with no phase
- // information, so we don't need to do anything at the beginning or
- // end of a pinch.
- // TODO(565980): Consider sending the rest of the wheel events as
- // non-blocking if the first wheel event of the pinch sequence is not
- // consumed.
+ blink::WebInputEvent::kGesturePinchBegin) {
client_->OnGestureEventForPinchAck(*pinch_event_awaiting_ack_,
InputEventAckSource::BROWSER,
INPUT_EVENT_ACK_STATE_IGNORED);
@@ -146,9 +163,34 @@ void TouchpadPinchEventQueue::TryForwardNextEventToRenderer() {
return;
}
+ blink::WebMouseWheelEvent::Phase phase =
+ blink::WebMouseWheelEvent::kPhaseNone;
+ bool cancelable = true;
+
+ if (pinch_event_awaiting_ack_->event.GetType() ==
+ blink::WebInputEvent::kGesturePinchEnd) {
+ first_event_prevented_.reset();
+ phase = blink::WebMouseWheelEvent::kPhaseEnded;
+ cancelable = false;
+ } else {
+ DCHECK_EQ(pinch_event_awaiting_ack_->event.GetType(),
+ blink::WebInputEvent::kGesturePinchUpdate);
+ // The first pinch update event should send a synthetic wheel with phase
+ // began.
+ if (!first_event_prevented_.has_value()) {
+ phase = blink::WebMouseWheelEvent::kPhaseBegan;
+ cancelable = true;
+ } else {
+ phase = blink::WebMouseWheelEvent::kPhaseChanged;
+ cancelable =
+ !touchpad_async_pinch_events_ || first_event_prevented_.value();
+ }
+ }
+
+ DCHECK_NE(phase, blink::WebMouseWheelEvent::kPhaseNone);
const MouseWheelEventWithLatencyInfo synthetic_wheel(
CreateSyntheticWheelFromTouchpadPinchEvent(
- pinch_event_awaiting_ack_->event),
+ pinch_event_awaiting_ack_->event, phase, cancelable),
pinch_event_awaiting_ack_->latency);
client_->SendMouseWheelEventForPinchImmediately(synthetic_wheel);
diff --git a/chromium/content/browser/renderer_host/input/touchpad_pinch_event_queue.h b/chromium/content/browser/renderer_host/input/touchpad_pinch_event_queue.h
index f7def2c8636..4fbbb71f1d0 100644
--- a/chromium/content/browser/renderer_host/input/touchpad_pinch_event_queue.h
+++ b/chromium/content/browser/renderer_host/input/touchpad_pinch_event_queue.h
@@ -8,6 +8,7 @@
#include <memory>
#include "base/containers/circular_deque.h"
+#include "base/optional.h"
#include "content/common/content_export.h"
#include "content/common/input/event_with_latency_info.h"
#include "content/public/common/input_event_ack_source.h"
@@ -63,10 +64,12 @@ class CONTENT_EXPORT TouchpadPinchEventQueue {
private:
void TryForwardNextEventToRenderer();
+ const bool touchpad_async_pinch_events_;
TouchpadPinchEventQueueClient* client_;
base::circular_deque<std::unique_ptr<QueuedTouchpadPinchEvent>> pinch_queue_;
std::unique_ptr<QueuedTouchpadPinchEvent> pinch_event_awaiting_ack_;
+ base::Optional<bool> first_event_prevented_;
DISALLOW_COPY_AND_ASSIGN(TouchpadPinchEventQueue);
};
diff --git a/chromium/content/browser/renderer_host/input/touchpad_pinch_event_queue_unittest.cc b/chromium/content/browser/renderer_host/input/touchpad_pinch_event_queue_unittest.cc
index 73c6424a06e..e273c29e681 100644
--- a/chromium/content/browser/renderer_host/input/touchpad_pinch_event_queue_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/touchpad_pinch_event_queue_unittest.cc
@@ -6,7 +6,9 @@
#include <string>
+#include "base/test/scoped_feature_list.h"
#include "content/common/input/event_with_latency_info.h"
+#include "content/public/common/content_features.h"
#include "content/public/common/input_event_ack_source.h"
#include "content/public/common/input_event_ack_state.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -30,13 +32,22 @@ class MockTouchpadPinchEventQueueClient : public TouchpadPinchEventQueueClient {
InputEventAckState ack_result));
};
-class TouchpadPinchEventQueueTest : public ::testing::Test {
+class TouchpadPinchEventQueueTest : public testing::TestWithParam<bool> {
protected:
- TouchpadPinchEventQueueTest() : queue_(&mock_client_) {}
+ TouchpadPinchEventQueueTest() : async_events_enabled_(GetParam()) {
+ if (async_events_enabled_) {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kTouchpadAsyncPinchEvents);
+ } else {
+ scoped_feature_list_.InitAndDisableFeature(
+ features::kTouchpadAsyncPinchEvents);
+ }
+ queue_ = std::make_unique<TouchpadPinchEventQueue>(&mock_client_);
+ }
~TouchpadPinchEventQueueTest() = default;
void QueueEvent(const blink::WebGestureEvent& event) {
- queue_.QueueEvent(GestureEventWithLatencyInfo(event));
+ queue_->QueueEvent(GestureEventWithLatencyInfo(event));
}
void QueuePinchBegin() {
@@ -79,13 +90,17 @@ class TouchpadPinchEventQueueTest : public ::testing::Test {
void SendWheelEventAck(InputEventAckSource ack_source,
InputEventAckState ack_result) {
- queue_.ProcessMouseWheelAck(ack_source, ack_result, ui::LatencyInfo());
+ queue_->ProcessMouseWheelAck(ack_source, ack_result, ui::LatencyInfo());
}
+ base::test::ScopedFeatureList scoped_feature_list_;
testing::StrictMock<MockTouchpadPinchEventQueueClient> mock_client_;
- TouchpadPinchEventQueue queue_;
+ std::unique_ptr<TouchpadPinchEventQueue> queue_;
+ const bool async_events_enabled_;
};
+INSTANTIATE_TEST_CASE_P(, TouchpadPinchEventQueueTest, ::testing::Bool());
+
MATCHER_P(EventHasType,
type,
std::string(negation ? "does not have" : "has") + " type " +
@@ -93,6 +108,13 @@ MATCHER_P(EventHasType,
return arg.event.GetType() == type;
}
+MATCHER_P(EventHasPhase,
+ phase,
+ std::string(negation ? "does not have" : "has") + " phase " +
+ ::testing::PrintToString(phase)) {
+ return arg.event.phase == phase;
+}
+
MATCHER(EventHasCtrlModifier,
std::string(negation ? "does not have" : "has") + " control modifier") {
return (arg.event.GetModifiers() & blink::WebInputEvent::kControlKey) != 0;
@@ -105,7 +127,7 @@ MATCHER(EventIsBlocking,
// Ensure that when the queue receives a touchpad pinch sequence, it sends a
// synthetic mouse wheel event and acks the pinch events back to the client.
-TEST_F(TouchpadPinchEventQueueTest, Basic) {
+TEST_P(TouchpadPinchEventQueueTest, Basic) {
::testing::InSequence sequence;
EXPECT_CALL(mock_client_,
OnGestureEventForPinchAck(
@@ -120,6 +142,9 @@ TEST_F(TouchpadPinchEventQueueTest, Basic) {
InputEventAckSource::COMPOSITOR_THREAD,
INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS));
EXPECT_CALL(mock_client_,
+ SendMouseWheelEventForPinchImmediately(::testing::AllOf(
+ EventHasCtrlModifier(), ::testing::Not(EventIsBlocking()))));
+ EXPECT_CALL(mock_client_,
OnGestureEventForPinchAck(
EventHasType(blink::WebInputEvent::kGesturePinchEnd),
InputEventAckSource::BROWSER, INPUT_EVENT_ACK_STATE_IGNORED));
@@ -129,11 +154,60 @@ TEST_F(TouchpadPinchEventQueueTest, Basic) {
SendWheelEventAck(InputEventAckSource::COMPOSITOR_THREAD,
INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
QueuePinchEnd();
+ SendWheelEventAck(InputEventAckSource::BROWSER,
+ INPUT_EVENT_ACK_STATE_IGNORED);
+}
+
+// Ensure the queue sends the wheel events with phase information.
+TEST_P(TouchpadPinchEventQueueTest, MouseWheelPhase) {
+ ::testing::InSequence sequence;
+ EXPECT_CALL(mock_client_,
+ OnGestureEventForPinchAck(
+ EventHasType(blink::WebInputEvent::kGesturePinchBegin),
+ InputEventAckSource::BROWSER, INPUT_EVENT_ACK_STATE_IGNORED));
+ EXPECT_CALL(mock_client_,
+ SendMouseWheelEventForPinchImmediately(
+ EventHasPhase(blink::WebMouseWheelEvent::kPhaseBegan)));
+ EXPECT_CALL(mock_client_,
+ OnGestureEventForPinchAck(
+ EventHasType(blink::WebInputEvent::kGesturePinchUpdate),
+ InputEventAckSource::COMPOSITOR_THREAD,
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS));
+ EXPECT_CALL(mock_client_,
+ SendMouseWheelEventForPinchImmediately(
+ EventHasPhase(blink::WebMouseWheelEvent::kPhaseChanged)));
+ EXPECT_CALL(mock_client_,
+ OnGestureEventForPinchAck(
+ EventHasType(blink::WebInputEvent::kGesturePinchUpdate),
+ testing::_, testing::_));
+ EXPECT_CALL(mock_client_,
+ SendMouseWheelEventForPinchImmediately(
+ EventHasPhase(blink::WebMouseWheelEvent::kPhaseEnded)));
+ EXPECT_CALL(mock_client_,
+ OnGestureEventForPinchAck(
+ EventHasType(blink::WebInputEvent::kGesturePinchEnd),
+ InputEventAckSource::BROWSER, INPUT_EVENT_ACK_STATE_IGNORED));
+
+ QueuePinchBegin();
+ QueuePinchUpdate(1.23, false);
+ SendWheelEventAck(InputEventAckSource::COMPOSITOR_THREAD,
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+ QueuePinchUpdate(1.23, false);
+ if (async_events_enabled_) {
+ SendWheelEventAck(InputEventAckSource::BROWSER,
+ INPUT_EVENT_ACK_STATE_IGNORED);
+ } else {
+ SendWheelEventAck(InputEventAckSource::COMPOSITOR_THREAD,
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+ }
+ QueuePinchEnd();
+ SendWheelEventAck(InputEventAckSource::BROWSER,
+ INPUT_EVENT_ACK_STATE_IGNORED);
}
// Ensure that if the renderer consumes the synthetic wheel event, the ack of
// the GesturePinchUpdate reflects this.
-TEST_F(TouchpadPinchEventQueueTest, Consumed) {
+TEST_P(TouchpadPinchEventQueueTest, Consumed) {
::testing::InSequence sequence;
EXPECT_CALL(mock_client_,
OnGestureEventForPinchAck(
@@ -147,6 +221,11 @@ TEST_F(TouchpadPinchEventQueueTest, Consumed) {
OnGestureEventForPinchAck(
EventHasType(blink::WebInputEvent::kGesturePinchUpdate),
InputEventAckSource::MAIN_THREAD, INPUT_EVENT_ACK_STATE_CONSUMED));
+
+ EXPECT_CALL(mock_client_,
+ SendMouseWheelEventForPinchImmediately(::testing::AllOf(
+ EventHasCtrlModifier(), ::testing::Not(EventIsBlocking()))));
+
EXPECT_CALL(mock_client_,
OnGestureEventForPinchAck(
EventHasType(blink::WebInputEvent::kGesturePinchEnd),
@@ -157,11 +236,13 @@ TEST_F(TouchpadPinchEventQueueTest, Consumed) {
SendWheelEventAck(InputEventAckSource::MAIN_THREAD,
INPUT_EVENT_ACK_STATE_CONSUMED);
QueuePinchEnd();
+ SendWheelEventAck(InputEventAckSource::BROWSER,
+ INPUT_EVENT_ACK_STATE_IGNORED);
}
// Ensure that the queue sends wheel events for updates with |zoom_disabled| as
// well.
-TEST_F(TouchpadPinchEventQueueTest, ZoomDisabled) {
+TEST_P(TouchpadPinchEventQueueTest, ZoomDisabled) {
::testing::InSequence sequence;
EXPECT_CALL(mock_client_,
OnGestureEventForPinchAck(
@@ -175,6 +256,11 @@ TEST_F(TouchpadPinchEventQueueTest, ZoomDisabled) {
EventHasType(blink::WebInputEvent::kGesturePinchUpdate),
InputEventAckSource::COMPOSITOR_THREAD,
INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS));
+
+ EXPECT_CALL(mock_client_,
+ SendMouseWheelEventForPinchImmediately(::testing::AllOf(
+ EventHasCtrlModifier(), ::testing::Not(EventIsBlocking()))));
+
EXPECT_CALL(mock_client_,
OnGestureEventForPinchAck(
EventHasType(blink::WebInputEvent::kGesturePinchEnd),
@@ -185,16 +271,18 @@ TEST_F(TouchpadPinchEventQueueTest, ZoomDisabled) {
SendWheelEventAck(InputEventAckSource::COMPOSITOR_THREAD,
INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
QueuePinchEnd();
+ SendWheelEventAck(InputEventAckSource::BROWSER,
+ INPUT_EVENT_ACK_STATE_IGNORED);
}
-TEST_F(TouchpadPinchEventQueueTest, MultipleSequences) {
+TEST_P(TouchpadPinchEventQueueTest, MultipleSequences) {
EXPECT_CALL(mock_client_,
OnGestureEventForPinchAck(
EventHasType(blink::WebInputEvent::kGesturePinchBegin),
InputEventAckSource::BROWSER, INPUT_EVENT_ACK_STATE_IGNORED))
.Times(2);
EXPECT_CALL(mock_client_, SendMouseWheelEventForPinchImmediately(testing::_))
- .Times(2);
+ .Times(4);
EXPECT_CALL(mock_client_,
OnGestureEventForPinchAck(
EventHasType(blink::WebInputEvent::kGesturePinchUpdate),
@@ -212,17 +300,21 @@ TEST_F(TouchpadPinchEventQueueTest, MultipleSequences) {
SendWheelEventAck(InputEventAckSource::COMPOSITOR_THREAD,
INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
QueuePinchEnd();
+ SendWheelEventAck(InputEventAckSource::BROWSER,
+ INPUT_EVENT_ACK_STATE_IGNORED);
QueuePinchBegin();
QueuePinchUpdate(1.23, false);
SendWheelEventAck(InputEventAckSource::COMPOSITOR_THREAD,
INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
QueuePinchEnd();
+ SendWheelEventAck(InputEventAckSource::BROWSER,
+ INPUT_EVENT_ACK_STATE_IGNORED);
}
// Ensure we can queue additional pinch event sequences while the queue is
// waiting for a wheel event ack.
-TEST_F(TouchpadPinchEventQueueTest, MultipleQueuedSequences) {
+TEST_P(TouchpadPinchEventQueueTest, MultipleQueuedSequences) {
EXPECT_CALL(mock_client_,
OnGestureEventForPinchAck(
EventHasType(blink::WebInputEvent::kGesturePinchBegin),
@@ -255,9 +347,13 @@ TEST_F(TouchpadPinchEventQueueTest, MultipleQueuedSequences) {
OnGestureEventForPinchAck(
EventHasType(blink::WebInputEvent::kGesturePinchBegin),
InputEventAckSource::BROWSER, INPUT_EVENT_ACK_STATE_IGNORED));
- EXPECT_CALL(mock_client_, SendMouseWheelEventForPinchImmediately(testing::_));
+ EXPECT_CALL(mock_client_, SendMouseWheelEventForPinchImmediately(testing::_))
+ .Times(2);
SendWheelEventAck(InputEventAckSource::COMPOSITOR_THREAD,
INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+ // ACK for end event.
+ SendWheelEventAck(InputEventAckSource::BROWSER,
+ INPUT_EVENT_ACK_STATE_IGNORED);
// After acking the first wheel event, the queue continues.
testing::Mock::VerifyAndClearExpectations(&mock_client_);
@@ -271,25 +367,61 @@ TEST_F(TouchpadPinchEventQueueTest, MultipleQueuedSequences) {
OnGestureEventForPinchAck(
EventHasType(blink::WebInputEvent::kGesturePinchEnd),
InputEventAckSource::BROWSER, INPUT_EVENT_ACK_STATE_IGNORED));
+ EXPECT_CALL(mock_client_, SendMouseWheelEventForPinchImmediately(testing::_));
SendWheelEventAck(InputEventAckSource::COMPOSITOR_THREAD,
INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+ // ACK for end event.
+ SendWheelEventAck(InputEventAckSource::BROWSER,
+ INPUT_EVENT_ACK_STATE_IGNORED);
}
// Ensure the queue handles pinch event sequences with multiple updates.
-TEST_F(TouchpadPinchEventQueueTest, MultipleUpdatesInSequence) {
+TEST_P(TouchpadPinchEventQueueTest, MultipleUpdatesInSequence) {
EXPECT_CALL(mock_client_,
OnGestureEventForPinchAck(
EventHasType(blink::WebInputEvent::kGesturePinchBegin),
InputEventAckSource::BROWSER, INPUT_EVENT_ACK_STATE_IGNORED));
- EXPECT_CALL(mock_client_,
- SendMouseWheelEventForPinchImmediately(EventHasCtrlModifier()))
- .Times(3);
- EXPECT_CALL(mock_client_,
- OnGestureEventForPinchAck(
- EventHasType(blink::WebInputEvent::kGesturePinchUpdate),
- InputEventAckSource::COMPOSITOR_THREAD,
- INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS))
- .Times(3);
+ if (async_events_enabled_) {
+ // Only first wheel event is cancelable.
+ // Here the second and the third wheel events are not blocking because we
+ // ack the first wheel event as unconsumed.
+ EXPECT_CALL(mock_client_,
+ SendMouseWheelEventForPinchImmediately(::testing::AllOf(
+ EventHasCtrlModifier(), EventIsBlocking())));
+ EXPECT_CALL(mock_client_,
+ SendMouseWheelEventForPinchImmediately(::testing::AllOf(
+ EventHasCtrlModifier(), ::testing::Not(EventIsBlocking()))))
+ .Times(3);
+ } else {
+ EXPECT_CALL(mock_client_,
+ SendMouseWheelEventForPinchImmediately(::testing::AllOf(
+ EventHasCtrlModifier(), EventIsBlocking())))
+ .Times(3);
+ EXPECT_CALL(
+ mock_client_,
+ SendMouseWheelEventForPinchImmediately(::testing::AllOf(
+ EventHasCtrlModifier(), ::testing::Not(EventIsBlocking()))));
+ }
+ if (async_events_enabled_) {
+ EXPECT_CALL(mock_client_,
+ OnGestureEventForPinchAck(
+ EventHasType(blink::WebInputEvent::kGesturePinchUpdate),
+ InputEventAckSource::COMPOSITOR_THREAD,
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS));
+ EXPECT_CALL(
+ mock_client_,
+ OnGestureEventForPinchAck(
+ EventHasType(blink::WebInputEvent::kGesturePinchUpdate),
+ InputEventAckSource::BROWSER, INPUT_EVENT_ACK_STATE_IGNORED))
+ .Times(2);
+ } else {
+ EXPECT_CALL(mock_client_,
+ OnGestureEventForPinchAck(
+ EventHasType(blink::WebInputEvent::kGesturePinchUpdate),
+ InputEventAckSource::COMPOSITOR_THREAD,
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS))
+ .Times(3);
+ }
EXPECT_CALL(mock_client_,
OnGestureEventForPinchAck(
EventHasType(blink::WebInputEvent::kGesturePinchEnd),
@@ -300,29 +432,72 @@ TEST_F(TouchpadPinchEventQueueTest, MultipleUpdatesInSequence) {
SendWheelEventAck(InputEventAckSource::COMPOSITOR_THREAD,
INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
QueuePinchUpdate(1.23, false);
- SendWheelEventAck(InputEventAckSource::COMPOSITOR_THREAD,
- INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+ if (async_events_enabled_) {
+ SendWheelEventAck(InputEventAckSource::BROWSER,
+ INPUT_EVENT_ACK_STATE_IGNORED);
+ } else {
+ SendWheelEventAck(InputEventAckSource::COMPOSITOR_THREAD,
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+ }
QueuePinchUpdate(1.23, false);
- SendWheelEventAck(InputEventAckSource::COMPOSITOR_THREAD,
- INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+ if (async_events_enabled_) {
+ SendWheelEventAck(InputEventAckSource::BROWSER,
+ INPUT_EVENT_ACK_STATE_IGNORED);
+ } else {
+ SendWheelEventAck(InputEventAckSource::COMPOSITOR_THREAD,
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+ }
QueuePinchEnd();
+ SendWheelEventAck(InputEventAckSource::BROWSER,
+ INPUT_EVENT_ACK_STATE_IGNORED);
}
// Ensure the queue coalesces pinch update events.
-TEST_F(TouchpadPinchEventQueueTest, MultipleUpdatesCoalesced) {
+TEST_P(TouchpadPinchEventQueueTest, MultipleUpdatesCoalesced) {
EXPECT_CALL(mock_client_,
OnGestureEventForPinchAck(
EventHasType(blink::WebInputEvent::kGesturePinchBegin),
InputEventAckSource::BROWSER, INPUT_EVENT_ACK_STATE_IGNORED));
- EXPECT_CALL(mock_client_,
- SendMouseWheelEventForPinchImmediately(EventHasCtrlModifier()))
- .Times(2);
- EXPECT_CALL(mock_client_,
- OnGestureEventForPinchAck(
- EventHasType(blink::WebInputEvent::kGesturePinchUpdate),
- InputEventAckSource::COMPOSITOR_THREAD,
- INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS))
- .Times(2);
+ if (async_events_enabled_) {
+ // Only the first wheel event is cancelable.
+ // Here the second wheel is not blocking because we ack the first wheel
+ // event as unconsumed.
+ EXPECT_CALL(mock_client_,
+ SendMouseWheelEventForPinchImmediately(::testing::AllOf(
+ EventHasCtrlModifier(), EventIsBlocking())));
+ EXPECT_CALL(mock_client_,
+ SendMouseWheelEventForPinchImmediately(::testing::AllOf(
+ EventHasCtrlModifier(), ::testing::Not(EventIsBlocking()))))
+ .Times(2);
+ } else {
+ EXPECT_CALL(mock_client_,
+ SendMouseWheelEventForPinchImmediately(::testing::AllOf(
+ EventHasCtrlModifier(), EventIsBlocking())))
+ .Times(2);
+ EXPECT_CALL(
+ mock_client_,
+ SendMouseWheelEventForPinchImmediately(::testing::AllOf(
+ EventHasCtrlModifier(), ::testing::Not(EventIsBlocking()))));
+ }
+ if (async_events_enabled_) {
+ EXPECT_CALL(mock_client_,
+ OnGestureEventForPinchAck(
+ EventHasType(blink::WebInputEvent::kGesturePinchUpdate),
+ InputEventAckSource::COMPOSITOR_THREAD,
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS));
+ EXPECT_CALL(
+ mock_client_,
+ OnGestureEventForPinchAck(
+ EventHasType(blink::WebInputEvent::kGesturePinchUpdate),
+ InputEventAckSource::BROWSER, INPUT_EVENT_ACK_STATE_IGNORED));
+ } else {
+ EXPECT_CALL(mock_client_,
+ OnGestureEventForPinchAck(
+ EventHasType(blink::WebInputEvent::kGesturePinchUpdate),
+ InputEventAckSource::COMPOSITOR_THREAD,
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS))
+ .Times(2);
+ }
EXPECT_CALL(mock_client_,
OnGestureEventForPinchAck(
EventHasType(blink::WebInputEvent::kGesturePinchEnd),
@@ -342,9 +517,57 @@ TEST_F(TouchpadPinchEventQueueTest, MultipleUpdatesCoalesced) {
SendWheelEventAck(InputEventAckSource::COMPOSITOR_THREAD,
INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
// Ack for the wheel event corresponding to the second and third updates.
- SendWheelEventAck(InputEventAckSource::COMPOSITOR_THREAD,
- INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
- EXPECT_FALSE(queue_.has_pending());
+ if (async_events_enabled_) {
+ SendWheelEventAck(InputEventAckSource::BROWSER,
+ INPUT_EVENT_ACK_STATE_IGNORED);
+ } else {
+ SendWheelEventAck(InputEventAckSource::COMPOSITOR_THREAD,
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+ }
+ // ACK for end event.
+ SendWheelEventAck(InputEventAckSource::BROWSER,
+ INPUT_EVENT_ACK_STATE_IGNORED);
+ EXPECT_FALSE(queue_->has_pending());
+}
+
+// Ensure the queue handles pinch event sequences with multiple canceled
+// updates.
+TEST_P(TouchpadPinchEventQueueTest, MultipleCanceledUpdatesInSequence) {
+ EXPECT_CALL(mock_client_,
+ OnGestureEventForPinchAck(
+ EventHasType(blink::WebInputEvent::kGesturePinchBegin),
+ InputEventAckSource::BROWSER, INPUT_EVENT_ACK_STATE_IGNORED));
+ EXPECT_CALL(mock_client_,
+ SendMouseWheelEventForPinchImmediately(
+ ::testing::AllOf(EventHasCtrlModifier(), EventIsBlocking())))
+ .Times(3);
+ EXPECT_CALL(
+ mock_client_,
+ OnGestureEventForPinchAck(
+ EventHasType(blink::WebInputEvent::kGesturePinchUpdate),
+ InputEventAckSource::MAIN_THREAD, INPUT_EVENT_ACK_STATE_CONSUMED))
+ .Times(3);
+ EXPECT_CALL(mock_client_,
+ SendMouseWheelEventForPinchImmediately(::testing::AllOf(
+ EventHasCtrlModifier(), ::testing::Not(EventIsBlocking()))));
+ EXPECT_CALL(mock_client_,
+ OnGestureEventForPinchAck(
+ EventHasType(blink::WebInputEvent::kGesturePinchEnd),
+ InputEventAckSource::BROWSER, INPUT_EVENT_ACK_STATE_IGNORED));
+
+ QueuePinchBegin();
+ QueuePinchUpdate(1.23, false);
+ SendWheelEventAck(InputEventAckSource::MAIN_THREAD,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ QueuePinchUpdate(1.23, false);
+ SendWheelEventAck(InputEventAckSource::MAIN_THREAD,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ QueuePinchUpdate(1.23, false);
+ SendWheelEventAck(InputEventAckSource::MAIN_THREAD,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ QueuePinchEnd();
+ SendWheelEventAck(InputEventAckSource::BROWSER,
+ INPUT_EVENT_ACK_STATE_IGNORED);
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/web_input_event_builders_android.cc b/chromium/content/browser/renderer_host/input/web_input_event_builders_android.cc
index 5a0fe4d5439..7972b781664 100644
--- a/chromium/content/browser/renderer_host/input/web_input_event_builders_android.cc
+++ b/chromium/content/browser/renderer_host/input/web_input_event_builders_android.cc
@@ -143,7 +143,9 @@ WebMouseEvent WebMouseEventBuilder::Build(
ui::SetWebPointerPropertiesFromMotionEventData(
result, motion_event.GetPointerId(0), motion_event.GetPressure(0),
motion_event.GetOrientation(0), motion_event.GetTiltX(0),
- motion_event.GetTiltY(0), button, motion_event.GetToolType(0));
+ motion_event.GetTiltY(0), motion_event.GetTwist(0),
+ motion_event.GetTangentialPressure(0), button,
+ motion_event.GetToolType(0));
return result;
}
diff --git a/chromium/content/browser/renderer_host/input/web_input_event_builders_mac.h b/chromium/content/browser/renderer_host/input/web_input_event_builders_mac.h
index d5755a74318..99f0d8695c1 100644
--- a/chromium/content/browser/renderer_host/input/web_input_event_builders_mac.h
+++ b/chromium/content/browser/renderer_host/input/web_input_event_builders_mac.h
@@ -10,6 +10,7 @@
#include "third_party/blink/public/platform/web_input_event.h"
#include "third_party/blink/public/platform/web_keyboard_event.h"
#include "third_party/blink/public/platform/web_mouse_wheel_event.h"
+#include "third_party/blink/public/platform/web_touch_event.h"
@class NSEvent;
@class NSView;
@@ -41,6 +42,11 @@ class CONTENT_EXPORT WebGestureEventBuilder {
static blink::WebGestureEvent Build(NSEvent*, NSView*);
};
+class CONTENT_EXPORT WebTouchEventBuilder {
+ public:
+ static blink::WebTouchEvent Build(NSEvent* event, NSView* view);
+};
+
} // namespace content
#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_WEB_INPUT_EVENT_BUILDERS_MAC_H_
diff --git a/chromium/content/browser/renderer_host/input/web_input_event_builders_mac.mm b/chromium/content/browser/renderer_host/input/web_input_event_builders_mac.mm
index be7624b1be3..cb734666c35 100644
--- a/chromium/content/browser/renderer_host/input/web_input_event_builders_mac.mm
+++ b/chromium/content/browser/renderer_host/input/web_input_event_builders_mac.mm
@@ -571,4 +571,72 @@ blink::WebGestureEvent WebGestureEventBuilder::Build(NSEvent* event,
return result;
}
+// WebTouchEvent --------------------------------------------------------------
+
+blink::WebTouchEvent WebTouchEventBuilder::Build(NSEvent* event, NSView* view) {
+ blink::WebInputEvent::Type event_type =
+ blink::WebInputEvent::Type::kUndefined;
+ NSEventType type = [event type];
+ blink::WebTouchPoint::State state = blink::WebTouchPoint::kStateUndefined;
+ switch (type) {
+ case NSLeftMouseDown:
+ event_type = blink::WebInputEvent::kTouchStart;
+ state = blink::WebTouchPoint::kStatePressed;
+ break;
+ case NSLeftMouseUp:
+ event_type = blink::WebInputEvent::kTouchEnd;
+ state = blink::WebTouchPoint::kStateReleased;
+ break;
+ case NSLeftMouseDragged:
+ case NSRightMouseDragged:
+ case NSOtherMouseDragged:
+ case NSMouseMoved:
+ case NSRightMouseDown:
+ case NSOtherMouseDown:
+ case NSRightMouseUp:
+ case NSOtherMouseUp:
+ event_type = blink::WebInputEvent::kTouchMove;
+ state = blink::WebTouchPoint::kStateMoved;
+ break;
+ default:
+ NOTREACHED() << "Invalid types for touch events." << type;
+ }
+
+ blink::WebTouchEvent result(event_type, ModifiersFromEvent(event),
+ ui::EventTimeStampFromSeconds([event timestamp]));
+ result.hovering = event_type == blink::WebInputEvent::kTouchEnd;
+ result.unique_touch_event_id = ui::GetNextTouchEventId();
+ result.touches_length = 1;
+
+ // Use a temporary WebMouseEvent to get the location.
+ blink::WebMouseEvent temp;
+ SetWebEventLocationFromEventInView(&temp, event, view);
+ result.touches[0].SetPositionInWidget(temp.PositionInWidget());
+ result.touches[0].SetPositionInScreen(temp.PositionInScreen());
+ result.touches[0].movement_x = temp.movement_x;
+ result.touches[0].movement_y = temp.movement_y;
+
+ result.touches[0].state = state;
+ result.touches[0].pointer_type =
+ blink::WebPointerProperties::PointerType::kPen;
+ result.touches[0].id = [event pointingDeviceID];
+ result.touches[0].force = [event pressure];
+ NSPoint tilt = [event tilt];
+ result.touches[0].tilt_x = lround(tilt.x * 90);
+ result.touches[0].tilt_y = lround(tilt.y * 90);
+ result.touches[0].tangential_pressure = [event tangentialPressure];
+ // NSEvent spec doesn't specify the range of rotation, we make sure that
+ // this value is in the range of [0,359].
+ int twist = (int)[event rotation];
+ twist = twist % 360;
+ if (twist < 0)
+ twist += 360;
+ result.touches[0].twist = twist;
+ float rotation_angle = twist % 180;
+ if (rotation_angle > 90)
+ rotation_angle = 180.f - rotation_angle;
+ result.touches[0].rotation_angle = rotation_angle;
+ return result;
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/web_input_event_builders_mac_unittest.mm b/chromium/content/browser/renderer_host/input/web_input_event_builders_mac_unittest.mm
index 2b619cc0a7e..bad84541740 100644
--- a/chromium/content/browser/renderer_host/input/web_input_event_builders_mac_unittest.mm
+++ b/chromium/content/browser/renderer_host/input/web_input_event_builders_mac_unittest.mm
@@ -66,6 +66,31 @@ NSEvent* BuildFakeKeyEvent(NSUInteger key_code,
keyCode:key_code];
}
+#if !defined(MAC_OS_X_VERSION_10_12)
+NSEvent* BuildFakeMouseEvent(CGEventType mouse_type,
+ CGPoint location,
+ CGMouseButton button,
+ CGEventMouseSubtype subtype,
+ float rotation = 0.0,
+ float pressure = 0.0,
+ float tilt_x = 0.0,
+ float tilt_y = 0.0,
+ float tangential_pressure = 0.0) {
+ CGEventRef cg_event =
+ CGEventCreateMouseEvent(NULL, mouse_type, location, button);
+ CGEventSetIntegerValueField(cg_event, kCGMouseEventSubtype, subtype);
+ CGEventSetDoubleValueField(cg_event, kCGTabletEventRotation, rotation);
+ CGEventSetDoubleValueField(cg_event, kCGMouseEventPressure, pressure);
+ CGEventSetDoubleValueField(cg_event, kCGTabletEventTiltX, tilt_x);
+ CGEventSetDoubleValueField(cg_event, kCGTabletEventTiltY, tilt_y);
+ CGEventSetDoubleValueField(cg_event, kCGTabletEventTangentialPressure,
+ tangential_pressure);
+ NSEvent* event = [NSEvent eventWithCGEvent:cg_event];
+ CFRelease(cg_event);
+ return event;
+}
+#endif // MAC_OS_X_VERSION_10_12
+
} // namespace
// Test that arrow keys don't have numpad modifier set.
@@ -647,3 +672,113 @@ TEST(WebInputEventBuilderMacTest, ScrollWheelMatchesUIEvent) {
EXPECT_EQ(web_event.PositionInWidget().y, ui_event.y());
[window close];
}
+
+#if !defined(MAC_OS_X_VERSION_10_12)
+// Test if the value of twist and rotation_angle are set correctly when the
+// NSEvent's rotation is less than 90.
+TEST(WebInputEventBuilderMacTest, TouchEventsWithPointerTypePenRotationLess90) {
+ NSEvent* mac_event =
+ BuildFakeMouseEvent(kCGEventLeftMouseDown, {6, 9}, kCGMouseButtonLeft,
+ kCGEventMouseSubtypeTabletPoint, 60.0);
+ // Create a dummy window, but don't show it. It will be released when closed.
+ NSWindow* window =
+ [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 100, 100)
+ styleMask:NSBorderlessWindowMask
+ backing:NSBackingStoreBuffered
+ defer:NO];
+ blink::WebTouchEvent touch_event =
+ content::WebTouchEventBuilder::Build(mac_event, [window contentView]);
+ EXPECT_EQ(60, touch_event.touches[0].twist);
+ EXPECT_EQ(60, touch_event.touches[0].rotation_angle);
+}
+
+// Test if the value of twist and rotation_angle are set correctly when the
+// NSEvent's rotation is between 90 and 180.
+TEST(WebInputEventBuilderMacTest,
+ TouchEventsWithPointerTypePenRotationLess180) {
+ NSEvent* mac_event =
+ BuildFakeMouseEvent(kCGEventLeftMouseDown, {6, 9}, kCGMouseButtonLeft,
+ kCGEventMouseSubtypeTabletPoint, 160.0);
+ // Create a dummy window, but don't show it. It will be released when closed.
+ NSWindow* window =
+ [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 100, 100)
+ styleMask:NSBorderlessWindowMask
+ backing:NSBackingStoreBuffered
+ defer:NO];
+ blink::WebTouchEvent touch_event =
+ content::WebTouchEventBuilder::Build(mac_event, [window contentView]);
+ EXPECT_EQ(160, touch_event.touches[0].twist);
+ EXPECT_EQ(20, touch_event.touches[0].rotation_angle);
+}
+
+// Test if the value of twist and rotation_angle are set correctly when the
+// NSEvent's rotation is between 180 and 360.
+TEST(WebInputEventBuilderMacTest,
+ TouchEventsWithPointerTypePenRotationLess360) {
+ NSEvent* mac_event =
+ BuildFakeMouseEvent(kCGEventLeftMouseDown, {6, 9}, kCGMouseButtonLeft,
+ kCGEventMouseSubtypeTabletPoint, 260.0);
+ // Create a dummy window, but don't show it. It will be released when closed.
+ NSWindow* window =
+ [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 100, 100)
+ styleMask:NSBorderlessWindowMask
+ backing:NSBackingStoreBuffered
+ defer:NO];
+ blink::WebTouchEvent touch_event =
+ content::WebTouchEventBuilder::Build(mac_event, [window contentView]);
+ EXPECT_EQ(260, touch_event.touches[0].twist);
+ EXPECT_EQ(80, touch_event.touches[0].rotation_angle);
+}
+
+// Test if the value of twist and rotation_angle are set correctly when the
+// NSEvent's rotation is greater than 360.
+TEST(WebInputEventBuilderMacTest,
+ TouchEventsWithPointerTypePenRotationGreater360) {
+ NSEvent* mac_event =
+ BuildFakeMouseEvent(kCGEventLeftMouseDown, {6, 9}, kCGMouseButtonLeft,
+ kCGEventMouseSubtypeTabletPoint, 390.0);
+ // Create a dummy window, but don't show it. It will be released when closed.
+ NSWindow* window =
+ [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 100, 100)
+ styleMask:NSBorderlessWindowMask
+ backing:NSBackingStoreBuffered
+ defer:NO];
+ blink::WebTouchEvent touch_event =
+ content::WebTouchEventBuilder::Build(mac_event, [window contentView]);
+ EXPECT_EQ(30, touch_event.touches[0].twist);
+ EXPECT_EQ(30, touch_event.touches[0].rotation_angle);
+}
+
+// Test if all the values of a WebTouchEvent are set correctly.
+TEST(WebInputEventBuilderMacTest, BuildWebTouchEvents) {
+ NSEvent* mac_event = BuildFakeMouseEvent(
+ kCGEventLeftMouseDown, {6, 9}, kCGMouseButtonLeft,
+ kCGEventMouseSubtypeTabletPoint, /* rotation */ 60.0,
+ /* pressure */ 0.3, /* tilt_x */ 0.5, /* tilt_y */ 0.6,
+ /* tangential_pressure */ 0.7);
+ // Create a dummy window, but don't show it. It will be released when closed.
+ NSWindow* window =
+ [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 100, 100)
+ styleMask:NSBorderlessWindowMask
+ backing:NSBackingStoreBuffered
+ defer:NO];
+ blink::WebTouchEvent touch_event =
+ content::WebTouchEventBuilder::Build(mac_event, [window contentView]);
+ EXPECT_EQ(blink::WebInputEvent::kTouchStart, touch_event.GetType());
+ EXPECT_FALSE(touch_event.hovering);
+ EXPECT_EQ(1U, touch_event.touches_length);
+ EXPECT_EQ(blink::WebFloatPoint(6, 9),
+ touch_event.touches[0].PositionInScreen());
+ EXPECT_EQ(blink::WebTouchPoint::kStatePressed, touch_event.touches[0].state);
+ EXPECT_EQ(blink::WebPointerProperties::PointerType::kPen,
+ touch_event.touches[0].pointer_type);
+ EXPECT_EQ(0, touch_event.touches[0].id);
+ EXPECT_FLOAT_EQ(0.3, std::round(touch_event.touches[0].force * 10) / 10);
+ EXPECT_EQ(0.5 * 90, touch_event.touches[0].tilt_x);
+ EXPECT_EQ(0.6 * 90, touch_event.touches[0].tilt_y);
+ EXPECT_FLOAT_EQ(
+ 0.7, std::round(touch_event.touches[0].tangential_pressure * 10) / 10);
+ EXPECT_EQ(60, touch_event.touches[0].twist);
+ EXPECT_FLOAT_EQ(60.0, touch_event.touches[0].rotation_angle);
+}
+#endif // MAC_OS_X_VERSION_10_12 \ No newline at end of file
diff --git a/chromium/content/browser/renderer_host/input/web_input_event_util_unittest.cc b/chromium/content/browser/renderer_host/input/web_input_event_util_unittest.cc
index 48b6e1e8d3f..ce88a3261db 100644
--- a/chromium/content/browser/renderer_host/input/web_input_event_util_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/web_input_event_util_unittest.cc
@@ -36,6 +36,8 @@ TEST(WebInputEventUtilTest, MotionEventConversion) {
pointer.orientation = -base::kPiFloat / 2;
pointer.tilt_x = 60;
pointer.tilt_y = 70;
+ pointer.twist = 160;
+ pointer.tangential_pressure = 0;
for (MotionEvent::ToolType tool_type : tool_types) {
pointer.tool_type = tool_type;
MotionEventGeneric event(MotionEvent::Action::DOWN, base::TimeTicks::Now(),
@@ -60,6 +62,8 @@ TEST(WebInputEventUtilTest, MotionEventConversion) {
if (tool_type == MotionEvent::ToolType::STYLUS) {
expected_pointer.tilt_x = 60;
expected_pointer.tilt_y = 70;
+ expected_pointer.twist = 160;
+ expected_pointer.tangential_pressure = 0;
} else {
expected_pointer.tilt_x = 0;
expected_pointer.tilt_y = 0;
diff --git a/chromium/content/browser/renderer_host/input/wheel_event_listener_browsertest.cc b/chromium/content/browser/renderer_host/input/wheel_event_listener_browsertest.cc
new file mode 100644
index 00000000000..d72cafc5941
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/wheel_event_listener_browsertest.cc
@@ -0,0 +1,135 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/test/scoped_feature_list.h"
+#include "content/browser/web_contents/web_contents_impl.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"
+#include "content/shell/browser/shell.h"
+#include "third_party/blink/public/platform/web_input_event.h"
+
+using blink::WebInputEvent;
+
+namespace {
+
+const std::string kWheelEventListenerDataURL = R"HTML(
+ <!DOCTYPE html>
+ <meta name='viewport' content='width=device-width'/>
+ <style>
+ html, body {
+ margin: 0;
+ }
+ .spacer { height: 10000px; }
+ </style>
+ <div class=spacer></div>
+ <script>
+ window.addEventListener('wheel', () => { while (true); });
+ document.title='ready';
+ </script>)HTML";
+
+const std::string kMouseWheelEventListenerDataURL = R"HTML(
+ <!DOCTYPE html>
+ <meta name='viewport' content='width=device-width'/>
+ <style>
+ html, body {
+ margin: 0;
+ }
+ .spacer { height: 10000px; }
+ </style>
+ <div class=spacer></div>
+ <script>
+ document.addEventListener('mousewheel', () => { while (true); });
+ document.title='ready';
+ </script>)HTML";
+} // namespace
+
+namespace content {
+
+class WheelEventListenerBrowserTest : public ContentBrowserTest {
+ public:
+ WheelEventListenerBrowserTest() {
+ feature_list_.InitWithFeatures(
+ {features::kPassiveDocumentWheelEventListeners}, {});
+ }
+ ~WheelEventListenerBrowserTest() override {}
+
+ protected:
+ RenderWidgetHostImpl* GetWidgetHost() {
+ return RenderWidgetHostImpl::From(
+ shell()->web_contents()->GetRenderViewHost()->GetWidget());
+ }
+
+ void LoadURL(const std::string& page_data) {
+ const GURL data_url("data:text/html," + page_data);
+ NavigateToURL(shell(), data_url);
+
+ RenderWidgetHostImpl* host = GetWidgetHost();
+ host->GetView()->SetSize(gfx::Size(400, 400));
+
+ base::string16 ready_title(base::ASCIIToUTF16("ready"));
+ TitleWatcher watcher(shell()->web_contents(), ready_title);
+ ignore_result(watcher.WaitAndGetTitle());
+
+ MainThreadFrameObserver main_thread_sync(host);
+ main_thread_sync.Wait();
+ }
+
+ void ScrollByMouseWheel() {
+ // Send a wheel event and wait for its ack.
+ auto wheel_msg_watcher = std::make_unique<InputMsgWatcher>(
+ GetWidgetHost(), blink::WebInputEvent::kMouseWheel);
+ double x = 10;
+ double y = 10;
+ blink::WebMouseWheelEvent wheel_event =
+ SyntheticWebMouseWheelEventBuilder::Build(x, y, x, y, -20, -20, 0,
+ true);
+ wheel_event.phase = blink::WebMouseWheelEvent::kPhaseBegan;
+ GetWidgetHost()->ForwardWheelEvent(wheel_event);
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING,
+ wheel_msg_watcher->WaitForAck());
+ }
+
+ void WaitForScroll() {
+ RenderFrameSubmissionObserver observer(
+ GetWidgetHost()->render_frame_metadata_provider());
+ gfx::Vector2dF default_scroll_offset;
+ while (observer.LastRenderFrameMetadata()
+ .root_scroll_offset.value_or(default_scroll_offset)
+ .y() <= 0) {
+ observer.WaitForMetadataChange();
+ }
+ }
+
+ private:
+ base::test::ScopedFeatureList feature_list_;
+ DISALLOW_COPY_AND_ASSIGN(WheelEventListenerBrowserTest);
+};
+
+IN_PROC_BROWSER_TEST_F(WheelEventListenerBrowserTest,
+ DocumentWheelEventListenersPassiveByDefault) {
+ LoadURL(kWheelEventListenerDataURL);
+
+ // Send a wheel event and wait for its ack.
+ ScrollByMouseWheel();
+
+ // Wait for the page to scroll, the test will timeout if the wheel event
+ // listener added to window is not treated as passive.
+ WaitForScroll();
+}
+
+IN_PROC_BROWSER_TEST_F(WheelEventListenerBrowserTest,
+ DocumentMouseWheelEventListenersPassiveByDefault) {
+ LoadURL(kMouseWheelEventListenerDataURL);
+
+ // Send a wheel event and wait for its ack.
+ ScrollByMouseWheel();
+
+ // Wait for the page to scroll, the test will timeout if the mousewheel event
+ // listener added to document is not treated as passive.
+ WaitForScroll();
+}
+
+} // namespace content \ No newline at end of file
diff --git a/chromium/content/browser/renderer_host/legacy_render_widget_host_win.cc b/chromium/content/browser/renderer_host/legacy_render_widget_host_win.cc
index 71f08b4a2bc..f80b0a6e812 100644
--- a/chromium/content/browser/renderer_host/legacy_render_widget_host_win.cc
+++ b/chromium/content/browser/renderer_host/legacy_render_widget_host_win.cc
@@ -139,11 +139,6 @@ void LegacyRenderWidgetHostHWND::SetBounds(const gfx::Rect& bounds) {
direct_manipulation_helper_->SetSize(bounds_in_pixel.size());
}
-void LegacyRenderWidgetHostHWND::MoveCaretTo(const gfx::Rect& bounds) {
- DCHECK(ax_system_caret_);
- ax_system_caret_->MoveCaretTo(bounds);
-}
-
void LegacyRenderWidgetHostHWND::OnFinalMessage(HWND hwnd) {
if (host_) {
host_->OnLegacyWindowDestroyed();
@@ -182,7 +177,7 @@ bool LegacyRenderWidgetHostHWND::Init() {
DCHECK(SUCCEEDED(hr));
ui::AXMode mode =
- BrowserAccessibilityStateImpl::GetInstance()->accessibility_mode();
+ BrowserAccessibilityStateImpl::GetInstance()->GetAccessibilityMode();
if (!mode.has_mode(ui::AXMode::kNativeAPIs)) {
// Attempt to detect screen readers or other clients who want full
// accessibility support, by seeing if they respond to this event.
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 79bad955ddc..1e154cbc424 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,15 +5,14 @@
#ifndef CONTENT_BROWSER_RENDERER_HOST_LEGACY_RENDER_WIDGET_HOST_WIN_H_
#define CONTENT_BROWSER_RENDERER_HOST_LEGACY_RENDER_WIDGET_HOST_WIN_H_
-#include <atlbase.h>
#include <atlcrack.h>
-#include <atlwin.h>
#include <oleacc.h>
#include <wrl/client.h>
#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"
@@ -124,9 +123,6 @@ class CONTENT_EXPORT LegacyRenderWidgetHostHWND
host_ = host;
}
- // Changes the position of the system caret used for accessibility.
- void MoveCaretTo(const gfx::Rect& bounds);
-
// DirectManipulation needs to poll for new events every frame while finger
// gesturing on touchpad.
void PollForNextEvent();
diff --git a/chromium/content/browser/renderer_host/media/audio_input_delegate_impl.cc b/chromium/content/browser/renderer_host/media/audio_input_delegate_impl.cc
index d01a24bd4bf..718bb1a6e5a 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_delegate_impl.cc
+++ b/chromium/content/browser/renderer_host/media/audio_input_delegate_impl.cc
@@ -192,9 +192,9 @@ AudioInputDelegateImpl::AudioInputDelegateImpl(
const std::string& device_id = device->id;
if (WebContentsMediaCaptureId::Parse(device_id, nullptr)) {
- // For MEDIA_DESKTOP_AUDIO_CAPTURE, the source is selected from picker
- // window, we do not mute the source audio.
- // For MEDIA_TAB_AUDIO_CAPTURE, the probable use case is Cast, we mute
+ // For MEDIA_GUM_DESKTOP_AUDIO_CAPTURE, the source is selected from
+ // picker window, we do not mute the source audio. For
+ // MEDIA_GUM_TAB_AUDIO_CAPTURE, the probable use case is Cast, we mute
// the source audio.
// TODO(qiangchen): Analyze audio constraints to make a duplicating or
// diverting decision. It would give web developer more flexibility.
@@ -206,7 +206,7 @@ AudioInputDelegateImpl::AudioInputDelegateImpl(
writer_.get(), user_input_monitor);
DCHECK(controller_);
// Only count for captures from desktop media picker dialog.
- if (device->type == MEDIA_DESKTOP_AUDIO_CAPTURE)
+ if (device->type == MEDIA_GUM_DESKTOP_AUDIO_CAPTURE)
IncrementDesktopCaptureCounter(TAB_AUDIO_CAPTURER_CREATED);
} else {
controller_ = media::AudioInputController::Create(
@@ -216,7 +216,7 @@ AudioInputDelegateImpl::AudioInputDelegateImpl(
// Only count for captures from desktop media picker dialog and system loop
// back audio.
- if (device->type == MEDIA_DESKTOP_AUDIO_CAPTURE &&
+ if (device->type == MEDIA_GUM_DESKTOP_AUDIO_CAPTURE &&
(media::AudioDeviceDescription::IsLoopbackDevice(device_id))) {
IncrementDesktopCaptureCounter(SYSTEM_LOOPBACK_AUDIO_CAPTURER_CREATED);
}
diff --git a/chromium/content/browser/renderer_host/media/audio_input_device_manager.cc b/chromium/content/browser/renderer_host/media/audio_input_device_manager.cc
index db018e66062..2e72505f818 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_device_manager.cc
+++ b/chromium/content/browser/renderer_host/media/audio_input_device_manager.cc
@@ -94,7 +94,7 @@ int AudioInputDeviceManager::Open(const MediaStreamDevice& device) {
base::Optional<media::AudioParameters>()));
} else {
// TODO(tommi): As is, we hit this code path when device.type is
- // MEDIA_TAB_AUDIO_CAPTURE and the device id is not a device that
+ // MEDIA_GUM_TAB_AUDIO_CAPTURE and the device id is not a device that
// the AudioManager can know about. This currently does not fail because
// the implementation of GetInputStreamParameters returns valid parameters
// by default for invalid devices. That behavior is problematic because it
diff --git a/chromium/content/browser/renderer_host/media/audio_input_device_manager.h b/chromium/content/browser/renderer_host/media/audio_input_device_manager.h
index b22666bf9af..2f20d07aebc 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_device_manager.h
+++ b/chromium/content/browser/renderer_host/media/audio_input_device_manager.h
@@ -111,7 +111,7 @@ class CONTENT_EXPORT AudioInputDeviceManager : public MediaStreamProvider {
MediaStreamDevices::iterator GetDevice(int session_id);
// Only accessed on Browser::IO thread.
- base::ObserverList<MediaStreamProviderListener> listeners_;
+ base::ObserverList<MediaStreamProviderListener>::Unchecked listeners_;
int next_capture_session_id_;
MediaStreamDevices devices_;
diff --git a/chromium/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc b/chromium/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc
index ffac149e26c..499484ab8b7 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc
@@ -50,7 +50,8 @@ class MockAudioInputDeviceManagerListener
// TODO(henrika): there are special restrictions for Android since
// AudioInputDeviceManager::Open() must be called on the audio thread.
// This test suite must be modified to run on Android.
-#if defined(OS_ANDROID)
+// Flaky on Linux. See http://crbug.com/867397.
+#if defined(OS_ANDROID) || defined(OS_LINUX)
#define MAYBE_AudioInputDeviceManagerTest DISABLED_AudioInputDeviceManagerTest
#else
#define MAYBE_AudioInputDeviceManagerTest AudioInputDeviceManagerTest
@@ -311,9 +312,9 @@ class AudioInputDeviceManagerNoDevicesTest
std::make_unique<media::AudioThreadImpl>());
// Devices to request from AudioInputDeviceManager.
- devices_.emplace_back(MEDIA_TAB_AUDIO_CAPTURE, "tab_capture",
+ devices_.emplace_back(MEDIA_GUM_TAB_AUDIO_CAPTURE, "tab_capture",
"Tab capture");
- devices_.emplace_back(MEDIA_DESKTOP_AUDIO_CAPTURE, "desktop_capture",
+ devices_.emplace_back(MEDIA_GUM_DESKTOP_AUDIO_CAPTURE, "desktop_capture",
"Desktop capture");
devices_.emplace_back(MEDIA_DEVICE_AUDIO_CAPTURE, "fake_device",
"Fake Device");
diff --git a/chromium/content/browser/renderer_host/media/audio_output_authorization_handler.cc b/chromium/content/browser/renderer_host/media/audio_output_authorization_handler.cc
index 239c8be2a1e..5d888b45bed 100644
--- a/chromium/content/browser/renderer_host/media/audio_output_authorization_handler.cc
+++ b/chromium/content/browser/renderer_host/media/audio_output_authorization_handler.cc
@@ -254,8 +254,8 @@ void AudioOutputAuthorizationHandler::AccessChecked(
media_stream_manager_->media_devices_manager()->EnumerateDevices(
devices_to_enumerate,
base::BindOnce(&AudioOutputAuthorizationHandler::TranslateDeviceID,
- weak_factory_.GetWeakPtr(), base::Passed(&trace_scope),
- base::Passed(&cb), device_id, std::move(salt),
+ weak_factory_.GetWeakPtr(), std::move(trace_scope),
+ std::move(cb), device_id, std::move(salt),
std::move(security_origin)));
}
diff --git a/chromium/content/browser/renderer_host/media/audio_output_authorization_handler_unittest.cc b/chromium/content/browser/renderer_host/media/audio_output_authorization_handler_unittest.cc
index 5a72602b62c..15a70a66df8 100644
--- a/chromium/content/browser/renderer_host/media/audio_output_authorization_handler_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/audio_output_authorization_handler_unittest.cc
@@ -167,7 +167,7 @@ class AudioOutputAuthorizationHandlerTest : public RenderViewHostTestHarness {
media_stream_manager_->media_devices_manager()->EnumerateDevices(
devices_to_enumerate,
- base::Bind(
+ base::BindOnce(
[](std::string* out, const MediaDeviceEnumeration& result) {
// Index 0 is default, so use 1.
CHECK(result[MediaDeviceType::MEDIA_DEVICE_TYPE_AUDIO_OUTPUT]
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 62a7132a451..ac462bdb117 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
@@ -129,6 +129,7 @@ class DummyMojoAudioLogImpl : public media::mojom::AudioLog {
void OnClosed() override {}
void OnError() override {}
void OnSetVolume(double volume) override {}
+ void OnProcessingStateChanged(const std::string& message) override {}
void OnLogMessage(const std::string& message) override {}
};
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 a97377898da..2a7a25a0255 100644
--- a/chromium/content/browser/renderer_host/media/audio_service_listener.cc
+++ b/chromium/content/browser/renderer_host/media/audio_service_listener.cc
@@ -182,7 +182,7 @@ void AudioServiceListener::OnServiceStopped(
void AudioServiceListener::BrowserChildProcessHostDisconnected(
const ChildProcessData& data) {
DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
- if (base::GetProcId(data.handle) != process_id_)
+ if (base::GetProcId(data.GetHandle()) != process_id_)
return;
process_id_ = base::kNullProcessId;
metrics_.ServiceProcessTerminated(
@@ -193,7 +193,7 @@ void AudioServiceListener::BrowserChildProcessCrashed(
const ChildProcessData& data,
const ChildProcessTerminationInfo& info) {
DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
- if (base::GetProcId(data.handle) != process_id_)
+ if (base::GetProcId(data.GetHandle()) != process_id_)
return;
process_id_ = base::kNullProcessId;
metrics_.ServiceProcessTerminated(
@@ -204,7 +204,7 @@ void AudioServiceListener::BrowserChildProcessKilled(
const ChildProcessData& data,
const ChildProcessTerminationInfo& info) {
DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
- if (base::GetProcId(data.handle) != process_id_)
+ if (base::GetProcId(data.GetHandle()) != process_id_)
return;
process_id_ = base::kNullProcessId;
metrics_.ServiceProcessTerminated(
diff --git a/chromium/content/browser/renderer_host/media/audio_service_listener_unittest.cc b/chromium/content/browser/renderer_host/media/audio_service_listener_unittest.cc
index d6a66a9d5b4..d43d2541a02 100644
--- a/chromium/content/browser/renderer_host/media/audio_service_listener_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/audio_service_listener_unittest.cc
@@ -194,7 +194,7 @@ TEST(AudioServiceListenerTest,
MakeTestServiceInfo(audio_service_identity, pid));
audio_service_listener.OnServiceStarted(audio_service_identity, pid);
ChildProcessData data(content::ProcessType::PROCESS_TYPE_UTILITY);
- data.handle = handle;
+ data.SetHandle(handle);
audio_service_listener.BrowserChildProcessHostDisconnected(data);
histogram_tester.ExpectUniqueSample(
"Media.AudioService.ObservedProcessTerminationStatus",
@@ -215,7 +215,7 @@ TEST(AudioServiceListenerTest,
MakeTestServiceInfo(audio_service_identity, pid));
audio_service_listener.OnServiceStarted(audio_service_identity, pid);
ChildProcessData data(content::ProcessType::PROCESS_TYPE_UTILITY);
- data.handle = handle;
+ data.SetHandle(handle);
audio_service_listener.BrowserChildProcessCrashed(
data, content::ChildProcessTerminationInfo());
histogram_tester.ExpectUniqueSample(
@@ -236,7 +236,7 @@ TEST(AudioServiceListenerTest,
MakeTestServiceInfo(audio_service_identity, pid));
audio_service_listener.OnServiceStarted(audio_service_identity, pid);
ChildProcessData data(content::ProcessType::PROCESS_TYPE_UTILITY);
- data.handle = handle;
+ data.SetHandle(handle);
audio_service_listener.BrowserChildProcessKilled(
data, content::ChildProcessTerminationInfo());
histogram_tester.ExpectUniqueSample(
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 77742e8cd19..ffa3e8c0062 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
@@ -4,6 +4,10 @@
#include "content/browser/renderer_host/media/in_process_video_capture_device_launcher.h"
+#include <utility>
+#include <vector>
+
+#include "base/command_line.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/stringprintf.h"
#include "build/build_config.h"
@@ -11,8 +15,12 @@
#include "content/browser/renderer_host/media/video_capture_controller.h"
#include "content/browser/renderer_host/media/video_capture_dependencies.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/desktop_media_id.h"
#include "content/public/common/media_stream_request.h"
#include "media/base/bind_to_current_loop.h"
+#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/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"
@@ -22,7 +30,6 @@
#if defined(ENABLE_SCREEN_CAPTURE)
#include "content/browser/media/capture/desktop_capture_device_uma_types.h"
-#include "content/public/browser/desktop_media_id.h"
#if defined(OS_ANDROID)
#include "content/browser/media/capture/screen_capture_device_android.h"
#else
@@ -123,7 +130,7 @@ void InProcessVideoCaptureDeviceLauncher::LaunchDeviceAsync(
#if defined(ENABLE_SCREEN_CAPTURE)
#if !defined(OS_ANDROID)
- case MEDIA_TAB_VIDEO_CAPTURE:
+ case MEDIA_GUM_TAB_VIDEO_CAPTURE:
start_capture_closure = base::BindOnce(
&InProcessVideoCaptureDeviceLauncher::DoStartTabCaptureOnDeviceThread,
base::Unretained(this), device_id, params, std::move(receiver),
@@ -131,7 +138,9 @@ void InProcessVideoCaptureDeviceLauncher::LaunchDeviceAsync(
break;
#endif // !defined(OS_ANDROID)
- case MEDIA_DESKTOP_VIDEO_CAPTURE: {
+ case MEDIA_GUM_DESKTOP_VIDEO_CAPTURE:
+ FALLTHROUGH;
+ case MEDIA_DISPLAY_VIDEO_CAPTURE: {
const DesktopMediaID desktop_id = DesktopMediaID::Parse(device_id);
if (desktop_id.is_null()) {
DLOG(ERROR) << "Desktop media ID is null";
@@ -140,6 +149,18 @@ void InProcessVideoCaptureDeviceLauncher::LaunchDeviceAsync(
break;
}
+ if (desktop_id.id == DesktopMediaID::kFakeId) {
+ start_capture_closure = base::BindOnce(
+ &InProcessVideoCaptureDeviceLauncher::
+ DoStartFakeDisplayCaptureOnDeviceThread,
+ base::Unretained(this), desktop_id, params,
+ CreateDeviceClient(media::VideoCaptureBufferType::kSharedMemory,
+ kMaxNumberOfBuffers, std::move(receiver),
+ std::move(receiver_on_io_thread)),
+ std::move(after_start_capture_callback));
+ break;
+ }
+
#if !defined(OS_ANDROID)
if (desktop_id.type == DesktopMediaID::TYPE_WEB_CONTENTS) {
after_start_capture_callback = base::BindOnce(
@@ -240,7 +261,9 @@ void InProcessVideoCaptureDeviceLauncher::OnDeviceStarted(
if (!device) {
switch (state_copy) {
case State::DEVICE_START_IN_PROGRESS:
- callbacks->OnDeviceLaunchFailed();
+ callbacks->OnDeviceLaunchFailed(
+ media::VideoCaptureError::
+ kInProcessDeviceLauncherFailedToCreateDeviceInstance);
base::ResetAndReturn(&done_cb).Run();
return;
case State::DEVICE_START_ABORTING:
@@ -369,4 +392,40 @@ void InProcessVideoCaptureDeviceLauncher::DoStartDesktopCaptureOnDeviceThread(
#endif // defined(ENABLE_SCREEN_CAPTURE)
+void InProcessVideoCaptureDeviceLauncher::
+ DoStartFakeDisplayCaptureOnDeviceThread(
+ const DesktopMediaID& desktop_id,
+ const media::VideoCaptureParams& params,
+ std::unique_ptr<media::VideoCaptureDeviceClient> device_client,
+ ReceiveDeviceCallback result_callback) {
+ DCHECK(device_task_runner_->BelongsToCurrentThread());
+ DCHECK_EQ(DesktopMediaID::kFakeId, desktop_id.id);
+
+ auto fake_device_factory =
+ std::make_unique<media::FakeVideoCaptureDeviceFactory>();
+ const base::CommandLine* command_line =
+ base::CommandLine::ForCurrentProcess();
+ if (command_line &&
+ command_line->HasSwitch(switches::kUseFakeDeviceForMediaStream)) {
+ std::vector<media::FakeVideoCaptureDeviceSettings> config;
+ media::FakeVideoCaptureDeviceFactory::
+ ParseFakeDevicesConfigFromOptionsString(
+ command_line->GetSwitchValueASCII(
+ switches::kUseFakeDeviceForMediaStream),
+ &config);
+ fake_device_factory->SetToCustomDevicesConfig(config);
+ }
+ media::VideoCaptureDeviceDescriptors device_descriptors;
+ fake_device_factory->GetDeviceDescriptors(&device_descriptors);
+ if (device_descriptors.empty()) {
+ LOG(ERROR) << "Cannot start with no fake device config";
+ std::move(result_callback).Run(nullptr);
+ return;
+ }
+ auto video_capture_device =
+ fake_device_factory->CreateDevice(device_descriptors.front());
+ video_capture_device->AllocateAndStart(params, std::move(device_client));
+ std::move(result_callback).Run(std::move(video_capture_device));
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/in_process_video_capture_device_launcher.h b/chromium/content/browser/renderer_host/media/in_process_video_capture_device_launcher.h
index ce862c58484..67c77f9a050 100644
--- a/chromium/content/browser/renderer_host/media/in_process_video_capture_device_launcher.h
+++ b/chromium/content/browser/renderer_host/media/in_process_video_capture_device_launcher.h
@@ -5,6 +5,9 @@
#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_IN_PROCESS_VIDEO_CAPTURE_DEVICE_LAUNCHER_H_
#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_IN_PROCESS_VIDEO_CAPTURE_DEVICE_LAUNCHER_H_
+#include <memory>
+#include <string>
+
#include "base/single_thread_task_runner.h"
#include "content/browser/renderer_host/media/video_capture_controller.h"
#include "content/browser/renderer_host/media/video_capture_provider.h"
@@ -84,6 +87,12 @@ class InProcessVideoCaptureDeviceLauncher : public VideoCaptureDeviceLauncher {
std::unique_ptr<media::VideoCaptureDeviceClient> client,
ReceiveDeviceCallback result_callback);
+ void DoStartFakeDisplayCaptureOnDeviceThread(
+ const DesktopMediaID& desktop_id,
+ const media::VideoCaptureParams& params,
+ std::unique_ptr<media::VideoCaptureDeviceClient> client,
+ ReceiveDeviceCallback result_callback);
+
const scoped_refptr<base::SingleThreadTaskRunner> device_task_runner_;
media::VideoCaptureSystem* const video_capture_system_;
State state_;
diff --git a/chromium/content/browser/renderer_host/media/media_devices_dispatcher_host.cc b/chromium/content/browser/renderer_host/media/media_devices_dispatcher_host.cc
index c87ff868818..1812e217cec 100644
--- a/chromium/content/browser/renderer_host/media/media_devices_dispatcher_host.cc
+++ b/chromium/content/browser/renderer_host/media/media_devices_dispatcher_host.cc
@@ -207,7 +207,7 @@ void MediaDevicesDispatcherHost::GotDefaultVideoInputDeviceID(
requested_types,
base::BindOnce(
&MediaDevicesDispatcherHost::FinalizeGetVideoInputCapabilities,
- weak_factory_.GetWeakPtr(), base::Passed(&client_callback),
+ weak_factory_.GetWeakPtr(), std::move(client_callback),
std::move(salt_and_origin), std::move(default_device_id)));
}
diff --git a/chromium/content/browser/renderer_host/media/media_devices_dispatcher_host_unittest.cc b/chromium/content/browser/renderer_host/media/media_devices_dispatcher_host_unittest.cc
index 228ef4575cb..1d705047016 100644
--- a/chromium/content/browser/renderer_host/media/media_devices_dispatcher_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/media_devices_dispatcher_host_unittest.cc
@@ -149,8 +149,8 @@ class MediaDevicesDispatcherHostTest : public testing::TestWithParam<GURL> {
devices_to_enumerate[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT] = true;
media_stream_manager_->media_devices_manager()->EnumerateDevices(
devices_to_enumerate,
- base::Bind(&PhysicalDevicesEnumerated, run_loop.QuitClosure(),
- &physical_devices_));
+ base::BindOnce(&PhysicalDevicesEnumerated, run_loop.QuitClosure(),
+ &physical_devices_));
run_loop.Run();
ASSERT_GT(physical_devices_[MEDIA_DEVICE_TYPE_AUDIO_INPUT].size(), 0u);
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 c9fcb5e765b..307115c6d57 100644
--- a/chromium/content/browser/renderer_host/media/media_devices_manager.cc
+++ b/chromium/content/browser/renderer_host/media/media_devices_manager.cc
@@ -666,7 +666,7 @@ void MediaDevicesManager::OnPermissionsCheckDone(
internal_requested_types,
base::BindOnce(&MediaDevicesManager::OnDevicesEnumerated,
weak_factory_.GetWeakPtr(), requested_types,
- request_video_input_capabilities, base::Passed(&callback),
+ request_video_input_capabilities, std::move(callback),
std::move(salt_and_origin), has_permissions));
}
@@ -693,7 +693,7 @@ void MediaDevicesManager::OnDevicesEnumerated(
}
}
- std::move(callback).Run(std::move(result),
+ std::move(callback).Run(result,
video_input_capabilities_requested
? ComputeVideoInputCapabilities(
enumeration[MEDIA_DEVICE_TYPE_VIDEO_INPUT],
@@ -829,7 +829,10 @@ void MediaDevicesManager::UpdateSnapshot(
if (old_snapshot.size() != new_snapshot.size() ||
!std::equal(new_snapshot.begin(), new_snapshot.end(),
old_snapshot.begin(),
- ignore_group_id ? operator== : EqualDeviceAndGroupID)) {
+ ignore_group_id
+ ? [](const MediaDeviceInfo& lhs,
+ const MediaDeviceInfo& rhs) { return lhs == rhs; }
+ : EqualDeviceAndGroupID)) {
// Prevent sending notifications until group IDs are updated using
// a heuristic in ProcessRequests().
// TODO(crbug.com/627793): Remove |is_video_with_group_ids| and the
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 688ce189a4a..a1cd9c20c51 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
@@ -185,7 +185,7 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost,
void OnDeviceStoppedInternal(const std::string& label,
const MediaStreamDevice& device) {
- if (IsVideoMediaType(device.type))
+ if (IsVideoInputMediaType(device.type))
EXPECT_TRUE(device.IsSameDevice(video_devices_[0]));
if (IsAudioInputMediaType(device.type))
EXPECT_TRUE(device.IsSameDevice(audio_devices_[0]));
@@ -298,8 +298,8 @@ class MediaStreamDispatcherHostTest : public testing::Test {
devices_to_enumerate[MEDIA_DEVICE_TYPE_AUDIO_INPUT] = true;
media_stream_manager_->media_devices_manager()->EnumerateDevices(
devices_to_enumerate,
- base::Bind(&AudioInputDevicesEnumerated, run_loop.QuitClosure(),
- &audio_device_descriptions_));
+ base::BindOnce(&AudioInputDevicesEnumerated, run_loop.QuitClosure(),
+ &audio_device_descriptions_));
run_loop.Run();
ASSERT_GT(audio_device_descriptions_.size(), 0u);
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 71f785312be..a154e72ac00 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_manager.cc
+++ b/chromium/content/browser/renderer_host/media/media_stream_manager.cc
@@ -10,6 +10,7 @@
#include <algorithm>
#include <cctype>
#include <list>
+#include <vector>
#include "base/bind.h"
#include "base/command_line.h"
@@ -27,7 +28,6 @@
#include "base/threading/thread_local.h"
#include "build/build_config.h"
#include "content/browser/child_process_security_policy_impl.h"
-#include "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
#include "content/browser/gpu/gpu_process_host.h"
#include "content/browser/renderer_host/media/audio_input_device_manager.h"
#include "content/browser/renderer_host/media/audio_service_listener.h"
@@ -43,6 +43,7 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/desktop_media_id.h"
+#include "content/public/browser/desktop_streams_registry.h"
#include "content/public/browser/media_observer.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents_media_capture_id.h"
@@ -56,6 +57,8 @@
#include "media/base/channel_layout.h"
#include "media/base/media_switches.h"
#include "media/capture/video/create_video_capture_device_factory.h"
+#include "media/capture/video/fake_video_capture_device.h"
+#include "media/capture/video/fake_video_capture_device_factory.h"
#include "media/capture/video/video_capture_system_impl.h"
#include "services/video_capture/public/uma/video_capture_service_event.h"
#include "url/gurl.h"
@@ -67,6 +70,7 @@
#if defined(OS_CHROMEOS)
#include "chromeos/audio/cras_audio_handler.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"
#include "media/capture/video/chromeos/video_capture_device_factory_chromeos.h"
@@ -100,47 +104,6 @@ std::string RandomLabel() {
return label;
}
-void ParseStreamType(const StreamControls& controls,
- MediaStreamType* audio_type,
- MediaStreamType* video_type) {
- *audio_type = MEDIA_NO_SERVICE;
- *video_type = MEDIA_NO_SERVICE;
- const bool audio_support_flag_for_desktop_share =
- !base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableAudioSupportForDesktopShare);
- if (controls.audio.requested) {
- if (!controls.audio.stream_source.empty()) {
- // This is tab or screen capture.
- if (controls.audio.stream_source == kMediaStreamSourceTab) {
- *audio_type = MEDIA_TAB_AUDIO_CAPTURE;
- } else if (controls.audio.stream_source == kMediaStreamSourceSystem) {
- *audio_type = MEDIA_DESKTOP_AUDIO_CAPTURE;
- } else if (audio_support_flag_for_desktop_share &&
- controls.audio.stream_source == kMediaStreamSourceDesktop) {
- *audio_type = MEDIA_DESKTOP_AUDIO_CAPTURE;
- }
- } else {
- // This is normal audio device capture.
- *audio_type = MEDIA_DEVICE_AUDIO_CAPTURE;
- }
- }
- if (controls.video.requested) {
- if (!controls.video.stream_source.empty()) {
- // This is tab or screen capture.
- if (controls.video.stream_source == kMediaStreamSourceTab) {
- *video_type = MEDIA_TAB_VIDEO_CAPTURE;
- } else if (controls.video.stream_source == kMediaStreamSourceScreen) {
- *video_type = MEDIA_DESKTOP_VIDEO_CAPTURE;
- } else if (controls.video.stream_source == kMediaStreamSourceDesktop) {
- *video_type = MEDIA_DESKTOP_VIDEO_CAPTURE;
- }
- } else {
- // This is normal video device capture.
- *video_type = MEDIA_DEVICE_VIDEO_CAPTURE;
- }
- }
-}
-
// Turns off available audio effects (removes the flag) if the options
// explicitly turn them off.
void FilterAudioEffects(const StreamControls& controls, int* effects) {
@@ -216,6 +179,59 @@ void SendVideoCaptureLogMessage(const std::string& message) {
MediaStreamManager::SendMessageToNativeLog("video capture: " + message);
}
+MediaStreamType AdjustAudioStreamTypeBasedOnCommandLineSwitches(
+ MediaStreamType stream_type) {
+ if (stream_type != MEDIA_GUM_DESKTOP_AUDIO_CAPTURE)
+ return stream_type;
+ const bool audio_support_flag_for_desktop_share =
+ !base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableAudioSupportForDesktopShare);
+ return audio_support_flag_for_desktop_share ? MEDIA_GUM_DESKTOP_AUDIO_CAPTURE
+ : MEDIA_NO_SERVICE;
+}
+
+// Returns DesktopMediaID with fake initializers if
+// |kUseFakeDeviceForMediaStream| is set. Returns the default DesktopMediaID
+// otherwise.
+DesktopMediaID FindDesktopMediaIDFromFakeDeviceConfig() {
+ // TODO(emircan): When getDisplayMedia() accepts constraints, pick
+ // the corresponding type.
+ DesktopMediaID media_id =
+ DesktopMediaID(DesktopMediaID::TYPE_SCREEN, DesktopMediaID::kNullId);
+
+ const base::CommandLine* command_line =
+ base::CommandLine::ForCurrentProcess();
+ if (command_line &&
+ command_line->HasSwitch(switches::kUseFakeDeviceForMediaStream)) {
+ std::vector<media::FakeVideoCaptureDeviceSettings> config;
+ media::FakeVideoCaptureDeviceFactory::
+ ParseFakeDevicesConfigFromOptionsString(
+ command_line->GetSwitchValueASCII(
+ switches::kUseFakeDeviceForMediaStream),
+ &config);
+ if (config.empty())
+ return media_id;
+
+ DesktopMediaID::Type desktop_media_type = DesktopMediaID::TYPE_NONE;
+ switch (config[0].display_media_type) {
+ case media::FakeVideoCaptureDevice::DisplayMediaType::ANY:
+ desktop_media_type = DesktopMediaID::TYPE_SCREEN;
+ break;
+ case media::FakeVideoCaptureDevice::DisplayMediaType::MONITOR:
+ desktop_media_type = DesktopMediaID::TYPE_SCREEN;
+ break;
+ case media::FakeVideoCaptureDevice::DisplayMediaType::WINDOW:
+ desktop_media_type = DesktopMediaID::TYPE_WINDOW;
+ break;
+ case media::FakeVideoCaptureDevice::DisplayMediaType::BROWSER:
+ desktop_media_type = DesktopMediaID::TYPE_WEB_CONTENTS;
+ break;
+ }
+ media_id = DesktopMediaID(desktop_media_type, DesktopMediaID::kFakeId);
+ }
+ return media_id;
+}
+
} // namespace
// MediaStreamManager::DeviceRequest represents a request to either enumerate
@@ -259,7 +275,7 @@ class MediaStreamManager::DeviceRequest {
MediaStreamType audio_type() const { return audio_type_; }
void SetVideoType(MediaStreamType video_type) {
- DCHECK(IsVideoMediaType(video_type) || video_type == MEDIA_NO_SERVICE);
+ DCHECK(IsVideoInputMediaType(video_type) || video_type == MEDIA_NO_SERVICE);
video_type_ = video_type;
}
@@ -466,7 +482,7 @@ MediaStreamManager::MediaStreamManager(
#if defined(OS_CHROMEOS)
if (media::ShouldUseCrosCameraService()) {
media::VideoCaptureDeviceFactoryChromeOS::SetGpuBufferManager(
- BrowserGpuMemoryBufferManager::current());
+ GpuMemoryBufferManagerSingleton::GetInstance());
media::CameraHalDispatcherImpl::GetInstance()->Start(
base::BindRepeating(
&VideoCaptureDependencies::CreateJpegDecodeAccelerator),
@@ -588,7 +604,7 @@ std::string MediaStreamManager::MakeMediaAccessRequest(
// MediaStreamManager is deleted on the UI thread, after the IO thread has
// been stopped.
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(&MediaStreamManager::SetupRequest,
+ base::BindOnce(&MediaStreamManager::SetUpRequest,
base::Unretained(this), label));
return label;
}
@@ -632,7 +648,7 @@ void MediaStreamManager::GenerateStream(
// MediaStreamManager is deleted on the UI thread, after the IO thread has
// been stopped.
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(&MediaStreamManager::SetupRequest,
+ base::BindOnce(&MediaStreamManager::SetUpRequest,
base::Unretained(this), label));
}
@@ -809,9 +825,11 @@ void MediaStreamManager::OpenDevice(int render_process_id,
StreamControls controls;
if (IsAudioInputMediaType(type)) {
controls.audio.requested = true;
+ controls.audio.stream_type = type;
controls.audio.device_id = device_id;
- } else if (IsVideoMediaType(type)) {
+ } else if (IsVideoInputMediaType(type)) {
controls.video.requested = true;
+ controls.video.stream_type = type;
controls.video.device_id = device_id;
} else {
NOTREACHED();
@@ -830,7 +848,7 @@ void MediaStreamManager::OpenDevice(int render_process_id,
// MediaStreamManager is deleted on the UI thread, after the IO thread has
// been stopped.
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(&MediaStreamManager::SetupRequest,
+ base::BindOnce(&MediaStreamManager::SetUpRequest,
base::Unretained(this), label));
}
@@ -968,8 +986,9 @@ void MediaStreamManager::StartEnumeration(DeviceRequest* request,
devices_to_enumerate[MEDIA_DEVICE_TYPE_VIDEO_INPUT] = request_video_input;
media_devices_manager_->EnumerateDevices(
devices_to_enumerate,
- base::Bind(&MediaStreamManager::DevicesEnumerated, base::Unretained(this),
- request_audio_input, request_video_input, label));
+ base::BindOnce(&MediaStreamManager::DevicesEnumerated,
+ base::Unretained(this), request_audio_input,
+ request_video_input, label));
}
std::string MediaStreamManager::AddRequest(DeviceRequest* request) {
@@ -1016,10 +1035,11 @@ void MediaStreamManager::ReadOutputParamsAndPostRequestToUI(
const MediaDeviceEnumeration& enumeration) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- // Actual audio parameters are required only for MEDIA_TAB_AUDIO_CAPTURE.
- // TODO(guidou): MEDIA_TAB_AUDIO_CAPTURE should not be a special case. See
- // crbug.com/584287.
- if (request->audio_type() == MEDIA_TAB_AUDIO_CAPTURE) {
+ // Actual audio parameters are required only for
+ // MEDIA_GUM_TAB_AUDIO_CAPTURE.
+ // TODO(guidou): MEDIA_GUM_TAB_AUDIO_CAPTURE should not be a special
+ // case. See https://crbug.com/584287.
+ if (request->audio_type() == MEDIA_GUM_TAB_AUDIO_CAPTURE) {
// Using base::Unretained is safe: |audio_system_| will post
// PostRequestToUI() to IO thread, and MediaStreamManager is deleted on the
// UI thread, after the IO thread has been stopped.
@@ -1052,14 +1072,14 @@ void MediaStreamManager::PostRequestToUI(
// Post the request to UI and set the state.
if (IsAudioInputMediaType(audio_type))
request->SetState(audio_type, MEDIA_REQUEST_STATE_PENDING_APPROVAL);
- if (IsVideoMediaType(video_type))
+ if (IsVideoInputMediaType(video_type))
request->SetState(video_type, MEDIA_REQUEST_STATE_PENDING_APPROVAL);
// If using the fake UI, it will just auto-select from the available devices.
// The fake UI doesn't work for desktop sharing requests since we can't see
// its devices from here; always use the real UI for such requests.
if (fake_ui_factory_ &&
- request->video_type() != MEDIA_DESKTOP_VIDEO_CAPTURE) {
+ request->video_type() != MEDIA_GUM_DESKTOP_VIDEO_CAPTURE) {
MediaStreamDevices devices = ConvertToMediaStreamDevices(
request->audio_type(), enumeration[MEDIA_DEVICE_TYPE_AUDIO_INPUT]);
MediaStreamDevices video_devices = ConvertToMediaStreamDevices(
@@ -1067,6 +1087,13 @@ void MediaStreamManager::PostRequestToUI(
devices.reserve(devices.size() + video_devices.size());
devices.insert(devices.end(), video_devices.begin(), video_devices.end());
+ if (request->video_type() == MEDIA_DISPLAY_VIDEO_CAPTURE) {
+ DCHECK(devices.empty());
+ DesktopMediaID media_id = FindDesktopMediaIDFromFakeDeviceConfig();
+ devices.push_back(MediaStreamDevice(MEDIA_DISPLAY_VIDEO_CAPTURE,
+ media_id.ToString(),
+ media_id.ToString()));
+ }
std::unique_ptr<FakeMediaStreamUIProxy> fake_ui = fake_ui_factory_.Run();
fake_ui->SetAvailableDevices(devices);
@@ -1083,42 +1110,51 @@ void MediaStreamManager::PostRequestToUI(
media::AudioParameters::UnavailableDeviceParams())));
}
-void MediaStreamManager::SetupRequest(const std::string& label) {
+void MediaStreamManager::SetUpRequest(const std::string& label) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DeviceRequest* request = FindRequest(label);
if (!request) {
- DVLOG(1) << "SetupRequest label " << label << " doesn't exist!!";
+ DVLOG(1) << "SetUpRequest label " << label << " doesn't exist!!";
return; // This can happen if the request has been canceled.
}
- MediaStreamType audio_type = MEDIA_NO_SERVICE;
- MediaStreamType video_type = MEDIA_NO_SERVICE;
- ParseStreamType(request->controls, &audio_type, &video_type);
- request->SetAudioType(audio_type);
- request->SetVideoType(video_type);
+ request->SetAudioType(AdjustAudioStreamTypeBasedOnCommandLineSwitches(
+ request->controls.audio.stream_type));
+ request->SetVideoType(request->controls.video.stream_type);
- const bool is_web_contents_capture = audio_type == MEDIA_TAB_AUDIO_CAPTURE ||
- video_type == MEDIA_TAB_VIDEO_CAPTURE;
- if (is_web_contents_capture && !SetupTabCaptureRequest(request)) {
- FinalizeRequestFailed(label, request, MEDIA_DEVICE_TAB_CAPTURE_FAILURE);
+ const bool is_display_capture =
+ request->video_type() == MEDIA_DISPLAY_VIDEO_CAPTURE;
+ if (is_display_capture && !SetUpDisplayCaptureRequest(request)) {
+ FinalizeRequestFailed(label, request, MEDIA_DEVICE_SCREEN_CAPTURE_FAILURE);
+ return;
+ }
+
+ const bool is_tab_capture =
+ request->audio_type() == MEDIA_GUM_TAB_AUDIO_CAPTURE ||
+ request->video_type() == MEDIA_GUM_TAB_VIDEO_CAPTURE;
+ if (is_tab_capture) {
+ if (!SetUpTabCaptureRequest(request, label)) {
+ FinalizeRequestFailed(label, request, MEDIA_DEVICE_TAB_CAPTURE_FAILURE);
+ }
return;
}
- const bool is_screen_capture = video_type == MEDIA_DESKTOP_VIDEO_CAPTURE;
- if (is_screen_capture && !SetupScreenCaptureRequest(request)) {
+ const bool is_screen_capture =
+ request->video_type() == MEDIA_GUM_DESKTOP_VIDEO_CAPTURE;
+ if (is_screen_capture && !SetUpScreenCaptureRequest(request)) {
FinalizeRequestFailed(label, request, MEDIA_DEVICE_SCREEN_CAPTURE_FAILURE);
return;
}
- if (!is_web_contents_capture && !is_screen_capture) {
- if (audio_type == MEDIA_DEVICE_AUDIO_CAPTURE ||
- video_type == MEDIA_DEVICE_VIDEO_CAPTURE) {
+ if (!is_tab_capture && !is_screen_capture && !is_display_capture) {
+ if (IsDeviceMediaType(request->audio_type()) ||
+ IsDeviceMediaType(request->video_type())) {
StartEnumeration(request, label);
return;
}
// If no actual device capture is requested, set up the request with an
// empty device list.
- if (!SetupDeviceCaptureRequest(request, MediaDeviceEnumeration())) {
+ if (!SetUpDeviceCaptureRequest(request, MediaDeviceEnumeration())) {
FinalizeRequestFailed(label, request, MEDIA_DEVICE_NO_HARDWARE);
return;
}
@@ -1126,7 +1162,27 @@ void MediaStreamManager::SetupRequest(const std::string& label) {
ReadOutputParamsAndPostRequestToUI(label, request, MediaDeviceEnumeration());
}
-bool MediaStreamManager::SetupDeviceCaptureRequest(
+bool MediaStreamManager::SetUpDisplayCaptureRequest(DeviceRequest* request) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(request->video_type() == MEDIA_DISPLAY_VIDEO_CAPTURE);
+
+ // getDisplayMedia function does not permit the use of constraints for
+ // selection of a source, see
+ // https://w3c.github.io/mediacapture-screen-share/#constraints.
+ if (!request->controls.video.requested ||
+ !request->controls.video.device_id.empty()) {
+ LOG(ERROR) << "Invalid display media request.";
+ return false;
+ }
+
+ request->CreateUIRequest(std::string() /* requested_audio_device_id */,
+ std::string() /* requested_video_device_id */);
+ DVLOG(3) << "Audio requested " << request->controls.audio.requested
+ << " Video requested " << request->controls.video.requested;
+ return true;
+}
+
+bool MediaStreamManager::SetUpDeviceCaptureRequest(
DeviceRequest* request,
const MediaDeviceEnumeration& enumeration) {
DCHECK((request->audio_type() == MEDIA_DEVICE_AUDIO_CAPTURE ||
@@ -1156,9 +1212,10 @@ bool MediaStreamManager::SetupDeviceCaptureRequest(
return true;
}
-bool MediaStreamManager::SetupTabCaptureRequest(DeviceRequest* request) {
- DCHECK(request->audio_type() == MEDIA_TAB_AUDIO_CAPTURE ||
- request->video_type() == MEDIA_TAB_VIDEO_CAPTURE);
+bool MediaStreamManager::SetUpTabCaptureRequest(DeviceRequest* request,
+ const std::string& label) {
+ DCHECK(request->audio_type() == MEDIA_GUM_TAB_AUDIO_CAPTURE ||
+ request->video_type() == MEDIA_GUM_TAB_VIDEO_CAPTURE);
std::string capture_device_id;
if (!request->controls.audio.device_id.empty()) {
@@ -1169,17 +1226,56 @@ bool MediaStreamManager::SetupTabCaptureRequest(DeviceRequest* request) {
return false;
}
- // Customize controls for a WebContents based capture.
- WebContentsMediaCaptureId web_id;
- bool has_valid_device_id =
- WebContentsMediaCaptureId::Parse(capture_device_id, &web_id);
- if (!has_valid_device_id ||
- (request->audio_type() != MEDIA_TAB_AUDIO_CAPTURE &&
+ if ((request->audio_type() != MEDIA_GUM_TAB_AUDIO_CAPTURE &&
request->audio_type() != MEDIA_NO_SERVICE) ||
- (request->video_type() != MEDIA_TAB_VIDEO_CAPTURE &&
+ (request->video_type() != MEDIA_GUM_TAB_VIDEO_CAPTURE &&
request->video_type() != MEDIA_NO_SERVICE)) {
return false;
}
+
+ BrowserThread::PostTaskAndReplyWithResult(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&MediaStreamManager::ResolveTabCaptureDeviceIdOnUIThread,
+ base::Unretained(this), capture_device_id,
+ request->requesting_process_id,
+ request->requesting_frame_id,
+ request->salt_and_origin.origin.GetURL()),
+ base::BindOnce(
+ &MediaStreamManager::FinishTabCaptureRequestSetupWithDeviceId,
+ base::Unretained(this), label));
+ return true;
+}
+
+DesktopMediaID MediaStreamManager::ResolveTabCaptureDeviceIdOnUIThread(
+ const std::string& capture_device_id,
+ int requesting_process_id,
+ int requesting_frame_id,
+ const GURL& origin) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ // Resolve DesktopMediaID for the specified device id.
+ return DesktopStreamsRegistry::GetInstance()->RequestMediaForStreamId(
+ capture_device_id, requesting_process_id, requesting_frame_id, origin,
+ nullptr, kRegistryStreamTypeTab);
+}
+
+void MediaStreamManager::FinishTabCaptureRequestSetupWithDeviceId(
+ const std::string& label,
+ const DesktopMediaID& device_id) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+
+ DeviceRequest* request = FindRequest(label);
+ if (!request) {
+ DVLOG(1) << "SetUpRequest label " << label << " doesn't exist!!";
+ return; // This can happen if the request has been canceled.
+ }
+
+ // Received invalid device id.
+ if (device_id.type != content::DesktopMediaID::TYPE_WEB_CONTENTS) {
+ FinalizeRequestFailed(label, request, MEDIA_DEVICE_TAB_CAPTURE_FAILURE);
+ return;
+ }
+
+ content::WebContentsMediaCaptureId web_id = device_id.web_contents_id;
web_id.disable_local_echo = request->controls.disable_local_echo;
request->tab_capture_device_id = web_id.ToString();
@@ -1187,43 +1283,39 @@ bool MediaStreamManager::SetupTabCaptureRequest(DeviceRequest* request) {
request->CreateTabCaptureUIRequest(web_id.render_process_id,
web_id.main_render_frame_id);
- DVLOG(3) << "SetupTabCaptureRequest "
- << ", {capture_device_id = " << capture_device_id << "}"
+ DVLOG(3) << "SetUpTabCaptureRequest "
+ << ", {capture_device_id = " << web_id.ToString() << "}"
<< ", {target_render_process_id = " << web_id.render_process_id
<< "}"
<< ", {target_render_frame_id = " << web_id.main_render_frame_id
<< "}";
- return true;
+
+ ReadOutputParamsAndPostRequestToUI(label, request, MediaDeviceEnumeration());
}
-bool MediaStreamManager::SetupScreenCaptureRequest(DeviceRequest* request) {
- DCHECK(request->audio_type() == MEDIA_DESKTOP_AUDIO_CAPTURE ||
- request->video_type() == MEDIA_DESKTOP_VIDEO_CAPTURE);
+bool MediaStreamManager::SetUpScreenCaptureRequest(DeviceRequest* request) {
+ DCHECK(request->audio_type() == MEDIA_GUM_DESKTOP_AUDIO_CAPTURE ||
+ request->video_type() == MEDIA_GUM_DESKTOP_VIDEO_CAPTURE);
// For screen capture we only support two valid combinations:
// (1) screen video capture only, or
// (2) screen video capture with loopback audio capture.
- if (request->video_type() != MEDIA_DESKTOP_VIDEO_CAPTURE ||
+ if (request->video_type() != MEDIA_GUM_DESKTOP_VIDEO_CAPTURE ||
(request->audio_type() != MEDIA_NO_SERVICE &&
- request->audio_type() != MEDIA_DESKTOP_AUDIO_CAPTURE)) {
+ request->audio_type() != MEDIA_GUM_DESKTOP_AUDIO_CAPTURE)) {
LOG(ERROR) << "Invalid screen capture request.";
return false;
}
std::string video_device_id;
- if (request->video_type() == MEDIA_DESKTOP_VIDEO_CAPTURE) {
- const std::string& video_stream_source =
- request->controls.video.stream_source;
-
- if (video_stream_source == kMediaStreamSourceDesktop &&
- !request->controls.video.device_id.empty()) {
- video_device_id = request->controls.video.device_id;
- }
+ if (request->video_type() == MEDIA_GUM_DESKTOP_VIDEO_CAPTURE &&
+ !request->controls.video.device_id.empty()) {
+ video_device_id = request->controls.video.device_id;
}
const std::string audio_device_id =
- request->audio_type() == MEDIA_DESKTOP_AUDIO_CAPTURE ? video_device_id
- : "";
+ request->audio_type() == MEDIA_GUM_DESKTOP_AUDIO_CAPTURE ? video_device_id
+ : "";
request->CreateUIRequest(audio_device_id, video_device_id);
return true;
@@ -1285,7 +1377,7 @@ void MediaStreamManager::FinalizeGenerateStream(const std::string& label,
for (const MediaStreamDevice& device : request->devices) {
if (IsAudioInputMediaType(device.type))
audio_devices.push_back(device);
- else if (IsVideoMediaType(device.type))
+ else if (IsVideoInputMediaType(device.type))
video_devices.push_back(device);
else
NOTREACHED();
@@ -1410,7 +1502,7 @@ void MediaStreamManager::Opened(MediaStreamType stream_type,
for (MediaStreamDevice& device : request->devices) {
if (device.type == stream_type &&
device.session_id == capture_session_id) {
- CHECK(request->state(device.type) == MEDIA_REQUEST_STATE_OPENING);
+ CHECK_EQ(request->state(device.type), MEDIA_REQUEST_STATE_OPENING);
// We've found a matching request.
request->SetState(device.type, MEDIA_REQUEST_STATE_DONE);
@@ -1418,7 +1510,7 @@ void MediaStreamManager::Opened(MediaStreamType stream_type,
// Store the native audio parameters in the device struct.
// TODO(xians): Handle the tab capture sample rate/channel layout
// in AudioInputDeviceManager::Open().
- if (device.type != MEDIA_TAB_AUDIO_CAPTURE) {
+ if (device.type != MEDIA_GUM_TAB_AUDIO_CAPTURE) {
const MediaStreamDevice* opened_device =
audio_input_device_manager_->GetOpenedDeviceById(
device.session_id);
@@ -1493,7 +1585,7 @@ void MediaStreamManager::DevicesEnumerated(
}
}
- if (!SetupDeviceCaptureRequest(request, enumeration))
+ if (!SetUpDeviceCaptureRequest(request, enumeration))
FinalizeRequestFailed(label, request, MEDIA_DEVICE_NO_HARDWARE);
else
ReadOutputParamsAndPostRequestToUI(label, request, enumeration);
@@ -1587,16 +1679,16 @@ void MediaStreamManager::HandleAccessRequestResponse(
for (const MediaStreamDevice& media_stream_device : devices) {
MediaStreamDevice device = media_stream_device;
- if (device.type == MEDIA_TAB_VIDEO_CAPTURE ||
- device.type == MEDIA_TAB_AUDIO_CAPTURE) {
+ if (device.type == MEDIA_GUM_TAB_VIDEO_CAPTURE ||
+ device.type == MEDIA_GUM_TAB_AUDIO_CAPTURE) {
device.id = request->tab_capture_device_id;
}
// Initialize the sample_rate and channel_layout here since for audio
// mirroring, we don't go through EnumerateDevices where these are usually
// initialized.
- if (device.type == MEDIA_TAB_AUDIO_CAPTURE ||
- device.type == MEDIA_DESKTOP_AUDIO_CAPTURE) {
+ if (device.type == MEDIA_GUM_TAB_AUDIO_CAPTURE ||
+ device.type == MEDIA_GUM_DESKTOP_AUDIO_CAPTURE) {
int sample_rate = output_parameters.sample_rate();
// If we weren't able to get the native sampling rate or the sample_rate
// is outside the valid range for input devices set reasonable defaults.
@@ -1649,7 +1741,7 @@ void MediaStreamManager::HandleAccessRequestResponse(
DVLOG(1) << "Set no audio found label " << label;
}
- if (!found_video && IsVideoMediaType(request->video_type()))
+ if (!found_video && IsVideoInputMediaType(request->video_type()))
request->SetState(request->video_type(), MEDIA_REQUEST_STATE_ERROR);
if (RequestDone(*request))
@@ -1707,7 +1799,7 @@ void MediaStreamManager::NotifyDevicesChanged(
new_devices);
if (media_observer)
media_observer->OnAudioCaptureDevicesChanged();
- } else if (IsVideoMediaType(stream_type)) {
+ } else if (IsVideoInputMediaType(stream_type)) {
MediaCaptureDevicesImpl::GetInstance()->OnVideoCaptureDevicesChanged(
new_devices);
if (media_observer)
@@ -1721,7 +1813,7 @@ bool MediaStreamManager::RequestDone(const DeviceRequest& request) const {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
const bool requested_audio = IsAudioInputMediaType(request.audio_type());
- const bool requested_video = IsVideoMediaType(request.video_type());
+ const bool requested_video = IsVideoInputMediaType(request.video_type());
const bool audio_done =
!requested_audio ||
@@ -1742,7 +1834,7 @@ bool MediaStreamManager::RequestDone(const DeviceRequest& request) const {
MediaStreamProvider* MediaStreamManager::GetDeviceManager(
MediaStreamType stream_type) {
- if (IsVideoMediaType(stream_type))
+ if (IsVideoInputMediaType(stream_type))
return video_capture_manager();
else if (IsAudioInputMediaType(stream_type))
return audio_input_device_manager();
@@ -1758,13 +1850,13 @@ void MediaStreamManager::OnMediaStreamUIWindowId(
if (!window_id)
return;
- if (video_type != MEDIA_DESKTOP_VIDEO_CAPTURE)
+ if (video_type != MEDIA_GUM_DESKTOP_VIDEO_CAPTURE)
return;
// Pass along for desktop screen and window capturing when
// DesktopCaptureDevice is used.
for (const MediaStreamDevice& device : devices) {
- if (device.type != MEDIA_DESKTOP_VIDEO_CAPTURE)
+ if (device.type != MEDIA_GUM_DESKTOP_VIDEO_CAPTURE)
continue;
DesktopMediaID media_id = DesktopMediaID::Parse(device.id);
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 c73c8d60c26..2c0afbaa7fb 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_manager.h
+++ b/chromium/content/browser/renderer_host/media/media_stream_manager.h
@@ -49,6 +49,7 @@
#include "content/common/content_export.h"
#include "content/common/media/media_devices.h"
#include "content/common/media/media_stream_controls.h"
+#include "content/public/browser/desktop_media_id.h"
#include "content/public/browser/media_request_state.h"
#include "content/public/common/media_stream_request.h"
#include "media/base/video_facing.h"
@@ -351,20 +352,32 @@ class CONTENT_EXPORT MediaStreamManager
void DeleteRequest(const std::string& label);
// Prepare the request with label |label| by starting device enumeration if
// needed.
- void SetupRequest(const std::string& label);
+ void SetUpRequest(const std::string& label);
// Prepare |request| of type MEDIA_DEVICE_AUDIO_CAPTURE and/or
// MEDIA_DEVICE_VIDEO_CAPTURE for being posted to the UI by parsing
// StreamControls for requested device IDs.
- bool SetupDeviceCaptureRequest(DeviceRequest* request,
+ bool SetUpDeviceCaptureRequest(DeviceRequest* request,
const MediaDeviceEnumeration& enumeration);
- // Prepare |request| of type MEDIA_TAB_AUDIO_CAPTURE and/or
- // MEDIA_TAB_VIDEO_CAPTURE for being posted to the UI by parsing
- // StreamControls for requested tab capture IDs.
- bool SetupTabCaptureRequest(DeviceRequest* request);
- // Prepare |request| of type MEDIA_DESKTOP_AUDIO_CAPTURE and/or
- // MEDIA_DESKTOP_VIDEO_CAPTURE for being posted to the UI by parsing
+ // Prepare |request| of type MEDIA_DISPLAY_CAPTURE.
+ bool SetUpDisplayCaptureRequest(DeviceRequest* request);
+ // Prepare |request| of type MEDIA_GUM_DESKTOP_AUDIO_CAPTURE and/or
+ // MEDIA_GUM_DESKTOP_VIDEO_CAPTURE for being posted to the UI by parsing
// StreamControls for the requested desktop ID.
- bool SetupScreenCaptureRequest(DeviceRequest* request);
+ bool SetUpScreenCaptureRequest(DeviceRequest* request);
+ // Resolve the random device ID of tab capture on UI thread before proceeding
+ // with the tab capture UI request.
+ bool SetUpTabCaptureRequest(DeviceRequest* request, const std::string& label);
+ DesktopMediaID ResolveTabCaptureDeviceIdOnUIThread(
+ const std::string& capture_device_id,
+ int requesting_process_id,
+ int requesting_frame_id,
+ const GURL& origin);
+ // Prepare |request| of type MEDIA_GUM_TAB_AUDIO_CAPTURE and/or
+ // MEDIA_GUM_TAB_VIDEO_CAPTURE for being posted to the UI after the
+ // requested tab capture IDs are resolved from registry.
+ void FinishTabCaptureRequestSetupWithDeviceId(
+ const std::string& label,
+ const DesktopMediaID& device_id);
// Called when a request has been setup and devices have been enumerated if
// needed.
void ReadOutputParamsAndPostRequestToUI(
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 14d12b8b1a9..fae5c3ca81c 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
@@ -156,6 +156,20 @@ class TestBrowserClient : public ContentBrowserClient {
MediaObserver* media_observer_;
};
+class MockMediaStreamUIProxy : public FakeMediaStreamUIProxy {
+ public:
+ MockMediaStreamUIProxy()
+ : FakeMediaStreamUIProxy(/*tests_use_fake_render_frame_hosts=*/true) {}
+ void RequestAccess(std::unique_ptr<MediaStreamRequest> request,
+ ResponseCallback response_callback) override {
+ MockRequestAccess(request, response_callback);
+ }
+
+ MOCK_METHOD2(MockRequestAccess,
+ void(std::unique_ptr<MediaStreamRequest>& request,
+ ResponseCallback& response_callback));
+};
+
} // namespace
class MediaStreamManagerTest : public ::testing::Test {
@@ -250,17 +264,20 @@ TEST_F(MediaStreamManagerTest, MakeAndCancelMediaAccessRequest) {
EXPECT_CALL(*media_observer_,
OnMediaRequestStateChanged(_, _, _, _, MEDIA_DEVICE_VIDEO_CAPTURE,
MEDIA_REQUEST_STATE_CLOSING));
- EXPECT_CALL(*media_observer_,
- OnMediaRequestStateChanged(_, _, _, _, MEDIA_TAB_AUDIO_CAPTURE,
- MEDIA_REQUEST_STATE_CLOSING));
- EXPECT_CALL(*media_observer_,
- OnMediaRequestStateChanged(_, _, _, _, MEDIA_TAB_VIDEO_CAPTURE,
- MEDIA_REQUEST_STATE_CLOSING));
EXPECT_CALL(*media_observer_, OnMediaRequestStateChanged(
- _, _, _, _, MEDIA_DESKTOP_VIDEO_CAPTURE,
+ _, _, _, _, MEDIA_GUM_TAB_AUDIO_CAPTURE,
+ MEDIA_REQUEST_STATE_CLOSING));
+ EXPECT_CALL(*media_observer_, OnMediaRequestStateChanged(
+ _, _, _, _, MEDIA_GUM_TAB_VIDEO_CAPTURE,
+ MEDIA_REQUEST_STATE_CLOSING));
+ EXPECT_CALL(*media_observer_, OnMediaRequestStateChanged(
+ _, _, _, _, MEDIA_GUM_DESKTOP_VIDEO_CAPTURE,
+ MEDIA_REQUEST_STATE_CLOSING));
+ EXPECT_CALL(*media_observer_, OnMediaRequestStateChanged(
+ _, _, _, _, MEDIA_GUM_DESKTOP_AUDIO_CAPTURE,
MEDIA_REQUEST_STATE_CLOSING));
EXPECT_CALL(*media_observer_, OnMediaRequestStateChanged(
- _, _, _, _, MEDIA_DESKTOP_AUDIO_CAPTURE,
+ _, _, _, _, MEDIA_DISPLAY_VIDEO_CAPTURE,
MEDIA_REQUEST_STATE_CLOSING));
media_stream_manager_->CancelRequest(label);
run_loop_.RunUntilIdle();
@@ -301,17 +318,20 @@ TEST_F(MediaStreamManagerTest, MakeAndCancelMultipleRequests) {
EXPECT_CALL(*media_observer_,
OnMediaRequestStateChanged(_, _, _, _, MEDIA_DEVICE_VIDEO_CAPTURE,
MEDIA_REQUEST_STATE_CLOSING));
- EXPECT_CALL(*media_observer_,
- OnMediaRequestStateChanged(_, _, _, _, MEDIA_TAB_AUDIO_CAPTURE,
- MEDIA_REQUEST_STATE_CLOSING));
- EXPECT_CALL(*media_observer_,
- OnMediaRequestStateChanged(_, _, _, _, MEDIA_TAB_VIDEO_CAPTURE,
- MEDIA_REQUEST_STATE_CLOSING));
EXPECT_CALL(*media_observer_, OnMediaRequestStateChanged(
- _, _, _, _, MEDIA_DESKTOP_VIDEO_CAPTURE,
+ _, _, _, _, MEDIA_GUM_TAB_AUDIO_CAPTURE,
+ MEDIA_REQUEST_STATE_CLOSING));
+ EXPECT_CALL(*media_observer_, OnMediaRequestStateChanged(
+ _, _, _, _, MEDIA_GUM_TAB_VIDEO_CAPTURE,
+ MEDIA_REQUEST_STATE_CLOSING));
+ EXPECT_CALL(*media_observer_, OnMediaRequestStateChanged(
+ _, _, _, _, MEDIA_GUM_DESKTOP_VIDEO_CAPTURE,
+ MEDIA_REQUEST_STATE_CLOSING));
+ EXPECT_CALL(*media_observer_, OnMediaRequestStateChanged(
+ _, _, _, _, MEDIA_GUM_DESKTOP_AUDIO_CAPTURE,
MEDIA_REQUEST_STATE_CLOSING));
EXPECT_CALL(*media_observer_, OnMediaRequestStateChanged(
- _, _, _, _, MEDIA_DESKTOP_AUDIO_CAPTURE,
+ _, _, _, _, MEDIA_DISPLAY_VIDEO_CAPTURE,
MEDIA_REQUEST_STATE_CLOSING));
media_stream_manager_->CancelRequest(label1);
@@ -374,4 +394,90 @@ TEST_F(MediaStreamManagerTest, DeviceID) {
EXPECT_TRUE(base::IsAsciiDigit(c) || (c >= 'a' && c <= 'f'));
}
+TEST_F(MediaStreamManagerTest, GetDisplayMediaRequest) {
+ media_stream_manager_->UseFakeUIFactoryForTests(base::BindRepeating([]() {
+ return std::make_unique<FakeMediaStreamUIProxy>(
+ /*tests_use_fake_render_frame_hosts=*/true);
+ }));
+
+ StreamControls controls(false /* request_audio */, true /* request_video */);
+ controls.video.stream_type = MEDIA_DISPLAY_VIDEO_CAPTURE;
+ const int render_process_id = 1;
+ const int render_frame_id = 1;
+ const int page_request_id = 1;
+
+ MediaStreamDevice video_device;
+ MediaStreamManager::GenerateStreamCallback generate_stream_callback =
+ base::BindOnce(
+ [](base::RunLoop* wait_loop, MediaStreamDevice* video_device,
+ MediaStreamRequestResult result, const std::string& label,
+ const MediaStreamDevices& audio_devices,
+ const MediaStreamDevices& video_devices) {
+ EXPECT_EQ(0u, audio_devices.size());
+ ASSERT_EQ(1u, video_devices.size());
+ *video_device = video_devices[0];
+ wait_loop->Quit();
+ },
+ &run_loop_, &video_device);
+ MediaStreamManager::DeviceStoppedCallback stopped_callback;
+ EXPECT_CALL(*media_observer_, OnMediaRequestStateChanged(
+ _, _, _, _, MEDIA_DISPLAY_VIDEO_CAPTURE,
+ MEDIA_REQUEST_STATE_PENDING_APPROVAL));
+ EXPECT_CALL(*media_observer_, OnMediaRequestStateChanged(
+ _, _, _, _, MEDIA_DISPLAY_VIDEO_CAPTURE,
+ MEDIA_REQUEST_STATE_OPENING));
+ EXPECT_CALL(*media_observer_, OnMediaRequestStateChanged(
+ _, _, _, _, MEDIA_DISPLAY_VIDEO_CAPTURE,
+ MEDIA_REQUEST_STATE_DONE));
+ media_stream_manager_->GenerateStream(
+ render_process_id, render_frame_id, page_request_id, controls,
+ MediaDeviceSaltAndOrigin(), false /* user_gesture */,
+ std::move(generate_stream_callback), std::move(stopped_callback));
+ run_loop_.Run();
+
+ EXPECT_EQ(MEDIA_DISPLAY_VIDEO_CAPTURE, video_device.type);
+ EXPECT_CALL(*media_observer_, OnMediaRequestStateChanged(
+ _, _, _, _, MEDIA_DISPLAY_VIDEO_CAPTURE,
+ MEDIA_REQUEST_STATE_CLOSING));
+ media_stream_manager_->StopStreamDevice(render_process_id, render_frame_id,
+ video_device.id,
+ video_device.session_id);
+}
+
+TEST_F(MediaStreamManagerTest, GetDisplayMediaRequestCallsUIProxy) {
+ media_stream_manager_->UseFakeUIFactoryForTests(base::BindRepeating(
+ [](base::RunLoop* run_loop) {
+ auto mock_ui = std::make_unique<MockMediaStreamUIProxy>();
+ EXPECT_CALL(*mock_ui, MockRequestAccess(_, _))
+ .WillOnce(testing::Invoke(
+ [run_loop](std::unique_ptr<MediaStreamRequest>& request,
+ testing::Unused) {
+ EXPECT_EQ(MEDIA_DISPLAY_VIDEO_CAPTURE, request->video_type);
+ run_loop->Quit();
+ }));
+ return std::unique_ptr<FakeMediaStreamUIProxy>(std::move(mock_ui));
+ },
+ &run_loop_));
+ StreamControls controls(false /* request_audio */, true /* request_video */);
+ controls.video.stream_type = MEDIA_DISPLAY_VIDEO_CAPTURE;
+
+ MediaStreamManager::GenerateStreamCallback generate_stream_callback =
+ base::BindOnce([](MediaStreamRequestResult result,
+ const std::string& label,
+ const MediaStreamDevices& audio_devices,
+ const MediaStreamDevices& video_devices) {});
+ EXPECT_CALL(*media_observer_, OnMediaRequestStateChanged(
+ _, _, _, _, MEDIA_DISPLAY_VIDEO_CAPTURE,
+ MEDIA_REQUEST_STATE_PENDING_APPROVAL));
+ media_stream_manager_->GenerateStream(
+ 0, 0, 0, controls, MediaDeviceSaltAndOrigin(), false /* user_gesture */,
+ std::move(generate_stream_callback),
+ MediaStreamManager::DeviceStoppedCallback());
+ run_loop_.Run();
+
+ EXPECT_CALL(*media_observer_, OnMediaRequestStateChanged(_, _, _, _, _, _))
+ .Times(testing::AtLeast(1));
+ media_stream_manager_->CancelAllRequests(0, 0);
+}
+
} // namespace content
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 2f13d1d2045..43c3b83d83d 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
@@ -7,13 +7,11 @@
#include <utility>
#include "base/command_line.h"
-#include "base/feature_list.h"
#include "base/macros.h"
#include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/frame_host/render_frame_host_delegate.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/public/browser/browser_thread.h"
-#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "media/capture/video/fake_video_capture_device.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom.h"
@@ -25,9 +23,6 @@ namespace content {
bool IsFeatureEnabled(RenderFrameHost* rfh,
bool tests_use_fake_render_frame_hosts,
blink::mojom::FeaturePolicyFeature feature) {
- if (!base::FeatureList::IsEnabled(features::kUseFeaturePolicyForPermissions))
- return true;
-
// Some tests don't (or can't) set up the RenderFrameHost. In these cases we
// just ignore feature policy checks (there is no feature policy to test).
if (!rfh && tests_use_fake_render_frame_hosts)
@@ -125,9 +120,9 @@ void MediaStreamUIProxy::Core::RequestAccess(
render_delegate->RequestMediaAccessPermission(
*request,
- base::Bind(&Core::ProcessAccessRequestResponse,
- weak_factory_.GetWeakPtr(), request->render_process_id,
- request->render_frame_id));
+ base::BindOnce(&Core::ProcessAccessRequestResponse,
+ weak_factory_.GetWeakPtr(), request->render_process_id,
+ request->render_frame_id));
}
void MediaStreamUIProxy::Core::OnStarted(gfx::NativeViewId* window_id) {
@@ -324,9 +319,8 @@ void FakeMediaStreamUIProxy::RequestAccess(
request->requested_audio_device_id == it->id)) {
devices_to_use.push_back(*it);
accepted_audio = true;
- } else if (!accepted_video &&
- IsVideoMediaType(request->video_type) &&
- IsVideoMediaType(it->type) &&
+ } else if (!accepted_video && IsVideoInputMediaType(request->video_type) &&
+ IsVideoInputMediaType(it->type) &&
(request->requested_video_device_id.empty() ||
request->requested_video_device_id == it->id)) {
devices_to_use.push_back(*it);
diff --git a/chromium/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc b/chromium/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc
index 0acf2f42c16..54c050bceba 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc
@@ -9,10 +9,8 @@
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
-#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "content/browser/frame_host/render_frame_host_delegate.h"
-#include "content/public/common/content_features.h"
#include "content/public/test/test_browser_thread.h"
#include "content/test/test_render_frame_host.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -262,7 +260,7 @@ TEST_F(MediaStreamUIProxyTest, MAYBE_WindowIdCallbackCalled) {
std::unique_ptr<MediaStreamRequest> request(new MediaStreamRequest(
0, 0, 0, GURL("http://origin/"), false, MEDIA_GENERATE_STREAM,
std::string(), std::string(), MEDIA_NO_SERVICE,
- MEDIA_DESKTOP_VIDEO_CAPTURE, false));
+ MEDIA_GUM_DESKTOP_VIDEO_CAPTURE, false));
MediaStreamRequest* request_ptr = request.get();
proxy_->RequestAccess(
@@ -403,8 +401,6 @@ class MediaStreamUIProxyFeaturePolicyTest
};
TEST_F(MediaStreamUIProxyFeaturePolicyTest, FeaturePolicy) {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(features::kUseFeaturePolicyForPermissions);
MediaStreamDevices devices;
MediaStreamRequestResult result;
@@ -448,19 +444,6 @@ TEST_F(MediaStreamUIProxyFeaturePolicyTest, FeaturePolicy) {
&devices, &result);
EXPECT_EQ(MEDIA_DEVICE_PERMISSION_DENIED, result);
ASSERT_EQ(0u, devices.size());
-
- // Ensure that the policy is ignored if kUseFeaturePolicyForPermissions is
- // disabled.
- base::test::ScopedFeatureList empty_feature_list;
- empty_feature_list.InitAndDisableFeature(
- features::kUseFeaturePolicyForPermissions);
- GetResultForRequest(CreateRequest(main_rfh(), MEDIA_DEVICE_AUDIO_CAPTURE,
- MEDIA_DEVICE_VIDEO_CAPTURE),
- &devices, &result);
- EXPECT_EQ(MEDIA_DEVICE_OK, result);
- ASSERT_EQ(2u, devices.size());
- EXPECT_EQ(MEDIA_DEVICE_AUDIO_CAPTURE, devices[0].type);
- EXPECT_EQ(MEDIA_DEVICE_VIDEO_CAPTURE, devices[1].type);
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/old_render_frame_audio_input_stream_factory.cc b/chromium/content/browser/renderer_host/media/old_render_frame_audio_input_stream_factory.cc
index 6e33963efe7..5093cee0282 100644
--- a/chromium/content/browser/renderer_host/media/old_render_frame_audio_input_stream_factory.cc
+++ b/chromium/content/browser/renderer_host/media/old_render_frame_audio_input_stream_factory.cc
@@ -125,9 +125,12 @@ void OldRenderFrameAudioInputStreamFactory::CreateStream(
int32_t session_id,
const media::AudioParameters& audio_params,
bool automatic_gain_control,
- uint32_t shared_memory_count) {
+ uint32_t shared_memory_count,
+ audio::mojom::AudioProcessingConfigPtr processing_config) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
+// |processing_config| gets dropped here. It's not supported outside of the
+// audio service. As this class is slated for removal, it will not be updated
+// to support audio processing.
#if defined(OS_CHROMEOS)
if (audio_params.channel_layout() ==
media::CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC) {
diff --git a/chromium/content/browser/renderer_host/media/old_render_frame_audio_input_stream_factory.h b/chromium/content/browser/renderer_host/media/old_render_frame_audio_input_stream_factory.h
index 629b75e508b..01fb38b0bb6 100644
--- a/chromium/content/browser/renderer_host/media/old_render_frame_audio_input_stream_factory.h
+++ b/chromium/content/browser/renderer_host/media/old_render_frame_audio_input_stream_factory.h
@@ -69,11 +69,13 @@ class CONTENT_EXPORT OldRenderFrameAudioInputStreamFactory
base::UniquePtrComparator>;
// mojom::RendererAudioInputStreamFactory implementation.
- void CreateStream(mojom::RendererAudioInputStreamFactoryClientPtr client,
- int32_t session_id,
- const media::AudioParameters& audio_params,
- bool automatic_gain_control,
- uint32_t shared_memory_count) override;
+ void CreateStream(
+ mojom::RendererAudioInputStreamFactoryClientPtr client,
+ int32_t session_id,
+ const media::AudioParameters& audio_params,
+ bool automatic_gain_control,
+ uint32_t shared_memory_count,
+ audio::mojom::AudioProcessingConfigPtr processing_config) override;
void DoCreateStream(mojom::RendererAudioInputStreamFactoryClientPtr client,
int session_id,
diff --git a/chromium/content/browser/renderer_host/media/old_render_frame_audio_input_stream_factory_unittest.cc b/chromium/content/browser/renderer_host/media/old_render_frame_audio_input_stream_factory_unittest.cc
index fb2e934df02..76f0caebe61 100644
--- a/chromium/content/browser/renderer_host/media/old_render_frame_audio_input_stream_factory_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/old_render_frame_audio_input_stream_factory_unittest.cc
@@ -154,8 +154,8 @@ class OldOldRenderFrameAudioInputStreamFactoryTest : public testing::Test {
TEST_F(OldOldRenderFrameAudioInputStreamFactoryTest, CreateStream) {
factory_ptr_->CreateStream(std::move(client_ptr_), kSessionId,
- GetTestAudioParameters(), kAGC,
- kSharedMemoryCount);
+ GetTestAudioParameters(), kAGC, kSharedMemoryCount,
+ nullptr);
// Wait for delegate to be created and |event_handler| set.
base::RunLoop().RunUntilIdle();
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 b4f527af64f..8277d2d73d3 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
@@ -235,7 +235,11 @@ TEST(OldRenderFrameAudioOutputStreamFactoryTest, CreateStream) {
GetTestAudioParameters().AsHumanReadableString());
EXPECT_TRUE(id.empty());
- provider->Acquire(params, client.MakeProviderClientPtr());
+ // Ensure that we don't blow up getting a processing ID, despite not using it.
+ const base::UnguessableToken kUnusedProcessingId =
+ base::UnguessableToken::Create();
+ provider->Acquire(params, client.MakeProviderClientPtr(),
+ kUnusedProcessingId);
base::RunLoop().RunUntilIdle();
ASSERT_NE(event_handler, nullptr);
@@ -295,7 +299,8 @@ TEST(OldRenderFrameAudioOutputStreamFactoryTest,
const std::string& id) {}));
base::RunLoop().RunUntilIdle();
- provider->Acquire(GetTestAudioParameters(), client.MakeProviderClientPtr());
+ provider->Acquire(GetTestAudioParameters(), client.MakeProviderClientPtr(),
+ base::nullopt);
base::RunLoop().RunUntilIdle();
ASSERT_NE(event_handler, nullptr);
EXPECT_FALSE(delegate_is_destructed);
@@ -325,7 +330,8 @@ TEST(OldRenderFrameAudioOutputStreamFactoryTest, DelegateError_DeletesStream) {
const std::string& id) {}));
base::RunLoop().RunUntilIdle();
- provider->Acquire(GetTestAudioParameters(), client.MakeProviderClientPtr());
+ provider->Acquire(GetTestAudioParameters(), client.MakeProviderClientPtr(),
+ base::nullopt);
base::RunLoop().RunUntilIdle();
ASSERT_NE(event_handler, nullptr);
EXPECT_FALSE(delegate_is_destructed);
diff --git a/chromium/content/browser/renderer_host/media/render_frame_audio_input_stream_factory.cc b/chromium/content/browser/renderer_host/media/render_frame_audio_input_stream_factory.cc
index a07394101ea..d4d96fb5bfe 100644
--- a/chromium/content/browser/renderer_host/media/render_frame_audio_input_stream_factory.cc
+++ b/chromium/content/browser/renderer_host/media/render_frame_audio_input_stream_factory.cc
@@ -90,7 +90,8 @@ void RenderFrameAudioInputStreamFactory::CreateStream(
int32_t session_id,
const media::AudioParameters& audio_params,
bool automatic_gain_control,
- uint32_t shared_memory_count) {
+ uint32_t shared_memory_count,
+ audio::mojom::AudioProcessingConfigPtr processing_config) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
TRACE_EVENT_INSTANT1("audio",
"RenderFrameAudioInputStreamFactory::CreateStream",
@@ -105,7 +106,7 @@ void RenderFrameAudioInputStreamFactory::CreateStream(
CreateStreamAfterLookingUpDevice,
weak_ptr_factory_.GetWeakPtr(), std::move(client),
audio_params, automatic_gain_control,
- shared_memory_count)));
+ shared_memory_count, std::move(processing_config))));
}
void RenderFrameAudioInputStreamFactory::CreateStreamAfterLookingUpDevice(
@@ -113,6 +114,7 @@ void RenderFrameAudioInputStreamFactory::CreateStreamAfterLookingUpDevice(
const media::AudioParameters& audio_params,
bool automatic_gain_control,
uint32_t shared_memory_count,
+ audio::mojom::AudioProcessingConfigPtr processing_config,
const MediaStreamDevice& device) {
TRACE_EVENT1(
"audio",
@@ -126,9 +128,9 @@ void RenderFrameAudioInputStreamFactory::CreateStreamAfterLookingUpDevice(
WebContentsMediaCaptureId capture_id;
if (WebContentsMediaCaptureId::Parse(device.id, &capture_id)) {
- // For MEDIA_DESKTOP_AUDIO_CAPTURE, the source is selected from picker
- // window, we do not mute the source audio.
- // For MEDIA_TAB_AUDIO_CAPTURE, the probable use case is Cast, we mute
+ // For MEDIA_GUM_DESKTOP_AUDIO_CAPTURE, the source is selected from
+ // picker window, we do not mute the source audio. For
+ // MEDIA_GUM_TAB_AUDIO_CAPTURE, the probable use case is Cast, we mute
// the source audio.
// TODO(qiangchen): Analyze audio constraints to make a duplicating or
// diverting decision. It would give web developer more flexibility.
@@ -144,16 +146,16 @@ void RenderFrameAudioInputStreamFactory::CreateStreamAfterLookingUpDevice(
render_frame_host_, source_host, audio_params, shared_memory_count,
capture_id.disable_local_echo, std::move(client));
- if (device.type == MEDIA_DESKTOP_AUDIO_CAPTURE)
+ if (device.type == MEDIA_GUM_DESKTOP_AUDIO_CAPTURE)
IncrementDesktopCaptureCounter(SYSTEM_LOOPBACK_AUDIO_CAPTURER_CREATED);
} else {
factory->CreateInputStream(render_frame_host_, device.id, audio_params,
shared_memory_count, automatic_gain_control,
- std::move(client));
+ std::move(processing_config), std::move(client));
// Only count for captures from desktop media picker dialog and system loop
// back audio.
- if (device.type == MEDIA_DESKTOP_AUDIO_CAPTURE &&
+ if (device.type == MEDIA_GUM_DESKTOP_AUDIO_CAPTURE &&
(media::AudioDeviceDescription::IsLoopbackDevice(device.id))) {
IncrementDesktopCaptureCounter(SYSTEM_LOOPBACK_AUDIO_CAPTURER_CREATED);
}
diff --git a/chromium/content/browser/renderer_host/media/render_frame_audio_input_stream_factory.h b/chromium/content/browser/renderer_host/media/render_frame_audio_input_stream_factory.h
index a4597568026..49ec1176c36 100644
--- a/chromium/content/browser/renderer_host/media/render_frame_audio_input_stream_factory.h
+++ b/chromium/content/browser/renderer_host/media/render_frame_audio_input_stream_factory.h
@@ -6,6 +6,7 @@
#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_RENDER_FRAME_AUDIO_INPUT_STREAM_FACTORY_H_
#include <cstdint>
+#include <string>
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
@@ -41,17 +42,20 @@ class CONTENT_EXPORT RenderFrameAudioInputStreamFactory
private:
// mojom::RendererAudioInputStreamFactory implementation.
- void CreateStream(mojom::RendererAudioInputStreamFactoryClientPtr client,
- int32_t session_id,
- const media::AudioParameters& audio_params,
- bool automatic_gain_control,
- uint32_t shared_memory_count) override;
+ void CreateStream(
+ mojom::RendererAudioInputStreamFactoryClientPtr client,
+ int32_t session_id,
+ const media::AudioParameters& audio_params,
+ bool automatic_gain_control,
+ uint32_t shared_memory_count,
+ audio::mojom::AudioProcessingConfigPtr processing_config) override;
void CreateStreamAfterLookingUpDevice(
mojom::RendererAudioInputStreamFactoryClientPtr client,
const media::AudioParameters& audio_params,
bool automatic_gain_control,
uint32_t shared_memory_count,
+ audio::mojom::AudioProcessingConfigPtr processing_config,
const MediaStreamDevice& device);
void AssociateInputAndOutputForAec(
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 0a78c678b37..a5ae3806e45 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
@@ -100,6 +100,7 @@ class RenderFrameAudioInputStreamFactoryTest
uint32_t shared_memory_count,
bool enable_agc,
mojo::ScopedSharedBufferHandle key_press_count_buffer,
+ audio::mojom::AudioProcessingConfigPtr processing_config,
CreateInputStreamCallback created_callback) override {
last_created_callback = std::move(created_callback);
}
@@ -198,7 +199,7 @@ TEST_F(RenderFrameAudioInputStreamFactoryTest,
mojom::RendererAudioInputStreamFactoryClientPtr client;
mojo::MakeRequest(&client);
factory_ptr->CreateStream(std::move(client), session_id, kParams, kAGC,
- kSharedMemoryCount);
+ kSharedMemoryCount, nullptr);
base::RunLoop().RunUntilIdle();
@@ -217,13 +218,13 @@ TEST_F(RenderFrameAudioInputStreamFactoryTest,
WebContentsMediaCaptureId capture_id(main_frame->GetProcess()->GetID(),
main_frame->GetRoutingID());
int session_id = audio_input_device_manager()->Open(MediaStreamDevice(
- MEDIA_TAB_AUDIO_CAPTURE, capture_id.ToString(), kDeviceName));
+ MEDIA_GUM_TAB_AUDIO_CAPTURE, capture_id.ToString(), kDeviceName));
base::RunLoop().RunUntilIdle();
mojom::RendererAudioInputStreamFactoryClientPtr client;
mojo::MakeRequest(&client);
factory_ptr->CreateStream(std::move(client), session_id, kParams, kAGC,
- kSharedMemoryCount);
+ kSharedMemoryCount, nullptr);
base::RunLoop().RunUntilIdle();
@@ -242,14 +243,14 @@ TEST_F(RenderFrameAudioInputStreamFactoryTest,
WebContentsMediaCaptureId capture_id(main_frame->GetProcess()->GetID(),
main_frame->GetRoutingID());
int session_id = audio_input_device_manager()->Open(MediaStreamDevice(
- MEDIA_TAB_AUDIO_CAPTURE, capture_id.ToString(), kDeviceName));
+ MEDIA_GUM_TAB_AUDIO_CAPTURE, capture_id.ToString(), kDeviceName));
base::RunLoop().RunUntilIdle();
source_contents.reset();
mojom::RendererAudioInputStreamFactoryClientPtr client;
mojo::MakeRequest(&client);
factory_ptr->CreateStream(std::move(client), session_id, kParams, kAGC,
- kSharedMemoryCount);
+ kSharedMemoryCount, nullptr);
base::RunLoop().RunUntilIdle();
@@ -268,7 +269,7 @@ TEST_F(RenderFrameAudioInputStreamFactoryTest,
mojo::MakeRequest(&client);
factory_ptr->CreateStream(std::move(client), session_id, kParams, kAGC,
- kSharedMemoryCount);
+ kSharedMemoryCount, nullptr);
base::RunLoop().RunUntilIdle();
diff --git a/chromium/content/browser/renderer_host/media/render_frame_audio_output_stream_factory.cc b/chromium/content/browser/renderer_host/media/render_frame_audio_output_stream_factory.cc
index 00642ad3fe9..dadd1cdd502 100644
--- a/chromium/content/browser/renderer_host/media/render_frame_audio_output_stream_factory.cc
+++ b/chromium/content/browser/renderer_host/media/render_frame_audio_output_stream_factory.cc
@@ -37,7 +37,8 @@ class RenderFrameAudioOutputStreamFactory::ProviderImpl final
void Acquire(
const media::AudioParameters& params,
- media::mojom::AudioOutputStreamProviderClientPtr provider_client) final {
+ media::mojom::AudioOutputStreamProviderClientPtr provider_client,
+ const base::Optional<base::UnguessableToken>& processing_id) final {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
TRACE_EVENT1("audio",
"RenderFrameAudioOutputStreamFactory::ProviderImpl::Acquire",
@@ -50,7 +51,7 @@ class RenderFrameAudioOutputStreamFactory::ProviderImpl final
// It's possible that |frame| has already been destroyed, in which case we
// don't need to create a stream. In this case, the renderer will get a
// connection error since |provider_client| is dropped.
- factory->CreateOutputStream(frame, device_id_, params,
+ factory->CreateOutputStream(frame, device_id_, params, processing_id,
std::move(provider_client));
}
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 837204a6d62..ed17a87080b 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
@@ -100,6 +100,7 @@ class RenderFrameAudioOutputStreamFactoryTest
const std::string& output_device_id,
const media::AudioParameters& params,
const base::UnguessableToken& group_id,
+ const base::Optional<base::UnguessableToken>& processing_id,
CreateOutputStreamCallback created_callback) override {
last_created_callback = std::move(created_callback);
}
@@ -214,7 +215,7 @@ TEST_F(RenderFrameAudioOutputStreamFactoryTest,
{
media::mojom::AudioOutputStreamProviderClientPtr client;
mojo::MakeRequest(&client);
- provider_ptr->Acquire(kParams, std::move(client));
+ provider_ptr->Acquire(kParams, std::move(client), base::nullopt);
}
audio::mojom::StreamFactory::CreateOutputStreamCallback created_callback;
@@ -251,7 +252,7 @@ TEST_F(RenderFrameAudioOutputStreamFactoryTest,
{
media::mojom::AudioOutputStreamProviderClientPtr client;
mojo::MakeRequest(&client);
- provider_ptr->Acquire(kParams, std::move(client));
+ provider_ptr->Acquire(kParams, std::move(client), base::nullopt);
}
base::RunLoop().RunUntilIdle();
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 c2bf65e7950..07e01aaabe7 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
@@ -38,6 +38,7 @@ void ConcludeLaunchDeviceWithSuccess(
void ConcludeLaunchDeviceWithFailure(
bool abort_requested,
+ media::VideoCaptureError error,
std::unique_ptr<VideoCaptureFactoryDelegate> device_factory,
VideoCaptureDeviceLauncher::Callbacks* callbacks,
base::OnceClosure done_cb) {
@@ -45,7 +46,7 @@ void ConcludeLaunchDeviceWithFailure(
if (abort_requested)
callbacks->OnDeviceLaunchAborted();
else
- callbacks->OnDeviceLaunchFailed();
+ callbacks->OnDeviceLaunchFailed(error);
base::ResetAndReturn(&done_cb).Run();
}
@@ -84,8 +85,11 @@ void ServiceVideoCaptureDeviceLauncher::LaunchDeviceAsync(
// This can happen when the ServiceVideoCaptureProvider owning
// |device_factory_| loses connection to the service process and resets
// |device_factory_|.
- ConcludeLaunchDeviceWithFailure(false, std::move(device_factory_),
- callbacks, std::move(done_cb));
+ ConcludeLaunchDeviceWithFailure(
+ false,
+ media::VideoCaptureError::
+ kServiceDeviceLauncherLostConnectionToDeviceFactoryDuringDeviceStart,
+ std::move(device_factory_), callbacks, std::move(done_cb));
return;
}
@@ -157,9 +161,11 @@ void ServiceVideoCaptureDeviceLauncher::OnCreateDeviceCallback(
return;
case video_capture::mojom::DeviceAccessResultCode::ERROR_DEVICE_NOT_FOUND:
case video_capture::mojom::DeviceAccessResultCode::NOT_INITIALIZED:
- ConcludeLaunchDeviceWithFailure(abort_requested,
- std::move(device_factory_), callbacks,
- std::move(done_cb_));
+ ConcludeLaunchDeviceWithFailure(
+ abort_requested,
+ media::VideoCaptureError::
+ kServiceDeviceLauncherServiceRespondedWithDeviceNotFound,
+ std::move(device_factory_), callbacks, std::move(done_cb_));
return;
}
}
@@ -172,8 +178,11 @@ void ServiceVideoCaptureDeviceLauncher::
state_ = State::READY_TO_LAUNCH;
Callbacks* callbacks = callbacks_;
callbacks_ = nullptr;
- ConcludeLaunchDeviceWithFailure(abort_requested, std::move(device_factory_),
- callbacks, std::move(done_cb_));
+ ConcludeLaunchDeviceWithFailure(
+ abort_requested,
+ media::VideoCaptureError::
+ kServiceDeviceLauncherConnectionLostWhileWaitingForCallback,
+ std::move(device_factory_), callbacks, std::move(done_cb_));
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/service_video_capture_device_launcher_unittest.cc b/chromium/content/browser/renderer_host/media/service_video_capture_device_launcher_unittest.cc
index 2c04a18d030..37c732611ce 100644
--- a/chromium/content/browser/renderer_host/media/service_video_capture_device_launcher_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/service_video_capture_device_launcher_unittest.cc
@@ -74,7 +74,7 @@ class MockVideoCaptureDeviceLauncherCallbacks
MOCK_METHOD1(DoOnDeviceLaunched,
void(std::unique_ptr<LaunchedVideoCaptureDevice>* device));
- MOCK_METHOD0(OnDeviceLaunchFailed, void());
+ MOCK_METHOD1(OnDeviceLaunchFailed, void(media::VideoCaptureError error));
MOCK_METHOD0(OnDeviceLaunchAborted, void());
};
@@ -157,7 +157,7 @@ TEST_F(ServiceVideoCaptureDeviceLauncherTest, LaunchingDeviceSucceeds) {
EXPECT_CALL(mock_callbacks_, DoOnDeviceLaunched(_)).Times(1);
EXPECT_CALL(mock_callbacks_, OnDeviceLaunchAborted()).Times(0);
- EXPECT_CALL(mock_callbacks_, OnDeviceLaunchFailed()).Times(0);
+ EXPECT_CALL(mock_callbacks_, OnDeviceLaunchFailed(_)).Times(0);
EXPECT_CALL(connection_lost_cb_, Run()).Times(0);
base::RunLoop wait_for_done_cb;
EXPECT_CALL(done_cb_, Run())
@@ -224,7 +224,7 @@ void ServiceVideoCaptureDeviceLauncherTest::RunLaunchingDeviceIsAbortedTest(
}));
EXPECT_CALL(mock_callbacks_, DoOnDeviceLaunched(_)).Times(0);
EXPECT_CALL(mock_callbacks_, OnDeviceLaunchAborted()).Times(1);
- EXPECT_CALL(mock_callbacks_, OnDeviceLaunchFailed()).Times(0);
+ EXPECT_CALL(mock_callbacks_, OnDeviceLaunchFailed(_)).Times(0);
EXPECT_CALL(connection_lost_cb_, Run()).Times(0);
EXPECT_CALL(done_cb_, Run()).WillOnce(InvokeWithoutArgs([&step_2_run_loop]() {
step_2_run_loop.Quit();
@@ -272,7 +272,11 @@ TEST_F(ServiceVideoCaptureDeviceLauncherTest,
}));
EXPECT_CALL(mock_callbacks_, DoOnDeviceLaunched(_)).Times(0);
EXPECT_CALL(mock_callbacks_, OnDeviceLaunchAborted()).Times(0);
- EXPECT_CALL(mock_callbacks_, OnDeviceLaunchFailed()).Times(1);
+ EXPECT_CALL(mock_callbacks_,
+ OnDeviceLaunchFailed(
+ media::VideoCaptureError::
+ kServiceDeviceLauncherServiceRespondedWithDeviceNotFound))
+ .Times(1);
EXPECT_CALL(connection_lost_cb_, Run()).Times(0);
EXPECT_CALL(done_cb_, Run()).WillOnce(InvokeWithoutArgs([&run_loop]() {
run_loop.Quit();
@@ -292,7 +296,7 @@ TEST_F(ServiceVideoCaptureDeviceLauncherTest,
EXPECT_CALL(mock_callbacks_, DoOnDeviceLaunched(_)).Times(0);
EXPECT_CALL(mock_callbacks_, OnDeviceLaunchAborted()).Times(0);
- EXPECT_CALL(mock_callbacks_, OnDeviceLaunchFailed()).Times(1);
+ EXPECT_CALL(mock_callbacks_, OnDeviceLaunchFailed(_)).Times(1);
EXPECT_CALL(connection_lost_cb_, Run()).Times(0);
EXPECT_CALL(done_cb_, Run()).WillOnce(InvokeWithoutArgs([&run_loop]() {
run_loop.Quit();
@@ -327,7 +331,7 @@ TEST_F(ServiceVideoCaptureDeviceLauncherTest,
}));
EXPECT_CALL(mock_callbacks_, DoOnDeviceLaunched(_)).Times(0);
EXPECT_CALL(mock_callbacks_, OnDeviceLaunchAborted()).Times(0);
- EXPECT_CALL(mock_callbacks_, OnDeviceLaunchFailed()).Times(1);
+ EXPECT_CALL(mock_callbacks_, OnDeviceLaunchFailed(_)).Times(1);
// Note: |connection_lost_cb_| is only meant to be called when the connection
// to a successfully-launched device is lost, which is not the case here.
EXPECT_CALL(connection_lost_cb_, Run()).Times(0);
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 52ae899701f..34445f23d22 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,7 +4,6 @@
#include "content/browser/renderer_host/media/service_video_capture_provider.h"
-#include "content/browser/gpu/gpu_client_impl.h"
#include "content/browser/renderer_host/media/service_video_capture_device_launcher.h"
#include "content/browser/renderer_host/media/video_capture_dependencies.h"
#include "content/browser/renderer_host/media/video_capture_factory_delegate.h"
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 7cc051d35af..c1b58b70dc3 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
@@ -33,11 +33,11 @@ class CONTENT_EXPORT ServiceVideoCaptureProvider : public VideoCaptureProvider {
// This constructor creates a default ServiceConnector which
// uses the ServiceManager associated with the current process to connect
// to the video capture service. It uses a default factory for instances of
- // ui::mojom::Gpu which produces instances of class content::GpuClient.
+ // ws::mojom::Gpu which produces instances of class content::GpuClient.
explicit ServiceVideoCaptureProvider(
base::RepeatingCallback<void(const std::string&)> emit_log_message_cb);
// Lets clients provide a custom ServiceConnector and factory method for
- // creating instances of ui::mojom::Gpu.
+ // creating instances of ws::mojom::Gpu.
ServiceVideoCaptureProvider(
std::unique_ptr<ServiceConnector> service_connector,
CreateAcceleratorFactoryCallback create_accelerator_factory_cb,
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 b080b096ec5..0b5aecf53b7 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
@@ -103,7 +103,7 @@ class MockVideoCaptureDeviceLauncherCallbacks
MOCK_METHOD1(DoOnDeviceLaunched,
void(std::unique_ptr<LaunchedVideoCaptureDevice>* device));
- MOCK_METHOD0(OnDeviceLaunchFailed, void());
+ MOCK_METHOD1(OnDeviceLaunchFailed, void(media::VideoCaptureError error));
MOCK_METHOD0(OnDeviceLaunchAborted, void());
};
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 ee5dd193529..7306b1ee393 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_browsertest.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_browsertest.cc
@@ -48,7 +48,8 @@ class MockVideoCaptureControllerEventHandler
const media::mojom::VideoFrameInfoPtr& frame_info));
MOCK_METHOD1(OnStarted, void(VideoCaptureControllerID));
MOCK_METHOD1(OnEnded, void(VideoCaptureControllerID));
- MOCK_METHOD1(OnError, void(VideoCaptureControllerID));
+ MOCK_METHOD2(OnError,
+ void(VideoCaptureControllerID, media::VideoCaptureError));
MOCK_METHOD1(OnStartedUsingGpuDecode, void(VideoCaptureControllerID));
MOCK_METHOD1(OnStoppedUsingGpuDecode, void(VideoCaptureControllerID));
@@ -148,7 +149,7 @@ class VideoCaptureBrowserTest : public ContentBrowserTest,
video_capture_manager_->DisconnectClient(controller_.get(), stub_client_id_,
&mock_controller_event_handler_,
- false);
+ media::VideoCaptureError::kNone);
EXPECT_CALL(mock_stream_provider_listener_, Closed(_, _))
.WillOnce(InvokeWithoutArgs([continuation]() { continuation.Run(); }));
diff --git a/chromium/content/browser/renderer_host/media/video_capture_controller.cc b/chromium/content/browser/renderer_host/media/video_capture_controller.cc
index 4a948b2c47f..b964d0e82f9 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_controller.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_controller.cc
@@ -15,7 +15,6 @@
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "build/build_config.h"
-#include "components/viz/common/gl_helper.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/browser/renderer_host/media/video_capture_manager.h"
#include "content/public/browser/browser_thread.h"
@@ -48,9 +47,23 @@ static const int kInfiniteRatio = 99999;
base::UmaHistogramSparse( \
name, (height) ? ((width)*100) / (height) : kInfiniteRatio);
-void CallOnError(VideoCaptureControllerEventHandler* client,
+void LogVideoFrameDrop(media::VideoCaptureFrameDropReason reason) {
+ UMA_HISTOGRAM_ENUMERATION(
+ "Media.VideoCapture.FrameDrop", reason,
+ static_cast<int>(media::VideoCaptureFrameDropReason::kMaxValue) + 1);
+}
+
+void LogMaxConsecutiveVideoFrameDropCountExceeded(
+ media::VideoCaptureFrameDropReason reason) {
+ UMA_HISTOGRAM_ENUMERATION(
+ "Media.VideoCapture.MaxFrameDropExceeded", reason,
+ static_cast<int>(media::VideoCaptureFrameDropReason::kMaxValue) + 1);
+}
+
+void CallOnError(media::VideoCaptureError error,
+ VideoCaptureControllerEventHandler* client,
VideoCaptureControllerID id) {
- client->OnError(id);
+ client->OnError(id, error);
}
void CallOnStarted(VideoCaptureControllerEventHandler* client,
@@ -174,6 +187,9 @@ VideoCaptureController::BufferContext::CloneBufferHandle() {
result->set_shared_buffer_handle(
buffer_handle_->get_shared_buffer_handle()->Clone(
mojo::SharedBufferHandle::AccessMode::READ_WRITE));
+ } else if (buffer_handle_->is_read_only_shmem_region()) {
+ result->set_read_only_shmem_region(
+ buffer_handle_->get_read_only_shmem_region().Duplicate());
} else if (buffer_handle_->is_mailbox_handles()) {
result->set_mailbox_handles(buffer_handle_->get_mailbox_handles()->Clone());
} else {
@@ -182,6 +198,12 @@ VideoCaptureController::BufferContext::CloneBufferHandle() {
return result;
}
+VideoCaptureController::FrameDropLogState::FrameDropLogState(
+ media::VideoCaptureFrameDropReason reason)
+ : drop_count((reason == media::VideoCaptureFrameDropReason::kNone) ? 0 : 1),
+ drop_reason(reason),
+ max_log_count_exceeded(false) {}
+
VideoCaptureController::VideoCaptureController(
const std::string& device_id,
MediaStreamType stream_type,
@@ -231,7 +253,10 @@ void VideoCaptureController::AddClient(
// invalid or unsupported parameters.
LOG(DFATAL) << "Invalid or unsupported video capture parameters requested: "
<< media::VideoCaptureFormat::ToString(params.requested_format);
- event_handler->OnError(id);
+ event_handler->OnError(
+ id,
+ media::VideoCaptureError::
+ kVideoCaptureControllerInvalidOrUnsupportedVideoCaptureParametersRequested);
return;
}
@@ -241,7 +266,9 @@ void VideoCaptureController::AddClient(
// Signal error in case device is already in error state.
if (state_ == VIDEO_CAPTURE_STATE_ERROR) {
- event_handler->OnError(id);
+ event_handler->OnError(
+ id,
+ media::VideoCaptureError::kVideoCaptureControllerIsAlreadyInErrorState);
return;
}
@@ -417,6 +444,8 @@ void VideoCaptureController::OnFrameReadyInBuffer(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK_NE(buffer_id, media::VideoCaptureBufferPool::kInvalidId);
+ frame_drop_log_state_ = FrameDropLogState();
+
auto buffer_context_iter = FindUnretiredBufferContextFromBufferId(buffer_id);
DCHECK(buffer_context_iter != buffer_contexts_.end());
buffer_context_iter->set_frame_feedback_id(frame_feedback_id);
@@ -496,10 +525,39 @@ void VideoCaptureController::OnBufferRetired(int buffer_id) {
buffer_context_iter->set_is_retired();
}
-void VideoCaptureController::OnError() {
+void VideoCaptureController::OnError(media::VideoCaptureError error) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
state_ = VIDEO_CAPTURE_STATE_ERROR;
- PerformForClientsWithOpenSession(base::Bind(&CallOnError));
+ PerformForClientsWithOpenSession(base::BindRepeating(&CallOnError, error));
+}
+
+void VideoCaptureController::OnFrameDropped(
+ media::VideoCaptureFrameDropReason reason) {
+ if (reason == frame_drop_log_state_.drop_reason) {
+ if (frame_drop_log_state_.max_log_count_exceeded)
+ return;
+
+ if (++frame_drop_log_state_.drop_count >
+ kMaxConsecutiveFrameDropForSameReasonCount) {
+ frame_drop_log_state_.max_log_count_exceeded = true;
+ LogMaxConsecutiveVideoFrameDropCountExceeded(reason);
+ std::ostringstream string_stream;
+ string_stream << "Too many consecutive frames dropped with reason code "
+ << static_cast<int>(reason)
+ << ". Stopping to log dropped frames for this reason in "
+ "order to avoid log spam.";
+ EmitLogMessage(string_stream.str(), 1);
+ return;
+ }
+ } else {
+ frame_drop_log_state_ = FrameDropLogState(reason);
+ }
+
+ LogVideoFrameDrop(reason);
+ std::ostringstream string_stream;
+ string_stream << "Frame dropped with reason code "
+ << static_cast<int>(reason);
+ EmitLogMessage(string_stream.str(), 1);
}
void VideoCaptureController::OnLog(const std::string& message) {
@@ -510,13 +568,14 @@ void VideoCaptureController::OnLog(const std::string& message) {
void VideoCaptureController::OnStarted() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
state_ = VIDEO_CAPTURE_STATE_STARTED;
- PerformForClientsWithOpenSession(base::Bind(&CallOnStarted));
+ PerformForClientsWithOpenSession(base::BindRepeating(&CallOnStarted));
}
void VideoCaptureController::OnStartedUsingGpuDecode() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
OnLog("StartedUsingGpuDecode");
- PerformForClientsWithOpenSession(base::Bind(&CallOnStartedUsingGpuDecode));
+ PerformForClientsWithOpenSession(
+ base::BindRepeating(&CallOnStartedUsingGpuDecode));
}
void VideoCaptureController::OnDeviceLaunched(
@@ -530,10 +589,11 @@ void VideoCaptureController::OnDeviceLaunched(
}
}
-void VideoCaptureController::OnDeviceLaunchFailed() {
+void VideoCaptureController::OnDeviceLaunchFailed(
+ media::VideoCaptureError error) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (device_launch_observer_) {
- device_launch_observer_->OnDeviceLaunchFailed(this);
+ device_launch_observer_->OnDeviceLaunchFailed(this, error);
device_launch_observer_ = nullptr;
}
}
diff --git a/chromium/content/browser/renderer_host/media/video_capture_controller.h b/chromium/content/browser/renderer_host/media/video_capture_controller.h
index 62c39fa7901..9179ecde427 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_controller.h
+++ b/chromium/content/browser/renderer_host/media/video_capture_controller.h
@@ -48,6 +48,11 @@ class CONTENT_EXPORT VideoCaptureController
std::unique_ptr<VideoCaptureDeviceLauncher> device_launcher,
base::RepeatingCallback<void(const std::string&)> emit_log_message_cb);
+ // Warning: This value should not be changed, because doing so would change
+ // the meaning of logged UMA events for histograms Media.VideoCapture.Error
+ // and Media.VideoCapture.MaxFrameDropExceeded.
+ static constexpr int kMaxConsecutiveFrameDropForSameReasonCount = 10;
+
base::WeakPtr<VideoCaptureController> GetWeakPtrForIOThread();
// Start video capturing and try to use the resolution specified in |params|.
@@ -109,7 +114,8 @@ class CONTENT_EXPORT VideoCaptureController
buffer_read_permission,
media::mojom::VideoFrameInfoPtr frame_info) override;
void OnBufferRetired(int buffer_id) override;
- void OnError() override;
+ void OnError(media::VideoCaptureError error) override;
+ void OnFrameDropped(media::VideoCaptureFrameDropReason reason) override;
void OnLog(const std::string& message) override;
void OnStarted() override;
void OnStartedUsingGpuDecode() override;
@@ -117,7 +123,7 @@ class CONTENT_EXPORT VideoCaptureController
// Implementation of VideoCaptureDeviceLauncher::Callbacks interface:
void OnDeviceLaunched(
std::unique_ptr<LaunchedVideoCaptureDevice> device) override;
- void OnDeviceLaunchFailed() override;
+ void OnDeviceLaunchFailed(media::VideoCaptureError error) override;
void OnDeviceLaunchAborted() override;
void OnDeviceConnectionLost();
@@ -196,6 +202,16 @@ class CONTENT_EXPORT VideoCaptureController
buffer_read_permission_;
};
+ struct FrameDropLogState {
+ FrameDropLogState(media::VideoCaptureFrameDropReason reason =
+ media::VideoCaptureFrameDropReason::kNone);
+
+ int drop_count = 0;
+ media::VideoCaptureFrameDropReason drop_reason =
+ media::VideoCaptureFrameDropReason::kNone;
+ bool max_log_count_exceeded = false;
+ };
+
~VideoCaptureController() override;
// Find a client of |id| and |handler| in |clients|.
@@ -219,8 +235,8 @@ class CONTENT_EXPORT VideoCaptureController
const std::vector<BufferContext>::iterator& buffer_state_iter);
using EventHandlerAction =
- base::Callback<void(VideoCaptureControllerEventHandler* client,
- VideoCaptureControllerID id)>;
+ base::RepeatingCallback<void(VideoCaptureControllerEventHandler* client,
+ VideoCaptureControllerID id)>;
void PerformForClientsWithOpenSession(EventHandlerAction action);
void EmitLogMessage(const std::string& message, int verbose_log_level);
@@ -243,6 +259,8 @@ class CONTENT_EXPORT VideoCaptureController
// absorbing state which stops the flow of data to clients.
VideoCaptureState state_;
+ FrameDropLogState frame_drop_log_state_;
+
int next_buffer_context_id_ = 0;
// True if the controller has received a video frame from the device.
diff --git a/chromium/content/browser/renderer_host/media/video_capture_controller_event_handler.h b/chromium/content/browser/renderer_host/media/video_capture_controller_event_handler.h
index 4cac4888331..a2564afb998 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_controller_event_handler.h
+++ b/chromium/content/browser/renderer_host/media/video_capture_controller_event_handler.h
@@ -33,7 +33,8 @@ typedef int VideoCaptureControllerID;
class CONTENT_EXPORT VideoCaptureControllerEventHandler {
public:
// An Error has occurred in the VideoCaptureDevice.
- virtual void OnError(VideoCaptureControllerID id) = 0;
+ virtual void OnError(VideoCaptureControllerID id,
+ media::VideoCaptureError error) = 0;
virtual void OnNewBuffer(VideoCaptureControllerID id,
media::mojom::VideoBufferHandlePtr buffer_handle,
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 a9ae13311f3..a5af5ca6252 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
@@ -10,6 +10,7 @@
#include <memory>
#include <string>
#include <utility>
+#include "base/metrics/histogram_macros.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
@@ -18,6 +19,7 @@
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
+#include "base/test/metrics/histogram_tester.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/renderer_host/media/media_stream_provider.h"
#include "content/browser/renderer_host/media/mock_video_capture_provider.h"
@@ -62,11 +64,15 @@ class MockVideoCaptureControllerEventHandler
void(VideoCaptureControllerID, int buffer_id));
MOCK_METHOD2(DoBufferReady, void(VideoCaptureControllerID, const gfx::Size&));
MOCK_METHOD1(DoEnded, void(VideoCaptureControllerID));
- MOCK_METHOD1(DoError, void(VideoCaptureControllerID));
+ MOCK_METHOD2(DoError,
+ void(VideoCaptureControllerID, media::VideoCaptureError));
MOCK_METHOD1(OnStarted, void(VideoCaptureControllerID));
MOCK_METHOD1(OnStartedUsingGpuDecode, void(VideoCaptureControllerID));
- void OnError(VideoCaptureControllerID id) override { DoError(id); }
+ void OnError(VideoCaptureControllerID id,
+ media::VideoCaptureError error) override {
+ DoError(id, error);
+ }
void OnNewBuffer(VideoCaptureControllerID id,
media::mojom::VideoBufferHandlePtr buffer_handle,
int length,
@@ -513,14 +519,24 @@ TEST_F(VideoCaptureControllerTest, ErrorBeforeDeviceCreation) {
// Start with one client.
controller_->AddClient(route_id, client_a_.get(), 100, session_100);
- device_client_->OnError(FROM_HERE, "Test Error");
- EXPECT_CALL(*client_a_, DoError(route_id)).Times(1);
+ device_client_->OnError(
+ media::VideoCaptureError::kIntentionalErrorRaisedByUnitTest, FROM_HERE,
+ "Test Error");
+ EXPECT_CALL(
+ *client_a_,
+ DoError(route_id,
+ media::VideoCaptureError::kIntentionalErrorRaisedByUnitTest))
+ .Times(1);
base::RunLoop().RunUntilIdle();
Mock::VerifyAndClearExpectations(client_a_.get());
// Second client connects after the error state. It also should get told of
// the error.
- EXPECT_CALL(*client_b_, DoError(route_id)).Times(1);
+ EXPECT_CALL(
+ *client_b_,
+ DoError(route_id, media::VideoCaptureError::
+ kVideoCaptureControllerIsAlreadyInErrorState))
+ .Times(1);
controller_->AddClient(route_id, client_b_.get(), 200, session_200);
base::RunLoop().RunUntilIdle();
Mock::VerifyAndClearExpectations(client_b_.get());
@@ -568,18 +584,28 @@ TEST_F(VideoCaptureControllerTest, ErrorAfterDeviceCreation) {
arbitrary_frame_feedback_id);
ASSERT_TRUE(buffer.is_valid());
- device_client_->OnError(FROM_HERE, "Test Error");
+ device_client_->OnError(
+ media::VideoCaptureError::kIntentionalErrorRaisedByUnitTest, FROM_HERE,
+ "Test Error");
device_client_->OnIncomingCapturedBuffer(std::move(buffer), device_format,
arbitrary_reference_time_,
arbitrary_timestamp_);
- EXPECT_CALL(*client_a_, DoError(route_id)).Times(1);
+ EXPECT_CALL(
+ *client_a_,
+ DoError(route_id,
+ media::VideoCaptureError::kIntentionalErrorRaisedByUnitTest))
+ .Times(1);
base::RunLoop().RunUntilIdle();
Mock::VerifyAndClearExpectations(client_a_.get());
// Second client connects after the error state. It also should get told of
// the error.
- EXPECT_CALL(*client_b_, DoError(route_id)).Times(1);
+ EXPECT_CALL(
+ *client_b_,
+ DoError(route_id, media::VideoCaptureError::
+ kVideoCaptureControllerIsAlreadyInErrorState))
+ .Times(1);
controller_->AddClient(route_id, client_b_.get(), 200, session_200);
Mock::VerifyAndClearExpectations(client_b_.get());
}
@@ -828,4 +854,140 @@ TEST_F(VideoCaptureControllerTest, OnStartedForMultipleClients) {
controller_->AddClient(client_a_route_2, client_a_.get(), 200, session_200);
}
}
+
+TEST_F(VideoCaptureControllerTest, DroppedFramesGetLoggedInUMA) {
+ base::HistogramTester histogram_tester;
+
+ controller_->OnFrameDropped(
+ media::VideoCaptureFrameDropReason::kDeviceClientFrameHasInvalidFormat);
+ controller_->OnFrameDropped(
+ media::VideoCaptureFrameDropReason::
+ kDeviceClientFailedToReserveBufferFromBufferPool);
+ controller_->OnFrameDropped(
+ media::VideoCaptureFrameDropReason::kDeviceClientFrameHasInvalidFormat);
+
+ histogram_tester.ExpectBucketCount(
+ "Media.VideoCapture.FrameDrop",
+ media::VideoCaptureFrameDropReason::kDeviceClientFrameHasInvalidFormat,
+ 2);
+ histogram_tester.ExpectBucketCount(
+ "Media.VideoCapture.FrameDrop",
+ media::VideoCaptureFrameDropReason::
+ kDeviceClientFailedToReserveBufferFromBufferPool,
+ 1);
+}
+
+// Tests that too many frames dropped for the same reason emits a special UMA
+// log and disables further logging
+TEST_F(VideoCaptureControllerTest,
+ DroppedFrameLoggingGetsDisabledIfTooManyConsecutiveDropsForSameReason) {
+ base::HistogramTester histogram_tester;
+
+ for (int i = 0;
+ i < VideoCaptureController::kMaxConsecutiveFrameDropForSameReasonCount;
+ i++) {
+ controller_->OnFrameDropped(
+ media::VideoCaptureFrameDropReason::kDeviceClientFrameHasInvalidFormat);
+ }
+ histogram_tester.ExpectBucketCount(
+ "Media.VideoCapture.FrameDrop",
+ media::VideoCaptureFrameDropReason::kDeviceClientFrameHasInvalidFormat,
+ VideoCaptureController::kMaxConsecutiveFrameDropForSameReasonCount);
+
+ // Add one more count after already having reached the max allowed.
+ // This should not get counted.
+ controller_->OnFrameDropped(
+ media::VideoCaptureFrameDropReason::kDeviceClientFrameHasInvalidFormat);
+ histogram_tester.ExpectBucketCount(
+ "Media.VideoCapture.FrameDrop",
+ media::VideoCaptureFrameDropReason::kDeviceClientFrameHasInvalidFormat,
+ VideoCaptureController::kMaxConsecutiveFrameDropForSameReasonCount);
+
+ histogram_tester.ExpectBucketCount(
+ "Media.VideoCapture.MaxFrameDropExceeded",
+ media::VideoCaptureFrameDropReason::kDeviceClientFrameHasInvalidFormat,
+ 1);
+}
+
+TEST_F(VideoCaptureControllerTest,
+ DeliveredFrameInBetweenDroppedFramesResetsCounter) {
+ base::HistogramTester histogram_tester;
+ for (int i = 0;
+ i <
+ VideoCaptureController::kMaxConsecutiveFrameDropForSameReasonCount - 1;
+ i++) {
+ controller_->OnFrameDropped(
+ media::VideoCaptureFrameDropReason::kDeviceClientFrameHasInvalidFormat);
+ }
+
+ SendStubFrameToDeviceClient(arbitrary_format_);
+ base::RunLoop().RunUntilIdle();
+
+ for (int i = 0;
+ i < VideoCaptureController::kMaxConsecutiveFrameDropForSameReasonCount;
+ i++) {
+ controller_->OnFrameDropped(
+ media::VideoCaptureFrameDropReason::kDeviceClientFrameHasInvalidFormat);
+ }
+ histogram_tester.ExpectBucketCount(
+ "Media.VideoCapture.FrameDrop",
+ media::VideoCaptureFrameDropReason::kDeviceClientFrameHasInvalidFormat,
+ 2 * VideoCaptureController::kMaxConsecutiveFrameDropForSameReasonCount -
+ 1);
+}
+
+TEST_F(VideoCaptureControllerTest, DeliveredFrameReenablesDroppedFrameLogging) {
+ base::HistogramTester histogram_tester;
+
+ // Drop enough frames to disable logging
+ for (int i = 0;
+ i <
+ VideoCaptureController::kMaxConsecutiveFrameDropForSameReasonCount + 1;
+ i++) {
+ controller_->OnFrameDropped(
+ media::VideoCaptureFrameDropReason::kDeviceClientFrameHasInvalidFormat);
+ }
+
+ SendStubFrameToDeviceClient(arbitrary_format_);
+ base::RunLoop().RunUntilIdle();
+
+ controller_->OnFrameDropped(
+ media::VideoCaptureFrameDropReason::kDeviceClientFrameHasInvalidFormat);
+ histogram_tester.ExpectBucketCount(
+ "Media.VideoCapture.FrameDrop",
+ media::VideoCaptureFrameDropReason::kDeviceClientFrameHasInvalidFormat,
+ VideoCaptureController::kMaxConsecutiveFrameDropForSameReasonCount + 1);
+}
+
+TEST_F(VideoCaptureControllerTest,
+ ChangeInDropReasonReenablesDroppedFrameLogging) {
+ base::HistogramTester histogram_tester;
+
+ // Drop enough frames to disable logging
+ for (int i = 0;
+ i <
+ VideoCaptureController::kMaxConsecutiveFrameDropForSameReasonCount + 1;
+ i++) {
+ controller_->OnFrameDropped(
+ media::VideoCaptureFrameDropReason::kDeviceClientFrameHasInvalidFormat);
+ }
+
+ // Drop for a different reason
+ controller_->OnFrameDropped(
+ media::VideoCaptureFrameDropReason::
+ kDeviceClientFailedToReserveBufferFromBufferPool);
+
+ controller_->OnFrameDropped(
+ media::VideoCaptureFrameDropReason::kDeviceClientFrameHasInvalidFormat);
+ histogram_tester.ExpectBucketCount(
+ "Media.VideoCapture.FrameDrop",
+ media::VideoCaptureFrameDropReason::kDeviceClientFrameHasInvalidFormat,
+ VideoCaptureController::kMaxConsecutiveFrameDropForSameReasonCount + 1);
+ histogram_tester.ExpectBucketCount(
+ "Media.VideoCapture.FrameDrop",
+ media::VideoCaptureFrameDropReason::
+ kDeviceClientFailedToReserveBufferFromBufferPool,
+ 1);
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/video_capture_device_launch_observer.h b/chromium/content/browser/renderer_host/media/video_capture_device_launch_observer.h
index 33e4b1bfea8..a0f492972b5 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_device_launch_observer.h
+++ b/chromium/content/browser/renderer_host/media/video_capture_device_launch_observer.h
@@ -6,6 +6,7 @@
#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_DEVICE_LAUNCH_OBSERVER_H_
#include "content/common/content_export.h"
+#include "media/capture/video_capture_types.h"
namespace content {
@@ -15,7 +16,8 @@ class CONTENT_EXPORT VideoCaptureDeviceLaunchObserver {
public:
virtual ~VideoCaptureDeviceLaunchObserver() {}
virtual void OnDeviceLaunched(VideoCaptureController* controller) = 0;
- virtual void OnDeviceLaunchFailed(VideoCaptureController* controller) = 0;
+ virtual void OnDeviceLaunchFailed(VideoCaptureController* controller,
+ media::VideoCaptureError error) = 0;
virtual void OnDeviceLaunchAborted() = 0;
virtual void OnDeviceConnectionLost(VideoCaptureController* controller) = 0;
};
diff --git a/chromium/content/browser/renderer_host/media/video_capture_host.cc b/chromium/content/browser/renderer_host/media/video_capture_host.cc
index 209d64c83db..d35e6a28544 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_host.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_host.cc
@@ -89,7 +89,8 @@ VideoCaptureHost::~VideoCaptureHost() {
if (controller) {
const VideoCaptureControllerID controller_id(it->first);
media_stream_manager_->video_capture_manager()->DisconnectClient(
- controller.get(), controller_id, this, false);
+ controller.get(), controller_id, this,
+ media::VideoCaptureError::kNone);
++it;
} else {
// Remove the entry for this controller_id so that when the controller
@@ -104,13 +105,14 @@ VideoCaptureHost::~VideoCaptureHost() {
render_process_host_delegate_.release());
}
-void VideoCaptureHost::OnError(VideoCaptureControllerID controller_id) {
+void VideoCaptureHost::OnError(VideoCaptureControllerID controller_id,
+ media::VideoCaptureError error) {
DVLOG(1) << __func__;
DCHECK_CURRENTLY_ON(BrowserThread::IO);
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(&VideoCaptureHost::DoError, weak_factory_.GetWeakPtr(),
- controller_id));
+ controller_id, error));
}
void VideoCaptureHost::OnNewBuffer(
@@ -216,7 +218,7 @@ void VideoCaptureHost::Stop(int32_t device_id) {
}
device_id_to_observer_map_.erase(controller_id);
- DeleteVideoCaptureController(controller_id, false);
+ DeleteVideoCaptureController(controller_id, media::VideoCaptureError::kNone);
NotifyStreamRemoved();
}
@@ -316,7 +318,8 @@ void VideoCaptureHost::GetDeviceFormatsInUse(
std::move(callback).Run(formats_in_use);
}
-void VideoCaptureHost::DoError(VideoCaptureControllerID controller_id) {
+void VideoCaptureHost::DoError(VideoCaptureControllerID controller_id,
+ media::VideoCaptureError error) {
DVLOG(1) << __func__;
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (controllers_.find(controller_id) == controllers_.end())
@@ -327,7 +330,7 @@ void VideoCaptureHost::DoError(VideoCaptureControllerID controller_id) {
media::mojom::VideoCaptureState::FAILED);
}
- DeleteVideoCaptureController(controller_id, true);
+ DeleteVideoCaptureController(controller_id, error);
NotifyStreamRemoved();
}
@@ -342,7 +345,7 @@ void VideoCaptureHost::DoEnded(VideoCaptureControllerID controller_id) {
media::mojom::VideoCaptureState::ENDED);
}
- DeleteVideoCaptureController(controller_id, false);
+ DeleteVideoCaptureController(controller_id, media::VideoCaptureError::kNone);
NotifyStreamRemoved();
}
@@ -355,7 +358,8 @@ void VideoCaptureHost::OnControllerAdded(
if (it == controllers_.end()) {
if (controller) {
media_stream_manager_->video_capture_manager()->DisconnectClient(
- controller.get(), controller_id, this, false);
+ controller.get(), controller_id, this,
+ media::VideoCaptureError::kNone);
}
return;
}
@@ -374,7 +378,8 @@ void VideoCaptureHost::OnControllerAdded(
}
void VideoCaptureHost::DeleteVideoCaptureController(
- VideoCaptureControllerID controller_id, bool on_error) {
+ VideoCaptureControllerID controller_id,
+ media::VideoCaptureError error) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
auto it = controllers_.find(controller_id);
@@ -387,7 +392,7 @@ void VideoCaptureHost::DeleteVideoCaptureController(
return;
media_stream_manager_->video_capture_manager()->DisconnectClient(
- controller.get(), controller_id, this, on_error);
+ controller.get(), controller_id, this, error);
}
void VideoCaptureHost::NotifyStreamAdded() {
diff --git a/chromium/content/browser/renderer_host/media/video_capture_host.h b/chromium/content/browser/renderer_host/media/video_capture_host.h
index d19c4ad5b20..5fdecfe6c63 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_host.h
+++ b/chromium/content/browser/renderer_host/media/video_capture_host.h
@@ -53,7 +53,8 @@ class CONTENT_EXPORT VideoCaptureHost
FRIEND_TEST_ALL_PREFIXES(VideoCaptureTest, IncrementMatchesDecrementCalls);
// VideoCaptureControllerEventHandler implementation.
- void OnError(VideoCaptureControllerID id) override;
+ void OnError(VideoCaptureControllerID id,
+ media::VideoCaptureError error) override;
void OnNewBuffer(VideoCaptureControllerID id,
media::mojom::VideoBufferHandlePtr buffer_handle,
int length,
@@ -90,7 +91,7 @@ class CONTENT_EXPORT VideoCaptureHost
int32_t session_id,
GetDeviceFormatsInUseCallback callback) override;
- void DoError(VideoCaptureControllerID id);
+ void DoError(VideoCaptureControllerID id, media::VideoCaptureError error);
void DoEnded(VideoCaptureControllerID id);
// Bound as callback for VideoCaptureManager::StartCaptureForClient().
@@ -102,7 +103,7 @@ class CONTENT_EXPORT VideoCaptureHost
// to StopCaptureForClient(). |on_error| is true if this is triggered by
// VideoCaptureControllerEventHandler::OnError.
void DeleteVideoCaptureController(VideoCaptureControllerID controller_id,
- bool on_error);
+ media::VideoCaptureError error);
void NotifyStreamAdded();
void NotifyStreamRemoved();
diff --git a/chromium/content/browser/renderer_host/media/video_capture_manager.cc b/chromium/content/browser/renderer_host/media/video_capture_manager.cc
index 3cdff16e6ef..12e9dc70f33 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_manager.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_manager.cc
@@ -49,6 +49,12 @@ void LogVideoCaptureEvent(VideoCaptureEvent event) {
NUM_VIDEO_CAPTURE_EVENT);
}
+void LogVideoCaptureError(media::VideoCaptureError error) {
+ UMA_HISTOGRAM_ENUMERATION(
+ "Media.VideoCapture.Error", error,
+ static_cast<int>(media::VideoCaptureError::kMaxValue) + 1);
+}
+
const media::VideoCaptureSessionId kFakeSessionId = -1;
} // namespace
@@ -263,7 +269,10 @@ void VideoCaptureManager::ProcessDeviceStartRequestQueue() {
const media::VideoCaptureDeviceInfo* device_info =
GetDeviceInfoById(controller->device_id());
if (!device_info) {
- OnDeviceLaunchFailed(controller);
+ OnDeviceLaunchFailed(
+ controller,
+ media::VideoCaptureError::
+ kVideoCaptureManagerProcessDeviceStartQueueDeviceInfoNotFound);
return;
}
for (auto& observer : capture_observers_)
@@ -295,7 +304,7 @@ void VideoCaptureManager::OnDeviceLaunched(VideoCaptureController* controller) {
DCHECK_EQ(controller, device_start_request_queue_.begin()->controller());
DCHECK(controller);
- if (controller->stream_type() == MEDIA_DESKTOP_VIDEO_CAPTURE) {
+ if (controller->stream_type() == MEDIA_GUM_DESKTOP_VIDEO_CAPTURE) {
const media::VideoCaptureSessionId session_id =
device_start_request_queue_.front().session_id();
DCHECK(session_id != kFakeSessionId);
@@ -318,12 +327,13 @@ void VideoCaptureManager::OnDeviceLaunched(VideoCaptureController* controller) {
}
void VideoCaptureManager::OnDeviceLaunchFailed(
- VideoCaptureController* controller) {
+ VideoCaptureController* controller,
+ media::VideoCaptureError error) {
std::ostringstream string_stream;
string_stream << "Launching device has failed. device_id = "
<< controller->device_id();
EmitLogMessage(string_stream.str(), 1);
- controller->OnError();
+ controller->OnError(error);
device_start_request_queue_.pop_front();
ProcessDeviceStartRequestQueue();
@@ -341,7 +351,8 @@ void VideoCaptureManager::OnDeviceConnectionLost(
string_stream << "Lost connection to device. device_id = "
<< controller->device_id();
EmitLogMessage(string_stream.str(), 1);
- controller->OnError();
+ controller->OnError(
+ media::VideoCaptureError::kVideoCaptureManagerDeviceConnectionLost);
}
void VideoCaptureManager::ConnectClient(
@@ -387,7 +398,7 @@ void VideoCaptureManager::DisconnectClient(
VideoCaptureController* controller,
VideoCaptureControllerID client_id,
VideoCaptureControllerEventHandler* client_handler,
- bool aborted_due_to_error) {
+ media::VideoCaptureError error) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(controller);
DCHECK(client_handler);
@@ -396,7 +407,7 @@ void VideoCaptureManager::DisconnectClient(
NOTREACHED();
return;
}
- if (!aborted_due_to_error) {
+ if (error == media::VideoCaptureError::kNone) {
if (controller->has_received_frames()) {
LogVideoCaptureEvent(VIDEO_CAPTURE_STOP_CAPTURE_OK);
} else if (controller->stream_type() == MEDIA_DEVICE_VIDEO_CAPTURE) {
@@ -408,6 +419,11 @@ void VideoCaptureManager::DisconnectClient(
}
} else {
LogVideoCaptureEvent(VIDEO_CAPTURE_STOP_CAPTURE_DUE_TO_ERROR);
+ LogVideoCaptureError(error);
+ std::ostringstream string_stream;
+ string_stream << "Video capture session stopped with error code "
+ << static_cast<int>(error);
+ EmitLogMessage(string_stream.str(), 1);
for (auto it : sessions_) {
if (it.second.type == controller->stream_type() &&
it.second.id == controller->device_id()) {
@@ -573,7 +589,7 @@ void VideoCaptureManager::MaybePostDesktopCaptureWindowId(
return;
}
- DCHECK_EQ(MEDIA_DESKTOP_VIDEO_CAPTURE, existing_device->stream_type());
+ DCHECK_EQ(MEDIA_GUM_DESKTOP_VIDEO_CAPTURE, existing_device->stream_type());
DesktopMediaID id = DesktopMediaID::Parse(existing_device->device_id());
if (id.is_null())
return;
diff --git a/chromium/content/browser/renderer_host/media/video_capture_manager.h b/chromium/content/browser/renderer_host/media/video_capture_manager.h
index 0604c90425d..a32d287958c 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_manager.h
+++ b/chromium/content/browser/renderer_host/media/video_capture_manager.h
@@ -97,7 +97,7 @@ class CONTENT_EXPORT VideoCaptureManager
void DisconnectClient(VideoCaptureController* controller,
VideoCaptureControllerID client_id,
VideoCaptureControllerEventHandler* client_handler,
- bool aborted_due_to_error);
+ media::VideoCaptureError error);
// Called by VideoCaptureHost to pause to update video buffer specified by
// |client_id| and |client_handler|. If all clients of |controller| are
@@ -179,7 +179,8 @@ class CONTENT_EXPORT VideoCaptureManager
// VideoCaptureDeviceLaunchObserver implementation:
void OnDeviceLaunched(VideoCaptureController* controller) override;
- void OnDeviceLaunchFailed(VideoCaptureController* controller) override;
+ void OnDeviceLaunchFailed(VideoCaptureController* controller,
+ media::VideoCaptureError error) override;
void OnDeviceLaunchAborted() override;
void OnDeviceConnectionLost(VideoCaptureController* controller) override;
@@ -264,7 +265,7 @@ class CONTENT_EXPORT VideoCaptureManager
void EmitLogMessage(const std::string& message, int verbose_log_level);
// Only accessed on Browser::IO thread.
- base::ObserverList<MediaStreamProviderListener> listeners_;
+ base::ObserverList<MediaStreamProviderListener>::Unchecked listeners_;
media::VideoCaptureSessionId new_capture_session_id_;
// An entry is kept in this map for every session that has been created via
@@ -288,7 +289,7 @@ class CONTENT_EXPORT VideoCaptureManager
const std::unique_ptr<VideoCaptureProvider> video_capture_provider_;
base::RepeatingCallback<void(const std::string&)> emit_log_message_cb_;
- base::ObserverList<media::VideoCaptureObserver> capture_observers_;
+ base::ObserverList<media::VideoCaptureObserver>::Unchecked capture_observers_;
// Local cache of the enumerated DeviceInfos. GetDeviceSupportedFormats() will
// use this list if the device is not started, otherwise it will retrieve the
diff --git a/chromium/content/browser/renderer_host/media/video_capture_manager_unittest.cc b/chromium/content/browser/renderer_host/media/video_capture_manager_unittest.cc
index 5816d1b3803..ce592438e1d 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_manager_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_manager_unittest.cc
@@ -152,7 +152,9 @@ class MockMediaStreamProviderListener : public MediaStreamProviderListener {
// Needed as an input argument to ConnectClient().
class MockFrameObserver : public VideoCaptureControllerEventHandler {
public:
- MOCK_METHOD1(OnError, void(VideoCaptureControllerID id));
+ MOCK_METHOD2(OnError,
+ void(VideoCaptureControllerID id,
+ media::VideoCaptureError error));
MOCK_METHOD1(OnStarted, void(VideoCaptureControllerID id));
MOCK_METHOD1(OnStartedUsingGpuDecode, void(VideoCaptureControllerID id));
@@ -258,7 +260,8 @@ class VideoCaptureManagerTest : public testing::Test {
void StopClient(VideoCaptureControllerID client_id) {
ASSERT_TRUE(1 == controllers_.count(client_id));
vcm_->DisconnectClient(controllers_[client_id], client_id,
- frame_observer_.get(), false);
+ frame_observer_.get(),
+ media::VideoCaptureError::kNone);
controllers_.erase(client_id);
}
@@ -355,8 +358,9 @@ TEST_F(VideoCaptureManagerTest, CreateAndAbort) {
// Wait for device opened.
base::RunLoop().RunUntilIdle();
- vcm_->DisconnectClient(controllers_[client_id], client_id,
- frame_observer_.get(), true);
+ vcm_->DisconnectClient(
+ controllers_[client_id], client_id, frame_observer_.get(),
+ media::VideoCaptureError::kIntentionalErrorRaisedByUnitTest);
// Wait to check callbacks before removing the listener.
base::RunLoop().RunUntilIdle();
@@ -666,7 +670,7 @@ TEST_F(VideoCaptureManagerTest, OpenTwo) {
// Try open a non-existing device.
TEST_F(VideoCaptureManagerTest, OpenNotExisting) {
InSequence s;
- EXPECT_CALL(*frame_observer_, OnError(_));
+ EXPECT_CALL(*frame_observer_, OnError(_, _));
EXPECT_CALL(*listener_, Opened(MEDIA_DEVICE_VIDEO_CAPTURE, _));
EXPECT_CALL(*listener_, Closed(MEDIA_DEVICE_VIDEO_CAPTURE, _));
diff --git a/chromium/content/browser/renderer_host/media/video_capture_unittest.cc b/chromium/content/browser/renderer_host/media/video_capture_unittest.cc
index 6cebba5ed0f..13c722627ea 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_unittest.cc
@@ -142,9 +142,9 @@ class VideoCaptureTest : public testing::Test,
devices_to_enumerate[MEDIA_DEVICE_TYPE_VIDEO_INPUT] = true;
media_stream_manager_->media_devices_manager()->EnumerateDevices(
devices_to_enumerate,
- base::Bind(&VideoInputDevicesEnumerated, run_loop.QuitClosure(),
- browser_context_.GetMediaDeviceIDSalt(), security_origin,
- &video_devices));
+ base::BindOnce(&VideoInputDevicesEnumerated, run_loop.QuitClosure(),
+ browser_context_.GetMediaDeviceIDSalt(),
+ security_origin, &video_devices));
run_loop.Run();
}
ASSERT_FALSE(video_devices.empty());
@@ -277,7 +277,8 @@ class VideoCaptureTest : public testing::Test,
void SimulateError() {
EXPECT_CALL(*this, OnStateChanged(media::mojom::VideoCaptureState::FAILED));
VideoCaptureControllerID id(kDeviceId);
- host_->OnError(id);
+ host_->OnError(id,
+ media::VideoCaptureError::kIntentionalErrorRaisedByUnitTest);
base::RunLoop().RunUntilIdle();
}
diff --git a/chromium/content/browser/renderer_host/p2p/DEPS b/chromium/content/browser/renderer_host/p2p/DEPS
deleted file mode 100644
index 93e27aa264f..00000000000
--- a/chromium/content/browser/renderer_host/p2p/DEPS
+++ /dev/null
@@ -1,3 +0,0 @@
-include_rules = [
- "+jingle/glue",
-]
diff --git a/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.cc b/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.cc
index 270b2aaee40..ce859120f2e 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.cc
+++ b/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.cc
@@ -9,181 +9,29 @@
#include <algorithm>
#include "base/bind.h"
-#include "base/task_scheduler/post_task.h"
#include "content/browser/bad_message.h"
-#include "content/browser/renderer_host/p2p/socket_host.h"
-#include "content/common/p2p_messages.h"
-#include "content/public/browser/browser_thread.h"
-#include "net/base/address_list.h"
-#include "net/base/completion_callback.h"
+#include "content/browser/renderer_host/render_process_host_impl.h"
+#include "content/browser/storage_partition_impl.h"
#include "net/base/net_errors.h"
-#include "net/base/network_interfaces.h"
-#include "net/base/sys_addrinfo.h"
-#include "net/dns/host_resolver.h"
-#include "net/log/net_log_source.h"
-#include "net/log/net_log_with_source.h"
-#include "net/socket/client_socket_factory.h"
-#include "net/socket/datagram_client_socket.h"
-#include "net/traffic_annotation/network_traffic_annotation.h"
-#include "net/url_request/url_request_context.h"
-#include "net/url_request/url_request_context_getter.h"
-#include "services/network/proxy_resolving_client_socket_factory.h"
+#include "services/network/public/cpp/p2p_param_traits.h"
using content::BrowserMessageFilter;
using content::BrowserThread;
namespace content {
-namespace {
+P2PSocketDispatcherHost::P2PSocketDispatcherHost(int render_process_id)
+ : render_process_id_(render_process_id),
+ binding_(this),
+ weak_factory_(this) {}
-// Used by GetDefaultLocalAddress as the target to connect to for getting the
-// default local address. They are public DNS servers on the internet.
-const uint8_t kPublicIPv4Host[] = {8, 8, 8, 8};
-const uint8_t kPublicIPv6Host[] = {
- 0x20, 0x01, 0x48, 0x60, 0x48, 0x60, 0, 0, 0, 0, 0, 0, 0, 0, 0x88, 0x88};
-const int kPublicPort = 53; // DNS port.
-
-// Experimentation shows that creating too many sockets creates odd problems
-// because of resource exhaustion in the Unix sockets domain.
-// Trouble has been seen on Linux at 3479 sockets in test, so leave a margin.
-const int kMaxSimultaneousSockets = 3000;
-
-} // namespace
-
-const size_t kMaximumPacketSize = 32768;
-
-class P2PSocketDispatcherHost::DnsRequest {
- public:
- typedef base::Callback<void(const net::IPAddressList&)> DoneCallback;
-
- DnsRequest(int32_t request_id, net::HostResolver* host_resolver)
- : request_id_(request_id), resolver_(host_resolver) {}
-
- void Resolve(const std::string& host_name,
- const DoneCallback& done_callback) {
- DCHECK(!done_callback.is_null());
-
- host_name_ = host_name;
- done_callback_ = done_callback;
-
- // Return an error if it's an empty string.
- if (host_name_.empty()) {
- net::IPAddressList address_list;
- done_callback_.Run(address_list);
- return;
- }
-
- // Add period at the end to make sure that we only resolve
- // fully-qualified names.
- if (host_name_.back() != '.')
- host_name_ += '.';
-
- net::HostResolver::RequestInfo info(net::HostPortPair(host_name_, 0));
- int result = resolver_->Resolve(
- info, net::DEFAULT_PRIORITY, &addresses_,
- base::Bind(&P2PSocketDispatcherHost::DnsRequest::OnDone,
- base::Unretained(this)),
- &request_, net::NetLogWithSource());
- if (result != net::ERR_IO_PENDING)
- OnDone(result);
- }
-
- int32_t request_id() { return request_id_; }
-
- private:
- void OnDone(int result) {
- net::IPAddressList list;
- if (result != net::OK) {
- LOG(ERROR) << "Failed to resolve address for " << host_name_
- << ", errorcode: " << result;
- done_callback_.Run(list);
- return;
- }
-
- DCHECK(!addresses_.empty());
- for (net::AddressList::iterator iter = addresses_.begin();
- iter != addresses_.end(); ++iter) {
- list.push_back(iter->address());
- }
- done_callback_.Run(list);
- }
-
- int32_t request_id_;
- net::AddressList addresses_;
-
- std::string host_name_;
- net::HostResolver* resolver_;
- std::unique_ptr<net::HostResolver::Request> request_;
-
- DoneCallback done_callback_;
-};
-
-P2PSocketDispatcherHost::P2PSocketDispatcherHost(
- net::URLRequestContextGetter* url_context)
- : BrowserMessageFilter(P2PMsgStart),
- url_context_(url_context),
- monitoring_networks_(false),
- dump_incoming_rtp_packet_(false),
- dump_outgoing_rtp_packet_(false),
- network_list_task_runner_(base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::USER_VISIBLE})) {}
-
-void P2PSocketDispatcherHost::OnChannelClosing() {
- // Since the IPC sender is gone, close pending connections.
- sockets_.clear();
-
- dns_requests_.clear();
-
- if (monitoring_networks_) {
- net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
- monitoring_networks_ = false;
- }
-
- proxy_resolving_socket_factory_.reset();
-}
-
-void P2PSocketDispatcherHost::OnDestruct() const {
- BrowserThread::DeleteOnIOThread::Destruct(this);
-}
-
-bool P2PSocketDispatcherHost::OnMessageReceived(const IPC::Message& message) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(P2PSocketDispatcherHost, message)
- IPC_MESSAGE_HANDLER(P2PHostMsg_StartNetworkNotifications,
- OnStartNetworkNotifications)
- IPC_MESSAGE_HANDLER(P2PHostMsg_StopNetworkNotifications,
- OnStopNetworkNotifications)
- IPC_MESSAGE_HANDLER(P2PHostMsg_GetHostAddress, OnGetHostAddress)
- IPC_MESSAGE_HANDLER(P2PHostMsg_CreateSocket, OnCreateSocket)
- IPC_MESSAGE_HANDLER(P2PHostMsg_AcceptIncomingTcpConnection,
- OnAcceptIncomingTcpConnection)
- IPC_MESSAGE_HANDLER(P2PHostMsg_Send, OnSend)
- IPC_MESSAGE_HANDLER(P2PHostMsg_SetOption, OnSetOption)
- IPC_MESSAGE_HANDLER(P2PHostMsg_DestroySocket, OnDestroySocket)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-void P2PSocketDispatcherHost::OnNetworkChanged(
- net::NetworkChangeNotifier::ConnectionType type) {
- // NetworkChangeNotifier always emits CONNECTION_NONE notification whenever
- // network configuration changes. All other notifications can be ignored.
- if (type != net::NetworkChangeNotifier::CONNECTION_NONE)
- return;
-
- // Notify the renderer about changes to list of network interfaces.
- network_list_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&P2PSocketDispatcherHost::DoGetNetworkList, this));
-}
+P2PSocketDispatcherHost::~P2PSocketDispatcherHost() {}
void P2PSocketDispatcherHost::StartRtpDump(
bool incoming,
bool outgoing,
const RenderProcessHost::WebRtcRtpPacketCallback& packet_callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
if ((!dump_incoming_rtp_packet_ && incoming) ||
(!dump_outgoing_rtp_packet_ && outgoing)) {
if (incoming)
@@ -193,256 +41,70 @@ void P2PSocketDispatcherHost::StartRtpDump(
dump_outgoing_rtp_packet_ = true;
packet_callback_ = packet_callback;
- for (SocketsMap::iterator it = sockets_.begin(); it != sockets_.end(); ++it)
- it->second->StartRtpDump(incoming, outgoing, packet_callback);
+ if (trusted_socket_manager_)
+ trusted_socket_manager_->StartRtpDump(incoming, outgoing);
}
}
-void P2PSocketDispatcherHost::StopRtpDumpOnUIThread(bool incoming,
- bool outgoing) {
+void P2PSocketDispatcherHost::StopRtpDump(bool incoming, bool outgoing) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&P2PSocketDispatcherHost::StopRtpDumpOnIOThread, this,
- incoming, outgoing));
-}
-
-P2PSocketDispatcherHost::~P2PSocketDispatcherHost() {
- DCHECK(sockets_.empty());
- DCHECK(dns_requests_.empty());
-
- if (monitoring_networks_)
- net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
-}
-
-P2PSocketHost* P2PSocketDispatcherHost::LookupSocket(int socket_id) {
- SocketsMap::iterator it = sockets_.find(socket_id);
- return (it == sockets_.end()) ? nullptr : it->second.get();
-}
-
-void P2PSocketDispatcherHost::OnStartNetworkNotifications() {
- if (!monitoring_networks_) {
- net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
- monitoring_networks_ = true;
- }
-
- network_list_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&P2PSocketDispatcherHost::DoGetNetworkList, this));
-}
-
-void P2PSocketDispatcherHost::OnStopNetworkNotifications() {
- if (monitoring_networks_) {
- net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
- monitoring_networks_ = false;
- }
-}
-
-void P2PSocketDispatcherHost::OnGetHostAddress(const std::string& host_name,
- int32_t request_id) {
- std::unique_ptr<DnsRequest> request = std::make_unique<DnsRequest>(
- request_id, url_context_->GetURLRequestContext()->host_resolver());
- DnsRequest* request_ptr = request.get();
- dns_requests_.insert(std::move(request));
- request_ptr->Resolve(host_name,
- base::Bind(&P2PSocketDispatcherHost::OnAddressResolved,
- base::Unretained(this), request_ptr));
-}
-
-void P2PSocketDispatcherHost::OnCreateSocket(
- P2PSocketType type,
- int socket_id,
- const net::IPEndPoint& local_address,
- const P2PPortRange& port_range,
- const P2PHostAndIPEndPoint& remote_address) {
- if (port_range.min_port > port_range.max_port ||
- (port_range.min_port == 0 && port_range.max_port != 0)) {
- bad_message::ReceivedBadMessage(this, bad_message::SDH_INVALID_PORT_RANGE);
- return;
- }
-
- if (LookupSocket(socket_id)) {
- LOG(ERROR) << "Received P2PHostMsg_CreateSocket for socket "
- "that already exists.";
- return;
- }
-
- if (!proxy_resolving_socket_factory_) {
- proxy_resolving_socket_factory_ =
- std::make_unique<network::ProxyResolvingClientSocketFactory>(
- url_context_->GetURLRequestContext());
- }
- if (sockets_.size() > kMaxSimultaneousSockets) {
- LOG(ERROR) << "Too many sockets created";
- Send(new P2PMsg_OnError(socket_id));
- return;
- }
- std::unique_ptr<P2PSocketHost> socket(P2PSocketHost::Create(
- this, socket_id, type, url_context_.get(),
- proxy_resolving_socket_factory_.get(), &throttler_));
+ if ((dump_incoming_rtp_packet_ && incoming) ||
+ (dump_outgoing_rtp_packet_ && outgoing)) {
+ if (incoming)
+ dump_incoming_rtp_packet_ = false;
- if (!socket) {
- Send(new P2PMsg_OnError(socket_id));
- return;
- }
+ if (outgoing)
+ dump_outgoing_rtp_packet_ = false;
- if (socket->Init(local_address, port_range.min_port, port_range.max_port,
- remote_address)) {
- sockets_[socket_id] = std::move(socket);
+ if (!dump_incoming_rtp_packet_ && !dump_outgoing_rtp_packet_)
+ packet_callback_.Reset();
- if (dump_incoming_rtp_packet_ || dump_outgoing_rtp_packet_) {
- sockets_[socket_id]->StartRtpDump(dump_incoming_rtp_packet_,
- dump_outgoing_rtp_packet_,
- packet_callback_);
- }
+ if (trusted_socket_manager_)
+ trusted_socket_manager_->StopRtpDump(incoming, outgoing);
}
}
-void P2PSocketDispatcherHost::OnAcceptIncomingTcpConnection(
- int listen_socket_id, const net::IPEndPoint& remote_address,
- int connected_socket_id) {
- P2PSocketHost* socket = LookupSocket(listen_socket_id);
- if (!socket) {
- LOG(ERROR) << "Received P2PHostMsg_AcceptIncomingTcpConnection "
- "for invalid listen_socket_id.";
+void P2PSocketDispatcherHost::BindRequest(
+ network::mojom::P2PSocketManagerRequest request) {
+ auto* rph = RenderProcessHostImpl::FromID(render_process_id_);
+ if (!rph)
return;
- }
- if (LookupSocket(connected_socket_id) != nullptr) {
- LOG(ERROR) << "Received P2PHostMsg_AcceptIncomingTcpConnection "
- "for duplicated connected_socket_id.";
- return;
- }
- std::unique_ptr<P2PSocketHost> accepted_connection(
- socket->AcceptIncomingTcpConnection(remote_address, connected_socket_id));
- if (accepted_connection) {
- sockets_[connected_socket_id] = std::move(accepted_connection);
- }
-}
-
-void P2PSocketDispatcherHost::OnSend(
- int socket_id,
- const std::vector<char>& data,
- const P2PPacketInfo& packet_info,
- const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
- P2PSocketHost* socket = LookupSocket(socket_id);
- if (!socket) {
- LOG(ERROR) << "Received P2PHostMsg_Send for invalid socket_id.";
- return;
- }
+ network::mojom::P2PTrustedSocketManagerClientPtr
+ trusted_socket_manager_client;
+ binding_.Bind(mojo::MakeRequest(&trusted_socket_manager_client));
- if (data.size() > kMaximumPacketSize) {
- LOG(ERROR) << "Received P2PHostMsg_Send with a packet that is too big: "
- << data.size();
- Send(new P2PMsg_OnError(socket_id));
- sockets_.erase(socket_id); // deletes the socket
- return;
+ rph->GetStoragePartition()->GetNetworkContext()->CreateP2PSocketManager(
+ std::move(trusted_socket_manager_client),
+ mojo::MakeRequest(&trusted_socket_manager_), std::move(request));
+ if (dump_incoming_rtp_packet_ || dump_outgoing_rtp_packet_) {
+ trusted_socket_manager_->StartRtpDump(dump_incoming_rtp_packet_,
+ dump_outgoing_rtp_packet_);
}
-
- socket->Send(packet_info.destination, data, packet_info.packet_options,
- packet_info.packet_id,
- net::NetworkTrafficAnnotationTag(traffic_annotation));
}
-void P2PSocketDispatcherHost::OnSetOption(int socket_id,
- P2PSocketOption option,
- int value) {
- P2PSocketHost* socket = LookupSocket(socket_id);
- if (!socket) {
- LOG(ERROR) << "Received P2PHostMsg_SetOption for invalid socket_id.";
- return;
- }
-
- socket->SetOption(option, value);
+base::WeakPtr<P2PSocketDispatcherHost> P2PSocketDispatcherHost::GetWeakPtr() {
+ return weak_factory_.GetWeakPtr();
}
-void P2PSocketDispatcherHost::OnDestroySocket(int socket_id) {
- SocketsMap::iterator it = sockets_.find(socket_id);
- if (it != sockets_.end()) {
- sockets_.erase(it); // deletes the socket
- } else {
- LOG(ERROR) << "Received P2PHostMsg_DestroySocket for invalid socket_id.";
- }
+void P2PSocketDispatcherHost::InvalidSocketPortRangeRequested() {
+ bad_message::ReceivedBadMessage(render_process_id_,
+ bad_message::SDH_INVALID_PORT_RANGE);
}
-void P2PSocketDispatcherHost::DoGetNetworkList() {
- net::NetworkInterfaceList list;
- if (!net::GetNetworkList(&list, net::EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES)) {
- LOG(ERROR) << "GetNetworkList failed.";
+void P2PSocketDispatcherHost::DumpPacket(
+ const std::vector<uint8_t>& packet_header,
+ uint64_t packet_length,
+ bool incoming) {
+ if (!packet_callback_)
return;
- }
- default_ipv4_local_address_ = GetDefaultLocalAddress(AF_INET);
- default_ipv6_local_address_ = GetDefaultLocalAddress(AF_INET6);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&P2PSocketDispatcherHost::SendNetworkList, this, list,
- default_ipv4_local_address_, default_ipv6_local_address_));
-}
-
-void P2PSocketDispatcherHost::SendNetworkList(
- const net::NetworkInterfaceList& list,
- const net::IPAddress& default_ipv4_local_address,
- const net::IPAddress& default_ipv6_local_address) {
- Send(new P2PMsg_NetworkListChanged(list, default_ipv4_local_address,
- default_ipv6_local_address));
-}
-
-net::IPAddress P2PSocketDispatcherHost::GetDefaultLocalAddress(int family) {
- DCHECK(family == AF_INET || family == AF_INET6);
-
- // Creation and connection of a UDP socket might be janky.
- DCHECK(network_list_task_runner_->RunsTasksInCurrentSequence());
-
- auto socket =
- net::ClientSocketFactory::GetDefaultFactory()->CreateDatagramClientSocket(
- net::DatagramSocket::DEFAULT_BIND, nullptr, net::NetLogSource());
-
- net::IPAddress ip_address;
- if (family == AF_INET) {
- ip_address = net::IPAddress(kPublicIPv4Host);
- } else {
- ip_address = net::IPAddress(kPublicIPv6Host);
- }
-
- if (socket->Connect(net::IPEndPoint(ip_address, kPublicPort)) != net::OK) {
- return net::IPAddress();
- }
-
- net::IPEndPoint local_address;
- if (socket->GetLocalAddress(&local_address) != net::OK)
- return net::IPAddress();
-
- return local_address.address();
-}
-void P2PSocketDispatcherHost::OnAddressResolved(
- DnsRequest* request,
- const net::IPAddressList& addresses) {
- Send(new P2PMsg_GetHostAddressResult(request->request_id(), addresses));
+ std::unique_ptr<uint8_t[]> header_buffer(new uint8_t[packet_header.size()]);
+ memcpy(header_buffer.get(), &packet_header[0], packet_header.size());
- dns_requests_.erase(
- std::find_if(dns_requests_.begin(), dns_requests_.end(),
- [request](const std::unique_ptr<DnsRequest>& ptr) {
- return ptr.get() == request;
- }));
-}
-
-void P2PSocketDispatcherHost::StopRtpDumpOnIOThread(bool incoming,
- bool outgoing) {
- if ((dump_incoming_rtp_packet_ && incoming) ||
- (dump_outgoing_rtp_packet_ && outgoing)) {
- if (incoming)
- dump_incoming_rtp_packet_ = false;
-
- if (outgoing)
- dump_outgoing_rtp_packet_ = false;
-
- if (!dump_incoming_rtp_packet_ && !dump_outgoing_rtp_packet_)
- packet_callback_.Reset();
-
- for (SocketsMap::iterator it = sockets_.begin(); it != sockets_.end(); ++it)
- it->second->StopRtpDump(incoming, outgoing);
- }
+ packet_callback_.Run(std::move(header_buffer),
+ static_cast<size_t>(packet_header.size()),
+ static_cast<size_t>(packet_length), incoming);
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.h b/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.h
index 288c834e422..3802f73ec6b 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.h
+++ b/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.h
@@ -7,130 +7,60 @@
#include <stdint.h>
-#include <map>
#include <memory>
#include <set>
#include <string>
#include <vector>
#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
#include "base/sequenced_task_runner.h"
-#include "content/browser/renderer_host/p2p/socket_host_throttler.h"
-#include "content/common/p2p_socket_type.h"
-#include "content/public/browser/browser_message_filter.h"
-#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
-#include "net/base/ip_address.h"
-#include "net/base/ip_endpoint.h"
-#include "net/base/network_change_notifier.h"
-
-namespace net {
-struct MutableNetworkTrafficAnnotationTag;
-class URLRequestContextGetter;
-}
-
-namespace network {
-class ProxyResolvingClientSocketFactory;
-}
+#include "mojo/public/cpp/bindings/binding.h"
+#include "services/network/public/mojom/p2p.mojom.h"
+#include "services/network/public/mojom/p2p_trusted.mojom.h"
namespace content {
-class P2PSocketHost;
-
+// Responsible for P2P sockets. Lives on the UI thread.
class P2PSocketDispatcherHost
- : public content::BrowserMessageFilter,
- public net::NetworkChangeNotifier::NetworkChangeObserver {
+ : public network::mojom::P2PTrustedSocketManagerClient {
public:
- explicit P2PSocketDispatcherHost(net::URLRequestContextGetter* url_context);
-
- // content::BrowserMessageFilter overrides.
- void OnChannelClosing() override;
- void OnDestruct() const override;
- bool OnMessageReceived(const IPC::Message& message) override;
+ explicit P2PSocketDispatcherHost(int render_process_id);
+ ~P2PSocketDispatcherHost() override;
- // net::NetworkChangeNotifier::NetworkChangeObserver interface.
- void OnNetworkChanged(
- net::NetworkChangeNotifier::ConnectionType type) override;
- // Starts the RTP packet header dumping. Must be called on the IO thread.
+ // Starts the RTP packet header dumping.
void StartRtpDump(
bool incoming,
bool outgoing,
const RenderProcessHost::WebRtcRtpPacketCallback& packet_callback);
- // Stops the RTP packet header dumping. Must be Called on the UI thread.
- void StopRtpDumpOnUIThread(bool incoming, bool outgoing);
-
- protected:
- ~P2PSocketDispatcherHost() override;
-
- private:
- friend struct BrowserThread::DeleteOnThread<BrowserThread::IO>;
- friend class base::DeleteHelper<P2PSocketDispatcherHost>;
-
- typedef std::map<int, std::unique_ptr<P2PSocketHost>> SocketsMap;
+ // Stops the RTP packet header dumping.
+ void StopRtpDump(bool incoming, bool outgoing);
- class DnsRequest;
+ void BindRequest(network::mojom::P2PSocketManagerRequest request);
- P2PSocketHost* LookupSocket(int socket_id);
+ base::WeakPtr<P2PSocketDispatcherHost> GetWeakPtr();
- // Handlers for the messages coming from the renderer.
- void OnStartNetworkNotifications();
- void OnStopNetworkNotifications();
- void OnGetHostAddress(const std::string& host_name, int32_t request_id);
-
- void OnCreateSocket(P2PSocketType type,
- int socket_id,
- const net::IPEndPoint& local_address,
- const P2PPortRange& port_range,
- const P2PHostAndIPEndPoint& remote_address);
- void OnAcceptIncomingTcpConnection(int listen_socket_id,
- const net::IPEndPoint& remote_address,
- int connected_socket_id);
- void OnSend(
- int socket_id,
- const std::vector<char>& data,
- const P2PPacketInfo& packet_info,
- const net::MutableNetworkTrafficAnnotationTag& traffic_annotation);
- void OnSetOption(int socket_id, P2PSocketOption option, int value);
- void OnDestroySocket(int socket_id);
-
- void DoGetNetworkList();
- void SendNetworkList(const net::NetworkInterfaceList& list,
- const net::IPAddress& default_ipv4_local_address,
- const net::IPAddress& default_ipv6_local_address);
-
- // This connects a UDP socket to a public IP address and gets local
- // address. Since it binds to the "any" address (0.0.0.0 or ::) internally, it
- // retrieves the default local address.
- net::IPAddress GetDefaultLocalAddress(int family);
-
- void OnAddressResolved(DnsRequest* request,
- const net::IPAddressList& addresses);
-
- void StopRtpDumpOnIOThread(bool incoming, bool outgoing);
-
- scoped_refptr<net::URLRequestContextGetter> url_context_;
- // Initialized on browser IO thread.
- std::unique_ptr<network::ProxyResolvingClientSocketFactory>
- proxy_resolving_socket_factory_;
-
- SocketsMap sockets_;
+ private:
+ // network::mojom::P2PTrustedSocketManagerClient overrides:
+ void InvalidSocketPortRangeRequested() override;
+ void DumpPacket(const std::vector<uint8_t>& packet_header,
+ uint64_t packet_length,
+ bool incoming) override;
- bool monitoring_networks_;
+ int render_process_id_;
- std::set<std::unique_ptr<DnsRequest>> dns_requests_;
- P2PMessageThrottler throttler_;
+ bool dump_incoming_rtp_packet_ = false;
+ bool dump_outgoing_rtp_packet_ = false;
+ RenderProcessHost::WebRtcRtpPacketCallback packet_callback_;
- net::IPAddress default_ipv4_local_address_;
- net::IPAddress default_ipv6_local_address_;
+ mojo::Binding<network::mojom::P2PTrustedSocketManagerClient> binding_;
+ network::mojom::P2PTrustedSocketManagerPtr trusted_socket_manager_;
- bool dump_incoming_rtp_packet_;
- bool dump_outgoing_rtp_packet_;
- RenderProcessHost::WebRtcRtpPacketCallback packet_callback_;
+ network::mojom::P2PNetworkNotificationClientPtr network_notification_client_;
- // Used to call DoGetNetworkList, which may briefly block since getting the
- // default local address involves creating a dummy socket.
- const scoped_refptr<base::SequencedTaskRunner> network_list_task_runner_;
+ base::WeakPtrFactory<P2PSocketDispatcherHost> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(P2PSocketDispatcherHost);
};
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host.cc b/chromium/content/browser/renderer_host/p2p/socket_host.cc
deleted file mode 100644
index 8173bcfddd3..00000000000
--- a/chromium/content/browser/renderer_host/p2p/socket_host.cc
+++ /dev/null
@@ -1,332 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/renderer_host/p2p/socket_host.h"
-
-#include "base/metrics/histogram_macros.h"
-#include "base/sys_byteorder.h"
-#include "content/browser/renderer_host/p2p/socket_host_tcp.h"
-#include "content/browser/renderer_host/p2p/socket_host_tcp_server.h"
-#include "content/browser/renderer_host/p2p/socket_host_udp.h"
-#include "content/browser/renderer_host/render_process_host_impl.h"
-#include "content/public/browser/browser_thread.h"
-#include "net/base/net_errors.h"
-#include "net/url_request/url_request_context.h"
-#include "net/url_request/url_request_context_getter.h"
-#include "services/network/proxy_resolving_client_socket_factory.h"
-#include "third_party/webrtc/media/base/rtputils.h"
-#include "third_party/webrtc/media/base/turnutils.h"
-
-namespace {
-
-// Used to back histogram value of "WebRTC.ICE.TcpSocketErrorCode" and
-// "WebRTC.ICE.UdpSocketErrorCode".
-enum class SocketErrorCode {
- ERR_MSG_TOO_BIG,
- ERR_ADDRESS_UNREACHABLE,
- ERR_ADDRESS_INVALID,
- ERR_INTERNET_DISCONNECTED,
- ERR_TIMED_OUT,
- ERR_INSUFFICIENT_RESOURCES,
- ERR_OUT_OF_MEMORY,
- ERR_OTHER // For all the others
-};
-
-const uint32_t kStunMagicCookie = 0x2112A442;
-const size_t kMinRtcpHeaderLength = 8;
-const size_t kDtlsRecordHeaderLength = 13;
-
-bool IsDtlsPacket(const char* data, size_t length) {
- const uint8_t* u = reinterpret_cast<const uint8_t*>(data);
- return (length >= kDtlsRecordHeaderLength && (u[0] > 19 && u[0] < 64));
-}
-
-bool IsRtcpPacket(const char* data, size_t length) {
- if (length < kMinRtcpHeaderLength) {
- return false;
- }
-
- int type = (static_cast<uint8_t>(data[1]) & 0x7F);
- return (type >= 64 && type < 96);
-}
-
-// Map the network error to SocketErrorCode for the UMA histogram.
-// static
-static SocketErrorCode MapNetErrorToSocketErrorCode(int net_err) {
- switch (net_err) {
- case net::OK:
- NOTREACHED();
- return SocketErrorCode::ERR_OTHER;
- case net::ERR_MSG_TOO_BIG:
- return SocketErrorCode::ERR_MSG_TOO_BIG;
- case net::ERR_ADDRESS_UNREACHABLE:
- return SocketErrorCode::ERR_ADDRESS_UNREACHABLE;
- case net::ERR_ADDRESS_INVALID:
- return SocketErrorCode::ERR_ADDRESS_INVALID;
- case net::ERR_INTERNET_DISCONNECTED:
- return SocketErrorCode::ERR_INTERNET_DISCONNECTED;
- case net::ERR_TIMED_OUT:
- return SocketErrorCode::ERR_TIMED_OUT;
- case net::ERR_INSUFFICIENT_RESOURCES:
- return SocketErrorCode::ERR_INSUFFICIENT_RESOURCES;
- case net::ERR_OUT_OF_MEMORY:
- return SocketErrorCode::ERR_OUT_OF_MEMORY;
- default:
- return SocketErrorCode::ERR_OTHER;
- }
-}
-} // namespace
-
-namespace content {
-
-P2PSocketHost::P2PSocketHost(IPC::Sender* message_sender,
- int socket_id,
- ProtocolType protocol_type)
- : message_sender_(message_sender),
- id_(socket_id),
- state_(STATE_UNINITIALIZED),
- dump_incoming_rtp_packet_(false),
- dump_outgoing_rtp_packet_(false),
- protocol_type_(protocol_type),
- send_packets_delayed_total_(0),
- send_packets_total_(0),
- send_bytes_delayed_max_(0),
- send_bytes_delayed_cur_(0),
- weak_ptr_factory_(this) {
-}
-
-P2PSocketHost::~P2PSocketHost() {
- if (protocol_type_ == P2PSocketHost::UDP) {
- UMA_HISTOGRAM_COUNTS_10000("WebRTC.SystemMaxConsecutiveBytesDelayed_UDP",
- send_bytes_delayed_max_);
- } else {
- UMA_HISTOGRAM_COUNTS_10000("WebRTC.SystemMaxConsecutiveBytesDelayed_TCP",
- send_bytes_delayed_max_);
- }
-
- if (send_packets_total_ > 0) {
- int delay_rate = (send_packets_delayed_total_ * 100) / send_packets_total_;
- if (protocol_type_ == P2PSocketHost::UDP) {
- UMA_HISTOGRAM_PERCENTAGE("WebRTC.SystemPercentPacketsDelayed_UDP",
- delay_rate);
- } else {
- UMA_HISTOGRAM_PERCENTAGE("WebRTC.SystemPercentPacketsDelayed_TCP",
- delay_rate);
- }
- }
-}
-
-// Verifies that the packet |data| has a valid STUN header.
-// static
-bool P2PSocketHost::GetStunPacketType(
- const char* data, int data_size, StunMessageType* type) {
-
- if (data_size < kStunHeaderSize) {
- return false;
- }
-
- uint32_t cookie =
- base::NetToHost32(*reinterpret_cast<const uint32_t*>(data + 4));
- if (cookie != kStunMagicCookie) {
- return false;
- }
-
- uint16_t length =
- base::NetToHost16(*reinterpret_cast<const uint16_t*>(data + 2));
- if (length != data_size - kStunHeaderSize) {
- return false;
- }
-
- int message_type =
- base::NetToHost16(*reinterpret_cast<const uint16_t*>(data));
-
- // Verify that the type is known:
- switch (message_type) {
- case STUN_BINDING_REQUEST:
- case STUN_BINDING_RESPONSE:
- case STUN_BINDING_ERROR_RESPONSE:
- case STUN_SHARED_SECRET_REQUEST:
- case STUN_SHARED_SECRET_RESPONSE:
- case STUN_SHARED_SECRET_ERROR_RESPONSE:
- case STUN_ALLOCATE_REQUEST:
- case STUN_ALLOCATE_RESPONSE:
- case STUN_ALLOCATE_ERROR_RESPONSE:
- case STUN_SEND_REQUEST:
- case STUN_SEND_RESPONSE:
- case STUN_SEND_ERROR_RESPONSE:
- case STUN_DATA_INDICATION:
- *type = static_cast<StunMessageType>(message_type);
- return true;
-
- default:
- return false;
- }
-}
-
-// static
-bool P2PSocketHost::IsRequestOrResponse(StunMessageType type) {
- return type == STUN_BINDING_REQUEST || type == STUN_BINDING_RESPONSE ||
- type == STUN_ALLOCATE_REQUEST || type == STUN_ALLOCATE_RESPONSE;
-}
-
-// static
-void P2PSocketHost::ReportSocketError(int result, const char* histogram_name) {
- SocketErrorCode error_code = MapNetErrorToSocketErrorCode(result);
- UMA_HISTOGRAM_ENUMERATION(histogram_name, static_cast<int>(error_code),
- static_cast<int>(SocketErrorCode::ERR_OTHER) + 1);
-}
-
-// static
-P2PSocketHost* P2PSocketHost::Create(
- IPC::Sender* message_sender,
- int socket_id,
- P2PSocketType type,
- net::URLRequestContextGetter* url_context,
- network::ProxyResolvingClientSocketFactory* proxy_resolving_socket_factory,
- P2PMessageThrottler* throttler) {
- switch (type) {
- case P2P_SOCKET_UDP:
- return new P2PSocketHostUdp(
- message_sender, socket_id, throttler,
- url_context->GetURLRequestContext()->net_log());
- case P2P_SOCKET_TCP_SERVER:
- return new P2PSocketHostTcpServer(
- message_sender, socket_id, P2P_SOCKET_TCP_CLIENT);
-
- case P2P_SOCKET_STUN_TCP_SERVER:
- return new P2PSocketHostTcpServer(
- message_sender, socket_id, P2P_SOCKET_STUN_TCP_CLIENT);
-
- case P2P_SOCKET_TCP_CLIENT:
- case P2P_SOCKET_SSLTCP_CLIENT:
- case P2P_SOCKET_TLS_CLIENT:
- return new P2PSocketHostTcp(message_sender, socket_id, type, url_context,
- proxy_resolving_socket_factory);
-
- case P2P_SOCKET_STUN_TCP_CLIENT:
- case P2P_SOCKET_STUN_SSLTCP_CLIENT:
- case P2P_SOCKET_STUN_TLS_CLIENT:
- return new P2PSocketHostStunTcp(message_sender, socket_id, type,
- url_context,
- proxy_resolving_socket_factory);
- }
-
- NOTREACHED();
- return nullptr;
-}
-
-void P2PSocketHost::StartRtpDump(
- bool incoming,
- bool outgoing,
- const RenderProcessHost::WebRtcRtpPacketCallback& packet_callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(!packet_callback.is_null());
- DCHECK(incoming || outgoing);
-
- if (incoming) {
- dump_incoming_rtp_packet_ = true;
- }
-
- if (outgoing) {
- dump_outgoing_rtp_packet_ = true;
- }
-
- packet_dump_callback_ = packet_callback;
-}
-
-void P2PSocketHost::StopRtpDump(bool incoming, bool outgoing) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(incoming || outgoing);
-
- if (incoming) {
- dump_incoming_rtp_packet_ = false;
- }
-
- if (outgoing) {
- dump_outgoing_rtp_packet_ = false;
- }
-
- if (!dump_incoming_rtp_packet_ && !dump_outgoing_rtp_packet_) {
- packet_dump_callback_.Reset();
- }
-}
-
-void P2PSocketHost::DumpRtpPacket(const char* packet,
- size_t length,
- bool incoming) {
- if (IsDtlsPacket(packet, length) || IsRtcpPacket(packet, length)) {
- return;
- }
-
- size_t rtp_packet_pos = 0;
- size_t rtp_packet_length = length;
- if (!cricket::UnwrapTurnPacket(reinterpret_cast<const uint8_t*>(packet),
- length, &rtp_packet_pos, &rtp_packet_length)) {
- return;
- }
-
- packet += rtp_packet_pos;
-
- size_t header_length = 0;
- bool valid =
- cricket::ValidateRtpHeader(reinterpret_cast<const uint8_t*>(packet),
- rtp_packet_length, &header_length);
- if (!valid) {
- NOTREACHED();
- return;
- }
-
- std::unique_ptr<uint8_t[]> header_buffer(new uint8_t[header_length]);
- memcpy(header_buffer.get(), packet, header_length);
-
- // Posts to the IO thread as the data members should be accessed on the IO
- // thread only.
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&P2PSocketHost::DumpRtpPacketOnIOThread,
- weak_ptr_factory_.GetWeakPtr(), std::move(header_buffer),
- header_length, rtp_packet_length, incoming));
-}
-
-void P2PSocketHost::DumpRtpPacketOnIOThread(
- std::unique_ptr<uint8_t[]> packet_header,
- size_t header_length,
- size_t packet_length,
- bool incoming) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- if ((incoming && !dump_incoming_rtp_packet_) ||
- (!incoming && !dump_outgoing_rtp_packet_) ||
- packet_dump_callback_.is_null()) {
- return;
- }
-
- // |packet_dump_callback_| must be called on the UI thread.
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(packet_dump_callback_, std::move(packet_header),
- header_length, packet_length, incoming));
-}
-
-void P2PSocketHost::IncrementDelayedPackets() {
- send_packets_delayed_total_++;
-}
-
-void P2PSocketHost::IncrementTotalSentPackets() {
- send_packets_total_++;
-}
-
-void P2PSocketHost::IncrementDelayedBytes(uint32_t size) {
- send_bytes_delayed_cur_ += size;
- if (send_bytes_delayed_cur_ > send_bytes_delayed_max_) {
- send_bytes_delayed_max_ = send_bytes_delayed_cur_;
- }
-}
-
-void P2PSocketHost::DecrementDelayedBytes(uint32_t size) {
- send_bytes_delayed_cur_ -= size;
- DCHECK_GE(send_bytes_delayed_cur_, 0);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host.h b/chromium/content/browser/renderer_host/p2p/socket_host.h
deleted file mode 100644
index f330cdd3f55..00000000000
--- a/chromium/content/browser/renderer_host/p2p/socket_host.h
+++ /dev/null
@@ -1,183 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_RENDERER_HOST_P2P_SOCKET_HOST_H_
-#define CONTENT_BROWSER_RENDERER_HOST_P2P_SOCKET_HOST_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <memory>
-
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "content/common/content_export.h"
-#include "content/common/p2p_socket_type.h"
-#include "content/public/browser/render_process_host.h"
-#include "net/base/ip_endpoint.h"
-#include "net/socket/datagram_socket.h"
-#include "net/traffic_annotation/network_traffic_annotation.h"
-
-namespace IPC {
-class Sender;
-}
-
-namespace net {
-class URLRequestContextGetter;
-}
-
-namespace network {
-class ProxyResolvingClientSocketFactory;
-}
-
-namespace rtc {
-struct PacketOptions;
-}
-
-namespace content {
-class P2PMessageThrottler;
-
-// Base class for P2P sockets.
-class CONTENT_EXPORT P2PSocketHost {
- public:
- static const int kStunHeaderSize = 20;
- // Creates P2PSocketHost of the specific type.
- static P2PSocketHost* Create(IPC::Sender* message_sender,
- int socket_id,
- P2PSocketType type,
- net::URLRequestContextGetter* url_context,
- network::ProxyResolvingClientSocketFactory*
- proxy_resolving_socket_factory,
- P2PMessageThrottler* throttler);
-
- virtual ~P2PSocketHost();
-
- // Initalizes the socket. Returns false when initialization fails.
- // |min_port| and |max_port| specify the valid range of allowed ports.
- // |min_port| must be less than or equal to |max_port|.
- // If |min_port| is zero, |max_port| must also be zero and it means all ports
- // are valid.
- // If |local_address.port()| is zero, the socket will be initialized to a port
- // in the valid range.
- // If |local_address.port()| is nonzero and not in the valid range,
- // initialization will fail.
- virtual bool Init(const net::IPEndPoint& local_address,
- uint16_t min_port,
- uint16_t max_port,
- const P2PHostAndIPEndPoint& remote_address) = 0;
-
- // Sends |data| on the socket to |to|.
- virtual void Send(
- const net::IPEndPoint& to,
- const std::vector<char>& data,
- const rtc::PacketOptions& options,
- uint64_t packet_id,
- const net::NetworkTrafficAnnotationTag traffic_annotation) = 0;
-
- virtual std::unique_ptr<P2PSocketHost> AcceptIncomingTcpConnection(
- const net::IPEndPoint& remote_address,
- int id) = 0;
-
- virtual bool SetOption(P2PSocketOption option, int value) = 0;
-
- void StartRtpDump(
- bool incoming,
- bool outgoing,
- const RenderProcessHost::WebRtcRtpPacketCallback& packet_callback);
- void StopRtpDump(bool incoming, bool outgoing);
-
- protected:
- friend class P2PSocketHostTcpTestBase;
-
- // This should match suffix IPProtocolType defined in histograms.xml.
- enum ProtocolType { UDP = 0x1, TCP = 0x2 };
-
- // TODO(mallinath) - Remove this below enum and use one defined in
- // libjingle/souce/talk/p2p/base/stun.h
- enum StunMessageType {
- STUN_BINDING_REQUEST = 0x0001,
- STUN_BINDING_RESPONSE = 0x0101,
- STUN_BINDING_ERROR_RESPONSE = 0x0111,
- STUN_SHARED_SECRET_REQUEST = 0x0002,
- STUN_SHARED_SECRET_RESPONSE = 0x0102,
- STUN_SHARED_SECRET_ERROR_RESPONSE = 0x0112,
- STUN_ALLOCATE_REQUEST = 0x0003,
- STUN_ALLOCATE_RESPONSE = 0x0103,
- STUN_ALLOCATE_ERROR_RESPONSE = 0x0113,
- STUN_SEND_REQUEST = 0x0004,
- STUN_SEND_RESPONSE = 0x0104,
- STUN_SEND_ERROR_RESPONSE = 0x0114,
- STUN_DATA_INDICATION = 0x0115,
- TURN_SEND_INDICATION = 0x0016,
- TURN_DATA_INDICATION = 0x0017,
- TURN_CREATE_PERMISSION_REQUEST = 0x0008,
- TURN_CREATE_PERMISSION_RESPONSE = 0x0108,
- TURN_CREATE_PERMISSION_ERROR_RESPONSE = 0x0118,
- TURN_CHANNEL_BIND_REQUEST = 0x0009,
- TURN_CHANNEL_BIND_RESPONSE = 0x0109,
- TURN_CHANNEL_BIND_ERROR_RESPONSE = 0x0119,
- };
-
- enum State {
- STATE_UNINITIALIZED,
- STATE_CONNECTING,
- STATE_OPEN,
- STATE_ERROR,
- };
-
- P2PSocketHost(IPC::Sender* message_sender,
- int socket_id,
- ProtocolType protocol_type);
-
- // Verifies that the packet |data| has a valid STUN header. In case
- // of success stores type of the message in |type|.
- static bool GetStunPacketType(const char* data, int data_size,
- StunMessageType* type);
- static bool IsRequestOrResponse(StunMessageType type);
-
- static void ReportSocketError(int result, const char* histogram_name);
-
- // Calls |packet_dump_callback_| to record the RTP header.
- void DumpRtpPacket(const char* packet, size_t length, bool incoming);
-
- // A helper to dump the packet on the IO thread.
- void DumpRtpPacketOnIOThread(std::unique_ptr<uint8_t[]> packet_header,
- size_t header_length,
- size_t packet_length,
- bool incoming);
-
- // Used by subclasses to track the metrics of delayed bytes and packets.
- void IncrementDelayedPackets();
- void IncrementTotalSentPackets();
- void IncrementDelayedBytes(uint32_t size);
- void DecrementDelayedBytes(uint32_t size);
-
- IPC::Sender* message_sender_;
- int id_;
- State state_;
- bool dump_incoming_rtp_packet_;
- bool dump_outgoing_rtp_packet_;
- RenderProcessHost::WebRtcRtpPacketCallback packet_dump_callback_;
-
- ProtocolType protocol_type_;
-
- private:
- // Track total delayed packets for calculating how many packets are
- // delayed by system at the end of call.
- uint32_t send_packets_delayed_total_;
- uint32_t send_packets_total_;
-
- // Track the maximum of consecutive delayed bytes caused by system's
- // EWOULDBLOCK.
- int32_t send_bytes_delayed_max_;
- int32_t send_bytes_delayed_cur_;
-
- base::WeakPtrFactory<P2PSocketHost> weak_ptr_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(P2PSocketHost);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_P2P_SOCKET_HOST_H_
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_tcp.cc b/chromium/content/browser/renderer_host/p2p/socket_host_tcp.cc
deleted file mode 100644
index efc6c63a375..00000000000
--- a/chromium/content/browser/renderer_host/p2p/socket_host_tcp.cc
+++ /dev/null
@@ -1,620 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/renderer_host/p2p/socket_host_tcp.h"
-
-#include <stddef.h>
-#include <utility>
-
-#include "base/location.h"
-#include "base/single_thread_task_runner.h"
-#include "base/sys_byteorder.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "content/common/p2p_messages.h"
-#include "ipc/ipc_sender.h"
-#include "jingle/glue/fake_ssl_client_socket.h"
-#include "net/base/io_buffer.h"
-#include "net/base/net_errors.h"
-#include "net/socket/client_socket_factory.h"
-#include "net/socket/client_socket_handle.h"
-#include "net/socket/ssl_client_socket.h"
-#include "net/socket/tcp_client_socket.h"
-#include "net/url_request/url_request_context.h"
-#include "net/url_request/url_request_context_getter.h"
-#include "services/network/proxy_resolving_client_socket.h"
-#include "services/network/proxy_resolving_client_socket_factory.h"
-#include "third_party/webrtc/media/base/rtputils.h"
-#include "url/gurl.h"
-
-namespace {
-
-typedef uint16_t PacketLength;
-const int kPacketHeaderSize = sizeof(PacketLength);
-const int kTcpReadBufferSize = 4096;
-const int kPacketLengthOffset = 2;
-const int kTurnChannelDataHeaderSize = 4;
-const int kTcpRecvSocketBufferSize = 128 * 1024;
-const int kTcpSendSocketBufferSize = 128 * 1024;
-
-bool IsTlsClientSocket(content::P2PSocketType type) {
- return (type == content::P2P_SOCKET_STUN_TLS_CLIENT ||
- type == content::P2P_SOCKET_TLS_CLIENT);
-}
-
-bool IsPseudoTlsClientSocket(content::P2PSocketType type) {
- return (type == content::P2P_SOCKET_SSLTCP_CLIENT ||
- type == content::P2P_SOCKET_STUN_SSLTCP_CLIENT);
-}
-
-} // namespace
-
-namespace content {
-
-P2PSocketHostTcp::SendBuffer::SendBuffer() : rtc_packet_id(-1) {}
-P2PSocketHostTcp::SendBuffer::SendBuffer(
- int32_t rtc_packet_id,
- scoped_refptr<net::DrainableIOBuffer> buffer,
- const net::NetworkTrafficAnnotationTag traffic_annotation)
- : rtc_packet_id(rtc_packet_id),
- buffer(buffer),
- traffic_annotation(traffic_annotation) {}
-P2PSocketHostTcp::SendBuffer::SendBuffer(const SendBuffer& rhs) = default;
-P2PSocketHostTcp::SendBuffer::~SendBuffer() {}
-
-P2PSocketHostTcpBase::P2PSocketHostTcpBase(
- IPC::Sender* message_sender,
- int socket_id,
- P2PSocketType type,
- net::URLRequestContextGetter* url_context,
- network::ProxyResolvingClientSocketFactory* proxy_resolving_socket_factory)
- : P2PSocketHost(message_sender, socket_id, P2PSocketHost::TCP),
- write_pending_(false),
- connected_(false),
- type_(type),
- url_context_(url_context),
- proxy_resolving_socket_factory_(proxy_resolving_socket_factory) {}
-
-P2PSocketHostTcpBase::~P2PSocketHostTcpBase() {
- if (state_ == STATE_OPEN) {
- DCHECK(socket_.get());
- socket_.reset();
- }
-}
-
-bool P2PSocketHostTcpBase::InitAccepted(
- const net::IPEndPoint& remote_address,
- std::unique_ptr<net::StreamSocket> socket) {
- DCHECK(socket);
- DCHECK_EQ(state_, STATE_UNINITIALIZED);
-
- remote_address_.ip_address = remote_address;
- // TODO(ronghuawu): Add FakeSSLServerSocket.
- socket_ = std::move(socket);
- state_ = STATE_OPEN;
- DoRead();
- return state_ != STATE_ERROR;
-}
-
-bool P2PSocketHostTcpBase::Init(const net::IPEndPoint& local_address,
- uint16_t min_port,
- uint16_t max_port,
- const P2PHostAndIPEndPoint& remote_address) {
- DCHECK_EQ(state_, STATE_UNINITIALIZED);
-
- remote_address_ = remote_address;
- state_ = STATE_CONNECTING;
-
- net::HostPortPair dest_host_port_pair;
- // If there is a domain name, let's try it first, it's required by some proxy
- // to only take hostname for CONNECT. If it has been DNS resolved, the result
- // is likely cached and shouldn't cause 2nd DNS resolution in the case of
- // direct connect (i.e. no proxy).
- if (!remote_address.hostname.empty()) {
- dest_host_port_pair = net::HostPortPair(remote_address.hostname,
- remote_address.ip_address.port());
- } else {
- DCHECK(!remote_address.ip_address.address().empty());
- dest_host_port_pair = net::HostPortPair::FromIPEndPoint(
- remote_address.ip_address);
- }
-
- // TODO(mallinath) - We are ignoring local_address altogether. We should
- // find a way to inject this into ProxyResolvingClientSocket. This could be
- // a problem on multi-homed host.
-
- socket_ = proxy_resolving_socket_factory_->CreateSocket(
- GURL("https://" + dest_host_port_pair.ToString()),
- IsTlsClientSocket(type_));
-
- if (IsPseudoTlsClientSocket(type_)) {
- socket_ =
- std::make_unique<jingle_glue::FakeSSLClientSocket>(std::move(socket_));
- }
-
- int status = socket_->Connect(base::BindOnce(
- &P2PSocketHostTcpBase::OnConnected, base::Unretained(this)));
- if (status != net::ERR_IO_PENDING) {
- // We defer execution of ProcessConnectDone instead of calling it
- // directly here as the caller may not expect an error/close to
- // happen here. This is okay, as from the caller's point of view,
- // the connect always happens asynchronously.
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(&P2PSocketHostTcpBase::OnConnected,
- base::Unretained(this), status));
- }
-
- return state_ != STATE_ERROR;
-}
-
-void P2PSocketHostTcpBase::OnError() {
- socket_.reset();
-
- if (state_ == STATE_UNINITIALIZED || state_ == STATE_CONNECTING ||
- state_ == STATE_OPEN) {
- message_sender_->Send(new P2PMsg_OnError(id_));
- }
-
- state_ = STATE_ERROR;
-}
-
-void P2PSocketHostTcpBase::OnConnected(int result) {
- DCHECK_EQ(state_, STATE_CONNECTING);
- DCHECK_NE(result, net::ERR_IO_PENDING);
-
- if (result != net::OK) {
- LOG(WARNING) << "Error from connecting socket, result=" << result;
- OnError();
- return;
- }
-
- OnOpen();
-}
-
-void P2PSocketHostTcpBase::OnOpen() {
- state_ = STATE_OPEN;
- // Setting socket send and receive buffer size.
- if (net::OK != socket_->SetReceiveBufferSize(kTcpRecvSocketBufferSize)) {
- LOG(WARNING) << "Failed to set socket receive buffer size to "
- << kTcpRecvSocketBufferSize;
- }
-
- if (net::OK != socket_->SetSendBufferSize(kTcpSendSocketBufferSize)) {
- LOG(WARNING) << "Failed to set socket send buffer size to "
- << kTcpSendSocketBufferSize;
- }
-
- if (!DoSendSocketCreateMsg())
- return;
-
- DCHECK_EQ(state_, STATE_OPEN);
- DoRead();
-}
-
-bool P2PSocketHostTcpBase::DoSendSocketCreateMsg() {
- DCHECK(socket_.get());
-
- net::IPEndPoint local_address;
- int result = socket_->GetLocalAddress(&local_address);
- if (result < 0) {
- LOG(ERROR) << "P2PSocketHostTcpBase::OnConnected: unable to get local"
- << " address: " << result;
- OnError();
- return false;
- }
-
- VLOG(1) << "Local address: " << local_address.ToString();
-
- net::IPEndPoint remote_address;
-
- // GetPeerAddress returns ERR_NAME_NOT_RESOLVED if the socket is connected
- // through a proxy.
- result = socket_->GetPeerAddress(&remote_address);
- if (result < 0 && result != net::ERR_NAME_NOT_RESOLVED) {
- LOG(ERROR) << "P2PSocketHostTcpBase::OnConnected: unable to get peer"
- << " address: " << result;
- OnError();
- return false;
- }
-
- if (!remote_address.address().empty()) {
- VLOG(1) << "Remote address: " << remote_address.ToString();
- if (remote_address_.ip_address.address().empty()) {
- // Save |remote_address| if address is empty.
- remote_address_.ip_address = remote_address;
- }
- } else {
- VLOG(1) << "Remote address is unknown since connection is proxied";
- }
-
- // If we are not doing TLS, we are ready to send data now.
- // In case of TLS SignalConnect will be sent only after TLS handshake is
- // successful. So no buffering will be done at socket handlers if any
- // packets sent before that by the application.
- message_sender_->Send(new P2PMsg_OnSocketCreated(
- id_, local_address, remote_address));
- return true;
-}
-
-void P2PSocketHostTcpBase::DoRead() {
- int result;
- do {
- if (!read_buffer_.get()) {
- read_buffer_ = new net::GrowableIOBuffer();
- read_buffer_->SetCapacity(kTcpReadBufferSize);
- } else if (read_buffer_->RemainingCapacity() < kTcpReadBufferSize) {
- // Make sure that we always have at least kTcpReadBufferSize of
- // remaining capacity in the read buffer. Normally all packets
- // are smaller than kTcpReadBufferSize, so this is not really
- // required.
- read_buffer_->SetCapacity(read_buffer_->capacity() + kTcpReadBufferSize -
- read_buffer_->RemainingCapacity());
- }
- result = socket_->Read(
- read_buffer_.get(),
- read_buffer_->RemainingCapacity(),
- base::Bind(&P2PSocketHostTcp::OnRead, base::Unretained(this)));
- DidCompleteRead(result);
- } while (result > 0);
-}
-
-void P2PSocketHostTcpBase::OnRead(int result) {
- DidCompleteRead(result);
- if (state_ == STATE_OPEN) {
- DoRead();
- }
-}
-
-void P2PSocketHostTcpBase::OnPacket(const std::vector<char>& data) {
- if (!connected_) {
- P2PSocketHost::StunMessageType type;
- bool stun = GetStunPacketType(&*data.begin(), data.size(), &type);
- if (stun && IsRequestOrResponse(type)) {
- connected_ = true;
- } else if (!stun || type == STUN_DATA_INDICATION) {
- LOG(ERROR) << "Received unexpected data packet from "
- << remote_address_.ip_address.ToString()
- << " before STUN binding is finished. "
- << "Terminating connection.";
- OnError();
- return;
- }
- }
-
- message_sender_->Send(new P2PMsg_OnDataReceived(
- id_, remote_address_.ip_address, data, base::TimeTicks::Now()));
-
- if (dump_incoming_rtp_packet_)
- DumpRtpPacket(&data[0], data.size(), true);
-}
-
-// Note: dscp is not actually used on TCP sockets as this point,
-// but may be honored in the future.
-void P2PSocketHostTcpBase::Send(
- const net::IPEndPoint& to,
- const std::vector<char>& data,
- const rtc::PacketOptions& options,
- uint64_t packet_id,
- const net::NetworkTrafficAnnotationTag traffic_annotation) {
- if (!socket_) {
- // The Send message may be sent after the an OnError message was
- // sent by hasn't been processed the renderer.
- return;
- }
-
- if (!(to == remote_address_.ip_address)) {
- // Renderer should use this socket only to send data to |remote_address_|.
- NOTREACHED();
- OnError();
- return;
- }
-
- if (!connected_) {
- P2PSocketHost::StunMessageType type = P2PSocketHost::StunMessageType();
- bool stun = GetStunPacketType(&*data.begin(), data.size(), &type);
- if (!stun || type == STUN_DATA_INDICATION) {
- LOG(ERROR) << "Page tried to send a data packet to " << to.ToString()
- << " before STUN binding is finished.";
- OnError();
- return;
- }
- }
-
- DoSend(to, data, options, traffic_annotation);
-}
-
-void P2PSocketHostTcpBase::WriteOrQueue(SendBuffer& send_buffer) {
- IncrementTotalSentPackets();
- if (write_buffer_.buffer.get()) {
- write_queue_.push(send_buffer);
- IncrementDelayedPackets();
- IncrementDelayedBytes(send_buffer.buffer->size());
- return;
- }
-
- write_buffer_ = send_buffer;
- DoWrite();
-}
-
-void P2PSocketHostTcpBase::DoWrite() {
- while (write_buffer_.buffer.get() && state_ == STATE_OPEN &&
- !write_pending_) {
- int result = socket_->Write(
- write_buffer_.buffer.get(), write_buffer_.buffer->BytesRemaining(),
- base::Bind(&P2PSocketHostTcp::OnWritten, base::Unretained(this)),
- net::NetworkTrafficAnnotationTag(write_buffer_.traffic_annotation));
- HandleWriteResult(result);
- }
-}
-
-void P2PSocketHostTcpBase::OnWritten(int result) {
- DCHECK(write_pending_);
- DCHECK_NE(result, net::ERR_IO_PENDING);
-
- write_pending_ = false;
- HandleWriteResult(result);
- DoWrite();
-}
-
-void P2PSocketHostTcpBase::HandleWriteResult(int result) {
- DCHECK(write_buffer_.buffer.get());
- if (result >= 0) {
- write_buffer_.buffer->DidConsume(result);
- if (write_buffer_.buffer->BytesRemaining() == 0) {
- base::TimeTicks send_time = base::TimeTicks::Now();
- message_sender_->Send(new P2PMsg_OnSendComplete(
- id_,
- P2PSendPacketMetrics(0, write_buffer_.rtc_packet_id, send_time)));
- if (write_queue_.empty()) {
- write_buffer_.buffer = nullptr;
- write_buffer_.rtc_packet_id = -1;
- } else {
- write_buffer_ = write_queue_.front();
- write_queue_.pop();
- // Update how many bytes are still waiting to be sent.
- DecrementDelayedBytes(write_buffer_.buffer->size());
- }
- }
- } else if (result == net::ERR_IO_PENDING) {
- write_pending_ = true;
- } else {
- ReportSocketError(result, "WebRTC.ICE.TcpSocketWriteErrorCode");
-
- LOG(ERROR) << "Error when sending data in TCP socket: " << result;
- OnError();
- }
-}
-
-std::unique_ptr<P2PSocketHost>
-P2PSocketHostTcpBase::AcceptIncomingTcpConnection(
- const net::IPEndPoint& remote_address,
- int id) {
- NOTREACHED();
- OnError();
- return nullptr;
-}
-
-void P2PSocketHostTcpBase::DidCompleteRead(int result) {
- DCHECK_EQ(state_, STATE_OPEN);
-
- if (result == net::ERR_IO_PENDING) {
- return;
- } else if (result < 0) {
- LOG(ERROR) << "Error when reading from TCP socket: " << result;
- OnError();
- return;
- } else if (result == 0) {
- LOG(WARNING) << "Remote peer has shutdown TCP socket.";
- OnError();
- return;
- }
-
- read_buffer_->set_offset(read_buffer_->offset() + result);
- char* head = read_buffer_->StartOfBuffer(); // Purely a convenience.
- int pos = 0;
- while (pos <= read_buffer_->offset() && state_ == STATE_OPEN) {
- int consumed = ProcessInput(head + pos, read_buffer_->offset() - pos);
- if (!consumed)
- break;
- pos += consumed;
- }
- // We've consumed all complete packets from the buffer; now move any remaining
- // bytes to the head of the buffer and set offset to reflect this.
- if (pos && pos <= read_buffer_->offset()) {
- memmove(head, head + pos, read_buffer_->offset() - pos);
- read_buffer_->set_offset(read_buffer_->offset() - pos);
- }
-}
-
-bool P2PSocketHostTcpBase::SetOption(P2PSocketOption option, int value) {
- if (state_ != STATE_OPEN) {
- DCHECK_EQ(state_, STATE_ERROR);
- return false;
- }
-
- switch (option) {
- case P2P_SOCKET_OPT_RCVBUF:
- return socket_->SetReceiveBufferSize(value) == net::OK;
- case P2P_SOCKET_OPT_SNDBUF:
- return socket_->SetSendBufferSize(value) == net::OK;
- case P2P_SOCKET_OPT_DSCP:
- return false; // For TCP sockets DSCP setting is not available.
- default:
- NOTREACHED();
- return false;
- }
-}
-
-P2PSocketHostTcp::P2PSocketHostTcp(
- IPC::Sender* message_sender,
- int socket_id,
- P2PSocketType type,
- net::URLRequestContextGetter* url_context,
- network::ProxyResolvingClientSocketFactory* proxy_resolving_socket_factory)
- : P2PSocketHostTcpBase(message_sender,
- socket_id,
- type,
- url_context,
- proxy_resolving_socket_factory) {
- DCHECK(type == P2P_SOCKET_TCP_CLIENT ||
- type == P2P_SOCKET_SSLTCP_CLIENT ||
- type == P2P_SOCKET_TLS_CLIENT);
-}
-
-P2PSocketHostTcp::~P2PSocketHostTcp() {
-}
-
-int P2PSocketHostTcp::ProcessInput(char* input, int input_len) {
- if (input_len < kPacketHeaderSize)
- return 0;
- int packet_size = base::NetToHost16(*reinterpret_cast<uint16_t*>(input));
- if (input_len < packet_size + kPacketHeaderSize)
- return 0;
-
- int consumed = kPacketHeaderSize;
- char* cur = input + consumed;
- std::vector<char> data(cur, cur + packet_size);
- OnPacket(data);
- consumed += packet_size;
- return consumed;
-}
-
-void P2PSocketHostTcp::DoSend(
- const net::IPEndPoint& to,
- const std::vector<char>& data,
- const rtc::PacketOptions& options,
- const net::NetworkTrafficAnnotationTag traffic_annotation) {
- int size = kPacketHeaderSize + data.size();
- SendBuffer send_buffer(
- options.packet_id,
- new net::DrainableIOBuffer(new net::IOBuffer(size), size),
- traffic_annotation);
- *reinterpret_cast<uint16_t*>(send_buffer.buffer->data()) =
- base::HostToNet16(data.size());
- memcpy(send_buffer.buffer->data() + kPacketHeaderSize, &data[0], data.size());
-
- cricket::ApplyPacketOptions(
- reinterpret_cast<uint8_t*>(send_buffer.buffer->data()) +
- kPacketHeaderSize,
- send_buffer.buffer->BytesRemaining() - kPacketHeaderSize,
- options.packet_time_params,
- (base::TimeTicks::Now() - base::TimeTicks()).InMicroseconds());
-
- WriteOrQueue(send_buffer);
-}
-
-// P2PSocketHostStunTcp
-P2PSocketHostStunTcp::P2PSocketHostStunTcp(
- IPC::Sender* message_sender,
- int socket_id,
- P2PSocketType type,
- net::URLRequestContextGetter* url_context,
- network::ProxyResolvingClientSocketFactory* proxy_resolving_socket_factory)
- : P2PSocketHostTcpBase(message_sender,
- socket_id,
- type,
- url_context,
- proxy_resolving_socket_factory) {
- DCHECK(type == P2P_SOCKET_STUN_TCP_CLIENT ||
- type == P2P_SOCKET_STUN_SSLTCP_CLIENT ||
- type == P2P_SOCKET_STUN_TLS_CLIENT);
-}
-
-P2PSocketHostStunTcp::~P2PSocketHostStunTcp() {
-}
-
-int P2PSocketHostStunTcp::ProcessInput(char* input, int input_len) {
- if (input_len < kPacketHeaderSize + kPacketLengthOffset)
- return 0;
-
- int pad_bytes;
- int packet_size = GetExpectedPacketSize(
- input, input_len, &pad_bytes);
-
- if (input_len < packet_size + pad_bytes)
- return 0;
-
- // We have a complete packet. Read through it.
- int consumed = 0;
- char* cur = input;
- std::vector<char> data(cur, cur + packet_size);
- OnPacket(data);
- consumed += packet_size;
- consumed += pad_bytes;
- return consumed;
-}
-
-void P2PSocketHostStunTcp::DoSend(
- const net::IPEndPoint& to,
- const std::vector<char>& data,
- const rtc::PacketOptions& options,
- const net::NetworkTrafficAnnotationTag traffic_annotation) {
- // Each packet is expected to have header (STUN/TURN ChannelData), where
- // header contains message type and and length of message.
- if (data.size() < kPacketHeaderSize + kPacketLengthOffset) {
- NOTREACHED();
- OnError();
- return;
- }
-
- int pad_bytes;
- size_t expected_len = GetExpectedPacketSize(
- &data[0], data.size(), &pad_bytes);
-
- // Accepts only complete STUN/TURN packets.
- if (data.size() != expected_len) {
- NOTREACHED();
- OnError();
- return;
- }
-
- // Add any pad bytes to the total size.
- int size = data.size() + pad_bytes;
-
- SendBuffer send_buffer(
- options.packet_id,
- new net::DrainableIOBuffer(new net::IOBuffer(size), size),
- traffic_annotation);
- memcpy(send_buffer.buffer->data(), &data[0], data.size());
-
- cricket::ApplyPacketOptions(
- reinterpret_cast<uint8_t*>(send_buffer.buffer->data()), data.size(),
- options.packet_time_params,
- (base::TimeTicks::Now() - base::TimeTicks()).InMicroseconds());
-
- if (pad_bytes) {
- char padding[4] = {0};
- DCHECK_LE(pad_bytes, 4);
- memcpy(send_buffer.buffer->data() + data.size(), padding, pad_bytes);
- }
- WriteOrQueue(send_buffer);
-
- if (dump_outgoing_rtp_packet_)
- DumpRtpPacket(send_buffer.buffer->data(), data.size(), false);
-}
-
-int P2PSocketHostStunTcp::GetExpectedPacketSize(
- const char* data, int len, int* pad_bytes) {
- DCHECK_LE(kTurnChannelDataHeaderSize, len);
- // Both stun and turn had length at offset 2.
- int packet_size = base::NetToHost16(
- *reinterpret_cast<const uint16_t*>(data + kPacketLengthOffset));
-
- // Get packet type (STUN or TURN).
- uint16_t msg_type =
- base::NetToHost16(*reinterpret_cast<const uint16_t*>(data));
-
- *pad_bytes = 0;
- // Add heder length to packet length.
- if ((msg_type & 0xC000) == 0) {
- packet_size += kStunHeaderSize;
- } else {
- packet_size += kTurnChannelDataHeaderSize;
- // Calculate any padding if present.
- if (packet_size % 4)
- *pad_bytes = 4 - packet_size % 4;
- }
- return packet_size;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_tcp.h b/chromium/content/browser/renderer_host/p2p/socket_host_tcp.h
deleted file mode 100644
index 6031e5d70a6..00000000000
--- a/chromium/content/browser/renderer_host/p2p/socket_host_tcp.h
+++ /dev/null
@@ -1,181 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_RENDERER_HOST_P2P_SOCKET_HOST_TCP_H_
-#define CONTENT_BROWSER_RENDERER_HOST_P2P_SOCKET_HOST_TCP_H_
-
-#include <stdint.h>
-
-#include <memory>
-#include <vector>
-
-#include "base/compiler_specific.h"
-#include "base/containers/queue.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "content/browser/renderer_host/p2p/socket_host.h"
-#include "content/common/p2p_socket_type.h"
-#include "net/base/completion_callback.h"
-#include "net/base/ip_endpoint.h"
-#include "net/traffic_annotation/network_traffic_annotation.h"
-
-namespace network {
-class ProxyResolvingClientSocketFactory;
-} // namespace network
-
-namespace net {
-class DrainableIOBuffer;
-class GrowableIOBuffer;
-class StreamSocket;
-class URLRequestContextGetter;
-} // namespace net
-
-namespace content {
-
-class CONTENT_EXPORT P2PSocketHostTcpBase : public P2PSocketHost {
- public:
- P2PSocketHostTcpBase(IPC::Sender* message_sender,
- int socket_id,
- P2PSocketType type,
- net::URLRequestContextGetter* url_context,
- network::ProxyResolvingClientSocketFactory*
- proxy_resolving_socket_factory);
- ~P2PSocketHostTcpBase() override;
-
- bool InitAccepted(const net::IPEndPoint& remote_address,
- std::unique_ptr<net::StreamSocket> socket);
-
- // P2PSocketHost overrides.
- bool Init(const net::IPEndPoint& local_address,
- uint16_t min_port,
- uint16_t max_port,
- const P2PHostAndIPEndPoint& remote_address) override;
- void Send(const net::IPEndPoint& to,
- const std::vector<char>& data,
- const rtc::PacketOptions& options,
- uint64_t packet_id,
- const net::NetworkTrafficAnnotationTag traffic_annotation) override;
- std::unique_ptr<P2PSocketHost> AcceptIncomingTcpConnection(
- const net::IPEndPoint& remote_address,
- int id) override;
- bool SetOption(P2PSocketOption option, int value) override;
-
- protected:
- struct SendBuffer {
- SendBuffer();
- SendBuffer(int32_t packet_id,
- scoped_refptr<net::DrainableIOBuffer> buffer,
- const net::NetworkTrafficAnnotationTag traffic_annotation);
- SendBuffer(const SendBuffer& rhs);
- ~SendBuffer();
-
- int32_t rtc_packet_id;
- scoped_refptr<net::DrainableIOBuffer> buffer;
- net::MutableNetworkTrafficAnnotationTag traffic_annotation;
- };
-
- // Derived classes will provide the implementation.
- virtual int ProcessInput(char* input, int input_len) = 0;
- virtual void DoSend(
- const net::IPEndPoint& to,
- const std::vector<char>& data,
- const rtc::PacketOptions& options,
- const net::NetworkTrafficAnnotationTag traffic_annotation) = 0;
-
- void WriteOrQueue(SendBuffer& send_buffer);
- void OnPacket(const std::vector<char>& data);
- void OnError();
-
- private:
- friend class P2PSocketHostTcpTestBase;
- friend class P2PSocketHostTcpServerTest;
-
- void DidCompleteRead(int result);
- void DoRead();
-
- void DoWrite();
- void HandleWriteResult(int result);
-
- // Callbacks for Connect(), Read() and Write().
- void OnConnected(int result);
- void OnRead(int result);
- void OnWritten(int result);
-
- // Helper method to send socket create message and start read.
- void OnOpen();
- bool DoSendSocketCreateMsg();
-
- P2PHostAndIPEndPoint remote_address_;
-
- std::unique_ptr<net::StreamSocket> socket_;
- scoped_refptr<net::GrowableIOBuffer> read_buffer_;
- base::queue<SendBuffer> write_queue_;
- SendBuffer write_buffer_;
-
- bool write_pending_;
-
- bool connected_;
- P2PSocketType type_;
- scoped_refptr<net::URLRequestContextGetter> url_context_;
- network::ProxyResolvingClientSocketFactory* proxy_resolving_socket_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(P2PSocketHostTcpBase);
-};
-
-class CONTENT_EXPORT P2PSocketHostTcp : public P2PSocketHostTcpBase {
- public:
- P2PSocketHostTcp(IPC::Sender* message_sender,
- int socket_id,
- P2PSocketType type,
- net::URLRequestContextGetter* url_context,
- network::ProxyResolvingClientSocketFactory*
- proxy_resolving_socket_factory);
-
- ~P2PSocketHostTcp() override;
-
- protected:
- int ProcessInput(char* input, int input_len) override;
- void DoSend(
- const net::IPEndPoint& to,
- const std::vector<char>& data,
- const rtc::PacketOptions& options,
- const net::NetworkTrafficAnnotationTag traffic_annotation) override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(P2PSocketHostTcp);
-};
-
-// P2PSocketHostStunTcp class provides the framing of STUN messages when used
-// with TURN. These messages will not have length at front of the packet and
-// are padded to multiple of 4 bytes.
-// Formatting of messages is defined in RFC5766.
-class CONTENT_EXPORT P2PSocketHostStunTcp : public P2PSocketHostTcpBase {
- public:
- P2PSocketHostStunTcp(IPC::Sender* message_sender,
- int socket_id,
- P2PSocketType type,
- net::URLRequestContextGetter* url_context,
- network::ProxyResolvingClientSocketFactory*
- proxy_resolving_socket_factory);
-
- ~P2PSocketHostStunTcp() override;
-
- protected:
- int ProcessInput(char* input, int input_len) override;
- void DoSend(
- const net::IPEndPoint& to,
- const std::vector<char>& data,
- const rtc::PacketOptions& options,
- const net::NetworkTrafficAnnotationTag traffic_annotation) override;
-
- private:
- int GetExpectedPacketSize(const char* data, int len, int* pad_bytes);
-
- DISALLOW_COPY_AND_ASSIGN(P2PSocketHostStunTcp);
-};
-
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_P2P_SOCKET_HOST_TCP_H_
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_tcp_server.cc b/chromium/content/browser/renderer_host/p2p/socket_host_tcp_server.cc
deleted file mode 100644
index 628b90de501..00000000000
--- a/chromium/content/browser/renderer_host/p2p/socket_host_tcp_server.cc
+++ /dev/null
@@ -1,155 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/renderer_host/p2p/socket_host_tcp_server.h"
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "content/browser/renderer_host/p2p/socket_host_tcp.h"
-#include "content/common/p2p_messages.h"
-#include "net/base/address_list.h"
-#include "net/base/net_errors.h"
-#include "net/log/net_log_source.h"
-#include "net/socket/stream_socket.h"
-
-namespace {
-const int kListenBacklog = 5;
-} // namespace
-
-namespace content {
-
-P2PSocketHostTcpServer::P2PSocketHostTcpServer(IPC::Sender* message_sender,
- int socket_id,
- P2PSocketType client_type)
- : P2PSocketHost(message_sender, socket_id, P2PSocketHost::TCP),
- client_type_(client_type),
- socket_(new net::TCPServerSocket(nullptr, net::NetLogSource())),
- accept_callback_(base::Bind(&P2PSocketHostTcpServer::OnAccepted,
- base::Unretained(this))) {
-}
-
-P2PSocketHostTcpServer::~P2PSocketHostTcpServer() {
- if (state_ == STATE_OPEN) {
- DCHECK(socket_.get());
- socket_.reset();
- }
-}
-
-// TODO(guidou): Add support for port range.
-bool P2PSocketHostTcpServer::Init(const net::IPEndPoint& local_address,
- uint16_t min_port,
- uint16_t max_port,
- const P2PHostAndIPEndPoint& remote_address) {
- DCHECK_EQ(state_, STATE_UNINITIALIZED);
-
- int result = socket_->Listen(local_address, kListenBacklog);
- if (result < 0) {
- LOG(ERROR) << "Listen() failed: " << result;
- OnError();
- return false;
- }
-
- result = socket_->GetLocalAddress(&local_address_);
- if (result < 0) {
- LOG(ERROR) << "P2PSocketHostTcpServer::Init(): can't to get local address: "
- << result;
- OnError();
- return false;
- }
- VLOG(1) << "Local address: " << local_address_.ToString();
-
- state_ = STATE_OPEN;
- // NOTE: Remote address can be empty as socket is just listening
- // in this state.
- message_sender_->Send(new P2PMsg_OnSocketCreated(
- id_, local_address_, remote_address.ip_address));
- DoAccept();
- return true;
-}
-
-void P2PSocketHostTcpServer::OnError() {
- socket_.reset();
-
- if (state_ == STATE_UNINITIALIZED || state_ == STATE_OPEN)
- message_sender_->Send(new P2PMsg_OnError(id_));
-
- state_ = STATE_ERROR;
-}
-
-void P2PSocketHostTcpServer::DoAccept() {
- while (true) {
- int result = socket_->Accept(&accept_socket_, accept_callback_);
- if (result == net::ERR_IO_PENDING) {
- break;
- } else {
- HandleAcceptResult(result);
- }
- }
-}
-
-void P2PSocketHostTcpServer::HandleAcceptResult(int result) {
- if (result < 0) {
- if (result != net::ERR_IO_PENDING)
- OnError();
- return;
- }
-
- net::IPEndPoint address;
- if (accept_socket_->GetPeerAddress(&address) != net::OK) {
- LOG(ERROR) << "Failed to get address of an accepted socket.";
- accept_socket_.reset();
- return;
- }
- accepted_sockets_[address] = std::move(accept_socket_);
- message_sender_->Send(
- new P2PMsg_OnIncomingTcpConnection(id_, address));
-}
-
-void P2PSocketHostTcpServer::OnAccepted(int result) {
- HandleAcceptResult(result);
- if (result == net::OK)
- DoAccept();
-}
-
-void P2PSocketHostTcpServer::Send(
- const net::IPEndPoint& to,
- const std::vector<char>& data,
- const rtc::PacketOptions& options,
- uint64_t packet_id,
- const net::NetworkTrafficAnnotationTag traffic_annotation) {
- NOTREACHED();
- OnError();
-}
-
-std::unique_ptr<P2PSocketHost>
-P2PSocketHostTcpServer::AcceptIncomingTcpConnection(
- const net::IPEndPoint& remote_address,
- int id) {
- auto it = accepted_sockets_.find(remote_address);
- if (it == accepted_sockets_.end())
- return nullptr;
-
- std::unique_ptr<net::StreamSocket> socket = std::move(it->second);
- accepted_sockets_.erase(it);
-
- std::unique_ptr<P2PSocketHostTcpBase> result;
- if (client_type_ == P2P_SOCKET_TCP_CLIENT) {
- result.reset(new P2PSocketHostTcp(message_sender_, id, client_type_,
- nullptr, nullptr));
- } else {
- result.reset(new P2PSocketHostStunTcp(message_sender_, id, client_type_,
- nullptr, nullptr));
- }
- if (!result->InitAccepted(remote_address, std::move(socket)))
- return nullptr;
- return std::move(result);
-}
-
-bool P2PSocketHostTcpServer::SetOption(P2PSocketOption option,
- int value) {
- // Currently we don't have use case tcp server sockets are used for p2p.
- return false;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_tcp_server.h b/chromium/content/browser/renderer_host/p2p/socket_host_tcp_server.h
deleted file mode 100644
index 9b249463ff4..00000000000
--- a/chromium/content/browser/renderer_host/p2p/socket_host_tcp_server.h
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_RENDERER_HOST_P2P_SOCKET_HOST_TCP_SERVER_H_
-#define CONTENT_BROWSER_RENDERER_HOST_P2P_SOCKET_HOST_TCP_SERVER_H_
-
-#include <stdint.h>
-
-#include <map>
-#include <memory>
-#include <vector>
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "content/browser/renderer_host/p2p/socket_host.h"
-#include "content/common/content_export.h"
-#include "content/common/p2p_socket_type.h"
-#include "ipc/ipc_sender.h"
-#include "net/base/completion_callback.h"
-#include "net/socket/tcp_server_socket.h"
-#include "net/traffic_annotation/network_traffic_annotation.h"
-
-namespace net {
-class StreamSocket;
-} // namespace net
-
-namespace content {
-
-class CONTENT_EXPORT P2PSocketHostTcpServer : public P2PSocketHost {
- public:
- P2PSocketHostTcpServer(IPC::Sender* message_sender,
- int socket_id,
- P2PSocketType client_type);
- ~P2PSocketHostTcpServer() override;
-
- // P2PSocketHost overrides.
- bool Init(const net::IPEndPoint& local_address,
- uint16_t min_port,
- uint16_t max_port,
- const P2PHostAndIPEndPoint& remote_address) override;
- void Send(const net::IPEndPoint& to,
- const std::vector<char>& data,
- const rtc::PacketOptions& options,
- uint64_t packet_id,
- const net::NetworkTrafficAnnotationTag traffic_annotation) override;
- std::unique_ptr<P2PSocketHost> AcceptIncomingTcpConnection(
- const net::IPEndPoint& remote_address,
- int id) override;
- bool SetOption(P2PSocketOption option, int value) override;
-
- private:
- friend class P2PSocketHostTcpServerTest;
-
- void OnError();
-
- void DoAccept();
- void HandleAcceptResult(int result);
-
- // Callback for Accept().
- void OnAccepted(int result);
-
- const P2PSocketType client_type_;
- std::unique_ptr<net::ServerSocket> socket_;
- net::IPEndPoint local_address_;
-
- std::unique_ptr<net::StreamSocket> accept_socket_;
- std::map<net::IPEndPoint, std::unique_ptr<net::StreamSocket>>
- accepted_sockets_;
-
- net::CompletionCallback accept_callback_;
-
- DISALLOW_COPY_AND_ASSIGN(P2PSocketHostTcpServer);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_P2P_SOCKET_HOST_TCP_SERVER_H_
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_tcp_server_unittest.cc b/chromium/content/browser/renderer_host/p2p/socket_host_tcp_server_unittest.cc
deleted file mode 100644
index ca1ea46195c..00000000000
--- a/chromium/content/browser/renderer_host/p2p/socket_host_tcp_server_unittest.cc
+++ /dev/null
@@ -1,173 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/renderer_host/p2p/socket_host_tcp_server.h"
-
-#include <stdint.h>
-
-#include <list>
-
-#include "content/browser/renderer_host/p2p/socket_host_tcp.h"
-#include "content/browser/renderer_host/p2p/socket_host_test_utils.h"
-#include "net/base/completion_callback.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using ::testing::_;
-using ::testing::DeleteArg;
-using ::testing::DoAll;
-using ::testing::Return;
-
-namespace {
-
-class FakeServerSocket : public net::ServerSocket {
- public:
- FakeServerSocket() : listening_(false), accept_socket_(nullptr) {}
-
- ~FakeServerSocket() override {}
-
- bool listening() { return listening_; }
-
- void AddIncoming(net::StreamSocket* socket) {
- if (!accept_callback_.is_null()) {
- DCHECK(incoming_sockets_.empty());
- accept_socket_->reset(socket);
- accept_socket_ = nullptr;
-
- // This copy is necessary because this implementation of ServerSocket
- // bases logic on the null-ness of |accept_callback_| in the bound
- // callback.
- net::CompletionCallback cb = accept_callback_;
- accept_callback_.Reset();
- std::move(cb).Run(net::OK);
- } else {
- incoming_sockets_.push_back(socket);
- }
- }
-
- int Listen(const net::IPEndPoint& address, int backlog) override {
- local_address_ = address;
- listening_ = true;
- return net::OK;
- }
-
- int GetLocalAddress(net::IPEndPoint* address) const override {
- *address = local_address_;
- return net::OK;
- }
-
- int Accept(std::unique_ptr<net::StreamSocket>* socket,
- const net::CompletionCallback& callback) override {
- DCHECK(socket);
- if (!incoming_sockets_.empty()) {
- socket->reset(incoming_sockets_.front());
- incoming_sockets_.pop_front();
- return net::OK;
- } else {
- accept_socket_ = socket;
- accept_callback_ = callback;
- return net::ERR_IO_PENDING;
- }
- }
-
- private:
- bool listening_;
-
- net::IPEndPoint local_address_;
-
- std::unique_ptr<net::StreamSocket>* accept_socket_;
- net::CompletionCallback accept_callback_;
-
- std::list<net::StreamSocket*> incoming_sockets_;
-};
-
-} // namespace
-
-namespace content {
-
-class P2PSocketHostTcpServerTest : public testing::Test {
- protected:
- void SetUp() override {
- socket_ = new FakeServerSocket();
- socket_host_.reset(
- new P2PSocketHostTcpServer(&sender_, 0, P2P_SOCKET_TCP_CLIENT));
- socket_host_->socket_.reset(socket_);
-
- EXPECT_CALL(
- sender_,
- Send(MatchMessage(static_cast<uint32_t>(P2PMsg_OnSocketCreated::ID))))
- .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
-
- P2PHostAndIPEndPoint dest;
- dest.ip_address = ParseAddress(kTestIpAddress1, kTestPort1);
-
- socket_host_->Init(ParseAddress(kTestLocalIpAddress, 0), 0, 0, dest);
- EXPECT_TRUE(socket_->listening());
- }
-
- // Needed by the chilt classes because only this class is a friend
- // of P2PSocketHostTcp.
- net::StreamSocket* GetSocketFormTcpSocketHost(P2PSocketHostTcp* host) {
- return host->socket_.get();
- }
-
- MockIPCSender sender_;
- FakeServerSocket* socket_; // Owned by |socket_host_|.
- std::unique_ptr<P2PSocketHostTcpServer> socket_host_;
-};
-
-// Accept incoming connection.
-TEST_F(P2PSocketHostTcpServerTest, Accept) {
- FakeSocket* incoming = new FakeSocket(nullptr);
- incoming->SetLocalAddress(ParseAddress(kTestLocalIpAddress, kTestPort1));
- net::IPEndPoint addr = ParseAddress(kTestIpAddress1, kTestPort1);
- incoming->SetPeerAddress(addr);
-
- EXPECT_CALL(sender_, Send(MatchIncomingSocketMessage(addr)))
- .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
- socket_->AddIncoming(incoming);
-
- const int kAcceptedSocketId = 1;
-
- std::unique_ptr<P2PSocketHost> new_host(
- socket_host_->AcceptIncomingTcpConnection(addr, kAcceptedSocketId));
- ASSERT_TRUE(new_host.get() != nullptr);
- EXPECT_EQ(incoming, GetSocketFormTcpSocketHost(
- reinterpret_cast<P2PSocketHostTcp*>(new_host.get())));
-}
-
-// Accept 2 simultaneous connections.
-TEST_F(P2PSocketHostTcpServerTest, Accept2) {
- FakeSocket* incoming1 = new FakeSocket(nullptr);
- incoming1->SetLocalAddress(ParseAddress(kTestLocalIpAddress, kTestPort1));
- net::IPEndPoint addr1 = ParseAddress(kTestIpAddress1, kTestPort1);
- incoming1->SetPeerAddress(addr1);
- FakeSocket* incoming2 = new FakeSocket(nullptr);
- incoming2->SetLocalAddress(ParseAddress(kTestLocalIpAddress, kTestPort1));
- net::IPEndPoint addr2 = ParseAddress(kTestIpAddress2, kTestPort2);
- incoming2->SetPeerAddress(addr2);
-
- EXPECT_CALL(sender_, Send(MatchIncomingSocketMessage(addr1)))
- .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
- EXPECT_CALL(sender_, Send(MatchIncomingSocketMessage(addr2)))
- .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
- socket_->AddIncoming(incoming1);
- socket_->AddIncoming(incoming2);
-
- const int kAcceptedSocketId1 = 1;
- const int kAcceptedSocketId2 = 2;
-
- std::unique_ptr<P2PSocketHost> new_host1(
- socket_host_->AcceptIncomingTcpConnection(addr1, kAcceptedSocketId1));
- ASSERT_TRUE(new_host1.get() != nullptr);
- EXPECT_EQ(incoming1, GetSocketFormTcpSocketHost(
- reinterpret_cast<P2PSocketHostTcp*>(new_host1.get())));
- std::unique_ptr<P2PSocketHost> new_host2(
- socket_host_->AcceptIncomingTcpConnection(addr2, kAcceptedSocketId2));
- ASSERT_TRUE(new_host2.get() != nullptr);
- EXPECT_EQ(incoming2, GetSocketFormTcpSocketHost(
- reinterpret_cast<P2PSocketHostTcp*>(new_host2.get())));
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_tcp_unittest.cc b/chromium/content/browser/renderer_host/p2p/socket_host_tcp_unittest.cc
deleted file mode 100644
index 1017d6bb1d9..00000000000
--- a/chromium/content/browser/renderer_host/p2p/socket_host_tcp_unittest.cc
+++ /dev/null
@@ -1,581 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/renderer_host/p2p/socket_host_tcp.h"
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
-#include "base/sys_byteorder.h"
-#include "base/test/scoped_task_environment.h"
-#include "content/browser/renderer_host/p2p/socket_host_test_utils.h"
-#include "jingle/glue/fake_ssl_client_socket.h"
-#include "net/socket/socket_test_util.h"
-#include "net/socket/stream_socket.h"
-#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
-#include "net/url_request/url_request_test_util.h"
-#include "services/network/proxy_resolving_client_socket_factory.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using ::testing::_;
-using ::testing::DeleteArg;
-using ::testing::DoAll;
-using ::testing::Return;
-
-namespace content {
-
-class P2PSocketHostTcpTestBase : public testing::Test {
- protected:
- explicit P2PSocketHostTcpTestBase(P2PSocketType type)
- : socket_type_(type) {
- }
-
- void SetUp() override {
- EXPECT_CALL(
- sender_,
- Send(MatchMessage(static_cast<uint32_t>(P2PMsg_OnSocketCreated::ID))))
- .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
-
- if (socket_type_ == P2P_SOCKET_TCP_CLIENT) {
- socket_host_.reset(new P2PSocketHostTcp(
- &sender_, 0, P2P_SOCKET_TCP_CLIENT, nullptr, nullptr));
- } else {
- socket_host_.reset(new P2PSocketHostStunTcp(
- &sender_, 0, P2P_SOCKET_STUN_TCP_CLIENT, nullptr, nullptr));
- }
-
- socket_ = new FakeSocket(&sent_data_);
- socket_->SetLocalAddress(ParseAddress(kTestLocalIpAddress, kTestPort1));
- socket_host_->socket_.reset(socket_);
-
- dest_.ip_address = ParseAddress(kTestIpAddress1, kTestPort1);
-
- local_address_ = ParseAddress(kTestLocalIpAddress, kTestPort1);
-
- socket_host_->remote_address_ = dest_;
- socket_host_->state_ = P2PSocketHost::STATE_CONNECTING;
- socket_host_->OnConnected(net::OK);
- }
-
- std::string IntToSize(int size) {
- std::string result;
- uint16_t size16 = base::HostToNet16(size);
- result.resize(sizeof(size16));
- memcpy(&result[0], &size16, sizeof(size16));
- return result;
- }
-
- std::string sent_data_;
- FakeSocket* socket_; // Owned by |socket_host_|.
- std::unique_ptr<P2PSocketHostTcpBase> socket_host_;
- MockIPCSender sender_;
-
- net::IPEndPoint local_address_;
- P2PHostAndIPEndPoint dest_;
- P2PSocketType socket_type_;
-};
-
-class P2PSocketHostTcpTest : public P2PSocketHostTcpTestBase {
- protected:
- P2PSocketHostTcpTest() : P2PSocketHostTcpTestBase(P2P_SOCKET_TCP_CLIENT) { }
-};
-
-class P2PSocketHostStunTcpTest : public P2PSocketHostTcpTestBase {
- protected:
- P2PSocketHostStunTcpTest()
- : P2PSocketHostTcpTestBase(P2P_SOCKET_STUN_TCP_CLIENT) {
- }
-};
-
-// Verify that we can send STUN message and that they are formatted
-// properly.
-TEST_F(P2PSocketHostTcpTest, SendStunNoAuth) {
- EXPECT_CALL(
- sender_,
- Send(MatchMessage(static_cast<uint32_t>(P2PMsg_OnSendComplete::ID))))
- .Times(3)
- .WillRepeatedly(DoAll(DeleteArg<0>(), Return(true)));
-
- rtc::PacketOptions options;
- std::vector<char> packet1;
- CreateStunRequest(&packet1);
- socket_host_->Send(dest_.ip_address, packet1, options, 0,
- TRAFFIC_ANNOTATION_FOR_TESTS);
-
- std::vector<char> packet2;
- CreateStunResponse(&packet2);
- socket_host_->Send(dest_.ip_address, packet2, options, 0,
- TRAFFIC_ANNOTATION_FOR_TESTS);
-
- std::vector<char> packet3;
- CreateStunError(&packet3);
- socket_host_->Send(dest_.ip_address, packet3, options, 0,
- TRAFFIC_ANNOTATION_FOR_TESTS);
-
- std::string expected_data;
- expected_data.append(IntToSize(packet1.size()));
- expected_data.append(packet1.begin(), packet1.end());
- expected_data.append(IntToSize(packet2.size()));
- expected_data.append(packet2.begin(), packet2.end());
- expected_data.append(IntToSize(packet3.size()));
- expected_data.append(packet3.begin(), packet3.end());
-
- EXPECT_EQ(expected_data, sent_data_);
-}
-
-// Verify that we can receive STUN messages from the socket, and that
-// the messages are parsed properly.
-TEST_F(P2PSocketHostTcpTest, ReceiveStun) {
- EXPECT_CALL(
- sender_,
- Send(MatchMessage(static_cast<uint32_t>(P2PMsg_OnSendComplete::ID))))
- .Times(3)
- .WillRepeatedly(DoAll(DeleteArg<0>(), Return(true)));
-
- rtc::PacketOptions options;
- std::vector<char> packet1;
- CreateStunRequest(&packet1);
- socket_host_->Send(dest_.ip_address, packet1, options, 0,
- TRAFFIC_ANNOTATION_FOR_TESTS);
-
- std::vector<char> packet2;
- CreateStunResponse(&packet2);
- socket_host_->Send(dest_.ip_address, packet2, options, 0,
- TRAFFIC_ANNOTATION_FOR_TESTS);
-
- std::vector<char> packet3;
- CreateStunError(&packet3);
- socket_host_->Send(dest_.ip_address, packet3, options, 0,
- TRAFFIC_ANNOTATION_FOR_TESTS);
-
- std::string received_data;
- received_data.append(IntToSize(packet1.size()));
- received_data.append(packet1.begin(), packet1.end());
- received_data.append(IntToSize(packet2.size()));
- received_data.append(packet2.begin(), packet2.end());
- received_data.append(IntToSize(packet3.size()));
- received_data.append(packet3.begin(), packet3.end());
-
- EXPECT_CALL(sender_, Send(MatchPacketMessage(packet1)))
- .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
- EXPECT_CALL(sender_, Send(MatchPacketMessage(packet2)))
- .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
- EXPECT_CALL(sender_, Send(MatchPacketMessage(packet3)))
- .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
-
- size_t pos = 0;
- size_t step_sizes[] = {3, 2, 1};
- size_t step = 0;
- while (pos < received_data.size()) {
- size_t step_size = std::min(step_sizes[step], received_data.size() - pos);
- socket_->AppendInputData(&received_data[pos], step_size);
- pos += step_size;
- if (++step >= arraysize(step_sizes))
- step = 0;
- }
-}
-
-// Verify that we can't send data before we've received STUN response
-// from the other side.
-TEST_F(P2PSocketHostTcpTest, SendDataNoAuth) {
- EXPECT_CALL(sender_,
- Send(MatchMessage(static_cast<uint32_t>(P2PMsg_OnError::ID))))
- .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
-
- rtc::PacketOptions options;
- std::vector<char> packet;
- CreateRandomPacket(&packet);
- socket_host_->Send(dest_.ip_address, packet, options, 0,
- TRAFFIC_ANNOTATION_FOR_TESTS);
-
- EXPECT_EQ(0U, sent_data_.size());
-}
-
-// Verify that SetOption() doesn't crash after an error.
-TEST_F(P2PSocketHostTcpTest, SetOptionAfterError) {
- // Get the sender into the error state.
- EXPECT_CALL(sender_,
- Send(MatchMessage(static_cast<uint32_t>(P2PMsg_OnError::ID))))
- .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
- socket_host_->Send(dest_.ip_address, {1, 2, 3, 4}, rtc::PacketOptions(), 0,
- TRAFFIC_ANNOTATION_FOR_TESTS);
- testing::Mock::VerifyAndClearExpectations(&sender_);
-
- // Verify that SetOptions() fails, but doesn't crash.
- EXPECT_FALSE(socket_host_->SetOption(P2P_SOCKET_OPT_RCVBUF, 2048));
-}
-
-// Verify that we can send data after we've received STUN response
-// from the other side.
-TEST_F(P2PSocketHostTcpTest, SendAfterStunRequest) {
- // Receive packet from |dest_|.
- std::vector<char> request_packet;
- CreateStunRequest(&request_packet);
-
- std::string received_data;
- received_data.append(IntToSize(request_packet.size()));
- received_data.append(request_packet.begin(), request_packet.end());
-
- EXPECT_CALL(
- sender_,
- Send(MatchMessage(static_cast<uint32_t>(P2PMsg_OnSendComplete::ID))))
- .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
- EXPECT_CALL(sender_, Send(MatchPacketMessage(request_packet)))
- .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
- socket_->AppendInputData(&received_data[0], received_data.size());
-
- rtc::PacketOptions options;
- // Now we should be able to send any data to |dest_|.
- std::vector<char> packet;
- CreateRandomPacket(&packet);
- socket_host_->Send(dest_.ip_address, packet, options, 0,
- TRAFFIC_ANNOTATION_FOR_TESTS);
-
- std::string expected_data;
- expected_data.append(IntToSize(packet.size()));
- expected_data.append(packet.begin(), packet.end());
-
- EXPECT_EQ(expected_data, sent_data_);
-}
-
-// Verify that asynchronous writes are handled correctly.
-TEST_F(P2PSocketHostTcpTest, AsyncWrites) {
- base::MessageLoop message_loop;
-
- socket_->set_async_write(true);
-
- EXPECT_CALL(
- sender_,
- Send(MatchMessage(static_cast<uint32_t>(P2PMsg_OnSendComplete::ID))))
- .Times(2)
- .WillRepeatedly(DoAll(DeleteArg<0>(), Return(true)));
-
- rtc::PacketOptions options;
- std::vector<char> packet1;
- CreateStunRequest(&packet1);
-
- socket_host_->Send(dest_.ip_address, packet1, options, 0,
- TRAFFIC_ANNOTATION_FOR_TESTS);
-
- std::vector<char> packet2;
- CreateStunResponse(&packet2);
- socket_host_->Send(dest_.ip_address, packet2, options, 0,
- TRAFFIC_ANNOTATION_FOR_TESTS);
-
- base::RunLoop().RunUntilIdle();
-
- std::string expected_data;
- expected_data.append(IntToSize(packet1.size()));
- expected_data.append(packet1.begin(), packet1.end());
- expected_data.append(IntToSize(packet2.size()));
- expected_data.append(packet2.begin(), packet2.end());
-
- EXPECT_EQ(expected_data, sent_data_);
-}
-
-TEST_F(P2PSocketHostTcpTest, PacketIdIsPropagated) {
- base::MessageLoop message_loop;
-
- socket_->set_async_write(true);
-
- const int32_t kRtcPacketId = 1234;
-
- base::TimeTicks now = base::TimeTicks::Now();
-
- EXPECT_CALL(sender_, Send(MatchSendPacketMetrics(kRtcPacketId, now)))
- .Times(1)
- .WillRepeatedly(DoAll(DeleteArg<0>(), Return(true)));
-
- rtc::PacketOptions options;
- options.packet_id = kRtcPacketId;
- std::vector<char> packet1;
- CreateStunRequest(&packet1);
-
- socket_host_->Send(dest_.ip_address, packet1, options, 0,
- TRAFFIC_ANNOTATION_FOR_TESTS);
-
- base::RunLoop().RunUntilIdle();
-
- std::string expected_data;
- expected_data.append(IntToSize(packet1.size()));
- expected_data.append(packet1.begin(), packet1.end());
-
- EXPECT_EQ(expected_data, sent_data_);
-}
-
-TEST_F(P2PSocketHostTcpTest, SendDataWithPacketOptions) {
- std::vector<char> request_packet;
- CreateStunRequest(&request_packet);
-
- std::string received_data;
- received_data.append(IntToSize(request_packet.size()));
- received_data.append(request_packet.begin(), request_packet.end());
-
- EXPECT_CALL(
- sender_,
- Send(MatchMessage(static_cast<uint32_t>(P2PMsg_OnSendComplete::ID))))
- .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
- EXPECT_CALL(sender_, Send(MatchPacketMessage(request_packet)))
- .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
- socket_->AppendInputData(&received_data[0], received_data.size());
-
- rtc::PacketOptions options;
- options.packet_time_params.rtp_sendtime_extension_id = 3;
- // Now we should be able to send any data to |dest_|.
- std::vector<char> packet;
- CreateRandomPacket(&packet);
- // Make it a RTP packet.
- *reinterpret_cast<uint16_t*>(&*packet.begin()) = base::HostToNet16(0x8000);
- socket_host_->Send(dest_.ip_address, packet, options, 0,
- TRAFFIC_ANNOTATION_FOR_TESTS);
-
- std::string expected_data;
- expected_data.append(IntToSize(packet.size()));
- expected_data.append(packet.begin(), packet.end());
-
- EXPECT_EQ(expected_data, sent_data_);
-}
-
-// Verify that we can send STUN message and that they are formatted
-// properly.
-TEST_F(P2PSocketHostStunTcpTest, SendStunNoAuth) {
- EXPECT_CALL(
- sender_,
- Send(MatchMessage(static_cast<uint32_t>(P2PMsg_OnSendComplete::ID))))
- .Times(3)
- .WillRepeatedly(DoAll(DeleteArg<0>(), Return(true)));
-
- rtc::PacketOptions options;
- std::vector<char> packet1;
- CreateStunRequest(&packet1);
- socket_host_->Send(dest_.ip_address, packet1, options, 0,
- TRAFFIC_ANNOTATION_FOR_TESTS);
-
- std::vector<char> packet2;
- CreateStunResponse(&packet2);
- socket_host_->Send(dest_.ip_address, packet2, options, 0,
- TRAFFIC_ANNOTATION_FOR_TESTS);
-
- std::vector<char> packet3;
- CreateStunError(&packet3);
- socket_host_->Send(dest_.ip_address, packet3, options, 0,
- TRAFFIC_ANNOTATION_FOR_TESTS);
-
- std::string expected_data;
- expected_data.append(packet1.begin(), packet1.end());
- expected_data.append(packet2.begin(), packet2.end());
- expected_data.append(packet3.begin(), packet3.end());
-
- EXPECT_EQ(expected_data, sent_data_);
-}
-
-// Verify that we can receive STUN messages from the socket, and that
-// the messages are parsed properly.
-TEST_F(P2PSocketHostStunTcpTest, ReceiveStun) {
- EXPECT_CALL(
- sender_,
- Send(MatchMessage(static_cast<uint32_t>(P2PMsg_OnSendComplete::ID))))
- .Times(3)
- .WillRepeatedly(DoAll(DeleteArg<0>(), Return(true)));
-
- rtc::PacketOptions options;
- std::vector<char> packet1;
- CreateStunRequest(&packet1);
- socket_host_->Send(dest_.ip_address, packet1, options, 0,
- TRAFFIC_ANNOTATION_FOR_TESTS);
-
- std::vector<char> packet2;
- CreateStunResponse(&packet2);
- socket_host_->Send(dest_.ip_address, packet2, options, 0,
- TRAFFIC_ANNOTATION_FOR_TESTS);
-
- std::vector<char> packet3;
- CreateStunError(&packet3);
- socket_host_->Send(dest_.ip_address, packet3, options, 0,
- TRAFFIC_ANNOTATION_FOR_TESTS);
-
- std::string received_data;
- received_data.append(packet1.begin(), packet1.end());
- received_data.append(packet2.begin(), packet2.end());
- received_data.append(packet3.begin(), packet3.end());
-
- EXPECT_CALL(sender_, Send(MatchPacketMessage(packet1)))
- .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
- EXPECT_CALL(sender_, Send(MatchPacketMessage(packet2)))
- .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
- EXPECT_CALL(sender_, Send(MatchPacketMessage(packet3)))
- .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
-
- size_t pos = 0;
- size_t step_sizes[] = {3, 2, 1};
- size_t step = 0;
- while (pos < received_data.size()) {
- size_t step_size = std::min(step_sizes[step], received_data.size() - pos);
- socket_->AppendInputData(&received_data[pos], step_size);
- pos += step_size;
- if (++step >= arraysize(step_sizes))
- step = 0;
- }
-}
-
-// Verify that we can't send data before we've received STUN response
-// from the other side.
-TEST_F(P2PSocketHostStunTcpTest, SendDataNoAuth) {
- EXPECT_CALL(sender_,
- Send(MatchMessage(static_cast<uint32_t>(P2PMsg_OnError::ID))))
- .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
-
- rtc::PacketOptions options;
- std::vector<char> packet;
- CreateRandomPacket(&packet);
- socket_host_->Send(dest_.ip_address, packet, options, 0,
- TRAFFIC_ANNOTATION_FOR_TESTS);
-
- EXPECT_EQ(0U, sent_data_.size());
-}
-
-// Verify that asynchronous writes are handled correctly.
-TEST_F(P2PSocketHostStunTcpTest, AsyncWrites) {
- base::MessageLoop message_loop;
-
- socket_->set_async_write(true);
-
- EXPECT_CALL(
- sender_,
- Send(MatchMessage(static_cast<uint32_t>(P2PMsg_OnSendComplete::ID))))
- .Times(2)
- .WillRepeatedly(DoAll(DeleteArg<0>(), Return(true)));
-
- rtc::PacketOptions options;
- std::vector<char> packet1;
- CreateStunRequest(&packet1);
- socket_host_->Send(dest_.ip_address, packet1, options, 0,
- TRAFFIC_ANNOTATION_FOR_TESTS);
-
- std::vector<char> packet2;
- CreateStunResponse(&packet2);
- socket_host_->Send(dest_.ip_address, packet2, options, 0,
- TRAFFIC_ANNOTATION_FOR_TESTS);
-
- base::RunLoop().RunUntilIdle();
-
- std::string expected_data;
- expected_data.append(packet1.begin(), packet1.end());
- expected_data.append(packet2.begin(), packet2.end());
-
- EXPECT_EQ(expected_data, sent_data_);
-}
-
-// When pseudo-tls is used (e.g. for P2P_SOCKET_SSLTCP_CLIENT),
-// network::ProxyResolvingClientSocket::Connect() won't be called twice.
-// Regression test for crbug.com/840797.
-TEST(P2PSocketHostTcpWithPseudoTlsTest, Basic) {
- base::test::ScopedTaskEnvironment scoped_task_environment(
- base::test::ScopedTaskEnvironment::MainThreadType::IO);
- MockIPCSender sender;
- EXPECT_CALL(
- sender,
- Send(MatchMessage(static_cast<uint32_t>(P2PMsg_OnSocketCreated::ID))))
- .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
-
- net::TestURLRequestContext context(true);
- net::MockClientSocketFactory mock_socket_factory;
- context.set_client_socket_factory(&mock_socket_factory);
- context.Init();
- network::ProxyResolvingClientSocketFactory factory(&context);
-
- base::StringPiece ssl_client_hello =
- jingle_glue::FakeSSLClientSocket::GetSslClientHello();
- base::StringPiece ssl_server_hello =
- jingle_glue::FakeSSLClientSocket::GetSslServerHello();
- net::MockRead reads[] = {
- net::MockRead(net::ASYNC, ssl_server_hello.data(),
- ssl_server_hello.size()),
- net::MockRead(net::SYNCHRONOUS, net::ERR_IO_PENDING)};
- net::MockWrite writes[] = {net::MockWrite(
- net::SYNCHRONOUS, ssl_client_hello.data(), ssl_client_hello.size())};
- net::StaticSocketDataProvider data_provider(reads, writes);
- net::IPEndPoint server_addr(net::IPAddress::IPv4Localhost(), 1234);
- data_provider.set_connect_data(
- net::MockConnect(net::SYNCHRONOUS, net::OK, server_addr));
- mock_socket_factory.AddSocketDataProvider(&data_provider);
-
- P2PSocketHostTcp host(&sender, 0 /*socket_id*/, P2P_SOCKET_SSLTCP_CLIENT,
- nullptr, &factory);
- P2PHostAndIPEndPoint dest;
- dest.ip_address = server_addr;
- bool success = host.Init(net::IPEndPoint(net::IPAddress::IPv4Localhost(), 0),
- 0, 0, dest);
- EXPECT_TRUE(success);
-
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(data_provider.AllReadDataConsumed());
- EXPECT_TRUE(data_provider.AllWriteDataConsumed());
-}
-
-class P2PSocketHostTcpWithTlsTest
- : public testing::TestWithParam<std::tuple<net::IoMode, P2PSocketType>> {};
-
-INSTANTIATE_TEST_CASE_P(
- /* no prefix */,
- P2PSocketHostTcpWithTlsTest,
- ::testing::Combine(::testing::Values(net::SYNCHRONOUS, net::ASYNC),
- ::testing::Values(P2P_SOCKET_TLS_CLIENT,
- P2P_SOCKET_STUN_TLS_CLIENT)));
-
-// Tests that if a socket type satisfies IsTlsClientSocket(), TLS connection is
-// established.
-TEST_P(P2PSocketHostTcpWithTlsTest, Basic) {
- base::test::ScopedTaskEnvironment scoped_task_environment(
- base::test::ScopedTaskEnvironment::MainThreadType::IO);
- MockIPCSender sender;
- EXPECT_CALL(
- sender,
- Send(MatchMessage(static_cast<uint32_t>(P2PMsg_OnSocketCreated::ID))))
- .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
-
- net::TestURLRequestContext context(true);
- net::MockClientSocketFactory mock_socket_factory;
- context.set_client_socket_factory(&mock_socket_factory);
- context.Init();
- network::ProxyResolvingClientSocketFactory factory(&context);
- const net::IoMode io_mode = std::get<0>(GetParam());
- const P2PSocketType socket_type = std::get<1>(GetParam());
- // OnOpen() calls DoRead(), so populate the mock socket with a pending read.
- net::MockRead reads[] = {
- net::MockRead(net::SYNCHRONOUS, net::ERR_IO_PENDING)};
- net::StaticSocketDataProvider data_provider(
- reads, base::span<const net::MockWrite>());
- net::IPEndPoint server_addr(net::IPAddress::IPv4Localhost(), 1234);
- data_provider.set_connect_data(
- net::MockConnect(io_mode, net::OK, server_addr));
- net::SSLSocketDataProvider ssl_socket_provider(io_mode, net::OK);
- mock_socket_factory.AddSocketDataProvider(&data_provider);
- mock_socket_factory.AddSSLSocketDataProvider(&ssl_socket_provider);
-
- std::unique_ptr<P2PSocketHostTcpBase> host;
- if (socket_type == P2P_SOCKET_STUN_TLS_CLIENT) {
- host = std::make_unique<P2PSocketHostStunTcp>(
- &sender, 0 /*socket_id*/, socket_type, nullptr, &factory);
- } else {
- host = std::make_unique<P2PSocketHostTcp>(&sender, 0 /*socket_id*/,
- socket_type, nullptr, &factory);
- }
- P2PHostAndIPEndPoint dest;
- dest.ip_address = server_addr;
- bool success = host->Init(net::IPEndPoint(net::IPAddress::IPv4Localhost(), 0),
- 0, 0, dest);
- EXPECT_TRUE(success);
-
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(data_provider.AllReadDataConsumed());
- EXPECT_TRUE(data_provider.AllWriteDataConsumed());
- EXPECT_TRUE(ssl_socket_provider.ConnectDataConsumed());
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_test_utils.cc b/chromium/content/browser/renderer_host/p2p/socket_host_test_utils.cc
deleted file mode 100644
index 6c18bea987b..00000000000
--- a/chromium/content/browser/renderer_host/p2p/socket_host_test_utils.cc
+++ /dev/null
@@ -1,217 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/renderer_host/p2p/socket_host_test_utils.h"
-
-#include <stddef.h>
-
-#include "base/logging.h"
-#include "base/sys_byteorder.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "net/base/completion_callback.h"
-#include "net/base/io_buffer.h"
-#include "net/base/ip_address.h"
-#include "net/traffic_annotation/network_traffic_annotation.h"
-
-const int kStunHeaderSize = 20;
-const uint16_t kStunBindingRequest = 0x0001;
-const uint16_t kStunBindingResponse = 0x0102;
-const uint16_t kStunBindingError = 0x0111;
-const uint32_t kStunMagicCookie = 0x2112A442;
-
-MockIPCSender::MockIPCSender() { }
-MockIPCSender::~MockIPCSender() { }
-
-FakeSocket::FakeSocket(std::string* written_data)
- : read_pending_(false),
- input_pos_(0),
- written_data_(written_data),
- async_write_(false),
- write_pending_(false) {
-}
-
-FakeSocket::~FakeSocket() { }
-
-void FakeSocket::AppendInputData(const char* data, int data_size) {
- input_data_.insert(input_data_.end(), data, data + data_size);
- // Complete pending read if any.
- if (read_pending_) {
- read_pending_ = false;
- int result = std::min(read_buffer_size_,
- static_cast<int>(input_data_.size() - input_pos_));
- CHECK(result > 0);
- memcpy(read_buffer_->data(), &input_data_[0] + input_pos_, result);
- input_pos_ += result;
- read_buffer_ = nullptr;
- std::move(read_callback_).Run(result);
- }
-}
-
-void FakeSocket::SetPeerAddress(const net::IPEndPoint& peer_address) {
- peer_address_ = peer_address;
-}
-
-void FakeSocket::SetLocalAddress(const net::IPEndPoint& local_address) {
- local_address_ = local_address;
-}
-
-int FakeSocket::Read(net::IOBuffer* buf,
- int buf_len,
- net::CompletionOnceCallback callback) {
- DCHECK(buf);
- if (input_pos_ < static_cast<int>(input_data_.size())){
- int result = std::min(buf_len,
- static_cast<int>(input_data_.size()) - input_pos_);
- memcpy(buf->data(), &(*input_data_.begin()) + input_pos_, result);
- input_pos_ += result;
- return result;
- } else {
- read_pending_ = true;
- read_buffer_ = buf;
- read_buffer_size_ = buf_len;
- read_callback_ = std::move(callback);
- return net::ERR_IO_PENDING;
- }
-}
-
-int FakeSocket::Write(
- net::IOBuffer* buf,
- int buf_len,
- net::CompletionOnceCallback callback,
- const net::NetworkTrafficAnnotationTag& /*traffic_annotation*/) {
- DCHECK(buf);
- DCHECK(!write_pending_);
-
- if (async_write_) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::BindOnce(&FakeSocket::DoAsyncWrite, base::Unretained(this),
- scoped_refptr<net::IOBuffer>(buf), buf_len,
- std::move(callback)));
- write_pending_ = true;
- return net::ERR_IO_PENDING;
- }
-
- if (written_data_) {
- written_data_->insert(written_data_->end(),
- buf->data(), buf->data() + buf_len);
- }
- return buf_len;
-}
-
-void FakeSocket::DoAsyncWrite(scoped_refptr<net::IOBuffer> buf,
- int buf_len,
- net::CompletionOnceCallback callback) {
- write_pending_ = false;
-
- if (written_data_) {
- written_data_->insert(written_data_->end(),
- buf->data(), buf->data() + buf_len);
- }
- std::move(callback).Run(buf_len);
-}
-
-int FakeSocket::SetReceiveBufferSize(int32_t size) {
- NOTIMPLEMENTED();
- return net::ERR_NOT_IMPLEMENTED;
-}
-
-int FakeSocket::SetSendBufferSize(int32_t size) {
- NOTIMPLEMENTED();
- return net::ERR_NOT_IMPLEMENTED;
-}
-
-int FakeSocket::Connect(net::CompletionOnceCallback callback) {
- return 0;
-}
-
-void FakeSocket::Disconnect() {
- NOTREACHED();
-}
-
-bool FakeSocket::IsConnected() const {
- return true;
-}
-
-bool FakeSocket::IsConnectedAndIdle() const {
- return false;
-}
-
-int FakeSocket::GetPeerAddress(net::IPEndPoint* address) const {
- *address = peer_address_;
- return net::OK;
-}
-
-int FakeSocket::GetLocalAddress(net::IPEndPoint* address) const {
- *address = local_address_;
- return net::OK;
-}
-
-const net::NetLogWithSource& FakeSocket::NetLog() const {
- NOTREACHED();
- return net_log_;
-}
-
-bool FakeSocket::WasEverUsed() const {
- return true;
-}
-
-bool FakeSocket::WasAlpnNegotiated() const {
- return false;
-}
-
-net::NextProto FakeSocket::GetNegotiatedProtocol() const {
- return net::kProtoUnknown;
-}
-
-bool FakeSocket::GetSSLInfo(net::SSLInfo* ssl_info) {
- return false;
-}
-
-void FakeSocket::GetConnectionAttempts(net::ConnectionAttempts* out) const {
- out->clear();
-}
-
-int64_t FakeSocket::GetTotalReceivedBytes() const {
- NOTIMPLEMENTED();
- return 0;
-}
-
-void CreateRandomPacket(std::vector<char>* packet) {
- size_t size = kStunHeaderSize + rand() % 1000;
- packet->resize(size);
- for (size_t i = 0; i < size; i++) {
- (*packet)[i] = rand() % 256;
- }
- // Always set the first bit to ensure that generated packet is not
- // valid STUN packet.
- (*packet)[0] = (*packet)[0] | 0x80;
-}
-
-static void CreateStunPacket(std::vector<char>* packet, uint16_t type) {
- CreateRandomPacket(packet);
- *reinterpret_cast<uint16_t*>(&*packet->begin()) = base::HostToNet16(type);
- *reinterpret_cast<uint16_t*>(&*packet->begin() + 2) =
- base::HostToNet16(packet->size() - kStunHeaderSize);
- *reinterpret_cast<uint32_t*>(&*packet->begin() + 4) =
- base::HostToNet32(kStunMagicCookie);
-}
-
-void CreateStunRequest(std::vector<char>* packet) {
- CreateStunPacket(packet, kStunBindingRequest);
-}
-
-void CreateStunResponse(std::vector<char>* packet) {
- CreateStunPacket(packet, kStunBindingResponse);
-}
-
-void CreateStunError(std::vector<char>* packet) {
- CreateStunPacket(packet, kStunBindingError);
-}
-
-net::IPEndPoint ParseAddress(const std::string& ip_str, uint16_t port) {
- net::IPAddress ip;
- EXPECT_TRUE(ip.AssignFromIPLiteral(ip_str));
- return net::IPEndPoint(ip, port);
-}
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_test_utils.h b/chromium/content/browser/renderer_host/p2p/socket_host_test_utils.h
deleted file mode 100644
index 296aab86dc0..00000000000
--- a/chromium/content/browser/renderer_host/p2p/socket_host_test_utils.h
+++ /dev/null
@@ -1,140 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_RENDERER_HOST_P2P_SOCKET_HOST_TEST_UTILS_H_
-#define CONTENT_BROWSER_RENDERER_HOST_P2P_SOCKET_HOST_TEST_UTILS_H_
-
-#include <stdint.h>
-
-#include <string>
-#include <tuple>
-#include <vector>
-
-#include "content/common/p2p_messages.h"
-#include "ipc/ipc_sender.h"
-#include "net/base/net_errors.h"
-#include "net/log/net_log_with_source.h"
-#include "net/socket/stream_socket.h"
-#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-const char kTestLocalIpAddress[] = "123.44.22.4";
-const char kTestIpAddress1[] = "123.44.22.31";
-const uint16_t kTestPort1 = 234;
-const char kTestIpAddress2[] = "133.11.22.33";
-const uint16_t kTestPort2 = 543;
-
-class MockIPCSender : public IPC::Sender {
- public:
- MockIPCSender();
- ~MockIPCSender() override;
-
- MOCK_METHOD1(Send, bool(IPC::Message* msg));
-};
-
-class FakeSocket : public net::StreamSocket {
- public:
- FakeSocket(std::string* written_data);
- ~FakeSocket() override;
-
- void set_async_write(bool async_write) { async_write_ = async_write; }
- void AppendInputData(const char* data, int data_size);
- int input_pos() const { return input_pos_; }
- bool read_pending() const { return read_pending_; }
- void SetPeerAddress(const net::IPEndPoint& peer_address);
- void SetLocalAddress(const net::IPEndPoint& local_address);
-
- // net::Socket implementation.
- int Read(net::IOBuffer* buf,
- int buf_len,
- net::CompletionOnceCallback callback) override;
- int Write(
- net::IOBuffer* buf,
- int buf_len,
- net::CompletionOnceCallback callback,
- const net::NetworkTrafficAnnotationTag& traffic_annotation) override;
- int SetReceiveBufferSize(int32_t size) override;
- int SetSendBufferSize(int32_t size) override;
- int Connect(net::CompletionOnceCallback callback) override;
- void Disconnect() override;
- bool IsConnected() const override;
- bool IsConnectedAndIdle() const override;
- int GetPeerAddress(net::IPEndPoint* address) const override;
- int GetLocalAddress(net::IPEndPoint* address) const override;
- const net::NetLogWithSource& NetLog() const override;
- bool WasEverUsed() const override;
- bool WasAlpnNegotiated() const override;
- net::NextProto GetNegotiatedProtocol() const override;
- bool GetSSLInfo(net::SSLInfo* ssl_info) override;
- void GetConnectionAttempts(net::ConnectionAttempts* out) const override;
- void ClearConnectionAttempts() override {}
- void AddConnectionAttempts(const net::ConnectionAttempts& attempts) override {
- }
- int64_t GetTotalReceivedBytes() const override;
- void ApplySocketTag(const net::SocketTag& tag) override {}
-
- private:
- void DoAsyncWrite(scoped_refptr<net::IOBuffer> buf,
- int buf_len,
- net::CompletionOnceCallback callback);
-
- bool read_pending_;
- scoped_refptr<net::IOBuffer> read_buffer_;
- int read_buffer_size_;
- net::CompletionOnceCallback read_callback_;
-
- std::string input_data_;
- int input_pos_;
-
- std::string* written_data_;
- bool async_write_;
- bool write_pending_;
-
- net::IPEndPoint peer_address_;
- net::IPEndPoint local_address_;
-
- net::NetLogWithSource net_log_;
-};
-
-void CreateRandomPacket(std::vector<char>* packet);
-void CreateStunRequest(std::vector<char>* packet);
-void CreateStunResponse(std::vector<char>* packet);
-void CreateStunError(std::vector<char>* packet);
-
-net::IPEndPoint ParseAddress(const std::string& ip_str, uint16_t port);
-
-MATCHER_P(MatchMessage, type, "") {
- return arg->type() == type;
-}
-
-MATCHER_P(MatchPacketMessage, packet_content, "") {
- if (arg->type() != P2PMsg_OnDataReceived::ID)
- return false;
- P2PMsg_OnDataReceived::Param params;
- P2PMsg_OnDataReceived::Read(arg, &params);
- return std::get<2>(params) == packet_content;
-}
-
-MATCHER_P(MatchIncomingSocketMessage, address, "") {
- if (arg->type() != P2PMsg_OnIncomingTcpConnection::ID)
- return false;
- P2PMsg_OnIncomingTcpConnection::Param params;
- P2PMsg_OnIncomingTcpConnection::Read(
- arg, &params);
- return std::get<1>(params) == address;
-}
-
-MATCHER_P2(MatchSendPacketMetrics, rtc_packet_id, test_start_time, "") {
- if (arg->type() != P2PMsg_OnSendComplete::ID)
- return false;
-
- P2PMsg_OnSendComplete::Param params;
- P2PMsg_OnSendComplete::Read(arg, &params);
- return std::get<1>(params).rtc_packet_id == rtc_packet_id &&
- std::get<1>(params).send_time >= test_start_time &&
- std::get<1>(params).send_time <= base::TimeTicks::Now();
-}
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_P2P_SOCKET_HOST_TEST_UTILS_H_
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_throttler.cc b/chromium/content/browser/renderer_host/p2p/socket_host_throttler.cc
deleted file mode 100644
index e54d190eee7..00000000000
--- a/chromium/content/browser/renderer_host/p2p/socket_host_throttler.cc
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/renderer_host/p2p/socket_host_throttler.h"
-
-#include <utility>
-
-#include "third_party/webrtc/rtc_base/data_rate_limiter.h"
-#include "third_party/webrtc/rtc_base/timeutils.h"
-
-namespace content {
-
-namespace {
-
-const int kMaxIceMessageBandwidth = 256 * 1024;
-
-} // namespace
-
-P2PMessageThrottler::P2PMessageThrottler()
- : rate_limiter_(new rtc::DataRateLimiter(kMaxIceMessageBandwidth, 1.0)) {}
-
-P2PMessageThrottler::~P2PMessageThrottler() {
-}
-
-void P2PMessageThrottler::SetSendIceBandwidth(int bandwidth_kbps) {
- rate_limiter_.reset(new rtc::DataRateLimiter(bandwidth_kbps, 1.0));
-}
-
-bool P2PMessageThrottler::DropNextPacket(size_t packet_len) {
- double now =
- rtc::TimeNanos() / static_cast<double>(rtc::kNumNanosecsPerSec);
- if (!rate_limiter_->CanUse(packet_len, now)) {
- // Exceeding the send rate, this packet should be dropped.
- return true;
- }
-
- rate_limiter_->Use(packet_len, now);
- return false;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_throttler.h b/chromium/content/browser/renderer_host/p2p/socket_host_throttler.h
deleted file mode 100644
index d8ad20c7dd3..00000000000
--- a/chromium/content/browser/renderer_host/p2p/socket_host_throttler.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_RENDERER_HOST_P2P_SOCKET_HOST_THROTTLER_H_
-#define CONTENT_BROWSER_RENDERER_HOST_P2P_SOCKET_HOST_THROTTLER_H_
-
-#include <stddef.h>
-
-#include <memory>
-
-#include "base/macros.h"
-#include "content/common/content_export.h"
-
-namespace rtc {
-class DataRateLimiter;
-}
-
-namespace content {
-
-// A very simple message throtller. User of this class must drop the packet if
-// DropNextPacket returns false for that packet. This method verifies the
-// current sendrate against the required sendrate.
-
-class CONTENT_EXPORT P2PMessageThrottler {
- public:
- P2PMessageThrottler();
- virtual ~P2PMessageThrottler();
-
- bool DropNextPacket(size_t packet_len);
- void SetSendIceBandwidth(int bandwith_kbps);
-
- private:
- std::unique_ptr<rtc::DataRateLimiter> rate_limiter_;
-
- DISALLOW_COPY_AND_ASSIGN(P2PMessageThrottler);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_P2P_SOCKET_HOST_THROTTLER_H_
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_udp.cc b/chromium/content/browser/renderer_host/p2p/socket_host_udp.cc
deleted file mode 100644
index 318ed0bbd5a..00000000000
--- a/chromium/content/browser/renderer_host/p2p/socket_host_udp.cc
+++ /dev/null
@@ -1,462 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/renderer_host/p2p/socket_host_udp.h"
-
-#include "base/bind.h"
-#include "base/memory/ptr_util.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/stl_util.h"
-#include "base/strings/stringprintf.h"
-#include "base/trace_event/trace_event.h"
-#include "build/build_config.h"
-#include "content/browser/renderer_host/p2p/socket_host_throttler.h"
-#include "content/common/p2p_messages.h"
-#include "content/public/browser/content_browser_client.h"
-#include "content/public/common/content_client.h"
-#include "ipc/ipc_sender.h"
-#include "net/base/io_buffer.h"
-#include "net/base/net_errors.h"
-#include "net/log/net_log_source.h"
-#include "third_party/webrtc/media/base/rtputils.h"
-
-namespace {
-
-// UDP packets cannot be bigger than 64k.
-const int kUdpReadBufferSize = 65536;
-// Socket receive buffer size.
-const int kUdpRecvSocketBufferSize = 65536; // 64K
-// Socket send buffer size.
-const int kUdpSendSocketBufferSize = 65536;
-
-// Defines set of transient errors. These errors are ignored when we get them
-// from sendto() or recvfrom() calls.
-//
-// net::ERR_OUT_OF_MEMORY
-//
-// This is caused by ENOBUFS which means the buffer of the network interface
-// is full.
-//
-// net::ERR_CONNECTION_RESET
-//
-// This is caused by WSAENETRESET or WSAECONNRESET which means the
-// last send resulted in an "ICMP Port Unreachable" message.
-struct {
- int code;
- const char* name;
-} static const kTransientErrors[] {
- {net::ERR_ADDRESS_UNREACHABLE, "net::ERR_ADDRESS_UNREACHABLE"},
- {net::ERR_ADDRESS_INVALID, "net::ERR_ADDRESS_INVALID"},
- {net::ERR_ACCESS_DENIED, "net::ERR_ACCESS_DENIED"},
- {net::ERR_CONNECTION_RESET, "net::ERR_CONNECTION_RESET"},
- {net::ERR_OUT_OF_MEMORY, "net::ERR_OUT_OF_MEMORY"},
- {net::ERR_INTERNET_DISCONNECTED, "net::ERR_INTERNET_DISCONNECTED"}
-};
-
-bool IsTransientError(int error) {
- for (const auto& transient_error : kTransientErrors) {
- if (transient_error.code == error)
- return true;
- }
- return false;
-}
-
-const char* GetTransientErrorName(int error) {
- for (const auto& transient_error : kTransientErrors) {
- if (transient_error.code == error)
- return transient_error.name;
- }
- return "";
-}
-
-} // namespace
-
-namespace content {
-
-P2PSocketHostUdp::PendingPacket::PendingPacket(
- const net::IPEndPoint& to,
- const std::vector<char>& content,
- const rtc::PacketOptions& options,
- uint64_t id,
- const net::NetworkTrafficAnnotationTag traffic_annotation)
- : to(to),
- data(new net::IOBuffer(content.size())),
- size(content.size()),
- packet_options(options),
- id(id),
- traffic_annotation(traffic_annotation) {
- memcpy(data->data(), &content[0], size);
-}
-
-P2PSocketHostUdp::PendingPacket::PendingPacket(const PendingPacket& other) =
- default;
-
-P2PSocketHostUdp::PendingPacket::~PendingPacket() {
-}
-
-P2PSocketHostUdp::P2PSocketHostUdp(
- IPC::Sender* message_sender,
- int socket_id,
- P2PMessageThrottler* throttler,
- net::NetLog* net_log,
- const DatagramServerSocketFactory& socket_factory)
- : P2PSocketHost(message_sender, socket_id, P2PSocketHost::UDP),
- socket_(socket_factory.Run(net_log)),
- send_pending_(false),
- last_dscp_(net::DSCP_CS0),
- throttler_(throttler),
- net_log_(net_log),
- socket_factory_(socket_factory) {}
-
-P2PSocketHostUdp::P2PSocketHostUdp(IPC::Sender* message_sender,
- int socket_id,
- P2PMessageThrottler* throttler,
- net::NetLog* net_log)
- : P2PSocketHostUdp(message_sender,
- socket_id,
- throttler,
- net_log,
- base::Bind(&P2PSocketHostUdp::DefaultSocketFactory)) {}
-
-P2PSocketHostUdp::~P2PSocketHostUdp() {
- if (state_ == STATE_OPEN) {
- DCHECK(socket_.get());
- socket_.reset();
- }
-}
-
-bool P2PSocketHostUdp::Init(const net::IPEndPoint& local_address,
- uint16_t min_port,
- uint16_t max_port,
- const P2PHostAndIPEndPoint& remote_address) {
- DCHECK_EQ(state_, STATE_UNINITIALIZED);
- DCHECK((min_port == 0 && max_port == 0) || min_port > 0);
- DCHECK_LE(min_port, max_port);
-
- int result = -1;
- if (min_port == 0) {
- result = socket_->Listen(local_address);
- } else if (local_address.port() == 0) {
- for (unsigned port = min_port; port <= max_port && result < 0; ++port) {
- result = socket_->Listen(net::IPEndPoint(local_address.address(), port));
- if (result < 0 && port != max_port)
- socket_ = socket_factory_.Run(net_log_);
- }
- } else if (local_address.port() >= min_port &&
- local_address.port() <= max_port) {
- result = socket_->Listen(local_address);
- }
- if (result < 0) {
- LOG(ERROR) << "bind() to " << local_address.address().ToString()
- << (min_port == 0
- ? base::StringPrintf(":%d", local_address.port())
- : base::StringPrintf(", port range [%d-%d]", min_port,
- max_port))
- << " failed: " << result;
- OnError();
- return false;
- }
-
- // Setting recv socket buffer size.
- if (socket_->SetReceiveBufferSize(kUdpRecvSocketBufferSize) != net::OK) {
- LOG(WARNING) << "Failed to set socket receive buffer size to "
- << kUdpRecvSocketBufferSize;
- }
-
- // Setting socket send buffer size.
- if (socket_->SetSendBufferSize(kUdpSendSocketBufferSize) != net::OK) {
- LOG(WARNING) << "Failed to set socket send buffer size to "
- << kUdpSendSocketBufferSize;
- }
-
- net::IPEndPoint address;
- result = socket_->GetLocalAddress(&address);
- if (result < 0) {
- LOG(ERROR) << "P2PSocketHostUdp::Init(): unable to get local address: "
- << result;
- OnError();
- return false;
- }
- VLOG(1) << "Local address: " << address.ToString();
-
- state_ = STATE_OPEN;
-
- // NOTE: Remote address will be same as what renderer provided.
- message_sender_->Send(new P2PMsg_OnSocketCreated(
- id_, address, remote_address.ip_address));
-
- recv_buffer_ = new net::IOBuffer(kUdpReadBufferSize);
- DoRead();
-
- return true;
-}
-
-void P2PSocketHostUdp::OnError() {
- socket_.reset();
- send_queue_.clear();
-
- if (state_ == STATE_UNINITIALIZED || state_ == STATE_OPEN)
- message_sender_->Send(new P2PMsg_OnError(id_));
-
- state_ = STATE_ERROR;
-}
-
-void P2PSocketHostUdp::DoRead() {
- int result;
- do {
- result = socket_->RecvFrom(
- recv_buffer_.get(), kUdpReadBufferSize, &recv_address_,
- base::Bind(&P2PSocketHostUdp::OnRecv, base::Unretained(this)));
- if (result == net::ERR_IO_PENDING)
- return;
- HandleReadResult(result);
- } while (state_ == STATE_OPEN);
-}
-
-void P2PSocketHostUdp::OnRecv(int result) {
- HandleReadResult(result);
- if (state_ == STATE_OPEN) {
- DoRead();
- }
-}
-
-void P2PSocketHostUdp::HandleReadResult(int result) {
- DCHECK_EQ(STATE_OPEN, state_);
-
- if (result > 0) {
- std::vector<char> data(recv_buffer_->data(), recv_buffer_->data() + result);
-
- if (!base::ContainsKey(connected_peers_, recv_address_)) {
- P2PSocketHost::StunMessageType type;
- bool stun = GetStunPacketType(&*data.begin(), data.size(), &type);
- if ((stun && IsRequestOrResponse(type))) {
- connected_peers_.insert(recv_address_);
- } else if (!stun || type == STUN_DATA_INDICATION) {
- LOG(ERROR) << "Received unexpected data packet from "
- << recv_address_.ToString()
- << " before STUN binding is finished.";
- return;
- }
- }
-
- message_sender_->Send(new P2PMsg_OnDataReceived(
- id_, recv_address_, data, base::TimeTicks::Now()));
-
- if (dump_incoming_rtp_packet_)
- DumpRtpPacket(&data[0], data.size(), true);
- } else if (result < 0 && !IsTransientError(result)) {
- LOG(ERROR) << "Error when reading from UDP socket: " << result;
- OnError();
- }
-}
-
-void P2PSocketHostUdp::Send(
- const net::IPEndPoint& to,
- const std::vector<char>& data,
- const rtc::PacketOptions& options,
- uint64_t packet_id,
- const net::NetworkTrafficAnnotationTag traffic_annotation) {
- if (!socket_) {
- // The Send message may be sent after the an OnError message was
- // sent by hasn't been processed the renderer.
- return;
- }
-
- IncrementTotalSentPackets();
-
- if (send_pending_) {
- send_queue_.push_back(
- PendingPacket(to, data, options, packet_id, traffic_annotation));
- IncrementDelayedBytes(data.size());
- IncrementDelayedPackets();
- } else {
- PendingPacket packet(to, data, options, packet_id, traffic_annotation);
- DoSend(packet);
- }
-}
-
-void P2PSocketHostUdp::DoSend(const PendingPacket& packet) {
- base::TimeTicks send_time = base::TimeTicks::Now();
-
- // The peer is considered not connected until the first incoming STUN
- // request/response. In that state the renderer is allowed to send only STUN
- // messages to that peer and they are throttled using the |throttler_|. This
- // has to be done here instead of Send() to ensure P2PMsg_OnSendComplete
- // messages are sent in correct order.
- if (!base::ContainsKey(connected_peers_, packet.to)) {
- P2PSocketHost::StunMessageType type = P2PSocketHost::StunMessageType();
- bool stun = GetStunPacketType(packet.data->data(), packet.size, &type);
- if (!stun || type == STUN_DATA_INDICATION) {
- LOG(ERROR) << "Page tried to send a data packet to "
- << packet.to.ToString() << " before STUN binding is finished.";
- OnError();
- return;
- }
-
- if (throttler_->DropNextPacket(packet.size)) {
- VLOG(0) << "Throttling outgoing STUN message.";
- // The renderer expects P2PMsg_OnSendComplete for all packets it generates
- // and in the same order it generates them, so we need to respond even
- // when the packet is dropped.
- message_sender_->Send(new P2PMsg_OnSendComplete(
- id_, P2PSendPacketMetrics(packet.id, packet.packet_options.packet_id,
- send_time)));
- // Do not reset the socket.
- return;
- }
- }
-
- TRACE_EVENT_ASYNC_STEP_INTO1("p2p", "Send", packet.id, "UdpAsyncSendTo",
- "size", packet.size);
- // Don't try to set DSCP in following conditions,
- // 1. If the outgoing packet is set to DSCP_NO_CHANGE
- // 2. If no change in DSCP value from last packet
- // 3. If there is any error in setting DSCP on socket.
- net::DiffServCodePoint dscp =
- static_cast<net::DiffServCodePoint>(packet.packet_options.dscp);
- if (dscp != net::DSCP_NO_CHANGE && last_dscp_ != dscp &&
- last_dscp_ != net::DSCP_NO_CHANGE) {
- int result = SetSocketDiffServCodePointInternal(dscp);
- if (result == net::OK) {
- last_dscp_ = dscp;
- } else if (!IsTransientError(result) && last_dscp_ != net::DSCP_CS0) {
- // We receieved a non-transient error, and it seems we have
- // not changed the DSCP in the past, disable DSCP as it unlikely
- // to work in the future.
- last_dscp_ = net::DSCP_NO_CHANGE;
- }
- }
-
- cricket::ApplyPacketOptions(reinterpret_cast<uint8_t*>(packet.data->data()),
- packet.size,
- packet.packet_options.packet_time_params,
- (send_time - base::TimeTicks()).InMicroseconds());
- auto callback_binding =
- base::Bind(&P2PSocketHostUdp::OnSend, base::Unretained(this), packet.id,
- packet.packet_options.packet_id, send_time);
-
- // TODO(crbug.com/656607): Pass traffic annotation after DatagramSocketServer
- // is updated.
- int result = socket_->SendTo(packet.data.get(), packet.size, packet.to,
- callback_binding);
-
- // sendto() may return an error, e.g. if we've received an ICMP Destination
- // Unreachable message. When this happens try sending the same packet again,
- // and just drop it if it fails again.
- if (IsTransientError(result)) {
- result = socket_->SendTo(packet.data.get(), packet.size, packet.to,
- std::move(callback_binding));
- }
-
- if (result == net::ERR_IO_PENDING) {
- send_pending_ = true;
- } else {
- HandleSendResult(packet.id, packet.packet_options.packet_id, send_time,
- result);
- }
-
- if (dump_outgoing_rtp_packet_)
- DumpRtpPacket(packet.data->data(), packet.size, false);
-}
-
-void P2PSocketHostUdp::OnSend(uint64_t packet_id,
- int32_t transport_sequence_number,
- base::TimeTicks send_time,
- int result) {
- DCHECK(send_pending_);
- DCHECK_NE(result, net::ERR_IO_PENDING);
-
- send_pending_ = false;
-
- HandleSendResult(packet_id, transport_sequence_number, send_time, result);
-
- // Send next packets if we have them waiting in the buffer.
- while (state_ == STATE_OPEN && !send_queue_.empty() && !send_pending_) {
- PendingPacket packet = send_queue_.front();
- send_queue_.pop_front();
- DoSend(packet);
- DecrementDelayedBytes(packet.size);
- }
-}
-
-void P2PSocketHostUdp::HandleSendResult(uint64_t packet_id,
- int32_t transport_sequence_number,
- base::TimeTicks send_time,
- int result) {
- TRACE_EVENT_ASYNC_END1("p2p", "Send", packet_id,
- "result", result);
- if (result < 0) {
- ReportSocketError(result, "WebRTC.ICE.UdpSocketWriteErrorCode");
-
- if (!IsTransientError(result)) {
- LOG(ERROR) << "Error when sending data in UDP socket: " << result;
- OnError();
- return;
- }
- VLOG(0) << "sendto() has failed twice returning a "
- " transient error " << GetTransientErrorName(result)
- << ". Dropping the packet.";
- }
-
- // UMA to track the histograms from 1ms to 1 sec for how long a packet spends
- // in the browser process.
- UMA_HISTOGRAM_TIMES("WebRTC.SystemSendPacketDuration_UDP" /* name */,
- base::TimeTicks::Now() - send_time /* sample */);
-
- message_sender_->Send(new P2PMsg_OnSendComplete(
- id_,
- P2PSendPacketMetrics(packet_id, transport_sequence_number, send_time)));
-}
-
-std::unique_ptr<P2PSocketHost> P2PSocketHostUdp::AcceptIncomingTcpConnection(
- const net::IPEndPoint& remote_address,
- int id) {
- NOTREACHED();
- OnError();
- return nullptr;
-}
-
-bool P2PSocketHostUdp::SetOption(P2PSocketOption option, int value) {
- if (state_ != STATE_OPEN) {
- DCHECK_EQ(state_, STATE_ERROR);
- return false;
- }
- switch (option) {
- case P2P_SOCKET_OPT_RCVBUF:
- return socket_->SetReceiveBufferSize(value) == net::OK;
- case P2P_SOCKET_OPT_SNDBUF:
- return socket_->SetSendBufferSize(value) == net::OK;
- case P2P_SOCKET_OPT_DSCP:
- return net::OK == SetSocketDiffServCodePointInternal(
- static_cast<net::DiffServCodePoint>(value));
- default:
- NOTREACHED();
- return false;
- }
-}
-
-// TODO(crbug.com/812137): We don't call SetDiffServCodePoint for the Windows
-// UDP socket, because this is known to cause a hanging thread.
-int P2PSocketHostUdp::SetSocketDiffServCodePointInternal(
- net::DiffServCodePoint dscp) {
-#if defined(OS_WIN)
- return net::OK;
-#else
- return socket_->SetDiffServCodePoint(dscp);
-#endif
-}
-
-// static
-std::unique_ptr<net::DatagramServerSocket>
-P2PSocketHostUdp::DefaultSocketFactory(net::NetLog* net_log) {
- net::UDPServerSocket* socket =
- new net::UDPServerSocket(net_log, net::NetLogSource());
-#if defined(OS_WIN)
- socket->UseNonBlockingIO();
-#endif
-
- return base::WrapUnique(socket);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_udp.h b/chromium/content/browser/renderer_host/p2p/socket_host_udp.h
deleted file mode 100644
index d4398740213..00000000000
--- a/chromium/content/browser/renderer_host/p2p/socket_host_udp.h
+++ /dev/null
@@ -1,131 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_RENDERER_HOST_P2P_SOCKET_HOST_UDP_H_
-#define CONTENT_BROWSER_RENDERER_HOST_P2P_SOCKET_HOST_UDP_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <memory>
-#include <set>
-#include <vector>
-
-#include "base/callback.h"
-#include "base/compiler_specific.h"
-#include "base/containers/circular_deque.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "content/browser/renderer_host/p2p/socket_host.h"
-#include "content/common/content_export.h"
-#include "content/common/p2p_socket_type.h"
-#include "net/base/ip_endpoint.h"
-#include "net/socket/diff_serv_code_point.h"
-#include "net/socket/udp_server_socket.h"
-#include "net/traffic_annotation/network_traffic_annotation.h"
-#include "third_party/webrtc/rtc_base/asyncpacketsocket.h"
-
-namespace net {
-class NetLog;
-} // namespace net
-
-namespace content {
-
-class P2PMessageThrottler;
-
-class CONTENT_EXPORT P2PSocketHostUdp : public P2PSocketHost {
- public:
- typedef base::Callback<std::unique_ptr<net::DatagramServerSocket>(
- net::NetLog* net_log)>
- DatagramServerSocketFactory;
- P2PSocketHostUdp(IPC::Sender* message_sender,
- int socket_id,
- P2PMessageThrottler* throttler,
- net::NetLog* net_log,
- const DatagramServerSocketFactory& socket_factory);
- P2PSocketHostUdp(IPC::Sender* message_sender,
- int socket_id,
- P2PMessageThrottler* throttler,
- net::NetLog* net_log);
- ~P2PSocketHostUdp() override;
-
- // P2PSocketHost overrides.
- bool Init(const net::IPEndPoint& local_address,
- uint16_t min_port,
- uint16_t max_port,
- const P2PHostAndIPEndPoint& remote_address) override;
- void Send(const net::IPEndPoint& to,
- const std::vector<char>& data,
- const rtc::PacketOptions& options,
- uint64_t packet_id,
- const net::NetworkTrafficAnnotationTag traffic_annotation) override;
- std::unique_ptr<P2PSocketHost> AcceptIncomingTcpConnection(
- const net::IPEndPoint& remote_address,
- int id) override;
- bool SetOption(P2PSocketOption option, int value) override;
-
- private:
- friend class P2PSocketHostUdpTest;
-
- typedef std::set<net::IPEndPoint> ConnectedPeerSet;
-
- struct PendingPacket {
- PendingPacket(const net::IPEndPoint& to,
- const std::vector<char>& content,
- const rtc::PacketOptions& options,
- uint64_t id,
- const net::NetworkTrafficAnnotationTag traffic_annotation);
- PendingPacket(const PendingPacket& other);
- ~PendingPacket();
- net::IPEndPoint to;
- scoped_refptr<net::IOBuffer> data;
- int size;
- rtc::PacketOptions packet_options;
- uint64_t id;
- const net::NetworkTrafficAnnotationTag traffic_annotation;
- };
-
- void OnError();
-
- void DoRead();
- void OnRecv(int result);
- void HandleReadResult(int result);
-
- void DoSend(const PendingPacket& packet);
- void OnSend(uint64_t packet_id,
- int32_t transport_sequence_number,
- base::TimeTicks send_time,
- int result);
- void HandleSendResult(uint64_t packet_id,
- int32_t transport_sequence_number,
- base::TimeTicks send_time,
- int result);
- int SetSocketDiffServCodePointInternal(net::DiffServCodePoint dscp);
- static std::unique_ptr<net::DatagramServerSocket> DefaultSocketFactory(
- net::NetLog* net_log);
-
- std::unique_ptr<net::DatagramServerSocket> socket_;
- scoped_refptr<net::IOBuffer> recv_buffer_;
- net::IPEndPoint recv_address_;
-
- base::circular_deque<PendingPacket> send_queue_;
- bool send_pending_;
- net::DiffServCodePoint last_dscp_;
-
- // Set of peer for which we have received STUN binding request or
- // response or relay allocation request or response.
- ConnectedPeerSet connected_peers_;
- P2PMessageThrottler* throttler_;
-
- net::NetLog* net_log_;
-
- // Callback object that returns a new socket when invoked.
- DatagramServerSocketFactory socket_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(P2PSocketHostUdp);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_P2P_SOCKET_HOST_UDP_H_
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_udp_unittest.cc b/chromium/content/browser/renderer_host/p2p/socket_host_udp_unittest.cc
deleted file mode 100644
index dafc06ba0fa..00000000000
--- a/chromium/content/browser/renderer_host/p2p/socket_host_udp_unittest.cc
+++ /dev/null
@@ -1,595 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/renderer_host/p2p/socket_host_udp.h"
-
-#include <stdint.h>
-#include <utility>
-#include <vector>
-
-#include "base/containers/circular_deque.h"
-#include "base/logging.h"
-#include "base/sys_byteorder.h"
-#include "content/browser/renderer_host/p2p/socket_host_test_utils.h"
-#include "content/browser/renderer_host/p2p/socket_host_throttler.h"
-#include "net/base/completion_once_callback.h"
-#include "net/base/io_buffer.h"
-#include "net/base/ip_endpoint.h"
-#include "net/base/net_errors.h"
-#include "net/log/net_log_with_source.h"
-#include "net/socket/datagram_server_socket.h"
-#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using ::testing::_;
-using ::testing::DeleteArg;
-using ::testing::DoAll;
-using ::testing::Return;
-
-namespace {
-
-// TODO(nisse): We can't currently use rtc::ScopedFakeClock, because
-// we don't link with webrtc rtc_base_tests_utils. So roll our own.
-
-// Creating an object of this class makes rtc::TimeMicros() and
-// related functions return zero unless the clock is advanced.
-class ScopedFakeClock : public rtc::ClockInterface {
- public:
- ScopedFakeClock() { prev_clock_ = rtc::SetClockForTesting(this); }
- ~ScopedFakeClock() override { rtc::SetClockForTesting(prev_clock_); }
- // ClockInterface implementation.
- int64_t TimeNanos() const override { return time_nanos_; }
- void SetTimeNanos(uint64_t time_nanos) { time_nanos_ = time_nanos; }
-
- private:
- ClockInterface* prev_clock_;
- uint64_t time_nanos_ = 0;
-};
-
-class FakeDatagramServerSocket : public net::DatagramServerSocket {
- public:
- typedef std::pair<net::IPEndPoint, std::vector<char> > UDPPacket;
-
- // P2PSocketHostUdp destroys a socket on errors so sent packets
- // need to be stored outside of this object.
- FakeDatagramServerSocket(base::circular_deque<UDPPacket>* sent_packets,
- std::vector<uint16_t>* used_ports)
- : sent_packets_(sent_packets),
- recv_address_(nullptr),
- recv_size_(0),
- used_ports_(used_ports) {}
-
- void Close() override {}
-
- int GetPeerAddress(net::IPEndPoint* address) const override {
- NOTREACHED();
- return net::ERR_SOCKET_NOT_CONNECTED;
- }
-
- int GetLocalAddress(net::IPEndPoint* address) const override {
- *address = address_;
- return 0;
- }
-
- void UseNonBlockingIO() override {}
-
- int Listen(const net::IPEndPoint& address) override {
- if (used_ports_) {
- for (auto used_port : *used_ports_) {
- if (used_port == address.port())
- return -1;
- }
- used_ports_->push_back(address.port());
- }
-
- address_ = address;
- return 0;
- }
-
- int RecvFrom(net::IOBuffer* buf,
- int buf_len,
- net::IPEndPoint* address,
- net::CompletionOnceCallback callback) override {
- CHECK(recv_callback_.is_null());
- if (incoming_packets_.size() > 0) {
- scoped_refptr<net::IOBuffer> buffer(buf);
- int size = std::min(
- static_cast<int>(incoming_packets_.front().second.size()), buf_len);
- memcpy(buffer->data(), &*incoming_packets_.front().second.begin(), size);
- *address = incoming_packets_.front().first;
- incoming_packets_.pop_front();
- return size;
- } else {
- recv_callback_ = std::move(callback);
- recv_buffer_ = buf;
- recv_size_ = buf_len;
- recv_address_ = address;
- return net::ERR_IO_PENDING;
- }
- }
-
- int SendTo(net::IOBuffer* buf,
- int buf_len,
- const net::IPEndPoint& address,
- net::CompletionOnceCallback callback) override {
- scoped_refptr<net::IOBuffer> buffer(buf);
- std::vector<char> data_vector(buffer->data(), buffer->data() + buf_len);
- sent_packets_->push_back(UDPPacket(address, data_vector));
- return buf_len;
- }
-
- int SetReceiveBufferSize(int32_t size) override { return net::OK; }
-
- int SetSendBufferSize(int32_t size) override { return net::OK; }
-
- int SetDoNotFragment() override { return net::OK; }
-
- void SetMsgConfirm(bool confirm) override {}
-
- void ReceivePacket(const net::IPEndPoint& address, std::vector<char> data) {
- if (!recv_callback_.is_null()) {
- int size = std::min(recv_size_, static_cast<int>(data.size()));
- memcpy(recv_buffer_->data(), &*data.begin(), size);
- *recv_address_ = address;
- recv_buffer_ = nullptr;
- std::move(recv_callback_).Run(size);
- } else {
- incoming_packets_.push_back(UDPPacket(address, data));
- }
- }
-
- const net::NetLogWithSource& NetLog() const override { return net_log_; }
-
- void AllowAddressReuse() override { NOTIMPLEMENTED(); }
-
- void AllowBroadcast() override { NOTIMPLEMENTED(); }
-
- int JoinGroup(const net::IPAddress& group_address) const override {
- NOTIMPLEMENTED();
- return net::ERR_NOT_IMPLEMENTED;
- }
-
- int LeaveGroup(const net::IPAddress& group_address) const override {
- NOTIMPLEMENTED();
- return net::ERR_NOT_IMPLEMENTED;
- }
-
- int SetMulticastInterface(uint32_t interface_index) override {
- NOTIMPLEMENTED();
- return net::ERR_NOT_IMPLEMENTED;
- }
-
- int SetMulticastTimeToLive(int time_to_live) override {
- NOTIMPLEMENTED();
- return net::ERR_NOT_IMPLEMENTED;
- }
-
- int SetMulticastLoopbackMode(bool loopback) override {
- NOTIMPLEMENTED();
- return net::ERR_NOT_IMPLEMENTED;
- }
-
- int SetDiffServCodePoint(net::DiffServCodePoint dscp) override {
- NOTIMPLEMENTED();
- return net::ERR_NOT_IMPLEMENTED;
- }
-
- void DetachFromThread() override { NOTIMPLEMENTED(); }
-
- private:
- net::IPEndPoint address_;
- base::circular_deque<UDPPacket>* sent_packets_;
- base::circular_deque<UDPPacket> incoming_packets_;
- net::NetLogWithSource net_log_;
-
- scoped_refptr<net::IOBuffer> recv_buffer_;
- net::IPEndPoint* recv_address_;
- int recv_size_;
- net::CompletionOnceCallback recv_callback_;
- std::vector<uint16_t>* used_ports_;
-};
-
-std::unique_ptr<net::DatagramServerSocket> CreateFakeDatagramServerSocket(
- base::circular_deque<FakeDatagramServerSocket::UDPPacket>* sent_packets,
- std::vector<uint16_t>* used_ports,
- net::NetLog* net_log) {
- return std::make_unique<FakeDatagramServerSocket>(sent_packets, used_ports);
-}
-
-} // namespace
-
-namespace content {
-
-class P2PSocketHostUdpTest : public testing::Test {
- protected:
- void SetUp() override {
- EXPECT_CALL(
- sender_,
- Send(MatchMessage(static_cast<uint32_t>(P2PMsg_OnSocketCreated::ID))))
- .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
-
- socket_host_.reset(new P2PSocketHostUdp(
- &sender_, 0, &throttler_, /*net_log=*/nullptr,
- base::Bind(&CreateFakeDatagramServerSocket, &sent_packets_, nullptr)));
-
- local_address_ = ParseAddress(kTestLocalIpAddress, kTestPort1);
- socket_host_->Init(local_address_, 0, 0, P2PHostAndIPEndPoint());
- socket_ = GetSocketFromHost(socket_host_.get());
-
- dest1_ = ParseAddress(kTestIpAddress1, kTestPort1);
- dest2_ = ParseAddress(kTestIpAddress2, kTestPort2);
- }
-
- static FakeDatagramServerSocket* GetSocketFromHost(
- P2PSocketHostUdp* socket_host) {
- return static_cast<FakeDatagramServerSocket*>(socket_host->socket_.get());
- }
-
- P2PMessageThrottler throttler_;
- ScopedFakeClock fake_clock_;
- base::circular_deque<FakeDatagramServerSocket::UDPPacket> sent_packets_;
- FakeDatagramServerSocket* socket_; // Owned by |socket_host_|.
- std::unique_ptr<P2PSocketHostUdp> socket_host_;
- MockIPCSender sender_;
-
- net::IPEndPoint local_address_;
-
- net::IPEndPoint dest1_;
- net::IPEndPoint dest2_;
-};
-
-// Verify that we can send STUN messages before we receive anything
-// from the other side.
-TEST_F(P2PSocketHostUdpTest, SendStunNoAuth) {
- EXPECT_CALL(
- sender_,
- Send(MatchMessage(static_cast<uint32_t>(P2PMsg_OnSendComplete::ID))))
- .Times(3)
- .WillRepeatedly(DoAll(DeleteArg<0>(), Return(true)));
-
- rtc::PacketOptions options;
- std::vector<char> packet1;
- CreateStunRequest(&packet1);
- socket_host_->Send(dest1_, packet1, options, 0, TRAFFIC_ANNOTATION_FOR_TESTS);
-
- std::vector<char> packet2;
- CreateStunResponse(&packet2);
- socket_host_->Send(dest1_, packet2, options, 0, TRAFFIC_ANNOTATION_FOR_TESTS);
-
- std::vector<char> packet3;
- CreateStunError(&packet3);
- socket_host_->Send(dest1_, packet3, options, 0, TRAFFIC_ANNOTATION_FOR_TESTS);
-
- ASSERT_EQ(sent_packets_.size(), 3U);
- ASSERT_EQ(sent_packets_[0].second, packet1);
- ASSERT_EQ(sent_packets_[1].second, packet2);
- ASSERT_EQ(sent_packets_[2].second, packet3);
-}
-
-// Verify that no data packets can be sent before STUN binding has
-// finished.
-TEST_F(P2PSocketHostUdpTest, SendDataNoAuth) {
- EXPECT_CALL(sender_,
- Send(MatchMessage(static_cast<uint32_t>(P2PMsg_OnError::ID))))
- .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
-
- rtc::PacketOptions options;
- std::vector<char> packet;
- CreateRandomPacket(&packet);
- socket_host_->Send(dest1_, packet, options, 0, TRAFFIC_ANNOTATION_FOR_TESTS);
-
- ASSERT_EQ(sent_packets_.size(), 0U);
-}
-
-// Verify that SetOption() doesn't crash after an error.
-TEST_F(P2PSocketHostUdpTest, SetOptionAfterError) {
- // Get the sender into the error state.
- EXPECT_CALL(sender_,
- Send(MatchMessage(static_cast<uint32_t>(P2PMsg_OnError::ID))))
- .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
- socket_host_->Send(dest1_, {1, 2, 3, 4}, rtc::PacketOptions(), 0,
- TRAFFIC_ANNOTATION_FOR_TESTS);
- testing::Mock::VerifyAndClearExpectations(&sender_);
-
- // Verify that SetOptions() fails, but doesn't crash.
- EXPECT_FALSE(socket_host_->SetOption(P2P_SOCKET_OPT_RCVBUF, 2048));
-}
-
-// Verify that we can send data after we've received STUN request
-// from the other side.
-TEST_F(P2PSocketHostUdpTest, SendAfterStunRequest) {
- // Receive packet from |dest1_|.
- std::vector<char> request_packet;
- CreateStunRequest(&request_packet);
-
- EXPECT_CALL(sender_, Send(MatchPacketMessage(request_packet)))
- .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
- socket_->ReceivePacket(dest1_, request_packet);
-
- // Now we should be able to send any data to |dest1_|.
- EXPECT_CALL(
- sender_,
- Send(MatchMessage(static_cast<uint32_t>(P2PMsg_OnSendComplete::ID))))
- .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
-
- rtc::PacketOptions options;
- std::vector<char> packet;
- CreateRandomPacket(&packet);
- socket_host_->Send(dest1_, packet, options, 0, TRAFFIC_ANNOTATION_FOR_TESTS);
-
- ASSERT_EQ(1U, sent_packets_.size());
- ASSERT_EQ(dest1_, sent_packets_[0].first);
-}
-
-// Verify that we can send data after we've received STUN response
-// from the other side.
-TEST_F(P2PSocketHostUdpTest, SendAfterStunResponse) {
- // Receive packet from |dest1_|.
- std::vector<char> request_packet;
- CreateStunRequest(&request_packet);
-
- EXPECT_CALL(sender_, Send(MatchPacketMessage(request_packet)))
- .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
- socket_->ReceivePacket(dest1_, request_packet);
-
- // Now we should be able to send any data to |dest1_|.
- EXPECT_CALL(
- sender_,
- Send(MatchMessage(static_cast<uint32_t>(P2PMsg_OnSendComplete::ID))))
- .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
-
- rtc::PacketOptions options;
- std::vector<char> packet;
- CreateRandomPacket(&packet);
- socket_host_->Send(dest1_, packet, options, 0, TRAFFIC_ANNOTATION_FOR_TESTS);
-
- ASSERT_EQ(1U, sent_packets_.size());
- ASSERT_EQ(dest1_, sent_packets_[0].first);
-}
-
-// Verify messages still cannot be sent to an unathorized host after
-// successful binding with different host.
-TEST_F(P2PSocketHostUdpTest, SendAfterStunResponseDifferentHost) {
- // Receive packet from |dest1_|.
- std::vector<char> request_packet;
- CreateStunRequest(&request_packet);
-
- EXPECT_CALL(sender_, Send(MatchPacketMessage(request_packet)))
- .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
- socket_->ReceivePacket(dest1_, request_packet);
-
- // Should fail when trying to send the same packet to |dest2_|.
- rtc::PacketOptions options;
- std::vector<char> packet;
- CreateRandomPacket(&packet);
- EXPECT_CALL(sender_,
- Send(MatchMessage(static_cast<uint32_t>(P2PMsg_OnError::ID))))
- .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
- socket_host_->Send(dest2_, packet, options, 0, TRAFFIC_ANNOTATION_FOR_TESTS);
-}
-
-// Verify throttler not allowing unlimited sending of ICE messages to
-// any destination.
-TEST_F(P2PSocketHostUdpTest, ThrottleAfterLimit) {
- EXPECT_CALL(
- sender_,
- Send(MatchMessage(static_cast<uint32_t>(P2PMsg_OnSendComplete::ID))))
- .Times(3)
- .WillRepeatedly(DoAll(DeleteArg<0>(), Return(true)));
-
- rtc::PacketOptions options;
- std::vector<char> packet1;
- CreateStunRequest(&packet1);
- throttler_.SetSendIceBandwidth(packet1.size() * 2);
- socket_host_->Send(dest1_, packet1, options, 0, TRAFFIC_ANNOTATION_FOR_TESTS);
- socket_host_->Send(dest2_, packet1, options, 0, TRAFFIC_ANNOTATION_FOR_TESTS);
-
- net::IPEndPoint dest3 = ParseAddress(kTestIpAddress1, 2222);
- // This packet must be dropped by the throttler.
- socket_host_->Send(dest3, packet1, options, 0, TRAFFIC_ANNOTATION_FOR_TESTS);
- ASSERT_EQ(sent_packets_.size(), 2U);
-}
-
-// Verify we can send packets to a known destination when ICE throttling is
-// active.
-TEST_F(P2PSocketHostUdpTest, ThrottleAfterLimitAfterReceive) {
- // Receive packet from |dest1_|.
- std::vector<char> request_packet;
- CreateStunRequest(&request_packet);
-
- EXPECT_CALL(sender_, Send(MatchPacketMessage(request_packet)))
- .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
- socket_->ReceivePacket(dest1_, request_packet);
-
- EXPECT_CALL(
- sender_,
- Send(MatchMessage(static_cast<uint32_t>(P2PMsg_OnSendComplete::ID))))
- .Times(6)
- .WillRepeatedly(DoAll(DeleteArg<0>(), Return(true)));
-
- rtc::PacketOptions options;
- std::vector<char> packet1;
- CreateStunRequest(&packet1);
- throttler_.SetSendIceBandwidth(packet1.size());
- // |dest1_| is known address, throttling will not be applied.
- socket_host_->Send(dest1_, packet1, options, 0, TRAFFIC_ANNOTATION_FOR_TESTS);
- // Trying to send the packet to dest1_ in the same window. It should go.
- socket_host_->Send(dest1_, packet1, options, 0, TRAFFIC_ANNOTATION_FOR_TESTS);
-
- // Throttler should allow this packet to go through.
- socket_host_->Send(dest2_, packet1, options, 0, TRAFFIC_ANNOTATION_FOR_TESTS);
-
- net::IPEndPoint dest3 = ParseAddress(kTestIpAddress1, 2223);
- // This packet will be dropped, as limit only for a single packet.
- socket_host_->Send(dest3, packet1, options, 0, TRAFFIC_ANNOTATION_FOR_TESTS);
- net::IPEndPoint dest4 = ParseAddress(kTestIpAddress1, 2224);
- // This packet should also be dropped.
- socket_host_->Send(dest4, packet1, options, 0, TRAFFIC_ANNOTATION_FOR_TESTS);
- // |dest1| is known, we can send as many packets to it.
- socket_host_->Send(dest1_, packet1, options, 0, TRAFFIC_ANNOTATION_FOR_TESTS);
- ASSERT_EQ(sent_packets_.size(), 4U);
-}
-
-// The fake clock mechanism used for this test doesn't work in component builds.
-// See: https://bugs.chromium.org/p/webrtc/issues/detail?id=6490
-#if defined(COMPONENT_BUILD)
-#define MAYBE_ThrottlingStopsAtExpectedTimes DISABLED_ThrottlingStopsAtExpectedTimes
-#else
-#define MAYBE_ThrottlingStopsAtExpectedTimes ThrottlingStopsAtExpectedTimes
-#endif
-// Test that once the limit is hit, the throttling stops at the expected time,
-// allowing packets to be sent again.
-TEST_F(P2PSocketHostUdpTest, MAYBE_ThrottlingStopsAtExpectedTimes) {
- EXPECT_CALL(
- sender_,
- Send(MatchMessage(static_cast<uint32_t>(P2PMsg_OnSendComplete::ID))))
- .Times(12)
- .WillRepeatedly(DoAll(DeleteArg<0>(), Return(true)));
-
- rtc::PacketOptions options;
- std::vector<char> packet;
- CreateStunRequest(&packet);
- // Limit of 2 packets per second.
- throttler_.SetSendIceBandwidth(packet.size() * 2);
- socket_host_->Send(dest1_, packet, options, 0, TRAFFIC_ANNOTATION_FOR_TESTS);
- socket_host_->Send(dest2_, packet, options, 0, TRAFFIC_ANNOTATION_FOR_TESTS);
- EXPECT_EQ(2U, sent_packets_.size());
-
- // These packets must be dropped by the throttler since the limit was hit and
- // the time hasn't advanced.
- socket_host_->Send(dest1_, packet, options, 0, TRAFFIC_ANNOTATION_FOR_TESTS);
- socket_host_->Send(dest2_, packet, options, 0, TRAFFIC_ANNOTATION_FOR_TESTS);
- EXPECT_EQ(2U, sent_packets_.size());
-
- // Advance the time to 0.999 seconds; throttling should still just barely be
- // active.
- fake_clock_.SetTimeNanos(rtc::kNumNanosecsPerMillisec * 999);
- socket_host_->Send(dest1_, packet, options, 0, TRAFFIC_ANNOTATION_FOR_TESTS);
- socket_host_->Send(dest2_, packet, options, 0, TRAFFIC_ANNOTATION_FOR_TESTS);
- EXPECT_EQ(2U, sent_packets_.size());
-
- // After hitting the second mark, we should be able to send again.
- // Add an extra millisecond to account for rounding errors.
- fake_clock_.SetTimeNanos(rtc::kNumNanosecsPerMillisec * 1001);
- socket_host_->Send(dest1_, packet, options, 0, TRAFFIC_ANNOTATION_FOR_TESTS);
- EXPECT_EQ(3U, sent_packets_.size());
-
- // This time, hit the limit in the middle of the period.
- fake_clock_.SetTimeNanos(rtc::kNumNanosecsPerMillisec * 1500);
- socket_host_->Send(dest2_, packet, options, 0, TRAFFIC_ANNOTATION_FOR_TESTS);
- EXPECT_EQ(4U, sent_packets_.size());
-
- // Again, throttling should be active until the next second mark.
- fake_clock_.SetTimeNanos(rtc::kNumNanosecsPerMillisec * 1999);
- socket_host_->Send(dest1_, packet, options, 0, TRAFFIC_ANNOTATION_FOR_TESTS);
- socket_host_->Send(dest2_, packet, options, 0, TRAFFIC_ANNOTATION_FOR_TESTS);
- EXPECT_EQ(4U, sent_packets_.size());
- fake_clock_.SetTimeNanos(rtc::kNumNanosecsPerMillisec * 2002);
- socket_host_->Send(dest1_, packet, options, 0, TRAFFIC_ANNOTATION_FOR_TESTS);
- socket_host_->Send(dest2_, packet, options, 0, TRAFFIC_ANNOTATION_FOR_TESTS);
- EXPECT_EQ(6U, sent_packets_.size());
-}
-
-// Verify that we can open UDP sockets listening in a given port range,
-// and fail if all ports in the range are already in use.
-TEST_F(P2PSocketHostUdpTest, PortRangeImplicitPort) {
- const uint16_t min_port = 10000;
- const uint16_t max_port = 10001;
- base::circular_deque<FakeDatagramServerSocket::UDPPacket> sent_packets;
- std::vector<uint16_t> used_ports;
- P2PSocketHostUdp::DatagramServerSocketFactory fake_socket_factory =
- base::Bind(&CreateFakeDatagramServerSocket, &sent_packets, &used_ports);
- P2PMessageThrottler throttler;
- MockIPCSender sender;
- EXPECT_CALL(
- sender,
- Send(MatchMessage(static_cast<uint32_t>(P2PMsg_OnSocketCreated::ID))))
- .Times(max_port - min_port + 1)
- .WillRepeatedly(DoAll(DeleteArg<0>(), Return(true)));
-
- for (unsigned port = min_port; port <= max_port; ++port) {
- std::unique_ptr<P2PSocketHostUdp> socket_host(new P2PSocketHostUdp(
- &sender, 0, &throttler, /*net_log=*/nullptr, fake_socket_factory));
- net::IPEndPoint local_address = ParseAddress(kTestLocalIpAddress, 0);
- bool rv = socket_host->Init(local_address, min_port, max_port,
- P2PHostAndIPEndPoint());
- EXPECT_TRUE(rv);
-
- FakeDatagramServerSocket* socket = GetSocketFromHost(socket_host.get());
- net::IPEndPoint bound_address;
- socket->GetLocalAddress(&bound_address);
- EXPECT_EQ(port, bound_address.port());
- }
-
- EXPECT_CALL(sender,
- Send(MatchMessage(static_cast<uint32_t>(P2PMsg_OnError::ID))))
- .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
- std::unique_ptr<P2PSocketHostUdp> socket_host(
- new P2PSocketHostUdp(&sender, 0, &throttler, /*net_log=*/nullptr,
- std::move(fake_socket_factory)));
- net::IPEndPoint local_address = ParseAddress(kTestLocalIpAddress, 0);
- bool rv = socket_host->Init(local_address, min_port, max_port,
- P2PHostAndIPEndPoint());
- EXPECT_FALSE(rv);
-}
-
-// Verify that we can open a UDP socket listening in a given port included in
-// a given valid range.
-TEST_F(P2PSocketHostUdpTest, PortRangeExplictValidPort) {
- const uint16_t min_port = 10000;
- const uint16_t max_port = 10001;
- const uint16_t valid_port = min_port;
- base::circular_deque<FakeDatagramServerSocket::UDPPacket> sent_packets;
- std::vector<uint16_t> used_ports;
- P2PSocketHostUdp::DatagramServerSocketFactory fake_socket_factory =
- base::Bind(&CreateFakeDatagramServerSocket, &sent_packets, &used_ports);
- P2PMessageThrottler throttler;
- MockIPCSender sender;
- EXPECT_CALL(
- sender,
- Send(MatchMessage(static_cast<uint32_t>(P2PMsg_OnSocketCreated::ID))))
- .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
-
- std::unique_ptr<P2PSocketHostUdp> socket_host(
- new P2PSocketHostUdp(&sender, 0, &throttler, /*net_log=*/nullptr,
- std::move(fake_socket_factory)));
- net::IPEndPoint local_address = ParseAddress(kTestLocalIpAddress, valid_port);
- bool rv = socket_host->Init(local_address, min_port, max_port,
- P2PHostAndIPEndPoint());
- EXPECT_TRUE(rv);
-
- FakeDatagramServerSocket* socket = GetSocketFromHost(socket_host.get());
- net::IPEndPoint bound_address;
- socket->GetLocalAddress(&bound_address);
- EXPECT_EQ(local_address.port(), bound_address.port());
-}
-
-// Verify that we cannot open a UDP socket listening in a given port not
-// included in a given valid range.
-TEST_F(P2PSocketHostUdpTest, PortRangeExplictInvalidPort) {
- const uint16_t min_port = 10000;
- const uint16_t max_port = 10001;
- const uint16_t invalid_port = max_port + 1;
- base::circular_deque<FakeDatagramServerSocket::UDPPacket> sent_packets;
- std::vector<uint16_t> used_ports;
- P2PSocketHostUdp::DatagramServerSocketFactory fake_socket_factory =
- base::Bind(&CreateFakeDatagramServerSocket, &sent_packets, &used_ports);
- P2PMessageThrottler throttler;
- MockIPCSender sender;
- EXPECT_CALL(sender,
- Send(MatchMessage(static_cast<uint32_t>(P2PMsg_OnError::ID))))
- .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
-
- std::unique_ptr<P2PSocketHostUdp> socket_host(
- new P2PSocketHostUdp(&sender, 0, &throttler, /*net_log=*/nullptr,
- std::move(fake_socket_factory)));
- net::IPEndPoint local_address =
- ParseAddress(kTestLocalIpAddress, invalid_port);
- bool rv = socket_host->Init(local_address, min_port, max_port,
- P2PHostAndIPEndPoint());
- EXPECT_FALSE(rv);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.h b/chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.h
index 6f00768bc50..8aeaed49765 100644
--- a/chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.h
+++ b/chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.h
@@ -137,7 +137,7 @@ class CONTENT_EXPORT BrowserPpapiHostImpl : public BrowserPpapiHost {
PepperRendererInstanceData renderer_data;
bool is_throttled;
- base::ObserverList<InstanceObserver> observer_list;
+ base::ObserverList<InstanceObserver>::Unchecked observer_list;
};
std::unique_ptr<ppapi::host::PpapiHost> ppapi_host_;
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.cc b/chromium/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.cc
index 628f9c9bab7..c4654b4f5a8 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.cc
@@ -8,7 +8,7 @@
#include "base/files/file_path.h"
#include "base/files/file_util.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/public/browser/browser_thread.h"
#include "ppapi/c/pp_errors.h"
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_file_io_host.cc b/chromium/content/browser/renderer_host/pepper/pepper_file_io_host.cc
index 474c1683dcd..14641886701 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_file_io_host.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_file_io_host.cc
@@ -10,11 +10,10 @@
#include "base/callback.h"
#include "base/memory/weak_ptr.h"
#include "base/sequenced_task_runner.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "content/browser/renderer_host/pepper/pepper_file_ref_host.h"
#include "content/browser/renderer_host/pepper/pepper_file_system_browser_host.h"
#include "content/browser/renderer_host/pepper/pepper_security_helper.h"
-#include "content/common/fileapi/file_system_messages.h"
#include "content/common/view_messages.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host.cc b/chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host.cc
index 6166a7b6616..ca2abd58bb4 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host.cc
@@ -459,7 +459,7 @@ void PepperFileSystemBrowserHost::GotReservedQuota(
std::string PepperFileSystemBrowserHost::GetPluginMimeType() const {
base::FilePath plugin_path = browser_ppapi_host_->GetPluginPath();
- PepperPluginInfo* info =
+ const PepperPluginInfo* info =
PluginService::GetInstance()->GetRegisteredPpapiPluginInfo(plugin_path);
if (!info || info->mime_types.empty())
return std::string();
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_flash_file_message_filter.cc b/chromium/content/browser/renderer_host/pepper/pepper_flash_file_message_filter.cc
index 4822d0d57e4..3619dfae8c8 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_flash_file_message_filter.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_flash_file_message_filter.cc
@@ -10,7 +10,7 @@
#include "base/files/file.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_util.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/renderer_host/pepper/pepper_security_helper.h"
#include "content/public/browser/browser_ppapi_host.h"
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_gamepad_host.h b/chromium/content/browser/renderer_host/pepper/pepper_gamepad_host.h
index cc3bcb581f7..3cec62b2c39 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_gamepad_host.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_gamepad_host.h
@@ -49,11 +49,13 @@ class CONTENT_EXPORT PepperGamepadHost :
const IPC::Message& msg,
ppapi::host::HostMessageContext* context) override;
- // GamepadConsumer implementation.
- void OnGamepadConnected(unsigned index,
+ // device::GamepadConsumer implementation.
+ void OnGamepadConnected(uint32_t index,
const device::Gamepad& gamepad) override {}
- void OnGamepadDisconnected(unsigned index,
+ void OnGamepadDisconnected(uint32_t index,
const device::Gamepad& gamepad) override {}
+ void OnGamepadButtonOrAxisChanged(uint32_t index,
+ const device::Gamepad& gamepad) override {}
private:
int32_t OnRequestMemory(ppapi::host::HostMessageContext* context);
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.cc b/chromium/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.cc
index 94a1f646ba9..d1cbc98e979 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.cc
@@ -10,7 +10,6 @@
#include "base/logging.h"
#include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h"
-#include "content/browser/renderer_host/pepper/pepper_lookup_request.h"
#include "content/browser/renderer_host/pepper/pepper_socket_utils.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
@@ -18,9 +17,6 @@
#include "content/public/browser/storage_partition.h"
#include "content/public/common/socket_permission_request.h"
#include "net/base/address_list.h"
-#include "net/dns/host_resolver.h"
-#include "net/url_request/url_request_context.h"
-#include "net/url_request/url_request_context_getter.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/private/ppb_host_resolver_private.h"
#include "ppapi/c/private/ppb_net_address_private.h"
@@ -38,28 +34,22 @@ namespace content {
namespace {
void PrepareRequestInfo(const PP_HostResolver_Private_Hint& hint,
- net::HostResolver::RequestInfo* request_info) {
- DCHECK(request_info);
-
- net::AddressFamily address_family;
+ network::mojom::ResolveHostParameters* params) {
switch (hint.family) {
case PP_NETADDRESSFAMILY_PRIVATE_IPV4:
- address_family = net::ADDRESS_FAMILY_IPV4;
+ params->dns_query_type = net::HostResolver::DnsQueryType::A;
break;
case PP_NETADDRESSFAMILY_PRIVATE_IPV6:
- address_family = net::ADDRESS_FAMILY_IPV6;
+ params->dns_query_type = net::HostResolver::DnsQueryType::AAAA;
break;
default:
- address_family = net::ADDRESS_FAMILY_UNSPECIFIED;
+ params->dns_query_type = net::HostResolver::DnsQueryType::UNSPECIFIED;
}
- request_info->set_address_family(address_family);
- net::HostResolverFlags host_resolver_flags = 0;
if (hint.flags & PP_HOST_RESOLVER_PRIVATE_FLAGS_CANONNAME)
- host_resolver_flags |= net::HOST_RESOLVER_CANONNAME;
+ params->include_canonical_name = true;
if (hint.flags & PP_HOST_RESOLVER_PRIVATE_FLAGS_LOOPBACK_ONLY)
- host_resolver_flags |= net::HOST_RESOLVER_LOOPBACK_ONLY;
- request_info->set_host_resolver_flags(host_resolver_flags);
+ params->loopback_only = true;
}
void CreateNetAddressListFromAddressList(
@@ -90,7 +80,8 @@ PepperHostResolverMessageFilter::PepperHostResolverMessageFilter(
: external_plugin_(host->external_plugin()),
private_api_(private_api),
render_process_id_(0),
- render_frame_id_(0) {
+ render_frame_id_(0),
+ binding_(this) {
DCHECK(host);
if (!host->GetRenderFrameIDsForInstance(
@@ -142,63 +133,56 @@ int32_t PepperHostResolverMessageFilter::OnMsgResolve(
return PP_ERROR_FAILED;
auto* storage_partition = render_process_host->GetStoragePartition();
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(
- &PepperHostResolverMessageFilter::DoResolve, this,
- context->MakeReplyMessageContext(), host_port, hint,
- base::WrapRefCounted(storage_partition->GetURLRequestContext())));
+ // Grab a reference to this class to ensure that it's fully alive if a
+ // connection error occurs (i.e. ref count is higher than 0 and there's no
+ // task from ResourceMessageFilterDeleteTraits to delete this object on the IO
+ // thread pending). Balanced in OnComplete();
+ AddRef();
+
+ network::mojom::ResolveHostClientPtr client_ptr;
+ binding_.Bind(mojo::MakeRequest(&client_ptr));
+ binding_.set_connection_error_handler(
+ base::BindOnce(&PepperHostResolverMessageFilter::OnComplete,
+ base::Unretained(this), net::ERR_FAILED, base::nullopt));
+
+ network::mojom::ResolveHostParametersPtr parameters =
+ network::mojom::ResolveHostParameters::New();
+ PrepareRequestInfo(hint, parameters.get());
+
+ storage_partition->GetNetworkContext()->ResolveHost(
+ net::HostPortPair(host_port.host, host_port.port), std::move(parameters),
+ std::move(client_ptr));
+ host_resolve_context_ = context->MakeReplyMessageContext();
+
return PP_OK_COMPLETIONPENDING;
}
-void PepperHostResolverMessageFilter::DoResolve(
- const ReplyMessageContext& context,
- const ppapi::HostPortPair& host_port,
- const PP_HostResolver_Private_Hint& hint,
- scoped_refptr<net::URLRequestContextGetter> url_request_context_getter) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- auto* url_request_context =
- url_request_context_getter->GetURLRequestContext();
- if (!url_request_context) {
- SendResolveError(PP_ERROR_FAILED, context);
- return;
- }
+void PepperHostResolverMessageFilter::OnComplete(
+ int result,
+ const base::Optional<net::AddressList>& resolved_addresses) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ binding_.Close();
- net::HostResolver* host_resolver = url_request_context->host_resolver();
- if (!host_resolver) {
- SendResolveError(PP_ERROR_FAILED, context);
- return;
- }
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&PepperHostResolverMessageFilter::OnLookupFinished, this,
+ result, std::move(resolved_addresses),
+ host_resolve_context_));
+ host_resolve_context_ = ppapi::host::ReplyMessageContext();
- net::HostResolver::RequestInfo request_info(
- net::HostPortPair(host_port.host, host_port.port));
- PrepareRequestInfo(hint, &request_info);
-
- std::unique_ptr<ReplyMessageContext> bound_info(
- new ReplyMessageContext(context));
-
- // The lookup request will delete itself on completion.
- PepperLookupRequest<ReplyMessageContext>* lookup_request =
- new PepperLookupRequest<ReplyMessageContext>(
- host_resolver,
- request_info,
- net::DEFAULT_PRIORITY,
- bound_info.release(),
- base::Bind(&PepperHostResolverMessageFilter::OnLookupFinished, this));
- lookup_request->Start();
+ Release(); // Balances AddRef in OnMsgResolve.
}
void PepperHostResolverMessageFilter::OnLookupFinished(
int net_result,
- const net::AddressList& addresses,
+ const base::Optional<net::AddressList>& addresses,
const ReplyMessageContext& context) {
if (net_result != net::OK) {
SendResolveError(NetErrorToPepperError(net_result), context);
} else {
- const std::string& canonical_name = addresses.canonical_name();
+ const std::string& canonical_name = addresses.value().canonical_name();
NetAddressList net_address_list;
- CreateNetAddressListFromAddressList(addresses, &net_address_list);
+ CreateNetAddressListFromAddressList(addresses.value(), &net_address_list);
if (net_address_list.empty())
SendResolveError(PP_ERROR_FAILED, context);
else
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.h b/chromium/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.h
index cd9f2121322..80b1e5c6b9c 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.h
@@ -14,15 +14,16 @@
#include "base/macros.h"
#include "content/common/content_export.h"
#include "content/public/common/process_type.h"
+#include "mojo/public/cpp/bindings/binding.h"
#include "ppapi/c/pp_instance.h"
#include "ppapi/host/resource_message_filter.h"
+#include "services/network/public/mojom/network_context.mojom.h"
struct PP_HostResolver_Private_Hint;
struct PP_NetAddress_Private;
namespace net {
class AddressList;
-class URLRequestContextGetter;
}
namespace ppapi {
@@ -38,7 +39,8 @@ namespace content {
class BrowserPpapiHostImpl;
class CONTENT_EXPORT PepperHostResolverMessageFilter
- : public ppapi::host::ResourceMessageFilter {
+ : public ppapi::host::ResourceMessageFilter,
+ public network::mojom::ResolveHostClient {
public:
PepperHostResolverMessageFilter(BrowserPpapiHostImpl* host,
PP_Instance instance,
@@ -61,16 +63,13 @@ class CONTENT_EXPORT PepperHostResolverMessageFilter
const ppapi::HostPortPair& host_port,
const PP_HostResolver_Private_Hint& hint);
- // Backend for OnMsgResolve(). Delegates host resolution to the
- // Browser's HostResolver. Must be called on the IO thread.
- void DoResolve(
- const ppapi::host::ReplyMessageContext& context,
- const ppapi::HostPortPair& host_port,
- const PP_HostResolver_Private_Hint& hint,
- scoped_refptr<net::URLRequestContextGetter> url_request_context_getter);
+ // network::mojom::ResolveHostClient overrides.
+ void OnComplete(
+ int result,
+ const base::Optional<net::AddressList>& resolved_addresses) override;
void OnLookupFinished(int net_result,
- const net::AddressList& addresses,
+ const base::Optional<net::AddressList>& addresses,
const ppapi::host::ReplyMessageContext& bound_info);
void SendResolveReply(int32_t result,
const std::string& canonical_name,
@@ -79,11 +78,21 @@ class CONTENT_EXPORT PepperHostResolverMessageFilter
void SendResolveError(int32_t error,
const ppapi::host::ReplyMessageContext& context);
+ // The following members are only accessed on the IO thread.
+
bool external_plugin_;
bool private_api_;
int render_process_id_;
int render_frame_id_;
+ // The following members are only accessed on the UI thread.
+
+ // A reference to |this| must always be taken while |binding_| is bound to
+ // ensure that if the error callback is called the object is alive.
+ mojo::Binding<network::mojom::ResolveHostClient> binding_;
+
+ ppapi::host::ReplyMessageContext host_resolve_context_;
+
DISALLOW_COPY_AND_ASSIGN(PepperHostResolverMessageFilter);
};
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_lookup_request.h b/chromium/content/browser/renderer_host/pepper/pepper_lookup_request.h
deleted file mode 100644
index 128b3632b51..00000000000
--- a/chromium/content/browser/renderer_host/pepper/pepper_lookup_request.h
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_LOOKUP_REQUEST_H_
-#define CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_LOOKUP_REQUEST_H_
-
-#include <memory>
-
-#include "base/callback.h"
-#include "base/macros.h"
-#include "net/base/address_list.h"
-#include "net/base/net_errors.h"
-#include "net/dns/host_resolver.h"
-#include "net/log/net_log_with_source.h"
-
-namespace content {
-
-template <class T>
-class PepperLookupRequest {
- public:
- typedef base::Callback<void(int, const net::AddressList&, const T&)>
- LookupRequestCallback;
-
- // Takes ownership over |bound_info|. |bound_info| will be passed to
- // callback, when lookup will finish.
- PepperLookupRequest(net::HostResolver* resolver,
- const net::HostResolver::RequestInfo& request_info,
- net::RequestPriority priority,
- T* bound_info,
- const LookupRequestCallback& callback)
- : resolver_(resolver),
- request_info_(request_info),
- priority_(priority),
- bound_info_(bound_info),
- callback_(callback) {}
-
- void Start() {
- int result =
- resolver_->Resolve(request_info_, priority_, &addresses_,
- base::Bind(&PepperLookupRequest<T>::OnLookupFinished,
- base::Unretained(this)),
- &request_, net::NetLogWithSource());
- if (result != net::ERR_IO_PENDING)
- OnLookupFinished(result);
- }
-
- private:
- void OnLookupFinished(int result) {
- callback_.Run(result, addresses_, *bound_info_);
- delete this;
- }
-
- net::HostResolver* resolver_;
- std::unique_ptr<net::HostResolver::Request> request_;
- net::HostResolver::RequestInfo request_info_;
- net::RequestPriority priority_;
- std::unique_ptr<T> bound_info_;
- LookupRequestCallback callback_;
-
- net::AddressList addresses_;
-
- DISALLOW_COPY_AND_ASSIGN(PepperLookupRequest);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_LOOKUP_REQUEST_H_
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_network_monitor_host.cc b/chromium/content/browser/renderer_host/pepper/pepper_network_monitor_host.cc
index ed62e219f02..9f0fc648abf 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_network_monitor_host.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_network_monitor_host.cc
@@ -6,8 +6,8 @@
#include <stddef.h>
+#include "base/task/post_task.h"
#include "base/task_runner_util.h"
-#include "base/task_scheduler/post_task.h"
#include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h"
#include "content/browser/renderer_host/pepper/pepper_socket_utils.h"
#include "content/public/browser/browser_thread.h"
@@ -90,7 +90,7 @@ void PepperNetworkMonitorHost::GetAndSendNetworkList() {
// Call GetNetworkList() on a thread that allows blocking IO.
base::PostTaskWithTraitsAndReplyWithResult(
- FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND},
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
base::Bind(&GetNetworkList),
base::Bind(&PepperNetworkMonitorHost::SendNetworkList,
weak_factory_.GetWeakPtr()));
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_network_proxy_host.cc b/chromium/content/browser/renderer_host/pepper/pepper_network_proxy_host.cc
index 3fcb804a5f8..75774080312 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_network_proxy_host.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_network_proxy_host.cc
@@ -6,56 +6,68 @@
#include "base/bind.h"
#include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h"
+#include "content/browser/renderer_host/pepper/pepper_proxy_lookup_helper.h"
#include "content/browser/renderer_host/pepper/pepper_socket_utils.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/site_instance.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/common/socket_permission_request.h"
-#include "net/base/net_errors.h"
-#include "net/log/net_log_with_source.h"
#include "net/proxy_resolution/proxy_info.h"
-#include "net/url_request/url_request_context.h"
-#include "net/url_request/url_request_context_getter.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/host/dispatch_host_message.h"
#include "ppapi/host/ppapi_host.h"
#include "ppapi/proxy/ppapi_messages.h"
+#include "services/network/public/mojom/network_context.mojom.h"
+#include "services/network/public/mojom/proxy_lookup_client.mojom.h"
namespace content {
+namespace {
+
+bool LookUpProxyForURLCallback(
+ int render_process_host_id,
+ int render_frame_host_id,
+ const GURL& url,
+ network::mojom::ProxyLookupClientPtr proxy_lookup_client) {
+ RenderFrameHost* render_frame_host =
+ RenderFrameHost::FromID(render_process_host_id, render_frame_host_id);
+ if (!render_frame_host)
+ return false;
+
+ SiteInstance* site_instance = render_frame_host->GetSiteInstance();
+ StoragePartition* storage_partition = BrowserContext::GetStoragePartition(
+ site_instance->GetBrowserContext(), site_instance);
+
+ storage_partition->GetNetworkContext()->LookUpProxyForURL(
+ url, std::move(proxy_lookup_client));
+ return true;
+}
+
+} // namespace
+
PepperNetworkProxyHost::PepperNetworkProxyHost(BrowserPpapiHostImpl* host,
PP_Instance instance,
PP_Resource resource)
: ResourceHost(host->GetPpapiHost(), instance, resource),
- proxy_resolution_service_(nullptr),
+ render_process_id_(0),
+ render_frame_id_(0),
is_allowed_(false),
waiting_for_ui_thread_data_(true),
weak_factory_(this) {
- int render_process_id(0), render_frame_id(0);
- host->GetRenderFrameIDsForInstance(
- instance, &render_process_id, &render_frame_id);
+ host->GetRenderFrameIDsForInstance(instance, &render_process_id_,
+ &render_frame_id_);
BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(&GetUIThreadDataOnUIThread,
- render_process_id,
- render_frame_id,
- host->external_plugin()),
- base::Bind(&PepperNetworkProxyHost::DidGetUIThreadData,
- weak_factory_.GetWeakPtr()));
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&GetUIThreadDataOnUIThread, render_process_id_,
+ render_frame_id_, host->external_plugin()),
+ base::BindOnce(&PepperNetworkProxyHost::DidGetUIThreadData,
+ weak_factory_.GetWeakPtr()));
}
-PepperNetworkProxyHost::~PepperNetworkProxyHost() {
- while (!pending_requests_.empty()) {
- // If the proxy_resolution_service_ is NULL, we shouldn't have any outstanding
- // requests.
- DCHECK(proxy_resolution_service_);
- net::ProxyResolutionService::Request* request = pending_requests_.front();
- proxy_resolution_service_->CancelRequest(request);
- pending_requests_.pop();
- }
-}
+PepperNetworkProxyHost::~PepperNetworkProxyHost() = default;
PepperNetworkProxyHost::UIThreadData::UIThreadData() : is_allowed(false) {}
@@ -71,9 +83,6 @@ PepperNetworkProxyHost::GetUIThreadDataOnUIThread(int render_process_id,
bool is_external_plugin) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
PepperNetworkProxyHost::UIThreadData result;
- RenderProcessHost* rph = RenderProcessHost::FromID(render_process_id);
- if (rph)
- result.context_getter = rph->GetStoragePartition()->GetURLRequestContext();
SocketPermissionRequest request(
content::SocketPermissionRequest::RESOLVE_PROXY, std::string(), 0);
@@ -89,16 +98,7 @@ PepperNetworkProxyHost::GetUIThreadDataOnUIThread(int render_process_id,
void PepperNetworkProxyHost::DidGetUIThreadData(
const UIThreadData& ui_thread_data) {
is_allowed_ = ui_thread_data.is_allowed;
- if (ui_thread_data.context_getter.get() &&
- ui_thread_data.context_getter->GetURLRequestContext()) {
- proxy_resolution_service_ =
- ui_thread_data.context_getter->GetURLRequestContext()->proxy_resolution_service();
- }
waiting_for_ui_thread_data_ = false;
- if (!proxy_resolution_service_) {
- DLOG_IF(WARNING, proxy_resolution_service_)
- << "Failed to find a ProxyResolutionService for Pepper plugin.";
- }
TryToSendUnsentRequests();
}
@@ -132,27 +132,23 @@ void PepperNetworkProxyHost::TryToSendUnsentRequests() {
while (!unsent_requests_.empty()) {
const UnsentRequest& request = unsent_requests_.front();
- if (!proxy_resolution_service_) {
- SendFailureReply(PP_ERROR_FAILED, request.reply_context);
- } else if (!is_allowed_) {
+ if (!is_allowed_) {
SendFailureReply(PP_ERROR_NOACCESS, request.reply_context);
} else {
// Everything looks valid, so try to resolve the proxy.
- net::ProxyInfo* proxy_info = new net::ProxyInfo;
- net::ProxyResolutionService::Request* pending_request = nullptr;
- base::Callback<void(int)> callback =
- base::Bind(&PepperNetworkProxyHost::OnResolveProxyCompleted,
- weak_factory_.GetWeakPtr(),
- request.reply_context,
- base::Owned(proxy_info));
- int result = proxy_resolution_service_->ResolveProxy(
- request.url, std::string(), proxy_info, callback, &pending_request,
- nullptr, net::NetLogWithSource());
- pending_requests_.push(pending_request);
- // If it was handled synchronously, we must run the callback now;
- // proxy_resolution_service_ won't run it for us in this case.
- if (result != net::ERR_IO_PENDING)
- std::move(callback).Run(result);
+ auto lookup_helper = std::make_unique<PepperProxyLookupHelper>();
+ PepperProxyLookupHelper::LookUpProxyForURLCallback
+ look_up_proxy_for_url_callback = base::BindOnce(
+ &LookUpProxyForURLCallback, render_process_id_, render_frame_id_);
+ PepperProxyLookupHelper::LookUpCompleteCallback
+ look_up_complete_callback =
+ base::BindOnce(&PepperNetworkProxyHost::OnResolveProxyCompleted,
+ weak_factory_.GetWeakPtr(), request.reply_context,
+ lookup_helper.get());
+ lookup_helper->Start(request.url,
+ std::move(look_up_proxy_for_url_callback),
+ std::move(look_up_complete_callback));
+ pending_requests_.insert(std::move(lookup_helper));
}
unsent_requests_.pop();
}
@@ -160,20 +156,24 @@ void PepperNetworkProxyHost::TryToSendUnsentRequests() {
void PepperNetworkProxyHost::OnResolveProxyCompleted(
ppapi::host::ReplyMessageContext context,
- net::ProxyInfo* proxy_info,
- int result) {
- pending_requests_.pop();
-
- if (result != net::OK) {
- // Currently, the only proxy-specific error we could get is
- // MANDATORY_PROXY_CONFIGURATION_FAILED. There's really no action a plugin
- // can take in this case, so there's no need to distinguish it from other
- // failures.
+ PepperProxyLookupHelper* pending_request,
+ base::Optional<net::ProxyInfo> proxy_info) {
+ auto it = pending_requests_.find(pending_request);
+ DCHECK(it != pending_requests_.end());
+ pending_requests_.erase(it);
+
+ std::string pac_string;
+ if (!proxy_info) {
+ // This can happen in cases of network service crash, shutdown, or when
+ // the request fails with ERR_MANDATORY_PROXY_CONFIGURATION_FAILED. There's
+ // really no action a plugin can take, so there's no need to distinguish
+ // which error occurred.
context.params.set_result(PP_ERROR_FAILED);
+ } else {
+ pac_string = proxy_info->ToPacString();
}
- host()->SendReply(context,
- PpapiPluginMsg_NetworkProxy_GetProxyForURLReply(
- proxy_info->ToPacString()));
+ host()->SendReply(
+ context, PpapiPluginMsg_NetworkProxy_GetProxyForURLReply(pac_string));
}
void PepperNetworkProxyHost::SendFailureReply(
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_network_proxy_host.h b/chromium/content/browser/renderer_host/pepper/pepper_network_proxy_host.h
index a3b9424aeba..081c4045864 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_network_proxy_host.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_network_proxy_host.h
@@ -8,20 +8,22 @@
#include <stdint.h>
#include <queue>
+#include <set>
#include <string>
#include "base/compiler_specific.h"
#include "base/containers/queue.h"
+#include "base/containers/unique_ptr_adapters.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
+#include "base/optional.h"
#include "content/common/content_export.h"
-#include "net/proxy_resolution/proxy_resolution_service.h"
#include "ppapi/host/host_message_context.h"
#include "ppapi/host/resource_host.h"
+#include "url/gurl.h"
namespace net {
class ProxyInfo;
-class URLRequestContextGetter;
}
namespace ppapi {
@@ -33,6 +35,7 @@ struct ReplyMessageContext;
namespace content {
class BrowserPpapiHostImpl;
+class PepperProxyLookupHelper;
// The host for PPB_NetworkProxy. This class lives on the IO thread.
class CONTENT_EXPORT PepperNetworkProxyHost : public ppapi::host::ResourceHost {
@@ -44,15 +47,14 @@ class CONTENT_EXPORT PepperNetworkProxyHost : public ppapi::host::ResourceHost {
~PepperNetworkProxyHost() override;
private:
- // We retrieve the appropriate URLRequestContextGetter and whether this API
- // is allowed for the instance on the UI thread and pass those to
- // DidGetUIThreadData, which sets allowed_ and proxy_resolution_service_.
+ // We retrieve whether this API is allowed for the instance on the UI thread
+ // and pass it to DidGetUIThreadData, which sets allowed_.
struct UIThreadData {
UIThreadData();
UIThreadData(const UIThreadData& other);
~UIThreadData();
+
bool is_allowed;
- scoped_refptr<net::URLRequestContextGetter> context_getter;
};
static UIThreadData GetUIThreadDataOnUIThread(int render_process_id,
int render_frame_id,
@@ -67,39 +69,39 @@ class CONTENT_EXPORT PepperNetworkProxyHost : public ppapi::host::ResourceHost {
int32_t OnMsgGetProxyForURL(ppapi::host::HostMessageContext* context,
const std::string& url);
- // If we have a valid proxy_resolution_service_, send all messages in
- // unsent_requests_.
+ // Send all messages in |unsent_requests_|.
void TryToSendUnsentRequests();
void OnResolveProxyCompleted(ppapi::host::ReplyMessageContext context,
- net::ProxyInfo* proxy_info,
- int result);
+ PepperProxyLookupHelper* pending_request,
+ base::Optional<net::ProxyInfo> proxy_info);
void SendFailureReply(int32_t error,
ppapi::host::ReplyMessageContext context);
- // The following two members are invalid until we get some information from
- // the UI thread. However, these are only ever set or accessed on the IO
- // thread.
- net::ProxyResolutionService* proxy_resolution_service_;
+ // Used to find correct NetworkContext to perform proxy lookups.
+ int render_process_id_;
+ int render_frame_id_;
+
+ // The following member is invalid until we get some information from the UI
+ // thread. However, it is only ever set or accessed on the IO thread.
bool is_allowed_;
- // True initially, but set to false once the values for
- // proxy_resolution_service_ and is_allowed_ have been set.
+ // True initially, but set to false once is_allowed_ has been set.
bool waiting_for_ui_thread_data_;
- // We have to get the URLRequestContextGetter from the UI thread before we
- // can retrieve proxy_resolution_service_. If we receive any calls for
- // GetProxyForURL before proxy_resolution_service_ is available, we save them
- // in unsent_requests_.
+ // We have to get is_allowed_ from the UI thread before we can start a
+ // request. If we receive any calls for GetProxyForURL before is_allowed_ is
+ // available, we save them in unsent_requests_.
struct UnsentRequest {
GURL url;
ppapi::host::ReplyMessageContext reply_context;
};
base::queue<UnsentRequest> unsent_requests_;
- // Requests awaiting a response from ProxyResolutionService. We need to store
+ // Requests awaiting a response from the network service. We need to store
// these so that we can cancel them if we get destroyed.
- base::queue<net::ProxyResolutionService::Request*> pending_requests_;
+ std::set<std::unique_ptr<PepperProxyLookupHelper>, base::UniquePtrComparator>
+ pending_requests_;
base::WeakPtrFactory<PepperNetworkProxyHost> weak_factory_;
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_proxy_lookup_helper.cc b/chromium/content/browser/renderer_host/pepper/pepper_proxy_lookup_helper.cc
new file mode 100644
index 00000000000..95928393273
--- /dev/null
+++ b/chromium/content/browser/renderer_host/pepper/pepper_proxy_lookup_helper.cc
@@ -0,0 +1,106 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/pepper/pepper_proxy_lookup_helper.h"
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/memory/ref_counted.h"
+#include "base/sequenced_task_runner.h"
+#include "base/threading/sequenced_task_runner_handle.h"
+#include "content/public/browser/browser_thread.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/interface_request.h"
+#include "url/gurl.h"
+
+namespace content {
+
+// Runs the proxy lookup on the UI thread. Created on the
+// PepperProxyLookupHelper's thread, but then does all work on the UI thread,
+// and is deleted there by a task posted by the PepperProxyLookupHelper.
+class PepperProxyLookupHelper::UIThreadHelper
+ : public network::mojom::ProxyLookupClient {
+ public:
+ UIThreadHelper(const GURL& url,
+ LookUpProxyForURLCallback look_up_proxy_for_url_callback,
+ LookUpCompleteCallback look_up_complete_callback)
+ : binding_(this),
+ look_up_complete_callback_(std::move(look_up_complete_callback)),
+ callback_task_runner_(base::SequencedTaskRunnerHandle::Get()) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&UIThreadHelper::StartLookup, base::Unretained(this),
+ url, std::move(look_up_proxy_for_url_callback)));
+ }
+
+ ~UIThreadHelper() override { DCHECK_CURRENTLY_ON(BrowserThread::UI); }
+
+ private:
+ void StartLookup(const GURL& url,
+ LookUpProxyForURLCallback look_up_proxy_for_url_callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ network::mojom::ProxyLookupClientPtr proxy_lookup_client;
+ binding_.Bind(mojo::MakeRequest(&proxy_lookup_client));
+ binding_.set_connection_error_handler(
+ base::BindOnce(&UIThreadHelper::OnProxyLookupComplete,
+ base::Unretained(this), base::nullopt));
+ if (!std::move(look_up_proxy_for_url_callback)
+ .Run(url, std::move(proxy_lookup_client))) {
+ OnProxyLookupComplete(base::nullopt);
+ }
+ }
+
+ void OnProxyLookupComplete(
+ const base::Optional<net::ProxyInfo>& proxy_info) override {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ binding_.Close();
+ callback_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(std::move(look_up_complete_callback_), proxy_info));
+ }
+
+ mojo::Binding<network::mojom::ProxyLookupClient> binding_;
+
+ LookUpCompleteCallback look_up_complete_callback_;
+ scoped_refptr<base::SequencedTaskRunner> callback_task_runner_;
+
+ DISALLOW_COPY_AND_ASSIGN(UIThreadHelper);
+};
+
+PepperProxyLookupHelper::PepperProxyLookupHelper() : weak_factory_(this) {}
+
+PepperProxyLookupHelper::~PepperProxyLookupHelper() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE,
+ std::move(ui_thread_helper_));
+}
+
+void PepperProxyLookupHelper::Start(
+ const GURL& url,
+ LookUpProxyForURLCallback look_up_proxy_for_url_callback,
+ LookUpCompleteCallback look_up_complete_callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(!look_up_complete_callback_);
+ DCHECK(!ui_thread_helper_);
+
+ look_up_complete_callback_ = std::move(look_up_complete_callback);
+
+ ui_thread_helper_ = std::make_unique<UIThreadHelper>(
+ url, std::move(look_up_proxy_for_url_callback),
+ base::BindOnce(&PepperProxyLookupHelper::OnProxyLookupComplete,
+ weak_factory_.GetWeakPtr()));
+}
+
+void PepperProxyLookupHelper::OnProxyLookupComplete(
+ base::Optional<net::ProxyInfo> proxy_info) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ std::move(look_up_complete_callback_).Run(std::move(proxy_info));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_proxy_lookup_helper.h b/chromium/content/browser/renderer_host/pepper/pepper_proxy_lookup_helper.h
new file mode 100644
index 00000000000..f6ea3869957
--- /dev/null
+++ b/chromium/content/browser/renderer_host/pepper/pepper_proxy_lookup_helper.h
@@ -0,0 +1,70 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_PROXY_LOOKUP_HELPER_H_
+#define CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_PROXY_LOOKUP_HELPER_H_
+
+#include <memory>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/optional.h"
+#include "base/sequence_checker.h"
+#include "content/common/content_export.h"
+#include "services/network/public/mojom/proxy_lookup_client.mojom.h"
+
+class GURL;
+
+namespace net {
+class ProxyInfo;
+}
+
+namespace content {
+
+// Class that runs a single proxy resolution on the UI thread. Lives on the
+// thread its created on, and uses a helper to run tasks off-thread. Can be
+// destroyed at any time.
+class CONTENT_EXPORT PepperProxyLookupHelper {
+ public:
+ // Callback to call LookUpProxyForURL. Called on the UI thread. Needed for
+ // testing. Returns false if unable to make the call, for whatever reason.
+ using LookUpProxyForURLCallback = base::OnceCallback<bool(
+ const GURL& url,
+ network::mojom::ProxyLookupClientPtr proxy_lookup_client)>;
+
+ // Callback to invoke when complete. Invoked on thread the
+ // PepperProxyLookupHelper was created on.
+ using LookUpCompleteCallback =
+ base::OnceCallback<void(base::Optional<net::ProxyInfo> proxy_info)>;
+
+ PepperProxyLookupHelper();
+ ~PepperProxyLookupHelper();
+
+ // Starts a lookup for |url| on the UI thread. Invokes
+ // |look_up_proxy_for_url_callback| on the UI thread to start the lookup, and
+ // calls |look_up_complete_callback| on the thread Start() was called on when
+ // complete. May only be invoked once.
+ void Start(const GURL& url,
+ LookUpProxyForURLCallback look_up_proxy_for_url_callback,
+ LookUpCompleteCallback look_up_complete_callback);
+
+ private:
+ class UIThreadHelper;
+
+ void OnProxyLookupComplete(base::Optional<net::ProxyInfo> proxy_info);
+
+ LookUpCompleteCallback look_up_complete_callback_;
+ std::unique_ptr<UIThreadHelper> ui_thread_helper_;
+
+ SEQUENCE_CHECKER(sequence_checker_);
+
+ base::WeakPtrFactory<PepperProxyLookupHelper> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(PepperProxyLookupHelper);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_PROXY_LOOKUP_HELPER_H_
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_proxy_lookup_helper_unittest.cc b/chromium/content/browser/renderer_host/pepper/pepper_proxy_lookup_helper_unittest.cc
new file mode 100644
index 00000000000..25f87fdcad3
--- /dev/null
+++ b/chromium/content/browser/renderer_host/pepper/pepper_proxy_lookup_helper_unittest.cc
@@ -0,0 +1,203 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/pepper/pepper_proxy_lookup_helper.h"
+
+#include <memory>
+#include <string>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/optional.h"
+#include "base/run_loop.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "net/proxy_resolution/proxy_info.h"
+#include "services/network/public/mojom/proxy_lookup_client.mojom.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace content {
+namespace {
+
+constexpr char kTestURL[] = "http://foo/";
+
+class PepperProxyLookupHelperTest : public testing::Test {
+ public:
+ PepperProxyLookupHelperTest() = default;
+ ~PepperProxyLookupHelperTest() override = default;
+
+ // Initializes |lookup_helper_| on the IO thread, and starts it there. Returns
+ // once it has called into LookUpProxyForURLOnUIThread on the UI thread.
+ void StartLookup() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ base::RunLoop run_loop;
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&PepperProxyLookupHelperTest::StartLookupOnIOThread,
+ base::Unretained(this), run_loop.QuitClosure()));
+ run_loop.Run();
+
+ EXPECT_TRUE(lookup_helper_);
+ if (!fail_to_start_request_)
+ EXPECT_TRUE(proxy_lookup_client_);
+ }
+
+ // Takes the |ProxyLookupClientPtr| passed by |lookup_helper_| to
+ // LookUpProxyForURLOnUIThread(). May only be called after |lookup_helper_|
+ // has successfully called into LookUpProxyForURLOnUIThread().
+ network::mojom::ProxyLookupClientPtr ClaimProxyLookupClient() {
+ EXPECT_TRUE(proxy_lookup_client_);
+ return std::move(proxy_lookup_client_);
+ }
+
+ void DestroyLookupHelper() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ base::RunLoop run_loop;
+
+ BrowserThread::PostTaskAndReply(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(
+ &PepperProxyLookupHelperTest::DestroyLookupHelperOnIOThread,
+ base::Unretained(this)),
+ run_loop.QuitClosure());
+ run_loop.Run();
+ }
+
+ // Waits for |lookup_helper_| to call into OnLookupCompleteOnIOThread(),
+ // signally proxy lookup completion.
+ void WaitForLookupCompletion() {
+ EXPECT_TRUE(lookup_helper_);
+ lookup_complete_run_loop_.Run();
+ }
+
+ // Get the proxy information passed into OnLookupCompleteOnIOThread().
+ const base::Optional<net::ProxyInfo>& proxy_info() const {
+ return proxy_info_;
+ }
+
+ // Setting this to true will make LookUpProxyForURLOnUIThread, the callback
+ // invoked to start looking up the proxy, return false.
+ void set_fail_to_start_request(bool fail_to_start_request) {
+ fail_to_start_request_ = fail_to_start_request;
+ }
+
+ private:
+ // Must be called on the IO thread. Initializes |lookup_helper_| and starts a
+ // proxy lookup. Invokes |closure| on the UI thread once the |lookup_helper_|
+ // has invoked LookUpProxyForURLOnUIThread on the UI thread.
+ void StartLookupOnIOThread(base::OnceClosure closure) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(!lookup_helper_);
+
+ lookup_helper_ = std::make_unique<PepperProxyLookupHelper>();
+ lookup_helper_->Start(
+ GURL(kTestURL),
+ base::BindOnce(
+ &PepperProxyLookupHelperTest::LookUpProxyForURLOnUIThread,
+ base::Unretained(this), std::move(closure)),
+ base::BindOnce(&PepperProxyLookupHelperTest::OnLookupCompleteOnIOThread,
+ base::Unretained(this)));
+ }
+
+ // Callback passed to |lookup_helper_| to start the proxy lookup.
+ bool LookUpProxyForURLOnUIThread(
+ base::OnceClosure closure,
+ const GURL& url,
+ network::mojom::ProxyLookupClientPtr proxy_lookup_client) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ std::move(closure).Run();
+
+ if (fail_to_start_request_)
+ return false;
+
+ EXPECT_EQ(GURL(kTestURL), url);
+ proxy_lookup_client_ = std::move(proxy_lookup_client);
+ return true;
+ }
+
+ // Invoked by |lookup_helper_| on the IO thread once the proxy lookup has
+ // completed.
+ void OnLookupCompleteOnIOThread(base::Optional<net::ProxyInfo> proxy_info) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ proxy_info_ = std::move(proxy_info);
+ lookup_helper_.reset();
+ lookup_complete_run_loop_.Quit();
+ }
+
+ void DestroyLookupHelperOnIOThread() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ lookup_helper_.reset();
+ }
+
+ TestBrowserThreadBundle test_browser_thread_bundle_;
+
+ bool fail_to_start_request_ = false;
+
+ std::unique_ptr<PepperProxyLookupHelper> lookup_helper_;
+
+ base::Optional<net::ProxyInfo> proxy_info_;
+ network::mojom::ProxyLookupClientPtr proxy_lookup_client_;
+
+ base::RunLoop lookup_complete_run_loop_;
+};
+
+TEST_F(PepperProxyLookupHelperTest, Success) {
+ StartLookup();
+ net::ProxyInfo proxy_info_response;
+ proxy_info_response.UseNamedProxy("result:80");
+ ClaimProxyLookupClient()->OnProxyLookupComplete(proxy_info_response);
+ WaitForLookupCompletion();
+ ASSERT_TRUE(proxy_info());
+ EXPECT_EQ("PROXY result:80", proxy_info()->ToPacString());
+}
+
+// Basic failure case - an error is passed to the PepperProxyLookupHelper
+// through the ProxyLookupClient API.
+TEST_F(PepperProxyLookupHelperTest, Failure) {
+ StartLookup();
+ ClaimProxyLookupClient()->OnProxyLookupComplete(base::nullopt);
+ WaitForLookupCompletion();
+ EXPECT_FALSE(proxy_info());
+}
+
+// The mojo pipe is closed before the PepperProxyLookupHelper's callback is
+// invoked.
+TEST_F(PepperProxyLookupHelperTest, PipeClosed) {
+ StartLookup();
+ ClaimProxyLookupClient().reset();
+ WaitForLookupCompletion();
+ EXPECT_FALSE(proxy_info());
+}
+
+// The proxy lookup fails to start - instead, the callback to start the lookup
+// returns false.
+TEST_F(PepperProxyLookupHelperTest, FailToStartRequest) {
+ set_fail_to_start_request(true);
+
+ StartLookup();
+ WaitForLookupCompletion();
+ EXPECT_FALSE(proxy_info());
+}
+
+// Destroy the helper before it completes a lookup. Make sure it cancels the
+// connection, and memory tools don't detect a leak.
+TEST_F(PepperProxyLookupHelperTest, DestroyBeforeComplete) {
+ StartLookup();
+ base::RunLoop run_loop;
+ network::mojom::ProxyLookupClientPtr proxy_lookup_client =
+ ClaimProxyLookupClient();
+ proxy_lookup_client.set_connection_error_handler(run_loop.QuitClosure());
+ DestroyLookupHelper();
+ run_loop.Run();
+}
+
+} // namespace
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_socket_utils.cc b/chromium/content/browser/renderer_host/pepper/pepper_socket_utils.cc
index 2050cf6f4d3..13816b2f8fe 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_socket_utils.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_socket_utils.cc
@@ -186,5 +186,94 @@ void OpenUDPFirewallHole(const net::IPEndPoint& address,
}
#endif // defined(OS_CHROMEOS)
+net::MutableNetworkTrafficAnnotationTag PepperTCPNetworkAnnotationTag() {
+ return net::MutableNetworkTrafficAnnotationTag(
+ net::DefineNetworkTrafficAnnotation("pepper_tcp_socket",
+ R"(
+ semantics {
+ sender: "Pepper TCP Socket"
+ description:
+ "Pepper plugins use this API to send and receive data over the "
+ "network using TCP connections. This inteface is used by Flash and "
+ "PDF viewer, and Chrome Apps which use plugins to send/receive TCP "
+ "traffic (require Chrome Apps TCP socket permission). This "
+ "interface allows creation of client and server sockets."
+ trigger:
+ "A request from a Pepper plugin."
+ data: "Any data that the plugin sends."
+ destination: OTHER
+ destination_other:
+ "Data can be sent to any destination."
+ }
+ policy {
+ cookies_allowed: NO
+ setting:
+ "These requests cannot be disabled, but will not happen if user "
+ "does not use Flash, internal PDF Viewer, or Chrome Apps that use "
+ "Pepper interface."
+ chrome_policy {
+ DefaultPluginsSetting {
+ DefaultPluginsSetting: 2
+ }
+ }
+ chrome_policy {
+ AlwaysOpenPdfExternally {
+ AlwaysOpenPdfExternally: true
+ }
+ }
+ chrome_policy {
+ ExtensionInstallBlacklist {
+ ExtensionInstallBlacklist: {
+ entries: '*'
+ }
+ }
+ }
+ })"));
+}
+
+net::MutableNetworkTrafficAnnotationTag PepperUDPNetworkAnnotationTag() {
+ return net::MutableNetworkTrafficAnnotationTag(
+ net::DefineNetworkTrafficAnnotation("pepper_udp_socket",
+ R"(
+ semantics {
+ sender: "Pepper UDP Socket"
+ description:
+ "Pepper plugins use this API to send and receive data over the "
+ "network using UDP connections. This inteface is used by Flash and "
+ "PDF viewer, and Chrome Apps which use plugins to send/receive UDP "
+ "traffic (require Chrome Apps UDP socket permission)."
+ trigger:
+ "A request from a Pepper plugin."
+ data: "Any data that the plugin sends."
+ destination: OTHER
+ destination_other:
+ "Data can be sent to any destination."
+ }
+ policy {
+ cookies_allowed: NO
+ setting:
+ "These requests cannot be disabled, but will not happen if user "
+ "does not use Flash, internal PDF Viewer, or Chrome Apps that use "
+ "Pepper interface."
+ chrome_policy {
+ DefaultPluginsSetting {
+ DefaultPluginsSetting: 2
+ }
+ }
+ chrome_policy {
+ AlwaysOpenPdfExternally {
+ AlwaysOpenPdfExternally: true
+ }
+ }
+ chrome_policy {
+ ExtensionInstallBlacklist {
+ ExtensionInstallBlacklist: {
+ entries: '*'
+ }
+ }
+ }
+ })"));
+}
+
} // namespace pepper_socket_utils
} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_socket_utils.h b/chromium/content/browser/renderer_host/pepper/pepper_socket_utils.h
index b10c940800f..c9863ab62a8 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_socket_utils.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_socket_utils.h
@@ -9,6 +9,7 @@
#include "build/build_config.h"
#include "content/public/common/socket_permission_request.h"
+#include "net/traffic_annotation/network_traffic_annotation.h"
#include "ppapi/c/pp_stdint.h"
#if defined(OS_CHROMEOS)
@@ -72,6 +73,11 @@ void OpenUDPFirewallHole(const net::IPEndPoint& address,
FirewallHoleOpenCallback callback);
#endif // defined(OS_CHROMEOS)
+// Annotations for TCP and UDP network requests. Defined here to make it easier
+// to keep them in sync.
+net::MutableNetworkTrafficAnnotationTag PepperTCPNetworkAnnotationTag();
+net::MutableNetworkTrafficAnnotationTag PepperUDPNetworkAnnotationTag();
+
} // namespace pepper_socket_utils
} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.cc b/chromium/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.cc
index 3a8cb7c6cd0..429d3d217da 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.cc
@@ -141,11 +141,9 @@ int32_t PepperTCPServerSocketMessageFilter::OnMsgAccept(
ppapi::host::ReplyMessageContext reply_context(
context->MakeReplyMessageContext());
int net_result = socket_->Accept(
- &accepted_socket_,
- &accepted_address_,
+ &accepted_socket_, &accepted_address_,
base::Bind(&PepperTCPServerSocketMessageFilter::OnAcceptCompleted,
- base::Unretained(this),
- reply_context));
+ base::Unretained(this), reply_context));
if (net_result != net::ERR_IO_PENDING)
OnAcceptCompleted(reply_context, net_result);
return PP_OK_COMPLETIONPENDING;
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc b/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc
index 17d9f021651..6eb9ecd9c87 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc
@@ -33,8 +33,6 @@
#include "net/socket/ssl_client_socket.h"
#include "net/socket/tcp_client_socket.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
-#include "net/url_request/url_request_context.h"
-#include "net/url_request/url_request_context_getter.h"
#include "ppapi/host/dispatch_host_message.h"
#include "ppapi/host/error_conversion.h"
#include "ppapi/host/ppapi_host.h"
@@ -70,6 +68,7 @@ PepperTCPSocketMessageFilter::PepperTCPSocketMessageFilter(
external_plugin_(host->external_plugin()),
render_process_id_(0),
render_frame_id_(0),
+ binding_(this),
host_(host),
factory_(factory),
instance_(instance),
@@ -107,6 +106,7 @@ PepperTCPSocketMessageFilter::PepperTCPSocketMessageFilter(
external_plugin_(host->external_plugin()),
render_process_id_(0),
render_frame_id_(0),
+ binding_(this),
host_(host),
factory_(nullptr),
instance_(instance),
@@ -214,6 +214,20 @@ void PepperTCPSocketMessageFilter::OnHostDestroyed() {
host_ = nullptr;
}
+void PepperTCPSocketMessageFilter::OnComplete(
+ int result,
+ const base::Optional<net::AddressList>& resolved_addresses) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ binding_.Close();
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&PepperTCPSocketMessageFilter::OnResolveCompleted, this,
+ result, std::move(resolved_addresses)));
+
+ Release(); // Balances AddRef in OnMsgConnect.
+}
+
int32_t PepperTCPSocketMessageFilter::OnMsgBind(
const ppapi::host::HostMessageContext* context,
const PP_NetAddress_Private& net_addr) {
@@ -267,13 +281,24 @@ int32_t PepperTCPSocketMessageFilter::OnMsgConnect(
if (!render_process_host)
return PP_ERROR_FAILED;
auto* storage_partition = render_process_host->GetStoragePartition();
+ // Grab a reference to this class to ensure that it's fully alive if a
+ // connection error occurs (i.e. ref count is higher than 0 and there's no
+ // task from ResourceMessageFilterDeleteTraits to delete this object on the IO
+ // thread pending). Balanced in OnComplete();
+ AddRef();
+
+ network::mojom::ResolveHostClientPtr client_ptr;
+ binding_.Bind(mojo::MakeRequest(&client_ptr));
+ binding_.set_connection_error_handler(
+ base::BindOnce(&PepperTCPSocketMessageFilter::OnComplete,
+ base::Unretained(this), net::ERR_FAILED, base::nullopt));
+ storage_partition->GetNetworkContext()->ResolveHost(
+ net::HostPortPair(host, port), nullptr, std::move(client_ptr));
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::BindOnce(
- &PepperTCPSocketMessageFilter::DoConnect, this,
- context->MakeReplyMessageContext(), host, port,
- base::WrapRefCounted(storage_partition->GetURLRequestContext())));
+ base::BindOnce(&PepperTCPSocketMessageFilter::HostResolvingStarted, this,
+ context->MakeReplyMessageContext()));
return PP_OK_COMPLETIONPENDING;
}
@@ -348,9 +373,8 @@ int32_t PepperTCPSocketMessageFilter::OnMsgSSLHandshake(
const ppapi::host::ReplyMessageContext reply_context(
context->MakeReplyMessageContext());
int net_result = ssl_socket_->Connect(
- base::Bind(&PepperTCPSocketMessageFilter::OnSSLHandshakeCompleted,
- base::Unretained(this),
- reply_context));
+ base::BindOnce(&PepperTCPSocketMessageFilter::OnSSLHandshakeCompleted,
+ base::Unretained(this), reply_context));
if (net_result != net::ERR_IO_PENDING)
OnSSLHandshakeCompleted(reply_context, net_result);
return PP_OK_COMPLETIONPENDING;
@@ -376,20 +400,16 @@ int32_t PepperTCPSocketMessageFilter::OnMsgRead(
int net_result = net::ERR_FAILED;
if (socket_) {
DCHECK_EQ(state_.state(), TCPSocketState::CONNECTED);
- net_result =
- socket_->Read(read_buffer_.get(),
- bytes_to_read,
- base::Bind(&PepperTCPSocketMessageFilter::OnReadCompleted,
- base::Unretained(this),
- reply_context));
+ net_result = socket_->Read(
+ read_buffer_.get(), bytes_to_read,
+ base::BindOnce(&PepperTCPSocketMessageFilter::OnReadCompleted,
+ base::Unretained(this), reply_context));
} else if (ssl_socket_) {
DCHECK_EQ(state_.state(), TCPSocketState::SSL_CONNECTED);
net_result = ssl_socket_->Read(
- read_buffer_.get(),
- bytes_to_read,
- base::Bind(&PepperTCPSocketMessageFilter::OnReadCompleted,
- base::Unretained(this),
- reply_context));
+ read_buffer_.get(), bytes_to_read,
+ base::BindOnce(&PepperTCPSocketMessageFilter::OnReadCompleted,
+ base::Unretained(this), reply_context));
}
if (net_result != net::ERR_IO_PENDING)
OnReadCompleted(reply_context, net_result);
@@ -413,10 +433,10 @@ int32_t PepperTCPSocketMessageFilter::OnMsgWrite(
return PP_ERROR_BADARGUMENT;
}
- write_buffer_base_ = new net::IOBuffer(data_size);
+ write_buffer_base_ = base::MakeRefCounted<net::IOBuffer>(data_size);
memcpy(write_buffer_base_->data(), data.data(), data_size);
- write_buffer_ =
- new net::DrainableIOBuffer(write_buffer_base_.get(), data_size);
+ write_buffer_ = base::MakeRefCounted<net::DrainableIOBuffer>(
+ write_buffer_base_, data_size);
DoWrite(context->MakeReplyMessageContext());
return PP_OK_COMPLETIONPENDING;
}
@@ -463,11 +483,9 @@ int32_t PepperTCPSocketMessageFilter::OnMsgAccept(
ppapi::host::ReplyMessageContext reply_context(
context->MakeReplyMessageContext());
int net_result = socket_->Accept(
- &accepted_socket_,
- &accepted_address_,
+ &accepted_socket_, &accepted_address_,
base::Bind(&PepperTCPSocketMessageFilter::OnAcceptCompleted,
- base::Unretained(this),
- reply_context));
+ base::Unretained(this), reply_context));
if (net_result != net::ERR_IO_PENDING)
OnAcceptCompleted(reply_context, net_result);
return PP_OK_COMPLETIONPENDING;
@@ -621,27 +639,12 @@ void PepperTCPSocketMessageFilter::DoBind(
state_.DoTransition(TCPSocketState::BIND, false);
}
-void PepperTCPSocketMessageFilter::DoConnect(
- const ppapi::host::ReplyMessageContext& context,
- const std::string& host,
- uint16_t port,
- scoped_refptr<net::URLRequestContextGetter> url_request_context_getter) {
+void PepperTCPSocketMessageFilter::HostResolvingStarted(
+ const ppapi::host::ReplyMessageContext& context) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
if (!state_.IsValidTransition(TCPSocketState::CONNECT)) {
- SendConnectError(context, PP_ERROR_FAILED);
- return;
- }
-
- auto* url_request_context =
- url_request_context_getter->GetURLRequestContext();
- if (!url_request_context) {
- SendConnectError(context, PP_ERROR_FAILED);
- return;
- }
-
- net::HostResolver* host_resolver = url_request_context->host_resolver();
- if (!host_resolver) {
+ NOTREACHED() << "This shouldn't be reached since the renderer only tries "
+ << "to connect once.";
SendConnectError(context, PP_ERROR_FAILED);
return;
}
@@ -649,15 +652,7 @@ void PepperTCPSocketMessageFilter::DoConnect(
state_.SetPendingTransition(TCPSocketState::CONNECT);
address_index_ = 0;
address_list_.clear();
- net::HostResolver::RequestInfo request_info(net::HostPortPair(host, port));
-
- int net_result = host_resolver->Resolve(
- request_info, net::DEFAULT_PRIORITY, &address_list_,
- base::Bind(&PepperTCPSocketMessageFilter::OnResolveCompleted,
- base::Unretained(this), context),
- &request_, net::NetLogWithSource());
- if (net_result != net::ERR_IO_PENDING)
- OnResolveCompleted(context, net_result);
+ host_resolve_context_ = context;
}
void PepperTCPSocketMessageFilter::DoConnectWithNetAddress(
@@ -697,60 +692,22 @@ void PepperTCPSocketMessageFilter::DoWrite(
DCHECK(state_.IsConnected());
int net_result = net::ERR_FAILED;
- net::NetworkTrafficAnnotationTag traffic_annotation =
- net::DefineNetworkTrafficAnnotation("pepper_tcp_socket", R"(
- semantics {
- sender: "Pepper TCP Socket"
- description:
- "Pepper plugins use this API to send and receive data over the "
- "network using TCP connections. This inteface is used by Flash and "
- "PDF viewer, and Chrome Apps which use plugins to send/receive TCP "
- "traffic (require Chrome Apps TCP socket permission)."
- trigger:
- "A request from a Pepper plugin."
- data: "Any data that the plugin sends."
- destination: OTHER
- destination_other:
- "Data can be sent to any destination."
- }
- policy {
- cookies_allowed: NO
- setting:
- "These requests cannot be disabled, but will not happen if user "
- "does not use Flash, internal PDF Viewer, or Chrome Apps that use "
- "Pepper interface."
- chrome_policy {
- DefaultPluginsSetting {
- DefaultPluginsSetting: 2
- }
- }
- chrome_policy {
- AlwaysOpenPdfExternally {
- AlwaysOpenPdfExternally: true
- }
- }
- chrome_policy {
- ExtensionInstallBlacklist {
- ExtensionInstallBlacklist: {
- entries: '*'
- }
- }
- }
- })");
if (socket_) {
DCHECK_EQ(state_.state(), TCPSocketState::CONNECTED);
net_result = socket_->Write(
write_buffer_.get(), write_buffer_->BytesRemaining(),
- base::Bind(&PepperTCPSocketMessageFilter::OnWriteCompleted,
- base::Unretained(this), context),
- traffic_annotation);
+ base::BindOnce(&PepperTCPSocketMessageFilter::OnWriteCompleted,
+ base::Unretained(this), context),
+ static_cast<net::NetworkTrafficAnnotationTag>(
+ pepper_socket_utils::PepperTCPNetworkAnnotationTag()));
} else if (ssl_socket_) {
DCHECK_EQ(state_.state(), TCPSocketState::SSL_CONNECTED);
net_result = ssl_socket_->Write(
write_buffer_.get(), write_buffer_->BytesRemaining(),
- base::Bind(&PepperTCPSocketMessageFilter::OnWriteCompleted,
- base::Unretained(this), context),
- traffic_annotation);
+ base::BindOnce(&PepperTCPSocketMessageFilter::OnWriteCompleted,
+ base::Unretained(this), context),
+ static_cast<net::NetworkTrafficAnnotationTag>(
+ pepper_socket_utils::PepperTCPNetworkAnnotationTag()));
}
if (net_result != net::ERR_IO_PENDING)
OnWriteCompleted(context, net_result);
@@ -779,9 +736,14 @@ void PepperTCPSocketMessageFilter::DoListen(
}
void PepperTCPSocketMessageFilter::OnResolveCompleted(
- const ppapi::host::ReplyMessageContext& context,
- int net_result) {
+ int net_result,
+ const base::Optional<net::AddressList>& resolved_addresses) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (!host_resolve_context_.is_valid())
+ return;
+
+ ppapi::host::ReplyMessageContext context = host_resolve_context_;
+ host_resolve_context_ = ppapi::host::ReplyMessageContext();
if (!state_.IsPending(TCPSocketState::CONNECT)) {
DCHECK(state_.state() == TCPSocketState::CLOSED);
@@ -795,6 +757,7 @@ void PepperTCPSocketMessageFilter::OnResolveCompleted(
return;
}
+ address_list_ = resolved_addresses.value();
StartConnect(context);
}
@@ -837,9 +800,8 @@ void PepperTCPSocketMessageFilter::StartConnect(
int net_result = socket_->Connect(
address_list_[address_index_],
- base::Bind(&PepperTCPSocketMessageFilter::OnConnectCompleted,
- base::Unretained(this),
- context));
+ base::BindOnce(&PepperTCPSocketMessageFilter::OnConnectCompleted,
+ base::Unretained(this), context));
if (net_result != net::ERR_IO_PENDING)
OnConnectCompleted(context, net_result);
}
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.h b/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.h
index fec0b7cbf0c..03648b64ef4 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.h
@@ -19,15 +19,16 @@
#include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h"
#include "content/browser/renderer_host/pepper/ssl_context_helper.h"
#include "content/common/content_export.h"
+#include "mojo/public/cpp/bindings/binding.h"
#include "net/base/address_list.h"
#include "net/base/ip_endpoint.h"
-#include "net/dns/host_resolver.h"
#include "net/socket/tcp_socket.h"
#include "ppapi/c/pp_instance.h"
#include "ppapi/c/ppb_tcp_socket.h"
#include "ppapi/c/private/ppb_net_address_private.h"
#include "ppapi/host/resource_message_filter.h"
#include "ppapi/shared_impl/ppb_tcp_socket_shared.h"
+#include "services/network/public/mojom/network_context.mojom.h"
#if defined(OS_CHROMEOS)
#include "chromeos/network/firewall_hole.h"
@@ -38,7 +39,6 @@ namespace net {
class DrainableIOBuffer;
class IOBuffer;
class SSLClientSocket;
-class URLRequestContextGetter;
}
namespace ppapi {
@@ -56,7 +56,8 @@ class ContentBrowserPepperHostFactory;
class CONTENT_EXPORT PepperTCPSocketMessageFilter
: public ppapi::host::ResourceMessageFilter,
- public BrowserPpapiHostImpl::InstanceObserver {
+ public BrowserPpapiHostImpl::InstanceObserver,
+ public network::mojom::ResolveHostClient {
public:
PepperTCPSocketMessageFilter(ContentBrowserPepperHostFactory* factory,
BrowserPpapiHostImpl* host,
@@ -91,6 +92,11 @@ class CONTENT_EXPORT PepperTCPSocketMessageFilter
void OnThrottleStateChanged(bool is_throttled) override;
void OnHostDestroyed() override;
+ // network::mojom::ResolveHostClient overrides.
+ void OnComplete(
+ int result,
+ const base::Optional<net::AddressList>& resolved_addresses) override;
+
int32_t OnMsgBind(const ppapi::host::HostMessageContext* context,
const PP_NetAddress_Private& net_addr);
int32_t OnMsgConnect(const ppapi::host::HostMessageContext* context,
@@ -119,19 +125,16 @@ class CONTENT_EXPORT PepperTCPSocketMessageFilter
void DoBind(const ppapi::host::ReplyMessageContext& context,
const PP_NetAddress_Private& net_addr);
- void DoConnect(
- const ppapi::host::ReplyMessageContext& context,
- const std::string& host,
- uint16_t port,
- scoped_refptr<net::URLRequestContextGetter> url_request_context_getter);
+ void HostResolvingStarted(const ppapi::host::ReplyMessageContext& context);
void DoConnectWithNetAddress(const ppapi::host::ReplyMessageContext& context,
const PP_NetAddress_Private& net_addr);
void DoWrite(const ppapi::host::ReplyMessageContext& context);
void DoListen(const ppapi::host::ReplyMessageContext& context,
int32_t backlog);
- void OnResolveCompleted(const ppapi::host::ReplyMessageContext& context,
- int net_result);
+ void OnResolveCompleted(
+ int net_result,
+ const base::Optional<net::AddressList>& resolved_addresses);
void StartConnect(const ppapi::host::ReplyMessageContext& context);
void OnConnectCompleted(const ppapi::host::ReplyMessageContext& context,
@@ -198,6 +201,10 @@ class CONTENT_EXPORT PepperTCPSocketMessageFilter
int render_process_id_;
int render_frame_id_;
+ // A reference to |this| must always be taken while |binding_| is bound to
+ // ensure that if the error callback is called the object is alive.
+ mojo::Binding<network::mojom::ResolveHostClient> binding_;
+
// The following fields are used only on the IO thread.
// Non-owning ptr.
BrowserPpapiHostImpl* host_;
@@ -237,6 +244,7 @@ class CONTENT_EXPORT PepperTCPSocketMessageFilter
net::AddressList address_list_;
// Where we are in the above list.
size_t address_index_;
+ ppapi::host::ReplyMessageContext host_resolve_context_;
// Non-null unless an SSL connection is requested.
std::unique_ptr<net::TCPSocket> socket_;
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
index 036149f4af4..6f4b48ee188 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_host.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_host.cc
@@ -5,8 +5,8 @@
#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 "base/task_scheduler/post_task.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"
@@ -32,7 +32,7 @@ PepperTrueTypeFontHost::PepperTrueTypeFontHost(
// Initialize the font on a TaskScheduler thread. This must complete before
// using |font_|.
task_runner_ = base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BACKGROUND});
+ {base::MayBlock(), base::TaskPriority::BEST_EFFORT});
SerializedTrueTypeFontDesc* actual_desc =
new SerializedTrueTypeFontDesc(desc);
base::PostTaskAndReplyWithResult(
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc b/chromium/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc
index 141d0b840a2..7a19d458a19 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc
@@ -13,15 +13,20 @@
#include "build/build_config.h"
#include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h"
#include "content/browser/renderer_host/pepper/pepper_socket_utils.h"
+#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/site_instance.h"
+#include "content/public/browser/storage_partition.h"
#include "content/public/common/process_type.h"
#include "content/public/common/socket_permission_request.h"
#include "ipc/ipc_message_macros.h"
+#include "mojo/public/cpp/bindings/interface_request.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/log/net_log_source.h"
-#include "net/socket/udp_socket.h"
+#include "net/traffic_annotation/network_traffic_annotation.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/private/ppb_net_address_private.h"
#include "ppapi/host/dispatch_host_message.h"
@@ -33,6 +38,7 @@
#include "ppapi/proxy/udp_socket_resource_constants.h"
#include "ppapi/shared_impl/private/net_address_private_impl.h"
#include "ppapi/shared_impl/socket_option_data.h"
+#include "services/network/public/mojom/network_context.mojom.h"
#if defined(OS_CHROMEOS)
#include "chromeos/network/firewall_hole.h"
@@ -42,20 +48,23 @@ using ppapi::NetAddressPrivateImpl;
using ppapi::host::NetErrorToPepperError;
using ppapi::proxy::UDPSocketResourceConstants;
+namespace content {
+
namespace {
+const PepperUDPSocketMessageFilter::CreateUDPSocketCallback*
+ g_create_udp_socket_callback_for_testing = nullptr;
+
size_t g_num_udp_filter_instances = 0;
} // namespace
-namespace content {
-
PepperUDPSocketMessageFilter::PendingSend::PendingSend(
const net::IPAddress& address,
int port,
- const scoped_refptr<net::IOBufferWithSize>& buffer,
+ std::vector<uint8_t> data,
const ppapi::host::ReplyMessageContext& context)
- : address(address), port(port), buffer(buffer), context(context) {}
+ : address(address), port(port), data(std::move(data)), context(context) {}
PepperUDPSocketMessageFilter::PendingSend::PendingSend(
const PendingSend& other) = default;
@@ -80,7 +89,13 @@ PepperUDPSocketMessageFilter::PepperUDPSocketMessageFilter(
render_process_id_(0),
render_frame_id_(0),
is_potentially_secure_plugin_context_(
- host->IsPotentiallySecurePluginContext(instance)) {
+ host->IsPotentiallySecurePluginContext(instance)),
+ binding_(this)
+#if defined(OS_CHROMEOS)
+ ,
+ firewall_hole_weak_ptr_factory_(this)
+#endif // defined(OS_CHROMEOS)
+{
++g_num_udp_filter_instances;
DCHECK(host);
@@ -91,15 +106,35 @@ PepperUDPSocketMessageFilter::PepperUDPSocketMessageFilter(
}
PepperUDPSocketMessageFilter::~PepperUDPSocketMessageFilter() {
- Close();
+ DCHECK(closed_);
+ DCHECK(!socket_);
+ DCHECK(!binding_);
--g_num_udp_filter_instances;
}
+void PepperUDPSocketMessageFilter::SetCreateUDPSocketCallbackForTesting(
+ const CreateUDPSocketCallback* create_udp_socket_callback) {
+ DCHECK(!create_udp_socket_callback ||
+ !g_create_udp_socket_callback_for_testing);
+ g_create_udp_socket_callback_for_testing = create_udp_socket_callback;
+}
+
// static
size_t PepperUDPSocketMessageFilter::GetNumInstances() {
return g_num_udp_filter_instances;
}
+void PepperUDPSocketMessageFilter::OnFilterDestroyed() {
+ ResourceMessageFilter::OnFilterDestroyed();
+ // Need to close the socket on the UI thread. Calling Close() also ensures
+ // that future messages will be ignored, so the mojo pipes won't be
+ // re-created, so after Close() runs, |this| can be safely deleted on the IO
+ // thread.
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&PepperUDPSocketMessageFilter::Close, this));
+}
+
scoped_refptr<base::TaskRunner>
PepperUDPSocketMessageFilter::OverrideTaskRunnerForMessage(
const IPC::Message& message) {
@@ -107,7 +142,6 @@ PepperUDPSocketMessageFilter::OverrideTaskRunnerForMessage(
case PpapiHostMsg_UDPSocket_SetOption::ID:
case PpapiHostMsg_UDPSocket_Close::ID:
case PpapiHostMsg_UDPSocket_RecvSlotAvailable::ID:
- return BrowserThread::GetTaskRunnerForThread(BrowserThread::IO);
case PpapiHostMsg_UDPSocket_Bind::ID:
case PpapiHostMsg_UDPSocket_SendTo::ID:
case PpapiHostMsg_UDPSocket_JoinGroup::ID:
@@ -142,14 +176,14 @@ int32_t PepperUDPSocketMessageFilter::OnMsgSetOption(
const ppapi::host::HostMessageContext* context,
PP_UDPSocket_Option name,
const ppapi::SocketOptionData& value) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (closed_)
return PP_ERROR_FAILED;
switch (name) {
case PP_UDPSOCKET_OPTION_ADDRESS_REUSE: {
- if (socket_.get()) {
+ if (socket_) {
// AllowReuseAddress is only effective before Bind().
// Note that this limitation originally comes from Windows, but
// PPAPI tries to provide platform independent APIs.
@@ -172,16 +206,20 @@ int32_t PepperUDPSocketMessageFilter::OnMsgSetOption(
if (!value.GetBool(&boolean_value))
return PP_ERROR_BADARGUMENT;
- // If the socket is already bound, proxy the value to UDPSocket.
- if (socket_.get())
- return NetErrorToPepperError(socket_->SetBroadcast(boolean_value));
+ if (socket_) {
+ socket_->SetBroadcast(
+ boolean_value,
+ CreateCompletionCallback<PpapiPluginMsg_UDPSocket_SetOptionReply>(
+ context));
+ return PP_OK_COMPLETIONPENDING;
+ }
- // UDPSocket instance is not yet created, so remember the value here.
if (boolean_value) {
socket_options_ |= SOCKET_OPTION_BROADCAST;
} else {
socket_options_ &= ~SOCKET_OPTION_BROADCAST;
}
+
return PP_OK;
}
case PP_UDPSOCKET_OPTION_SEND_BUFFER_SIZE: {
@@ -190,15 +228,18 @@ int32_t PepperUDPSocketMessageFilter::OnMsgSetOption(
integer_value > UDPSocketResourceConstants::kMaxSendBufferSize)
return PP_ERROR_BADARGUMENT;
- // If the socket is already bound, proxy the value to UDPSocket.
- if (socket_.get()) {
- return NetErrorToPepperError(
- socket_->SetSendBufferSize(integer_value));
- }
-
- // UDPSocket instance is not yet created, so remember the value here.
socket_options_ |= SOCKET_OPTION_SNDBUF_SIZE;
sndbuf_size_ = integer_value;
+
+ // If the socket is already initialized, proxy the value to UDPSocket.
+ if (socket_) {
+ socket_->SetSendBufferSize(
+ integer_value,
+ CreateCompletionCallback<PpapiPluginMsg_UDPSocket_SetOptionReply>(
+ context));
+ return PP_OK_COMPLETIONPENDING;
+ }
+
return PP_OK;
}
case PP_UDPSOCKET_OPTION_RECV_BUFFER_SIZE: {
@@ -207,15 +248,18 @@ int32_t PepperUDPSocketMessageFilter::OnMsgSetOption(
integer_value > UDPSocketResourceConstants::kMaxReceiveBufferSize)
return PP_ERROR_BADARGUMENT;
- // If the socket is already bound, proxy the value to UDPSocket.
- if (socket_.get()) {
- return NetErrorToPepperError(
- socket_->SetReceiveBufferSize(integer_value));
- }
-
- // UDPSocket instance is not yet created, so remember the value here.
socket_options_ |= SOCKET_OPTION_RCVBUF_SIZE;
rcvbuf_size_ = integer_value;
+
+ // If the socket is already initialized, proxy the value to UDPSocket.
+ if (socket_) {
+ socket_->SetReceiveBufferSize(
+ integer_value,
+ CreateCompletionCallback<PpapiPluginMsg_UDPSocket_SetOptionReply>(
+ context));
+ return PP_OK_COMPLETIONPENDING;
+ }
+
return PP_OK;
}
case PP_UDPSOCKET_OPTION_MULTICAST_LOOP: {
@@ -223,21 +267,22 @@ int32_t PepperUDPSocketMessageFilter::OnMsgSetOption(
if (!value.GetBool(&boolean_value))
return PP_ERROR_BADARGUMENT;
- // If the socket is already bound, proxy the value to UDPSocket.
+ if (boolean_value) {
+ socket_options_ |= SOCKET_OPTION_MULTICAST_LOOP;
+ } else {
+ socket_options_ &= ~SOCKET_OPTION_MULTICAST_LOOP;
+ }
+
+ // If the socket is already initialized, either fail if permissions
+ // disallow multicast, or lie and claim it succeeded, to maintain previous
+ // behavior.
if (socket_) {
if (can_use_multicast_ != PP_OK)
return can_use_multicast_;
- return NetErrorToPepperError(
- socket_->SetMulticastLoopbackMode(boolean_value));
+ return PP_OK;
}
- // UDPSocket instance is not yet created, so remember the value here.
- if (boolean_value) {
- socket_options_ |= SOCKET_OPTION_MULTICAST_LOOP;
- } else {
- socket_options_ &= ~SOCKET_OPTION_MULTICAST_LOOP;
- }
return PP_OK;
}
case PP_UDPSOCKET_OPTION_MULTICAST_TTL: {
@@ -246,18 +291,20 @@ int32_t PepperUDPSocketMessageFilter::OnMsgSetOption(
integer_value < 0 || integer_value > 255)
return PP_ERROR_BADARGUMENT;
- // If the socket is already bound, proxy the value to UDPSocket.
+ // UDPSocket instance is not yet created, so remember the value here.
+ socket_options_ |= SOCKET_OPTION_MULTICAST_TTL;
+ multicast_ttl_ = integer_value;
+
+ // If the socket is already initialized, either fail if permissions
+ // disallow multicast, or lie and claim it succeeded, to maintain previous
+ // behavior.
if (socket_) {
if (can_use_multicast_ != PP_OK)
return can_use_multicast_;
- return NetErrorToPepperError(
- socket_->SetMulticastTimeToLive(integer_value));
+ return PP_OK;
}
- // UDPSocket instance is not yet created, so remember the value here.
- socket_options_ |= SOCKET_OPTION_MULTICAST_TTL;
- multicast_ttl_ = integer_value;
return PP_OK;
}
default: {
@@ -273,6 +320,9 @@ int32_t PepperUDPSocketMessageFilter::OnMsgBind(
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(context);
+ if (closed_ || socket_)
+ return PP_ERROR_FAILED;
+
// Check for permissions to use multicast APIS. This check must be done while
// on the UI thread, so we cache the value here to be used later on.
PP_NetAddress_Private any_addr;
@@ -290,10 +340,83 @@ int32_t PepperUDPSocketMessageFilter::OnMsgBind(
return PP_ERROR_NOACCESS;
}
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&PepperUDPSocketMessageFilter::DoBind, this,
- context->MakeReplyMessageContext(), addr));
+ net::IPAddressBytes address;
+ uint16_t port;
+ if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(addr, &address, &port))
+ return PP_ERROR_ADDRESS_INVALID;
+ net::IPEndPoint end_point(net::IPAddress(address), port);
+
+ network::mojom::UDPSocketOptionsPtr udp_socket_options =
+ network::mojom::UDPSocketOptions::New();
+ udp_socket_options->allow_address_reuse =
+ !!(socket_options_ & SOCKET_OPTION_ADDRESS_REUSE);
+ udp_socket_options->allow_broadcast =
+ !!(socket_options_ & SOCKET_OPTION_BROADCAST);
+ if (socket_options_ & SOCKET_OPTION_SNDBUF_SIZE)
+ udp_socket_options->send_buffer_size = sndbuf_size_;
+ if (socket_options_ & SOCKET_OPTION_RCVBUF_SIZE)
+ udp_socket_options->receive_buffer_size = rcvbuf_size_;
+
+ if (socket_options_ & SOCKET_OPTION_MULTICAST_LOOP) {
+ if (can_use_multicast_ != PP_OK) {
+ // TODO(mmenke): The above line implies |can_use_multicast_| is a PP
+ // error code, but the next line implies it is a net error code. Fix that.
+ return NetErrorToPepperError(can_use_multicast_);
+ }
+ // TODO(mmenke): This doesn't seem to be doing anything - this is the
+ // default behavior.
+ udp_socket_options->multicast_loopback_mode = true;
+ }
+ if (socket_options_ & SOCKET_OPTION_MULTICAST_TTL) {
+ if (can_use_multicast_ != PP_OK) {
+ // TODO(mmenke): The above line implies |can_use_multicast_| is a PP
+ // error code, but the next line implies it is a net error code. Fix that.
+ return NetErrorToPepperError(can_use_multicast_);
+ }
+
+ udp_socket_options->multicast_time_to_live = multicast_ttl_;
+ }
+
+ RenderFrameHost* render_frame_host =
+ RenderFrameHost::FromID(render_process_id_, render_frame_id_);
+ // If the RenderFrameHost has been closed, just fail the request.
+ if (!render_frame_host)
+ return PP_ERROR_NOACCESS;
+
+ network::mojom::UDPSocketReceiverPtr udp_socket_receiver;
+ // Avoid binding the receiver until the socket has been successfully Bound (in
+ // a socket sense), to avoid providing read data to the caller until it has
+ // been told that the socket was bound.
+ network::mojom::UDPSocketReceiverRequest receiver_request =
+ mojo::MakeRequest(&udp_socket_receiver);
+
+ SiteInstance* site_instance = render_frame_host->GetSiteInstance();
+ network::mojom::NetworkContext* network_context =
+ BrowserContext::GetStoragePartition(site_instance->GetBrowserContext(),
+ site_instance)
+ ->GetNetworkContext();
+ if (g_create_udp_socket_callback_for_testing) {
+ g_create_udp_socket_callback_for_testing->Run(
+ network_context, mojo::MakeRequest(&socket_),
+ std::move(udp_socket_receiver));
+ } else {
+ network_context->CreateUDPSocket(mojo::MakeRequest(&socket_),
+ std::move(udp_socket_receiver));
+ }
+
+ ppapi::host::ReplyMessageContext reply_context =
+ context->MakeReplyMessageContext();
+ // Watch the socket for errors during the the Bind call.
+ socket_.set_connection_error_handler(
+ base::BindOnce(&PepperUDPSocketMessageFilter::SendBindError,
+ base::Unretained(this), reply_context, PP_ERROR_FAILED));
+
+ // This is the actual socket Bind call (i.e., not a Mojo Bind call).
+ socket_->Bind(end_point, std::move(udp_socket_options),
+ base::BindOnce(&PepperUDPSocketMessageFilter::DoBindCallback,
+ base::Unretained(this),
+ std::move(receiver_request), reply_context));
+
return PP_OK_COMPLETIONPENDING;
}
@@ -304,6 +427,11 @@ int32_t PepperUDPSocketMessageFilter::OnMsgSendTo(
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(context);
+ // Check |binding_| instead of |socket_| because |binding_| is only set
+ // after the Bind() call completes.
+ if (closed_ || !binding_)
+ return PP_ERROR_FAILED;
+
SocketPermissionRequest request =
pepper_socket_utils::CreateSocketPermissionRequest(
SocketPermissionRequest::UDP_SEND_TO, addr);
@@ -315,32 +443,61 @@ int32_t PepperUDPSocketMessageFilter::OnMsgSendTo(
return PP_ERROR_NOACCESS;
}
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&PepperUDPSocketMessageFilter::DoSendTo, this,
- context->MakeReplyMessageContext(), data, addr));
+ // Make sure a malicious plugin can't queue up an unlimited number of buffers.
+ size_t num_pending_sends = pending_sends_.size();
+ if (num_pending_sends == UDPSocketResourceConstants::kPluginSendBufferSlots) {
+ return PP_ERROR_FAILED;
+ }
+
+ size_t num_bytes = data.size();
+ if (num_bytes == 0 ||
+ num_bytes >
+ static_cast<size_t>(UDPSocketResourceConstants::kMaxWriteSize)) {
+ // Size of |data| is checked on the plugin side.
+ NOTREACHED();
+ return PP_ERROR_BADARGUMENT;
+ }
+
+ net::IPAddressBytes address;
+ uint16_t port;
+ if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(addr, &address, &port)) {
+ return PP_ERROR_ADDRESS_INVALID;
+ }
+
+ const uint8_t* data_ptr = reinterpret_cast<const uint8_t*>(data.data());
+ std::vector<uint8_t> data_vector(data_ptr, data_ptr + num_bytes);
+
+ pending_sends_.push(PendingSend(net::IPAddress(address), port,
+ std::move(data_vector),
+ context->MakeReplyMessageContext()));
+ // Can only start the send if there isn't another send pending.
+ if (num_pending_sends == 0)
+ StartPendingSend();
return PP_OK_COMPLETIONPENDING;
}
int32_t PepperUDPSocketMessageFilter::OnMsgClose(
const ppapi::host::HostMessageContext* context) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
Close();
return PP_OK;
}
int32_t PepperUDPSocketMessageFilter::OnMsgRecvSlotAvailable(
const ppapi::host::HostMessageContext* context) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (remaining_recv_slots_ <
UDPSocketResourceConstants::kPluginReceiveBufferSlots) {
- remaining_recv_slots_++;
- }
+ // If the pipe was closed, but the consumer has not yet closed the UDP
+ // socket, keep the read buffer filled with errors.
+ if (!binding_) {
+ PepperUDPSocketMessageFilter::SendRecvFromError(PP_ERROR_FAILED);
+ return PP_OK;
+ }
- if (!recvfrom_buffer_.get() && !closed_ && socket_.get()) {
- DCHECK_EQ(1u, remaining_recv_slots_);
- DoRecvFrom();
+ remaining_recv_slots_++;
+ socket_->ReceiveMore(1);
}
return PP_OK;
@@ -364,7 +521,11 @@ int32_t PepperUDPSocketMessageFilter::OnMsgJoinGroup(
if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(addr, &group, &port))
return PP_ERROR_ADDRESS_INVALID;
- return NetErrorToPepperError(socket_->JoinGroup(net::IPAddress(group)));
+ socket_->JoinGroup(
+ net::IPAddress(group),
+ CreateCompletionCallback<PpapiPluginMsg_UDPSocket_SetOptionReply>(
+ context));
+ return PP_OK_COMPLETIONPENDING;
}
int32_t PepperUDPSocketMessageFilter::OnMsgLeaveGroup(
@@ -385,309 +546,155 @@ int32_t PepperUDPSocketMessageFilter::OnMsgLeaveGroup(
if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(addr, &group, &port))
return PP_ERROR_ADDRESS_INVALID;
- return NetErrorToPepperError(socket_->LeaveGroup(net::IPAddress(group)));
+ socket_->LeaveGroup(
+ net::IPAddress(group),
+ CreateCompletionCallback<PpapiPluginMsg_UDPSocket_LeaveGroupReply>(
+ context));
+ return PP_OK_COMPLETIONPENDING;
}
-void PepperUDPSocketMessageFilter::DoBind(
+void PepperUDPSocketMessageFilter::DoBindCallback(
+ network::mojom::UDPSocketReceiverRequest receiver_request,
const ppapi::host::ReplyMessageContext& context,
- const PP_NetAddress_Private& addr) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ int result,
+ const base::Optional<net::IPEndPoint>& local_addr_out) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
- if (closed_ || socket_.get()) {
- SendBindError(context, PP_ERROR_FAILED);
+ if (result != net::OK) {
+ SendBindError(context, NetErrorToPepperError(result));
return;
}
- auto socket = std::make_unique<net::UDPSocket>(
- net::DatagramSocket::DEFAULT_BIND, nullptr, net::NetLogSource());
-
- net::IPAddressBytes address;
- uint16_t port;
- if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(addr, &address, &port)) {
- SendBindError(context, PP_ERROR_ADDRESS_INVALID);
- return;
- }
- net::IPEndPoint end_point(net::IPAddress(address), port);
- {
- int net_result = socket->Open(end_point.GetFamily());
- if (net_result != net::OK) {
- SendBindError(context, NetErrorToPepperError(net_result));
- return;
- }
- }
-
- if (socket_options_ & SOCKET_OPTION_ADDRESS_REUSE) {
- int net_result = socket->AllowAddressReuse();
- if (net_result != net::OK) {
- SendBindError(context, NetErrorToPepperError(net_result));
- return;
- }
- }
- if (socket_options_ & SOCKET_OPTION_BROADCAST) {
- int net_result = socket->SetBroadcast(true);
- if (net_result != net::OK) {
- SendBindError(context, NetErrorToPepperError(net_result));
- return;
- }
- }
- if (socket_options_ & SOCKET_OPTION_SNDBUF_SIZE) {
- int net_result = socket->SetSendBufferSize(sndbuf_size_);
- if (net_result != net::OK) {
- SendBindError(context, NetErrorToPepperError(net_result));
- return;
- }
- }
- if (socket_options_ & SOCKET_OPTION_RCVBUF_SIZE) {
- int net_result = socket->SetReceiveBufferSize(rcvbuf_size_);
- if (net_result != net::OK) {
- SendBindError(context, NetErrorToPepperError(net_result));
- return;
- }
- }
- if (socket_options_ & SOCKET_OPTION_MULTICAST_LOOP) {
- if (can_use_multicast_ != PP_OK) {
- SendBindError(context, NetErrorToPepperError(can_use_multicast_));
- return;
- }
-
- int net_result = socket->SetMulticastLoopbackMode(true);
- if (net_result != net::OK) {
- SendBindError(context, NetErrorToPepperError(net_result));
- return;
- }
- }
- if (socket_options_ & SOCKET_OPTION_MULTICAST_TTL) {
- if (can_use_multicast_ != PP_OK) {
- SendBindError(context, NetErrorToPepperError(can_use_multicast_));
- return;
- }
-
- int net_result = socket->SetMulticastTimeToLive(multicast_ttl_);
- if (net_result != net::OK) {
- SendBindError(context, NetErrorToPepperError(net_result));
- return;
- }
- }
-
- {
- int net_result = socket->Bind(end_point);
- if (net_result != net::OK) {
- SendBindError(context, NetErrorToPepperError(net_result));
- return;
- }
- }
-
- net::IPEndPoint bound_address;
- {
- int net_result = socket->GetLocalAddress(&bound_address);
- if (net_result != net::OK) {
- SendBindError(context, NetErrorToPepperError(net_result));
- return;
- }
- }
-
PP_NetAddress_Private net_address = NetAddressPrivateImpl::kInvalidNetAddress;
- if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
- bound_address.address().bytes(), bound_address.port(),
- &net_address)) {
+ if (!local_addr_out || !NetAddressPrivateImpl::IPEndPointToNetAddress(
+ local_addr_out->address().bytes(),
+ local_addr_out->port(), &net_address)) {
SendBindError(context, PP_ERROR_ADDRESS_INVALID);
return;
}
#if defined(OS_CHROMEOS)
- OpenFirewallHole(
- bound_address,
- base::Bind(&PepperUDPSocketMessageFilter::OnBindComplete, this,
- base::Passed(&socket), context, net_address));
-#else
- OnBindComplete(std::move(socket), context, net_address);
-#endif
+ pepper_socket_utils::OpenUDPFirewallHole(
+ *local_addr_out,
+ base::BindRepeating(&PepperUDPSocketMessageFilter::OnFirewallHoleOpened,
+ firewall_hole_weak_ptr_factory_.GetWeakPtr(),
+ base::Passed(std::move(receiver_request)), context,
+ net_address));
+#else // !defined(OS_CHROMEOS)
+ OnBindComplete(std::move(receiver_request), context, net_address);
+#endif // !defined(OS_CHROMEOS)
}
void PepperUDPSocketMessageFilter::OnBindComplete(
- std::unique_ptr<net::UDPSocket> socket,
+ network::mojom::UDPSocketReceiverRequest receiver_request,
const ppapi::host::ReplyMessageContext& context,
const PP_NetAddress_Private& net_address) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- socket_.swap(socket);
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(socket_);
+
SendBindReply(context, PP_OK, net_address);
- DoRecvFrom();
+ binding_.Bind(std::move(receiver_request));
+ binding_.set_connection_error_handler(base::BindOnce(
+ &PepperUDPSocketMessageFilter::PipeClosed, base::Unretained(this)));
+ socket_.set_connection_error_handler(base::BindOnce(
+ &PepperUDPSocketMessageFilter::PipeClosed, base::Unretained(this)));
+ socket_->ReceiveMore(UDPSocketResourceConstants::kPluginReceiveBufferSlots);
}
#if defined(OS_CHROMEOS)
-void PepperUDPSocketMessageFilter::OpenFirewallHole(
- const net::IPEndPoint& local_address,
- base::Closure bind_complete) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- pepper_socket_utils::FirewallHoleOpenCallback callback = base::Bind(
- &PepperUDPSocketMessageFilter::OnFirewallHoleOpened, this, bind_complete);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(&pepper_socket_utils::OpenUDPFirewallHole, local_address,
- callback));
-}
-
void PepperUDPSocketMessageFilter::OnFirewallHoleOpened(
- base::Closure bind_complete,
+ network::mojom::UDPSocketReceiverRequest receiver_request,
+ const ppapi::host::ReplyMessageContext& context,
+ const PP_NetAddress_Private& net_address,
std::unique_ptr<chromeos::FirewallHole> hole) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
LOG_IF(WARNING, !hole.get()) << "Firewall hole could not be opened.";
firewall_hole_.reset(hole.release());
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, bind_complete);
+ OnBindComplete(std::move(receiver_request), context, net_address);
}
#endif // defined(OS_CHROMEOS)
-void PepperUDPSocketMessageFilter::DoRecvFrom() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(!closed_);
- DCHECK(socket_.get());
- DCHECK(!recvfrom_buffer_.get());
- DCHECK_GT(remaining_recv_slots_, 0u);
-
- recvfrom_buffer_ =
- new net::IOBuffer(UDPSocketResourceConstants::kMaxReadSize);
-
- // Use base::Unretained(this), so that the lifespan of this object doesn't
- // have to last until the callback is called.
- // It is safe to do so because |socket_| is owned by this object. If this
- // object gets destroyed (and so does |socket_|), the callback won't be
- // called.
- int net_result = socket_->RecvFrom(
- recvfrom_buffer_.get(), UDPSocketResourceConstants::kMaxReadSize,
- &recvfrom_address_,
- base::Bind(&PepperUDPSocketMessageFilter::OnRecvFromCompleted,
- base::Unretained(this)));
- if (net_result != net::ERR_IO_PENDING)
- OnRecvFromCompleted(net_result);
-}
-
-void PepperUDPSocketMessageFilter::DoSendTo(
- const ppapi::host::ReplyMessageContext& context,
- const std::string& data,
- const PP_NetAddress_Private& addr) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(socket_.get());
-
- if (closed_ || !socket_.get()) {
- SendSendToError(context, PP_ERROR_FAILED);
- return;
- }
-
- size_t num_bytes = data.size();
- if (num_bytes == 0 ||
- num_bytes >
- static_cast<size_t>(UDPSocketResourceConstants::kMaxWriteSize)) {
- // Size of |data| is checked on the plugin side.
- NOTREACHED();
- SendSendToError(context, PP_ERROR_BADARGUMENT);
- return;
- }
-
- net::IPAddressBytes address;
- uint16_t port;
- if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(addr, &address, &port)) {
- SendSendToError(context, PP_ERROR_ADDRESS_INVALID);
- return;
- }
-
- scoped_refptr<net::IOBufferWithSize> buffer(
- new net::IOBufferWithSize(num_bytes));
- memcpy(buffer->data(), data.data(), num_bytes);
-
- // Make sure a malicious plugin can't queue up an unlimited number of buffers.
- size_t num_pending_sends = pending_sends_.size();
- if (num_pending_sends == UDPSocketResourceConstants::kPluginSendBufferSlots) {
- SendSendToError(context, PP_ERROR_FAILED);
- return;
- }
-
- pending_sends_.push(
- PendingSend(net::IPAddress(address), port, buffer, context));
- // If there are other sends pending, we can't start yet.
- if (num_pending_sends)
- return;
- int net_result = StartPendingSend();
- if (net_result != net::ERR_IO_PENDING)
- FinishPendingSend(net_result);
-}
-
-int PepperUDPSocketMessageFilter::StartPendingSend() {
+void PepperUDPSocketMessageFilter::StartPendingSend() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(!pending_sends_.empty());
+ DCHECK(socket_);
+
const PendingSend& pending_send = pending_sends_.front();
// See OnMsgRecvFrom() for the reason why we use base::Unretained(this)
// when calling |socket_| methods.
- int net_result = socket_->SendTo(
- pending_send.buffer.get(),
- pending_send.buffer->size(),
+ socket_->SendTo(
net::IPEndPoint(pending_send.address, pending_send.port),
- base::Bind(&PepperUDPSocketMessageFilter::OnSendToCompleted,
- base::Unretained(this)));
- return net_result;
+ pending_send.data, pepper_socket_utils::PepperUDPNetworkAnnotationTag(),
+ base::BindOnce(&PepperUDPSocketMessageFilter::OnSendToCompleted,
+ base::Unretained(this)));
}
void PepperUDPSocketMessageFilter::Close() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (socket_.get() && !closed_)
- socket_->Close();
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ socket_.reset();
+ binding_.Close();
closed_ = true;
}
-void PepperUDPSocketMessageFilter::OnRecvFromCompleted(int net_result) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(recvfrom_buffer_.get());
+void PepperUDPSocketMessageFilter::OnReceived(
+ int result,
+ const base::Optional<net::IPEndPoint>& src_addr,
+ base::Optional<base::span<const uint8_t>> data) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(!closed_);
- int32_t pp_result = NetErrorToPepperError(net_result);
+ int32_t pp_result = NetErrorToPepperError(result);
// Convert IPEndPoint we get back from RecvFrom to a PP_NetAddress_Private
// to send back.
PP_NetAddress_Private addr = NetAddressPrivateImpl::kInvalidNetAddress;
- if (pp_result >= 0 &&
- !NetAddressPrivateImpl::IPEndPointToNetAddress(
- recvfrom_address_.address().bytes(), recvfrom_address_.port(),
- &addr)) {
+ if (pp_result == PP_OK &&
+ (!src_addr ||
+ !NetAddressPrivateImpl::IPEndPointToNetAddress(
+ src_addr->address().bytes(), src_addr->port(), &addr))) {
pp_result = PP_ERROR_ADDRESS_INVALID;
}
- if (pp_result >= 0) {
- SendRecvFromResult(PP_OK, std::string(recvfrom_buffer_->data(), pp_result),
- addr);
+ if (pp_result == PP_OK) {
+ std::string data_string;
+ if (data) {
+ data_string = std::string(reinterpret_cast<const char*>(data->data()),
+ data->size());
+ }
+ SendRecvFromResult(PP_OK, data_string, addr);
} else {
SendRecvFromError(pp_result);
}
- recvfrom_buffer_ = nullptr;
-
- DCHECK_GT(remaining_recv_slots_, 0u);
- remaining_recv_slots_--;
-
- if (remaining_recv_slots_ > 0 && !closed_ && socket_.get())
- DoRecvFrom();
+ // This should always be the case, but best to protect against a broken /
+ // taken over network service.
+ if (remaining_recv_slots_ > 0)
+ remaining_recv_slots_--;
}
void PepperUDPSocketMessageFilter::OnSendToCompleted(int net_result) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
FinishPendingSend(net_result);
- // Start pending sends until none are left or a send doesn't complete.
- while (!pending_sends_.empty()) {
- net_result = StartPendingSend();
- if (net_result == net::ERR_IO_PENDING)
- break;
- FinishPendingSend(net_result);
- }
+ if (!pending_sends_.empty())
+ StartPendingSend();
}
void PepperUDPSocketMessageFilter::FinishPendingSend(int net_result) {
DCHECK(!pending_sends_.empty());
const PendingSend& pending_send = pending_sends_.front();
int32_t pp_result = NetErrorToPepperError(net_result);
- if (pp_result < 0)
+ if (pp_result < 0) {
SendSendToError(pending_send.context, pp_result);
- else
- SendSendToReply(pending_send.context, PP_OK, pp_result);
+ } else {
+ // The cast should be safe because of the
+ // UDPSocketResourceConstants::kMaxSendBufferSize before enqueuing the send.
+ SendSendToReply(pending_send.context, PP_OK,
+ static_cast<int>(pending_send.data.size()));
+ }
pending_sends_.pop();
}
@@ -708,6 +715,19 @@ void PepperUDPSocketMessageFilter::SendRecvFromResult(
int32_t result,
const std::string& data,
const PP_NetAddress_Private& addr) {
+ // Unlike SendReply, which is safe to call on any thread, SendUnsolicitedReply
+ // calls are only safe to make on the IO thread.
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(
+ &PepperUDPSocketMessageFilter::SendRecvFromResultOnIOThread, this,
+ result, data, addr));
+}
+
+void PepperUDPSocketMessageFilter::SendRecvFromResultOnIOThread(
+ int32_t result,
+ const std::string& data,
+ const PP_NetAddress_Private& addr) {
if (resource_host()) {
resource_host()->host()->SendUnsolicitedReply(
resource_host()->pp_resource(),
@@ -727,6 +747,12 @@ void PepperUDPSocketMessageFilter::SendSendToReply(
void PepperUDPSocketMessageFilter::SendBindError(
const ppapi::host::ReplyMessageContext& context,
int32_t result) {
+ socket_.reset();
+#if defined(OS_CHROMEOS)
+ // In the unlikely case that this is due to a Mojo error while trying to open
+ // a hole in the firewall on ChromeOS, abandon opening a hole in the firewall.
+ firewall_hole_weak_ptr_factory_.InvalidateWeakPtrs();
+#endif // !defined(OS_CHROMEOS)
SendBindReply(context, result, NetAddressPrivateImpl::kInvalidNetAddress);
}
@@ -742,6 +768,19 @@ void PepperUDPSocketMessageFilter::SendSendToError(
SendSendToReply(context, result, 0);
}
+void PepperUDPSocketMessageFilter::PipeClosed() {
+ Close();
+
+ while (!pending_sends_.empty())
+ FinishPendingSend(PP_ERROR_FAILED);
+
+ // Any reads should fail, after a pipe error.
+ while (remaining_recv_slots_ > 0) {
+ --remaining_recv_slots_;
+ SendRecvFromError(PP_ERROR_FAILED);
+ }
+}
+
int32_t PepperUDPSocketMessageFilter::CanUseMulticastAPI(
const PP_NetAddress_Private& addr) {
// Check for plugin permissions.
@@ -759,4 +798,29 @@ int32_t PepperUDPSocketMessageFilter::CanUseMulticastAPI(
return PP_OK;
}
+template <class ReturnMessage>
+base::OnceCallback<void(int result)>
+PepperUDPSocketMessageFilter::CreateCompletionCallback(
+ const ppapi::host::HostMessageContext* context) {
+ std::unique_ptr<int> result = std::make_unique<int>(net::ERR_FAILED);
+ int* result_ptr = result.get();
+ base::ScopedClosureRunner closure_runner(
+ base::BindOnce(&PepperUDPSocketMessageFilter::ReturnResult<ReturnMessage>,
+ base::Unretained(this), context->MakeReplyMessageContext(),
+ base::Passed(std::move(result))));
+ return base::BindOnce(
+ [](base::ScopedClosureRunner closure_runner, int* result_ptr,
+ int net_result) { *result_ptr = net_result; },
+ std::move(closure_runner), result_ptr);
+}
+
+template <class ReturnMessage>
+void PepperUDPSocketMessageFilter::ReturnResult(
+ const ppapi::host::ReplyMessageContext& context,
+ std::unique_ptr<int> result) {
+ ppapi::host::ReplyMessageContext reply_context(context);
+ reply_context.params.set_result(NetErrorToPepperError(*result));
+ SendReply(reply_context, ReturnMessage());
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.h b/chromium/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.h
index 37121831a0d..1e43afe7675 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.h
@@ -6,26 +6,29 @@
#define CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_UDP_SOCKET_MESSAGE_FILTER_H_
#include <stddef.h>
+#include <stdint.h>
#include <memory>
#include <string>
+#include <vector>
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/containers/queue.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
#include "build/build_config.h"
#include "content/common/content_export.h"
#include "content/public/common/process_type.h"
-#include "net/base/completion_callback.h"
+#include "mojo/public/cpp/bindings/binding.h"
#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
-#include "net/socket/udp_socket.h"
#include "ppapi/c/pp_instance.h"
#include "ppapi/c/pp_stdint.h"
#include "ppapi/c/ppb_udp_socket.h"
#include "ppapi/host/resource_message_filter.h"
+#include "services/network/public/mojom/udp_socket.mojom.h"
struct PP_NetAddress_Private;
@@ -34,11 +37,6 @@ struct PP_NetAddress_Private;
#include "content/public/browser/browser_thread.h"
#endif // defined(OS_CHROMEOS)
-namespace net {
-class IOBuffer;
-class IOBufferWithSize;
-}
-
namespace ppapi {
class SocketOptionData;
@@ -48,17 +46,32 @@ struct ReplyMessageContext;
}
}
+namespace network {
+namespace mojom {
+class NetworkContext;
+}
+} // namespace network
+
namespace content {
class BrowserPpapiHostImpl;
class CONTENT_EXPORT PepperUDPSocketMessageFilter
- : public ppapi::host::ResourceMessageFilter {
+ : public ppapi::host::ResourceMessageFilter,
+ public network::mojom::UDPSocketReceiver {
public:
PepperUDPSocketMessageFilter(BrowserPpapiHostImpl* host,
PP_Instance instance,
bool private_api);
+ using CreateUDPSocketCallback = base::RepeatingCallback<void(
+ network::mojom::NetworkContext* network_context,
+ network::mojom::UDPSocketRequest socket_request,
+ network::mojom::UDPSocketReceiverPtr socket_receiver)>;
+
+ static void SetCreateUDPSocketCallbackForTesting(
+ const CreateUDPSocketCallback* create_udp_socket_callback);
+
static size_t GetNumInstances();
protected:
@@ -77,18 +90,19 @@ class CONTENT_EXPORT PepperUDPSocketMessageFilter
struct PendingSend {
PendingSend(const net::IPAddress& address,
int port,
- const scoped_refptr<net::IOBufferWithSize>& buffer,
+ std::vector<uint8_t> data,
const ppapi::host::ReplyMessageContext& context);
PendingSend(const PendingSend& other);
~PendingSend();
net::IPAddress address;
int port;
- scoped_refptr<net::IOBufferWithSize> buffer;
+ std::vector<uint8_t> data;
ppapi::host::ReplyMessageContext context;
};
// ppapi::host::ResourceMessageFilter overrides.
+ void OnFilterDestroyed() override;
scoped_refptr<base::TaskRunner> OverrideTaskRunnerForMessage(
const IPC::Message& message) override;
int32_t OnResourceMessageReceived(
@@ -111,25 +125,28 @@ class CONTENT_EXPORT PepperUDPSocketMessageFilter
int32_t OnMsgLeaveGroup(const ppapi::host::HostMessageContext* context,
const PP_NetAddress_Private& addr);
- void DoBind(const ppapi::host::ReplyMessageContext& context,
- const PP_NetAddress_Private& addr);
- void OnBindComplete(std::unique_ptr<net::UDPSocket> socket,
+ void DoBindCallback(network::mojom::UDPSocketReceiverRequest receiver_request,
+ const ppapi::host::ReplyMessageContext& context,
+ int result,
+ const base::Optional<net::IPEndPoint>& local_addr_out);
+ void OnBindComplete(network::mojom::UDPSocketReceiverRequest receiver_request,
const ppapi::host::ReplyMessageContext& context,
const PP_NetAddress_Private& net_address);
#if defined(OS_CHROMEOS)
- void OpenFirewallHole(const net::IPEndPoint& local_address,
- base::Closure bind_complete);
- void OnFirewallHoleOpened(base::Closure bind_complete,
- std::unique_ptr<chromeos::FirewallHole> hole);
+ void OnFirewallHoleOpened(
+ network::mojom::UDPSocketReceiverRequest receiver_request,
+ const ppapi::host::ReplyMessageContext& context,
+ const PP_NetAddress_Private& net_address,
+ std::unique_ptr<chromeos::FirewallHole> hole);
#endif // defined(OS_CHROMEOS)
- void DoRecvFrom();
- void DoSendTo(const ppapi::host::ReplyMessageContext& context,
- const std::string& data,
- const PP_NetAddress_Private& addr);
- int StartPendingSend();
+ void StartPendingSend();
void Close();
- void OnRecvFromCompleted(int net_result);
+ // network::mojom::UDPSocketReceiver override:
+ void OnReceived(int result,
+ const base::Optional<net::IPEndPoint>& src_addr,
+ base::Optional<base::span<const uint8_t>> data) override;
+
void OnSendToCompleted(int net_result);
void FinishPendingSend(int net_result);
@@ -139,6 +156,9 @@ class CONTENT_EXPORT PepperUDPSocketMessageFilter
void SendRecvFromResult(int32_t result,
const std::string& data,
const PP_NetAddress_Private& addr);
+ void SendRecvFromResultOnIOThread(int32_t result,
+ const std::string& data,
+ const PP_NetAddress_Private& addr);
void SendSendToReply(const ppapi::host::ReplyMessageContext& context,
int32_t result,
int32_t bytes_written);
@@ -148,9 +168,18 @@ class CONTENT_EXPORT PepperUDPSocketMessageFilter
void SendRecvFromError(int32_t result);
void SendSendToError(const ppapi::host::ReplyMessageContext& context,
int32_t result);
+ void PipeClosed();
int32_t CanUseMulticastAPI(const PP_NetAddress_Private& addr);
+ template <class ReturnMessage>
+ base::OnceCallback<void(int result)> CreateCompletionCallback(
+ const ppapi::host::HostMessageContext* context);
+
+ template <class ReturnMessage>
+ void ReturnResult(const ppapi::host::ReplyMessageContext& context,
+ std::unique_ptr<int> result);
+
// Bitwise-or of SocketOption flags. This stores the state about whether
// each option is set before Bind() is called.
int socket_options_;
@@ -163,20 +192,10 @@ class CONTENT_EXPORT PepperUDPSocketMessageFilter
int multicast_ttl_;
int32_t can_use_multicast_;
- std::unique_ptr<net::UDPSocket> socket_;
bool closed_;
-#if defined(OS_CHROMEOS)
- std::unique_ptr<chromeos::FirewallHole,
- content::BrowserThread::DeleteOnUIThread>
- firewall_hole_;
-#endif // defined(OS_CHROMEOS)
-
- scoped_refptr<net::IOBuffer> recvfrom_buffer_;
base::queue<PendingSend> pending_sends_;
- net::IPEndPoint recvfrom_address_;
-
size_t remaining_recv_slots_;
bool external_plugin_;
@@ -187,6 +206,27 @@ class CONTENT_EXPORT PepperUDPSocketMessageFilter
const bool is_potentially_secure_plugin_context_;
+ // Bound (in a Mojo sense) when binding (in a network sense) starts. Closed in
+ // Close() and on Mojo pipe errors. Must only be accessed (and destroyed) on
+ // UI thread.
+ network::mojom::UDPSocketPtr socket_;
+
+ // Bound (in a Mojo sense) when binding (in a network sense) completes.
+ // Binding late avoids receiving data when still setting up the socket. Closed
+ // in Close() and on Mojo pipe errors. Must only be accessed (and destroyed)
+ // on UI thread.
+ mojo::Binding<network::mojom::UDPSocketReceiver> binding_;
+
+#if defined(OS_CHROMEOS)
+ std::unique_ptr<chromeos::FirewallHole,
+ content::BrowserThread::DeleteOnUIThread>
+ firewall_hole_;
+ // Allows for cancellation of opening a hole in the firewall in the case the
+ // network service crashes.
+ base::WeakPtrFactory<PepperUDPSocketMessageFilter>
+ firewall_hole_weak_ptr_factory_;
+#endif // defined(OS_CHROMEOS)
+
DISALLOW_COPY_AND_ASSIGN(PepperUDPSocketMessageFilter);
};
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 fe6117100bf..1e5fdb2bfa5 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
@@ -65,7 +65,7 @@ class CONTENT_EXPORT RenderFrameMetadataProviderImpl
const cc::RenderFrameMetadata& metadata) override;
void OnFrameSubmissionForTesting(uint32_t frame_token) override;
- base::ObserverList<Observer> observers_;
+ base::ObserverList<Observer>::Unchecked observers_;
cc::RenderFrameMetadata last_render_frame_metadata_;
diff --git a/chromium/content/browser/renderer_host/render_message_filter.cc b/chromium/content/browser/renderer_host/render_message_filter.cc
index 8ca3b5ed1ff..cc6d5b62567 100644
--- a/chromium/content/browser/renderer_host/render_message_filter.cc
+++ b/chromium/content/browser/renderer_host/render_message_filter.cc
@@ -18,7 +18,7 @@
#include "base/numerics/safe_math.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "base/threading/thread.h"
#include "build/build_config.h"
#include "components/download/public/common/download_stats.h"
@@ -29,6 +29,9 @@
#include "content/browser/cache_storage/cache_storage_cache_handle.h"
#include "content/browser/cache_storage/cache_storage_context_impl.h"
#include "content/browser/cache_storage/cache_storage_manager.h"
+#include "content/browser/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"
#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "content/browser/gpu/gpu_process_host.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
@@ -45,6 +48,8 @@
#include "content/public/browser/browser_context.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/resource_context.h"
+#include "content/public/browser/storage_partition.h"
+#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/context_menu_params.h"
#include "content/public/common/url_constants.h"
@@ -59,6 +64,7 @@
#include "net/http/http_cache.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
+#include "services/network/public/mojom/network_context.mojom.h"
#include "url/gurl.h"
#include "url/origin.h"
@@ -88,6 +94,26 @@ const uint32_t kRenderFilteredMessageClasses[] = {ViewMsgStart};
void NoOpCacheStorageErrorCallback(CacheStorageCacheHandle cache_handle,
CacheStorageError error) {}
+base::Optional<url::Origin> GetRendererOrigin(const GURL& url,
+ int render_process_id) {
+ GURL requesting_url =
+ ChildProcessSecurityPolicyImpl::GetInstance()->GetOriginLock(
+ render_process_id);
+
+ if (!requesting_url.is_valid() || !url.is_valid())
+ return base::nullopt;
+
+ url::Origin origin = url::Origin::Create(requesting_url);
+
+ // Don't cache the code corresponding to unique origins. The same-origin
+ // checks should always fail for unique origins but the serialized value of
+ // unique origins does not ensure this.
+ if (origin.unique())
+ return base::nullopt;
+
+ return origin;
+}
+
} // namespace
RenderMessageFilter::RenderMessageFilter(
@@ -96,7 +122,8 @@ RenderMessageFilter::RenderMessageFilter(
net::URLRequestContextGetter* request_context,
RenderWidgetHelper* render_widget_helper,
MediaInternals* media_internals,
- CacheStorageContextImpl* cache_storage_context)
+ CacheStorageContextImpl* cache_storage_context,
+ GeneratedCodeCacheContext* generated_code_cache_context)
: BrowserMessageFilter(kRenderFilteredMessageClasses,
arraysize(kRenderFilteredMessageClasses)),
BrowserAssociatedInterface<mojom::RenderMessageFilter>(this, this),
@@ -107,6 +134,7 @@ RenderMessageFilter::RenderMessageFilter(
render_process_id_(render_process_id),
media_internals_(media_internals),
cache_storage_context_(cache_storage_context),
+ generated_code_cache_context_(generated_code_cache_context),
weak_ptr_factory_(this) {
DCHECK(request_context_.get());
@@ -209,22 +237,69 @@ void RenderMessageFilter::DidGenerateCacheableMetadata(
return;
}
- net::HttpCache* cache = request_context_->GetURLRequestContext()->
- http_transaction_factory()->GetCache();
- if (!cache)
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (!base::FeatureList::IsEnabled(features::kIsolatedCodeCache)) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&RenderMessageFilter::DidGenerateCacheableMetadataOnUI,
+ this, url, expected_response_time, data));
+ } else {
+ if (!generated_code_cache_context_->generated_code_cache())
+ return;
+
+ base::Optional<url::Origin> requesting_origin =
+ GetRendererOrigin(url, render_process_id_);
+ if (!requesting_origin)
+ return;
+
+ generated_code_cache_context_->generated_code_cache()->WriteData(
+ url, *requesting_origin, expected_response_time, data);
+ }
+}
+
+void RenderMessageFilter::FetchCachedCode(const GURL& url,
+ FetchCachedCodeCallback callback) {
+ if (!generated_code_cache_context_->generated_code_cache()) {
+ std::move(callback).Run(base::Time(), std::vector<uint8_t>());
+ return;
+ }
+
+ base::Optional<url::Origin> requesting_origin =
+ GetRendererOrigin(url, render_process_id_);
+ if (!requesting_origin) {
+ std::move(callback).Run(base::Time(), std::vector<uint8_t>());
return;
+ }
- // Use the same priority for the metadata write as for script
- // resources (see defaultPriorityForResourceType() in WebKit's
- // CachedResource.cpp). Note that WebURLRequest::PriorityMedium
- // corresponds to net::LOW (see ConvertWebKitPriorityToNetPriority()
- // in weburlloader_impl.cc).
- const net::RequestPriority kPriority = net::LOW;
- scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(data.size()));
- if (!data.empty())
- memcpy(buf->data(), &data.front(), data.size());
- cache->WriteMetadata(url, kPriority, expected_response_time, buf.get(),
- data.size());
+ base::RepeatingCallback<void(const base::Time&, const std::vector<uint8_t>&)>
+ read_callback = base::BindRepeating(
+ &RenderMessageFilter::OnReceiveCachedCode,
+ weak_ptr_factory_.GetWeakPtr(), base::Passed(&callback));
+ generated_code_cache_context_->generated_code_cache()->FetchEntry(
+ url, *requesting_origin, read_callback);
+}
+
+void RenderMessageFilter::OnReceiveCachedCode(
+ FetchCachedCodeCallback callback,
+ const base::Time& response_time,
+ const std::vector<uint8_t>& data) {
+ // TODO(crbug.com/867848): Pass the data as a mojo data pipe instead
+ // of vector<uint8>
+ std::move(callback).Run(response_time, data);
+}
+
+void RenderMessageFilter::ClearCodeCacheEntry(const GURL& url) {
+ if (!generated_code_cache_context_->generated_code_cache())
+ return;
+
+ base::Optional<url::Origin> requesting_origin =
+ GetRendererOrigin(url, render_process_id_);
+ if (!requesting_origin)
+ return;
+
+ generated_code_cache_context_->generated_code_cache()->DeleteEntry(
+ url, *requesting_origin);
}
void RenderMessageFilter::DidGenerateCacheableMetadataInCacheStorage(
@@ -273,4 +348,23 @@ void RenderMessageFilter::HasGpuProcess(HasGpuProcessCallback callback) {
GpuProcessHost::GetHasGpuProcess(std::move(callback));
}
+void RenderMessageFilter::DidGenerateCacheableMetadataOnUI(
+ const GURL& url,
+ base::Time expected_response_time,
+ const std::vector<uint8_t>& data) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ RenderProcessHost* host = RenderProcessHost::FromID(render_process_id_);
+ if (!host)
+ return;
+
+ // Use the same priority for the metadata write as for script
+ // resources (see defaultPriorityForResourceType() in WebKit's
+ // CachedResource.cpp). Note that WebURLRequest::PriorityMedium
+ // corresponds to net::LOW (see ConvertWebKitPriorityToNetPriority()
+ // in weburlloader_impl.cc).
+ const net::RequestPriority kPriority = net::LOW;
+ host->GetStoragePartition()->GetNetworkContext()->WriteCacheMetadata(
+ url, kPriority, expected_response_time, data);
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_message_filter.h b/chromium/content/browser/renderer_host/render_message_filter.h
index b90944a9f34..76eda81660d 100644
--- a/chromium/content/browser/renderer_host/render_message_filter.h
+++ b/chromium/content/browser/renderer_host/render_message_filter.h
@@ -58,6 +58,7 @@ class MediaInternals;
class RenderWidgetHelper;
class ResourceContext;
class ResourceDispatcherHostImpl;
+class GeneratedCodeCacheContext;
// This class filters out incoming IPC messages for the renderer process on the
// IPC thread.
@@ -72,7 +73,8 @@ class CONTENT_EXPORT RenderMessageFilter
net::URLRequestContextGetter* request_context,
RenderWidgetHelper* render_widget_helper,
MediaInternals* media_internals,
- CacheStorageContextImpl* cache_storage_context);
+ CacheStorageContextImpl* cache_storage_context,
+ GeneratedCodeCacheContext* generated_code_cache_context);
// BrowserMessageFilter methods:
bool OnMessageReceived(const IPC::Message& message) override;
@@ -103,6 +105,8 @@ class CONTENT_EXPORT RenderMessageFilter
void DidGenerateCacheableMetadata(const GURL& url,
base::Time expected_response_time,
const std::vector<uint8_t>& data) override;
+ void FetchCachedCode(const GURL& url, FetchCachedCodeCallback) override;
+ void ClearCodeCacheEntry(const GURL& url) override;
void DidGenerateCacheableMetadataInCacheStorage(
const GURL& url,
base::Time expected_response_time,
@@ -122,6 +126,9 @@ class CONTENT_EXPORT RenderMessageFilter
base::ThreadPriority priority);
#endif
+ void OnReceiveCachedCode(FetchCachedCodeCallback callback,
+ const base::Time& response_time,
+ const std::vector<uint8_t>& data);
void OnCacheStorageOpenCallback(const GURL& url,
base::Time expected_response_time,
scoped_refptr<net::IOBuffer> buf,
@@ -133,6 +140,11 @@ class CONTENT_EXPORT RenderMessageFilter
bool CheckBenchmarkingEnabled() const;
bool CheckPreparsedJsCachingEnabled() const;
+ // NetworkContext must be called from the UI thread.
+ void DidGenerateCacheableMetadataOnUI(const GURL& url,
+ base::Time expected_response_time,
+ const std::vector<uint8_t>& data);
+
// Cached resource request dispatcher host, guaranteed to be non-null. We do
// not own it; it is managed by the BrowserProcess, which has a wider scope
// than we do.
@@ -151,6 +163,10 @@ class CONTENT_EXPORT RenderMessageFilter
MediaInternals* media_internals_;
CacheStorageContextImpl* cache_storage_context_;
+ // TODO(crbug.com/867347): Consider registering its own Mojo interface rather
+ // than going through RenderMessageFilter.
+ GeneratedCodeCacheContext* generated_code_cache_context_;
+
base::WeakPtrFactory<RenderMessageFilter> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(RenderMessageFilter);
diff --git a/chromium/content/browser/renderer_host/render_process_host_browsertest.cc b/chromium/content/browser/renderer_host/render_process_host_browsertest.cc
index c81f8ed3587..b168086cac1 100644
--- a/chromium/content/browser/renderer_host/render_process_host_browsertest.cc
+++ b/chromium/content/browser/renderer_host/render_process_host_browsertest.cc
@@ -136,38 +136,6 @@ class NonSpareRendererContentBrowserClient : public TestContentBrowserClient {
DISALLOW_COPY_AND_ASSIGN(NonSpareRendererContentBrowserClient);
};
-// Sometimes the renderer process's ShutdownRequest (corresponding to the
-// ViewMsg_WasSwappedOut from a previous navigation) doesn't arrive until after
-// the browser process decides to re-use the renderer for a new purpose. This
-// test makes sure the browser doesn't let the renderer die in that case. See
-// http://crbug.com/87176.
-IN_PROC_BROWSER_TEST_F(RenderProcessHostTest,
- ShutdownRequestFromActiveTabIgnored) {
- ASSERT_TRUE(embedded_test_server()->Start());
-
- GURL test_url = embedded_test_server()->GetURL("/simple_page.html");
- NavigateToURL(shell(), test_url);
- RenderProcessHost* rph =
- shell()->web_contents()->GetMainFrame()->GetProcess();
-
- host_destructions_ = 0;
- process_exits_ = 0;
-
- rph->AddObserver(this);
-
- static_cast<mojom::RendererHost*>(static_cast<RenderProcessHostImpl*>(rph))
- ->ShutdownRequest();
-
- // If the RPH sends a mistaken ProcessShutdown, the renderer process
- // will take some time to die. Wait for a second tab to load in order to give
- // that time to happen.
- NavigateToURL(CreateBrowser(), test_url);
-
- EXPECT_EQ(0, process_exits_);
- if (!host_destructions_)
- rph->RemoveObserver(this);
-}
-
IN_PROC_BROWSER_TEST_F(RenderProcessHostTest,
GuestsAreNotSuitableHosts) {
// Set max renderers to 1 to force running out of processes.
@@ -731,7 +699,9 @@ class AudioStartObserver : public WebContentsObserver {
// Note: This test can't run when the Mojo Renderer is used since it does not
// create audio streams through the normal audio pathways; at present this is
// only used by Chromecast.
-#if BUILDFLAG(ENABLE_MOJO_RENDERER)
+//
+// crbug.com/864476: flaky on Android for unclear reasons.
+#if BUILDFLAG(ENABLE_MOJO_RENDERER) || defined(OS_ANDROID)
#define KillProcessZerosAudioStreams DISABLED_KillProcessZerosAudioStreams
#endif
IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, KillProcessZerosAudioStreams) {
@@ -740,8 +710,8 @@ IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, KillProcessZerosAudioStreams) {
embedded_test_server()->ServeFilesFromSourceDirectory(
media::GetTestDataPath());
ASSERT_TRUE(embedded_test_server()->Start());
- NavigateToURL(shell(),
- embedded_test_server()->GetURL("/webaudio_oscillator.html"));
+ ASSERT_TRUE(NavigateToURL(
+ shell(), embedded_test_server()->GetURL("/webaudio_oscillator.html")));
RenderProcessHostImpl* rph = static_cast<RenderProcessHostImpl*>(
shell()->web_contents()->GetMainFrame()->GetProcess());
@@ -986,7 +956,15 @@ IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, KeepAliveRendererProcess) {
rph->RemoveObserver(this);
}
-IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, KeepAliveRendererProcess_Hung) {
+// Test is flaky on Android builders: https://crbug.com/875179
+#if defined(OS_ANDROID)
+#define MAYBE_KeepAliveRendererProcess_Hung \
+ DISABLED_KeepAliveRendererProcess_Hung
+#else
+#define MAYBE_KeepAliveRendererProcess_Hung KeepAliveRendererProcess_Hung
+#endif
+IN_PROC_BROWSER_TEST_F(RenderProcessHostTest,
+ MAYBE_KeepAliveRendererProcess_Hung) {
embedded_test_server()->RegisterRequestHandler(
base::BindRepeating(HandleHungBeacon));
ASSERT_TRUE(embedded_test_server()->Start());
@@ -1013,8 +991,16 @@ IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, KeepAliveRendererProcess_Hung) {
rph->RemoveObserver(this);
}
+// Test is flaky on Android builders: https://crbug.com/875179
+#if defined(OS_ANDROID)
+#define MAYBE_FetchKeepAliveRendererProcess_Hung \
+ DISABLED_FetchKeepAliveRendererProcess_Hung
+#else
+#define MAYBE_FetchKeepAliveRendererProcess_Hung \
+ FetchKeepAliveRendererProcess_Hung
+#endif
IN_PROC_BROWSER_TEST_F(RenderProcessHostTest,
- FetchKeepAliveRendererProcess_Hung) {
+ MAYBE_FetchKeepAliveRendererProcess_Hung) {
embedded_test_server()->RegisterRequestHandler(
base::BindRepeating(HandleHungBeacon));
ASSERT_TRUE(embedded_test_server()->Start());
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 05e0ee79e5a..989b52793c4 100644
--- a/chromium/content/browser/renderer_host/render_process_host_impl.cc
+++ b/chromium/content/browser/renderer_host/render_process_host_impl.cc
@@ -52,7 +52,7 @@
#include "base/supports_user_data.h"
#include "base/synchronization/lock.h"
#include "base/sys_info.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "base/threading/thread.h"
#include "base/threading/thread_restrictions.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -66,6 +66,7 @@
#include "components/metrics/single_sample_metrics.h"
#include "components/tracing/common/tracing_switches.h"
#include "components/viz/common/switches.h"
+#include "components/viz/host/gpu_client.h"
#include "content/browser/appcache/appcache_dispatcher_host.h"
#include "content/browser/appcache/chrome_appcache_service.h"
#include "content/browser/background_fetch/background_fetch_context.h"
@@ -87,10 +88,11 @@
#include "content/browser/dom_storage/dom_storage_context_wrapper.h"
#include "content/browser/dom_storage/dom_storage_message_filter.h"
#include "content/browser/field_trial_recorder.h"
-#include "content/browser/fileapi/fileapi_message_filter.h"
+#include "content/browser/fileapi/file_system_manager_impl.h"
+#include "content/browser/font_unique_name_lookup/font_unique_name_lookup_service.h"
#include "content/browser/frame_host/render_frame_message_filter.h"
+#include "content/browser/gpu/browser_gpu_client_delegate.h"
#include "content/browser/gpu/compositor_util.h"
-#include "content/browser/gpu/gpu_client_impl.h"
#include "content/browser/gpu/gpu_process_host.h"
#include "content/browser/gpu/shader_cache_factory.h"
#include "content/browser/histogram_controller.h"
@@ -150,6 +152,7 @@
#include "content/common/view_messages.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/network_service_instance.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_process_host_factory.h"
@@ -185,6 +188,7 @@
#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"
#include "mojo/public/cpp/system/platform_handle.h"
@@ -192,6 +196,7 @@
#include "ppapi/buildflags/buildflags.h"
#include "services/device/public/mojom/battery_monitor.mojom.h"
#include "services/device/public/mojom/constants.mojom.h"
+#include "services/network/cross_origin_read_blocking.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/network_switches.h"
#include "services/network/public/mojom/network_service.mojom.h"
@@ -906,11 +911,11 @@ class SiteProcessCountTracker : public base::SupportsUserData::Data,
map_.erase(site_url);
}
- void FindRenderProcessesForSite(
- const GURL& site_url,
+ void FindRenderProcessesForSiteInstance(
+ SiteInstanceImpl* site_instance,
std::set<RenderProcessHost*>* foreground_processes,
std::set<RenderProcessHost*>* background_processes) {
- auto result = map_.find(site_url);
+ auto result = map_.find(site_instance->GetSiteURL());
if (result == map_.end())
return;
@@ -932,8 +937,10 @@ class SiteProcessCountTracker : public base::SupportsUserData::Data,
// allow such hosts to be reused. See https://crbug.com/780661.
if (!host->MayReuseHost() ||
!RenderProcessHostImpl::IsSuitableHost(
- host, host->GetBrowserContext(), site_url))
+ host, host->GetBrowserContext(), site_instance->GetSiteURL(),
+ site_instance->lock_url())) {
continue;
+ }
if (host->VisibleClientCount())
foreground_processes->insert(host);
@@ -1028,13 +1035,13 @@ class UnmatchedServiceWorkerProcessTracker
public RenderProcessHostObserver {
public:
// Registers |render_process_host| as having an unmatched service worker for
- // |site_url|.
- static void Register(BrowserContext* browser_context,
- RenderProcessHost* render_process_host,
- const GURL& site_url) {
- DCHECK(!site_url.is_empty());
+ // |site_instance|.
+ static void Register(RenderProcessHost* render_process_host,
+ SiteInstanceImpl* site_instance) {
+ BrowserContext* browser_context = site_instance->GetBrowserContext();
+ DCHECK(!site_instance->GetSiteURL().is_empty());
if (!ShouldTrackProcessForSite(browser_context, render_process_host,
- site_url))
+ site_instance->GetSiteURL()))
return;
UnmatchedServiceWorkerProcessTracker* tracker =
@@ -1046,14 +1053,15 @@ class UnmatchedServiceWorkerProcessTracker
browser_context->SetUserData(kUnmatchedServiceWorkerProcessTrackerKey,
base::WrapUnique(tracker));
}
- tracker->RegisterProcessForSite(render_process_host, site_url);
+ tracker->RegisterProcessForSite(render_process_host, site_instance);
}
- // Find a process with an unmatched service worker for |site_url| and removes
- // the process from the tracker if it exists.
- static RenderProcessHost* MatchWithSite(BrowserContext* browser_context,
- const GURL& site_url) {
- if (!ShouldFindReusableProcessHostForSite(browser_context, site_url))
+ // Find a process with an unmatched service worker for |site_instance| and
+ // removes the process from the tracker if it exists.
+ static RenderProcessHost* MatchWithSite(SiteInstanceImpl* site_instance) {
+ BrowserContext* browser_context = site_instance->GetBrowserContext();
+ if (!ShouldFindReusableProcessHostForSite(browser_context,
+ site_instance->GetSiteURL()))
return nullptr;
UnmatchedServiceWorkerProcessTracker* tracker =
@@ -1062,7 +1070,7 @@ class UnmatchedServiceWorkerProcessTracker
kUnmatchedServiceWorkerProcessTrackerKey));
if (!tracker)
return nullptr;
- return tracker->TakeFreshestProcessForSite(site_url);
+ return tracker->TakeFreshestProcessForSite(site_instance);
}
UnmatchedServiceWorkerProcessTracker() {}
@@ -1086,14 +1094,17 @@ class UnmatchedServiceWorkerProcessTracker
}
private:
- void RegisterProcessForSite(RenderProcessHost* host, const GURL& site_url) {
+ void RegisterProcessForSite(RenderProcessHost* host,
+ SiteInstanceImpl* site_instance) {
if (!HasProcess(host))
host->AddObserver(this);
- site_process_set_.insert(SiteProcessIDPair(site_url, host->GetID()));
+ site_process_set_.insert(
+ SiteProcessIDPair(site_instance->GetSiteURL(), host->GetID()));
}
- RenderProcessHost* TakeFreshestProcessForSite(const GURL& site_url) {
- RenderProcessHost* host = FindFreshestProcessForSite(site_url);
+ RenderProcessHost* TakeFreshestProcessForSite(
+ SiteInstanceImpl* site_instance) {
+ RenderProcessHost* host = FindFreshestProcessForSite(site_instance);
if (!host)
return nullptr;
@@ -1101,8 +1112,10 @@ class UnmatchedServiceWorkerProcessTracker
// |site_url|, for example if it was used for a ServiceWorker for a
// nonexistent extension URL. See https://crbug.com/782349 and
// https://crbug.com/780661.
+ GURL site_url(site_instance->GetSiteURL());
if (!host->MayReuseHost() || !RenderProcessHostImpl::IsSuitableHost(
- host, host->GetBrowserContext(), site_url))
+ host, host->GetBrowserContext(), site_url,
+ site_instance->lock_url()))
return nullptr;
site_process_set_.erase(SiteProcessIDPair(site_url, host->GetID()));
@@ -1111,7 +1124,9 @@ class UnmatchedServiceWorkerProcessTracker
return host;
}
- RenderProcessHost* FindFreshestProcessForSite(const GURL& site_url) const {
+ RenderProcessHost* FindFreshestProcessForSite(
+ SiteInstanceImpl* site_instance) const {
+ GURL site_url(site_instance->GetSiteURL());
for (const auto& site_process_pair : base::Reversed(site_process_set_)) {
if (site_process_pair.first == site_url)
return RenderProcessHost::FromID(site_process_pair.second);
@@ -1192,9 +1207,9 @@ bool ShouldBoostPriorityForPendingViews() {
// TODO(gab): End the experiment and turn ShouldBoostPriorityForPendingViews()
// into a constant when results are in.
static bool should_boost_for_pending_views =
- base::StartsWith(base::FieldTrialList::FindFullName(
- "BoostRendererPriorityForPendingViews"),
- "Enabled", base::CompareCase::SENSITIVE);
+ !base::StartsWith(base::FieldTrialList::FindFullName(
+ "BoostRendererPriorityForPendingViews"),
+ "Disabled", base::CompareCase::SENSITIVE);
return should_boost_for_pending_views;
#endif
}
@@ -1207,6 +1222,69 @@ void CopyFeatureSwitch(const base::CommandLine& src,
dest->AppendSwitchASCII(switch_name, base::JoinString(features, ","));
}
+void GetNetworkChangeManager(
+ network::mojom::NetworkChangeManagerRequest request) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ GetNetworkService()->GetNetworkChangeManager(std::move(request));
+}
+
+void RemoveCorbExceptionForPluginOnIOThread(int process_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ // Without NetworkService the exception list is stored directly in the browser
+ // process.
+ if (!base::FeatureList::IsEnabled(network::features::kNetworkService))
+ network::CrossOriginReadBlocking::RemoveExceptionForPlugin(process_id);
+}
+
+// This is the entry point (i.e. this is called on the UI thread *before*
+// we post a task for RemoveCorbExceptionForPluginOnIOThread).
+void RemoveCorbExceptionForPluginOnUIThread(int process_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ GetNetworkService()->RemoveCorbExceptionForPlugin(process_id);
+ } else {
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&RemoveCorbExceptionForPluginOnIOThread, process_id));
+ }
+}
+
+void AddCorbExceptionForPluginOnUIThread(int process_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ RenderProcessHost* process = RenderProcessHostImpl::FromID(process_id);
+ if (!process) {
+ // In this case the exception won't be added via NetworkService (because of
+ // the early return below), but we need to proactively do clean-up on IO
+ // thread.
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&RemoveCorbExceptionForPluginOnIOThread, process_id));
+ return;
+ }
+ process->CleanupCorbExceptionForPluginUponDestruction();
+
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService))
+ GetNetworkService()->AddCorbExceptionForPlugin(process_id);
+}
+
+// This is the entry point (i.e. this is called on the IO thread *before*
+// we post a task for AddCorbExceptionForPluginOnUIThread).
+void AddCorbExceptionForPluginOnIOThread(int process_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ // Without NetworkService the exception list is stored directly in the browser
+ // process.
+ if (!base::FeatureList::IsEnabled(network::features::kNetworkService))
+ network::CrossOriginReadBlocking::AddExceptionForPlugin(process_id);
+
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&AddCorbExceptionForPluginOnUIThread, process_id));
+}
+
} // namespace
// Held by the RPH and used to control an (unowned) ConnectionFilterImpl from
@@ -1446,6 +1524,7 @@ RenderProcessHostImpl::RenderProcessHostImpl(
priority_(!blink::kLaunchingProcessIsBackgrounded,
false /* has_media_stream */,
frame_depth_,
+ false /* intersects_viewport */,
ShouldBoostPriorityForPendingViews(),
#if defined(OS_ANDROID)
// Only use |boost_for_pending_views| to infer is_background()
@@ -1531,12 +1610,12 @@ RenderProcessHostImpl::RenderProcessHostImpl(
InitializeChannelProxy();
- if (features::IsAshInBrowserProcess()) {
+ if (!features::IsUsingWindowService()) {
const int id = GetID();
const uint64_t tracing_id =
ChildProcessHostImpl::ChildProcessUniqueIdToTracingProcessId(id);
- gpu_client_.reset(new GpuClientImpl(
- id, tracing_id,
+ gpu_client_.reset(new viz::GpuClient(
+ std::make_unique<BrowserGpuClientDelegate>(), id, tracing_id,
BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)));
}
@@ -1606,6 +1685,9 @@ RenderProcessHostImpl::~RenderProcessHostImpl() {
}
GetMemoryDumpProvider().RemoveHost(this);
+
+ if (cleanup_corb_exception_for_plugin_upon_destruction_)
+ RemoveCorbExceptionForPluginOnUIThread(GetID());
}
bool RenderProcessHostImpl::Init() {
@@ -1862,11 +1944,14 @@ void RenderProcessHostImpl::CreateMessageFilters() {
scoped_refptr<net::URLRequestContextGetter> request_context(
storage_partition_impl_->GetURLRequestContext());
+ // TODO(crbug.com/867347): Consider registering Mojo interface for
+ // GeneratedCodeCache rather than going through RenderMessageFilter.
scoped_refptr<RenderMessageFilter> render_message_filter =
base::MakeRefCounted<RenderMessageFilter>(
GetID(), GetBrowserContext(), request_context.get(),
widget_helper_.get(), media_internals,
- storage_partition_impl_->GetCacheStorageContext());
+ storage_partition_impl_->GetCacheStorageContext(),
+ storage_partition_impl_->GetGeneratedCodeCacheContext());
AddFilter(render_message_filter.get());
render_frame_message_filter_ = new RenderFrameMessageFilter(
@@ -1913,21 +1998,16 @@ void RenderProcessHostImpl::CreateMessageFilters() {
#if BUILDFLAG(ENABLE_PLUGINS)
AddFilter(new PepperRendererConnection(GetID()));
#endif
- AddFilter(new FileAPIMessageFilter(
- GetID(), storage_partition_impl_->GetURLRequestContext(),
- storage_partition_impl_->GetFileSystemContext(),
- blob_storage_context.get()));
AddFilter(new BlobDispatcherHost(GetID(), blob_storage_context));
#if defined(OS_MACOSX)
AddFilter(new TextInputClientMessageFilter());
#endif
p2p_socket_dispatcher_host_ =
- new P2PSocketDispatcherHost(request_context.get());
- AddFilter(p2p_socket_dispatcher_host_.get());
+ std::make_unique<P2PSocketDispatcherHost>(GetID());
AddFilter(new TraceMessageFilter(GetID()));
- AddFilter(new ResolveProxyMsgHelper(request_context.get()));
+ AddFilter(new ResolveProxyMsgHelper(GetID()));
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context(
static_cast<ServiceWorkerContextWrapper*>(
@@ -1975,13 +2055,20 @@ void RenderProcessHostImpl::DelayProcessShutdownForUnload(
timeout);
}
+// static
+void RenderProcessHostImpl::AddCorbExceptionForPlugin(int process_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ AddCorbExceptionForPluginOnIOThread(process_id);
+}
+
+void RenderProcessHostImpl::CleanupCorbExceptionForPluginUponDestruction() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ cleanup_corb_exception_for_plugin_upon_destruction_ = true;
+}
+
void RenderProcessHostImpl::RegisterMojoInterfaces() {
auto registry = std::make_unique<service_manager::BinderRegistry>();
- channel_->AddAssociatedInterfaceForIOThread(
- base::Bind(&IndexedDBDispatcherHost::AddBinding,
- base::Unretained(indexed_db_factory_.get())));
-
channel_->AddAssociatedInterfaceForIOThread(base::BindRepeating(
&ServiceWorkerDispatcherHost::AddBinding,
base::Unretained(service_worker_dispatcher_host_.get())));
@@ -2048,6 +2135,13 @@ void RenderProcessHostImpl::RegisterMojoInterfaces() {
registry->AddInterface(base::Bind(&hyphenation::HyphenationImpl::Create),
hyphenation::HyphenationImpl::GetTaskRunner());
#endif
+#if defined(OS_ANDROID)
+ if (base::FeatureList::IsEnabled(features::kFontSrcLocalMatching)) {
+ registry->AddInterface(
+ base::BindRepeating(&FontUniqueNameLookupService::Create),
+ FontUniqueNameLookupService::GetTaskRunner());
+ }
+#endif
registry->AddInterface(base::Bind(&device::GamepadHapticsManager::Create));
@@ -2055,14 +2149,25 @@ void RenderProcessHostImpl::RegisterMojoInterfaces() {
base::Bind(&PushMessagingManager::BindRequest,
base::Unretained(push_messaging_manager_.get())));
+ file_system_manager_impl_.reset(new FileSystemManagerImpl(
+ GetID(), storage_partition_impl_->GetFileSystemContext(),
+ ChromeBlobStorageContext::GetFor(GetBrowserContext())));
+ registry->AddInterface(
+ base::BindRepeating(&FileSystemManagerImpl::BindRequest,
+ base::Unretained(file_system_manager_impl_.get())));
+
if (gpu_client_) {
// |gpu_client_| outlives the registry, because its destruction is posted to
// IO thread from the destructor of |this|.
registry->AddInterface(base::BindRepeating(
- &GpuClientImpl::Add, base::Unretained(gpu_client_.get())));
+ &viz::GpuClient::Add, base::Unretained(gpu_client_.get())));
}
registry->AddInterface(
+ base::BindRepeating(&IndexedDBDispatcherHost::AddBinding,
+ base::Unretained(indexed_db_factory_.get())));
+
+ registry->AddInterface(
base::Bind(
&WebDatabaseHostImpl::Create, GetID(),
base::WrapRefCounted(storage_partition_impl_->GetDatabaseTracker())),
@@ -2096,9 +2201,15 @@ void RenderProcessHostImpl::RegisterMojoInterfaces() {
base::Unretained(storage_partition_impl_->GetAppCacheService()),
GetID()));
+ AddUIThreadInterface(
+ registry.get(),
+ base::BindRepeating(&P2PSocketDispatcherHost::BindRequest,
+ base::Unretained(p2p_socket_dispatcher_host_.get())));
+
AddUIThreadInterface(registry.get(), base::Bind(&FieldTrialRecorder::Create));
- associated_interfaces_ = std::make_unique<AssociatedInterfaceRegistryImpl>();
+ associated_interfaces_ =
+ std::make_unique<blink::AssociatedInterfaceRegistry>();
blink::AssociatedInterfaceRegistry* associated_registry =
associated_interfaces_.get();
associated_registry->AddInterface(base::Bind(
@@ -2132,6 +2243,12 @@ void RenderProcessHostImpl::RegisterMojoInterfaces() {
registry->AddInterface(base::BindRepeating(&KeySystemSupportImpl::Create));
#endif // BUILDFLAG(ENABLE_LIBRARY_CDMS)
+ AddUIThreadInterface(registry.get(),
+ base::BindRepeating(&GetNetworkChangeManager));
+
+ registry->AddInterface(base::BindRepeating(
+ &RenderProcessHostImpl::BindVideoDecoderService, base::Unretained(this)));
+
// ---- Please do not register interfaces below this line ------
//
// This call should be done after registering all interfaces above, so that
@@ -2164,7 +2281,7 @@ void RenderProcessHostImpl::BindRouteProvider(
void RenderProcessHostImpl::GetRoute(
int32_t routing_id,
- mojom::AssociatedInterfaceProviderAssociatedRequest request) {
+ blink::mojom::AssociatedInterfaceProviderAssociatedRequest request) {
DCHECK(request.is_pending());
associated_interface_provider_bindings_.AddBinding(
this, std::move(request), routing_id);
@@ -2172,7 +2289,7 @@ void RenderProcessHostImpl::GetRoute(
void RenderProcessHostImpl::GetAssociatedInterface(
const std::string& name,
- mojom::AssociatedInterfaceAssociatedRequest request) {
+ blink::mojom::AssociatedInterfaceAssociatedRequest request) {
int32_t routing_id =
associated_interface_provider_bindings_.dispatch_context();
IPC::Listener* listener = listeners_.Lookup(routing_id);
@@ -2214,6 +2331,13 @@ void RenderProcessHostImpl::CreateStoragePartitionService(
storage_partition_impl_->Bind(id_, std::move(request));
}
+void RenderProcessHostImpl::BindVideoDecoderService(
+ media::mojom::InterfaceFactoryRequest request) {
+ if (!video_decoder_proxy_)
+ video_decoder_proxy_.reset(new VideoDecoderProxy());
+ video_decoder_proxy_->Add(std::move(request));
+}
+
void RenderProcessHostImpl::CreateRendererHost(
mojom::RendererHostAssociatedRequest request) {
renderer_host_binding_.Bind(std::move(request));
@@ -2496,6 +2620,10 @@ unsigned int RenderProcessHostImpl::GetFrameDepth() const {
return frame_depth_;
}
+bool RenderProcessHostImpl::GetIntersectsViewport() const {
+ return intersects_viewport_;
+}
+
#if defined(OS_ANDROID)
ChildProcessImportance RenderProcessHostImpl::GetEffectiveImportance() {
return effective_importance_;
@@ -2771,6 +2899,11 @@ void RenderProcessHostImpl::AppendRendererCommandLine(
child_connection_->service_token());
command_line->AppendSwitchASCII(switches::kRendererClientId,
std::to_string(GetID()));
+
+ if (SiteIsolationPolicy::UseDedicatedProcessesForAllSites()) {
+ // Disable V8 code mitigations if renderer processes are site-isolated.
+ command_line->AppendSwitch(switches::kNoV8UntrustedCodeMitigations);
+ }
}
void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
@@ -2815,6 +2948,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kDisableLogging,
switches::kDisableMediaSuspend,
switches::kDisableNotifications,
+ switches::kDisableOopRasterization,
switches::kDisableOriginTrialControlledBlinkFeatures,
switches::kDisablePepper3DImageChromium,
switches::kDisablePermissionsAPI,
@@ -2844,6 +2978,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kEnableLCDText,
switches::kEnableLogging,
switches::kEnableNetworkInformationDownlinkMax,
+ switches::kEnableOopRasterization,
switches::kEnablePluginPlaceholderTesting,
switches::kEnablePreciseMemoryInfo,
switches::kEnablePrintBrowser,
@@ -2863,7 +2998,6 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kEnableWebVR,
switches::kExplicitlyAllowedPorts,
switches::kFileUrlPathAlias,
- switches::kFMPNetworkQuietTimeout,
switches::kForceColorProfile,
switches::kForceDeviceScaleFactor,
switches::kForceGpuMemAvailableMb,
@@ -2878,6 +3012,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kMaxUntiledLayerHeight,
switches::kMSEAudioBufferSizeLimitMb,
switches::kMSEVideoBufferSizeLimitMb,
+ switches::kNetworkQuietTimeout,
switches::kNoZygote,
switches::kOverridePluginPowerSaverForTesting,
switches::kPassiveListenersDefault,
@@ -3174,9 +3309,7 @@ void RenderProcessHostImpl::OnAssociatedInterfaceRequest(
const std::string& interface_name,
mojo::ScopedInterfaceEndpointHandle handle) {
if (associated_interfaces_ &&
- associated_interfaces_->CanBindRequest(interface_name)) {
- associated_interfaces_->BindRequest(interface_name, std::move(handle));
- } else {
+ !associated_interfaces_->TryBindInterface(interface_name, &handle)) {
LOG(ERROR) << "Request for unknown Channel-associated interface: "
<< interface_name;
}
@@ -3443,18 +3576,13 @@ RenderProcessHostImpl::StartRtpDump(
bool incoming,
bool outgoing,
const WebRtcRtpPacketCallback& packet_callback) {
- if (!p2p_socket_dispatcher_host_.get())
- return WebRtcStopRtpDumpCallback();
-
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(&P2PSocketDispatcherHost::StartRtpDump,
- p2p_socket_dispatcher_host_, incoming,
- outgoing, packet_callback));
+ p2p_socket_dispatcher_host_->StartRtpDump(incoming, outgoing,
+ packet_callback);
if (stop_rtp_dump_callback_.is_null()) {
stop_rtp_dump_callback_ =
- base::Bind(&P2PSocketDispatcherHost::StopRtpDumpOnUIThread,
- p2p_socket_dispatcher_host_);
+ base::Bind(&P2PSocketDispatcherHost::StopRtpDump,
+ p2p_socket_dispatcher_host_->GetWeakPtr());
}
return stop_rtp_dump_callback_;
}
@@ -3533,7 +3661,8 @@ void RenderProcessHostImpl::FilterURL(RenderProcessHost* rph,
// static
bool RenderProcessHostImpl::IsSuitableHost(RenderProcessHost* host,
BrowserContext* browser_context,
- const GURL& site_url) {
+ const GURL& site_url,
+ const GURL& lock_url) {
if (run_renderer_in_process()) {
DCHECK_EQ(host->GetBrowserContext(), browser_context)
<< " Single-process mode does not support multiple browser contexts.";
@@ -3558,10 +3687,11 @@ bool RenderProcessHostImpl::IsSuitableHost(RenderProcessHost* host,
if (!host->InSameStoragePartition(dest_partition))
return false;
- // Check WebUI bindings and origin locks.
+ // Check WebUI bindings and origin locks. Note that |lock_url| may differ
+ // from |site_url| if an effective URL is used.
auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
bool host_has_web_ui_bindings = policy->HasWebUIBindings(host->GetID());
- auto lock_state = policy->CheckOriginLock(host->GetID(), site_url);
+ auto lock_state = policy->CheckOriginLock(host->GetID(), lock_url);
if (host->HostHasNotBeenUsed()) {
// If the host hasn't been used, it won't have the expected WebUI bindings
// or origin locks just *yet* - skip the checks in this case. One example
@@ -3583,8 +3713,8 @@ bool RenderProcessHostImpl::IsSuitableHost(RenderProcessHost* host,
case CheckOriginLockResult::HAS_WRONG_LOCK:
return false;
case CheckOriginLockResult::NO_LOCK:
- if (!host->IsUnused() && SiteInstanceImpl::ShouldLockToOrigin(
- browser_context, host, site_url)) {
+ if (!host->IsUnused() &&
+ SiteInstanceImpl::ShouldLockToOrigin(browser_context, site_url)) {
// If this process has been used to host any other content, it cannot
// be reused if the destination site requires a dedicated process and
// should use a process locked to just that site.
@@ -3674,8 +3804,7 @@ bool RenderProcessHost::ShouldTryToUseExistingProcessHost(
// static
RenderProcessHost* RenderProcessHostImpl::GetExistingProcessHost(
- BrowserContext* browser_context,
- const GURL& site_url) {
+ SiteInstanceImpl* site_instance) {
// First figure out which existing renderers we can use.
std::vector<RenderProcessHost*> suitable_renderers;
suitable_renderers.reserve(g_all_hosts.Get().size());
@@ -3683,8 +3812,9 @@ RenderProcessHost* RenderProcessHostImpl::GetExistingProcessHost(
iterator iter(AllHostsIterator());
while (!iter.IsAtEnd()) {
if (iter.GetCurrentValue()->MayReuseHost() &&
- RenderProcessHostImpl::IsSuitableHost(iter.GetCurrentValue(),
- browser_context, site_url)) {
+ RenderProcessHostImpl::IsSuitableHost(
+ iter.GetCurrentValue(), site_instance->GetBrowserContext(),
+ site_instance->GetSiteURL(), site_instance->lock_url())) {
// The spare is always considered before process reuse.
DCHECK_NE(iter.GetCurrentValue(),
g_spare_render_process_host_manager.Get()
@@ -3738,19 +3868,29 @@ bool RenderProcessHost::ShouldUseProcessPerSite(BrowserContext* browser_context,
}
// static
-RenderProcessHost* RenderProcessHostImpl::GetProcessHostForSite(
+RenderProcessHost* RenderProcessHostImpl::GetSoleProcessHostForURL(
BrowserContext* browser_context,
const GURL& url) {
+ GURL site_url = SiteInstance::GetSiteForURL(browser_context, url);
+ GURL lock_url =
+ SiteInstanceImpl::DetermineProcessLockURL(browser_context, url);
+ return GetSoleProcessHostForSite(browser_context, site_url, lock_url);
+}
+
+// static
+RenderProcessHost* RenderProcessHostImpl::GetSoleProcessHostForSite(
+ BrowserContext* browser_context,
+ const GURL& site_url,
+ const GURL& lock_url) {
// Look up the map of site to process for the given browser_context.
SiteProcessMap* map = GetSiteProcessMapForBrowserContext(browser_context);
// See if we have an existing process with appropriate bindings for this site.
// If not, the caller should create a new process and register it. Note that
// IsSuitableHost expects a site URL rather than the full |url|.
- GURL site_url = SiteInstance::GetSiteForURL(browser_context, url);
RenderProcessHost* host = map->FindProcess(site_url.possibly_invalid_spec());
if (host && (!host->MayReuseHost() ||
- !IsSuitableHost(host, browser_context, site_url))) {
+ !IsSuitableHost(host, browser_context, site_url, lock_url))) {
// The registered process does not have an appropriate set of bindings for
// the url. Remove it from the map so we can register a better one.
RecordAction(
@@ -3762,25 +3902,23 @@ RenderProcessHost* RenderProcessHostImpl::GetProcessHostForSite(
return host;
}
-void RenderProcessHostImpl::RegisterProcessHostForSite(
+void RenderProcessHostImpl::RegisterSoleProcessHostForSite(
BrowserContext* browser_context,
RenderProcessHost* process,
- const GURL& url) {
+ SiteInstanceImpl* site_instance) {
// Look up the map of site to process for the given browser_context.
SiteProcessMap* map = GetSiteProcessMapForBrowserContext(browser_context);
// Only register valid, non-empty sites. Empty or invalid sites will not
// use process-per-site mode. We cannot check whether the process has
// appropriate bindings here, because the bindings have not yet been granted.
- std::string site =
- SiteInstance::GetSiteForURL(browser_context, url).possibly_invalid_spec();
+ std::string site = site_instance->GetSiteURL().possibly_invalid_spec();
if (!site.empty())
map->RegisterProcess(site, process);
}
// static
RenderProcessHost* RenderProcessHostImpl::GetProcessHostForSiteInstance(
- BrowserContext* browser_context,
SiteInstanceImpl* site_instance) {
const GURL site_url = site_instance->GetSiteURL();
SiteInstanceImpl::ProcessReusePolicy process_reuse_policy =
@@ -3789,11 +3927,13 @@ RenderProcessHost* RenderProcessHostImpl::GetProcessHostForSiteInstance(
RenderProcessHost* render_process_host = nullptr;
bool is_unmatched_service_worker = site_instance->is_for_service_worker();
+ BrowserContext* browser_context = site_instance->GetBrowserContext();
// First, attempt to reuse an existing RenderProcessHost if necessary.
switch (process_reuse_policy) {
case SiteInstanceImpl::ProcessReusePolicy::PROCESS_PER_SITE:
- render_process_host = GetProcessHostForSite(browser_context, site_url);
+ render_process_host = GetSoleProcessHostForSite(
+ browser_context, site_url, site_instance->lock_url());
break;
case SiteInstanceImpl::ProcessReusePolicy::USE_DEFAULT_SUBFRAME_PROCESS:
DCHECK(SiteIsolationPolicy::IsTopDocumentIsolationEnabled());
@@ -3803,7 +3943,7 @@ RenderProcessHost* RenderProcessHostImpl::GetProcessHostForSiteInstance(
break;
case SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE:
render_process_host =
- FindReusableProcessHostForSite(browser_context, site_url);
+ FindReusableProcessHostForSiteInstance(site_instance);
UMA_HISTOGRAM_BOOLEAN(
"SiteIsolation.ReusePendingOrCommittedSite.CouldReuse",
render_process_host != nullptr);
@@ -3821,8 +3961,8 @@ RenderProcessHost* RenderProcessHostImpl::GetProcessHostForSiteInstance(
if (!render_process_host &&
!(process_reuse_policy == SiteInstanceImpl::ProcessReusePolicy::DEFAULT &&
site_instance->is_for_service_worker())) {
- render_process_host = UnmatchedServiceWorkerProcessTracker::MatchWithSite(
- browser_context, site_url);
+ render_process_host =
+ UnmatchedServiceWorkerProcessTracker::MatchWithSite(site_instance);
}
// See if the spare RenderProcessHost can be used.
@@ -3838,16 +3978,16 @@ RenderProcessHost* RenderProcessHostImpl::GetProcessHostForSiteInstance(
// If not (or if none found), see if we should reuse an existing process.
if (!render_process_host &&
ShouldTryToUseExistingProcessHost(browser_context, site_url)) {
- render_process_host = GetExistingProcessHost(browser_context, site_url);
+ render_process_host = GetExistingProcessHost(site_instance);
}
// If we found a process to reuse, sanity check that it is suitable for
// hosting |site_url|. For example, if |site_url| requires a dedicated
// process, we should never pick a process used by, or locked to, a different
// site.
- if (render_process_host &&
- !RenderProcessHostImpl::IsSuitableHost(render_process_host,
- browser_context, site_url)) {
+ if (render_process_host && !RenderProcessHostImpl::IsSuitableHost(
+ render_process_host, browser_context, site_url,
+ site_instance->lock_url())) {
ChildProcessSecurityPolicyImpl* policy =
ChildProcessSecurityPolicyImpl::GetInstance();
base::debug::SetCrashKeyString(bad_message::GetRequestedSiteURLKey(),
@@ -3881,8 +4021,8 @@ RenderProcessHost* RenderProcessHostImpl::GetProcessHostForSiteInstance(
spare_process_manager.PrepareForFutureRequests(browser_context);
if (is_unmatched_service_worker) {
- UnmatchedServiceWorkerProcessTracker::Register(
- browser_context, render_process_host, site_url);
+ UnmatchedServiceWorkerProcessTracker::Register(render_process_host,
+ site_instance);
}
// Make sure the chosen process is in the correct StoragePartition for the
@@ -4083,22 +4223,6 @@ void RenderProcessHostImpl::ReleaseOnCloseACK(
holder->Hold(sessions, view_route_id);
}
-void RenderProcessHostImpl::ShutdownRequest() {
- // Notify any contents that the renderer might shut down.
- for (auto& observer : observers_) {
- observer.RenderProcessShutdownRequested(this);
- }
-
- // Don't shut down if there are active RenderViews, or if there are pending
- // RenderViews being swapped back in.
- // In single process mode, we never shutdown the renderer.
- if (pending_views_ || run_renderer_in_process() || GetActiveViewCount() > 0) {
- return;
- }
-
- child_control_interface_->ProcessShutdown();
-}
-
void RenderProcessHostImpl::SuddenTerminationChanged(bool enabled) {
SetSuddenTerminationAllowed(enabled);
}
@@ -4106,6 +4230,7 @@ void RenderProcessHostImpl::SuddenTerminationChanged(bool enabled) {
void RenderProcessHostImpl::UpdateProcessPriorityInputs() {
int32_t new_visible_widgets_count = 0;
unsigned int new_frame_depth = kMaxFrameDepthForPriority;
+ bool new_intersects_viewport = false;
#if defined(OS_ANDROID)
ChildProcessImportance new_effective_importance =
ChildProcessImportance::NORMAL;
@@ -4118,12 +4243,17 @@ void RenderProcessHostImpl::UpdateProcessPriorityInputs() {
if (priority.is_hidden) {
if (!new_visible_widgets_count) {
new_frame_depth = std::min(new_frame_depth, priority.frame_depth);
+ new_intersects_viewport =
+ new_intersects_viewport || priority.intersects_viewport;
}
} else {
if (new_visible_widgets_count) {
new_frame_depth = std::min(new_frame_depth, priority.frame_depth);
+ new_intersects_viewport =
+ new_intersects_viewport || priority.intersects_viewport;
} else {
new_frame_depth = priority.frame_depth;
+ new_intersects_viewport = priority.intersects_viewport;
}
new_visible_widgets_count++;
}
@@ -4135,16 +4265,16 @@ void RenderProcessHostImpl::UpdateProcessPriorityInputs() {
}
bool inputs_changed = new_visible_widgets_count != visible_clients_;
-
// Hide this update behind the ShouldBoostPriorityForPendingViews() experiment
// at the moment to avoid causing an undesired early UpdateProcessPriority().
// See the comment in OnProcessLaunched() and https://crbug.com/560446.
if (ShouldBoostPriorityForPendingViews()) {
- inputs_changed = inputs_changed || frame_depth_ != new_frame_depth;
+ inputs_changed = inputs_changed || frame_depth_ != new_frame_depth ||
+ intersects_viewport_ != new_intersects_viewport;
}
-
visible_clients_ = new_visible_widgets_count;
frame_depth_ = new_frame_depth;
+ intersects_viewport_ = new_intersects_viewport;
#if defined(OS_ANDROID)
inputs_changed =
inputs_changed || new_effective_importance != effective_importance_;
@@ -4167,7 +4297,7 @@ void RenderProcessHostImpl::UpdateProcessPriority() {
const ChildProcessLauncherPriority priority(
visible_clients_ > 0 || base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableRendererBackgrounding),
- media_stream_count_ > 0, frame_depth_,
+ media_stream_count_ > 0, frame_depth_, intersects_viewport_,
!!pending_views_ /* boost_for_pending_views */,
#if defined(OS_ANDROID)
// Same hack as in RenderProcessHostImpl::RenderProcessHostImpl.
@@ -4362,9 +4492,11 @@ RenderProcessHost* RenderProcessHostImpl::GetDefaultSubframeProcessHost(
}
// static
-RenderProcessHost* RenderProcessHostImpl::FindReusableProcessHostForSite(
- BrowserContext* browser_context,
- const GURL& site_url) {
+RenderProcessHost*
+RenderProcessHostImpl::FindReusableProcessHostForSiteInstance(
+ SiteInstanceImpl* site_instance) {
+ BrowserContext* browser_context = site_instance->GetBrowserContext();
+ GURL site_url(site_instance->GetSiteURL());
if (!ShouldFindReusableProcessHostForSite(browser_context, site_url))
return nullptr;
@@ -4377,8 +4509,8 @@ RenderProcessHost* RenderProcessHostImpl::FindReusableProcessHostForSite(
static_cast<SiteProcessCountTracker*>(
browser_context->GetUserData(kPendingSiteProcessCountTrackerKey));
if (pending_tracker) {
- pending_tracker->FindRenderProcessesForSite(
- site_url, &eligible_foreground_hosts, &eligible_background_hosts);
+ pending_tracker->FindRenderProcessesForSiteInstance(
+ site_instance, &eligible_foreground_hosts, &eligible_background_hosts);
}
if (eligible_foreground_hosts.empty()) {
@@ -4388,8 +4520,9 @@ RenderProcessHost* RenderProcessHostImpl::FindReusableProcessHostForSite(
static_cast<SiteProcessCountTracker*>(
browser_context->GetUserData(kCommittedSiteProcessCountTrackerKey));
if (committed_tracker) {
- committed_tracker->FindRenderProcessesForSite(
- site_url, &eligible_foreground_hosts, &eligible_background_hosts);
+ committed_tracker->FindRenderProcessesForSiteInstance(
+ site_instance, &eligible_foreground_hosts,
+ &eligible_background_hosts);
}
}
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 582d8037c2b..37bc9b79afd 100644
--- a/chromium/content/browser/renderer_host/render_process_host_impl.h
+++ b/chromium/content/browser/renderer_host/render_process_host_impl.h
@@ -28,14 +28,13 @@
#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"
#include "content/browser/renderer_host/embedded_frame_sink_provider_impl.h"
#include "content/browser/renderer_host/frame_sink_provider_impl.h"
#include "content/browser/renderer_host/media/renderer_audio_output_stream_factory_context_impl.h"
-#include "content/common/associated_interface_registry_impl.h"
#include "content/common/associated_interfaces.mojom.h"
#include "content/common/child_control.mojom.h"
#include "content/common/content_export.h"
-#include "content/common/indexed_db/indexed_db.mojom.h"
#include "content/common/media/media_stream.mojom.h"
#include "content/common/media/renderer_audio_output_stream_factory.mojom.h"
#include "content/common/renderer.mojom.h"
@@ -53,9 +52,12 @@
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "services/service_manager/public/cpp/binder_registry.h"
#include "services/service_manager/public/mojom/service.mojom.h"
-#include "services/ui/public/interfaces/gpu.mojom.h"
#include "services/viz/public/interfaces/compositing/compositing_mode_watcher.mojom.h"
+#include "services/ws/public/mojom/gpu.mojom.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
+#include "third_party/blink/public/mojom/associated_interfaces/associated_interfaces.mojom.h"
#include "third_party/blink/public/mojom/dom_storage/storage_partition_service.mojom.h"
+#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h"
#include "ui/gfx/gpu_memory_buffer.h"
#include "ui/gl/gpu_switching_observer.h"
@@ -69,10 +71,14 @@ class MessageLoop;
class SharedPersistentMemoryAllocator;
}
+namespace viz {
+class GpuClient;
+}
+
namespace content {
class BrowserPluginMessageFilter;
class ChildConnection;
-class GpuClientImpl;
+class FileSystemManagerImpl;
class IndexedDBDispatcherHost;
class InProcessChildThreadParams;
class MediaStreamTrackMetricsHost;
@@ -121,7 +127,7 @@ class CONTENT_EXPORT RenderProcessHostImpl
public ChildProcessLauncher::Client,
public ui::GpuSwitchingObserver,
public mojom::RouteProvider,
- public mojom::AssociatedInterfaceProvider,
+ public blink::mojom::AssociatedInterfaceProvider,
public mojom::RendererHost {
public:
// Special depth used when there are no PriorityClients.
@@ -152,6 +158,7 @@ class CONTENT_EXPORT RenderProcessHostImpl
void UpdateClientPriority(PriorityClient* client) override;
int VisibleClientCount() const override;
unsigned int GetFrameDepth() const override;
+ bool GetIntersectsViewport() const override;
bool IsForGuestsOnly() const override;
StoragePartition* GetStoragePartition() const override;
bool Shutdown(int exit_code) override;
@@ -220,6 +227,7 @@ class CONTENT_EXPORT RenderProcessHostImpl
void LockToOrigin(const GURL& lock_url) override;
void BindCacheStorage(blink::mojom::CacheStorageRequest request,
const url::Origin& origin) override;
+ void CleanupCorbExceptionForPluginUponDestruction() override;
mojom::RouteProvider* GetRemoteRouteProvider();
@@ -261,11 +269,16 @@ class CONTENT_EXPORT RenderProcessHostImpl
// Implementation of FilterURL below that can be shared with the mock class.
static void FilterURL(RenderProcessHost* rph, bool empty_allowed, GURL* url);
- // Returns true if |host| is suitable for launching a new view with |site_url|
- // in the given |browser_context|.
+ // Returns true if |host| is suitable for rendering a page in the given
+ // |browser_context|, where the page would utilize |site_url| as its
+ // SiteInstance site URL, and its process would be locked to |lock_url|.
+ // |site_url| and |lock_url| may differ in cases where an effective URL is
+ // not the actual site that the process is locked to, which happens for
+ // hosted apps.
static bool IsSuitableHost(RenderProcessHost* host,
BrowserContext* browser_context,
- const GURL& site_url);
+ const GURL& site_url,
+ const GURL& lock_url);
// Returns an existing RenderProcessHost for |url| in |browser_context|,
// if one exists. Otherwise a new RenderProcessHost should be created and
@@ -273,25 +286,45 @@ class CONTENT_EXPORT RenderProcessHostImpl
// This should only be used for process-per-site mode, which can be enabled
// globally with a command line flag or per-site, as determined by
// SiteInstanceImpl::ShouldUseProcessPerSite.
- static RenderProcessHost* GetProcessHostForSite(
+ // Important: |url| should be a full URL and *not* a site URL.
+ static RenderProcessHost* GetSoleProcessHostForURL(
BrowserContext* browser_context,
const GURL& url);
- // Registers the given |process| to be used for any instance of |url|
- // within |browser_context|.
+ // Variant of the above that takes in a SiteInstance site URL and the
+ // process's origin lock URL, when they are known.
+ static RenderProcessHost* GetSoleProcessHostForSite(
+ BrowserContext* browser_context,
+ const GURL& site_url,
+ const GURL& lock_url);
+
+ // Registers the given |process| to be used for all sites identified by
+ // |site_instance| within |browser_context|.
// This should only be used for process-per-site mode, which can be enabled
// globally with a command line flag or per-site, as determined by
// SiteInstanceImpl::ShouldUseProcessPerSite.
- static void RegisterProcessHostForSite(
- BrowserContext* browser_context,
- RenderProcessHost* process,
- const GURL& url);
+ static void RegisterSoleProcessHostForSite(BrowserContext* browser_context,
+ RenderProcessHost* process,
+ SiteInstanceImpl* site_instance);
// Returns a suitable RenderProcessHost to use for |site_instance|. Depending
// on the SiteInstance's ProcessReusePolicy and its url, this may be an
// existing RenderProcessHost or a new one.
+ //
+ // This is the main entrypoint into the process assignment logic, which
+ // handles all cases. These cases include:
+ // - process-per-site: see
+ // RegisterSoleProcessHostForSite/GetSoleProcessHostForSite.
+ // - TDI: see GetDefaultSubframeProcessHost.
+ // - REUSE_PENDING_OR_COMMITTED reuse policy (for ServiceWorkers and OOPIFs):
+ // see FindReusableProcessHostForSiteInstance.
+ // - normal process reuse when over process limit: see
+ // GetExistingProcessHost.
+ // - using the spare RenderProcessHost when possible: see
+ // MaybeTakeSpareRenderProcessHost.
+ // - process creation when an existing process couldn't be found: see
+ // CreateRenderProcessHost.
static RenderProcessHost* GetProcessHostForSiteInstance(
- BrowserContext* browser_context,
SiteInstanceImpl* site_instance);
// Should be called when |browser_context| is used in a navigation.
@@ -412,6 +445,15 @@ class CONTENT_EXPORT RenderProcessHostImpl
// before the process shuts down.
void DelayProcessShutdownForUnload(const base::TimeDelta& timeout);
+ FileSystemManagerImpl* GetFileSystemManagerForTesting() {
+ return file_system_manager_impl_.get();
+ }
+
+ // Adds a CORB (Cross-Origin Read Blocking) exception for |process_id|. The
+ // exception will be removed when the corresponding RenderProcessHostImpl is
+ // destroyed (see |cleanup_corb_exception_for_plugin_upon_destruction_|).
+ static void AddCorbExceptionForPlugin(int process_id);
+
protected:
// A proxy for our IPC::Channel that lives on the IO thread.
std::unique_ptr<IPC::ChannelProxy> channel_;
@@ -436,7 +478,6 @@ class CONTENT_EXPORT RenderProcessHostImpl
friend class ChildProcessLauncherBrowserTest_ChildSpawnFail_Test;
friend class VisitRelayingRenderProcessHost;
friend class StoragePartitonInterceptor;
- friend class SecurityExploitBrowserTest;
class ConnectionFilterController;
class ConnectionFilterImpl;
@@ -461,14 +502,14 @@ class CONTENT_EXPORT RenderProcessHostImpl
void RegisterMojoInterfaces();
// mojom::RouteProvider:
- void GetRoute(
- int32_t routing_id,
- mojom::AssociatedInterfaceProviderAssociatedRequest request) override;
+ void GetRoute(int32_t routing_id,
+ blink::mojom::AssociatedInterfaceProviderAssociatedRequest
+ request) override;
- // mojom::AssociatedInterfaceProvider:
+ // blink::mojom::AssociatedInterfaceProvider:
void GetAssociatedInterface(
const std::string& name,
- mojom::AssociatedInterfaceAssociatedRequest request) override;
+ blink::mojom::AssociatedInterfaceAssociatedRequest request) override;
// mojom::RendererHost
using BrowserHistogramCallback =
@@ -476,7 +517,6 @@ class CONTENT_EXPORT RenderProcessHostImpl
void GetBrowserHistogram(const std::string& name,
BrowserHistogramCallback callback) override;
void SuddenTerminationChanged(bool enabled) override;
- void ShutdownRequest() override;
void BindRouteProvider(mojom::RouteProviderAssociatedRequest request);
@@ -488,6 +528,7 @@ class CONTENT_EXPORT RenderProcessHostImpl
void CreateStoragePartitionService(
blink::mojom::StoragePartitionServiceRequest request);
void CreateRendererHost(mojom::RendererHostAssociatedRequest request);
+ void BindVideoDecoderService(media::mojom::InterfaceFactoryRequest request);
// Control message handlers.
void OnUserMetricsRecordAction(const std::string& action);
@@ -543,20 +584,19 @@ class CONTENT_EXPORT RenderProcessHostImpl
// Get an existing RenderProcessHost associated with the given browser
// context, if possible. The renderer process is chosen randomly from
// suitable renderers that share the same context and type (determined by the
- // site url).
+ // site url of |site_instance|).
// Returns nullptr if no suitable renderer process is available, in which case
// the caller is free to create a new renderer.
static RenderProcessHost* GetExistingProcessHost(
- content::BrowserContext* browser_context,
- const GURL& site_url);
+ SiteInstanceImpl* site_instance);
FRIEND_TEST_ALL_PREFIXES(RenderProcessHostUnitTest,
GuestsAreNotSuitableHosts);
- // Returns a RenderProcessHost that is rendering |site_url| in one of its
- // frames, or that is expecting a navigation to |site_url|.
- static RenderProcessHost* FindReusableProcessHostForSite(
- BrowserContext* browser_context,
- const GURL& site_url);
+ // Returns a RenderProcessHost that is rendering a URL corresponding to
+ // |site_instance| in one of its frames, or that is expecting a navigation to
+ // that SiteInstance.
+ static RenderProcessHost* FindReusableProcessHostForSiteInstance(
+ SiteInstanceImpl* site_instance);
void CreateMediaStreamDispatcherHost(
MediaStreamManager* media_stream_manager,
@@ -646,10 +686,10 @@ class CONTENT_EXPORT RenderProcessHostImpl
// Mojo interfaces provided to the child process are registered here if they
// need consistent delivery ordering with legacy IPC, and are process-wide in
// nature (e.g. metrics, memory usage).
- std::unique_ptr<AssociatedInterfaceRegistryImpl> associated_interfaces_;
+ std::unique_ptr<blink::AssociatedInterfaceRegistry> associated_interfaces_;
mojo::AssociatedBinding<mojom::RouteProvider> route_provider_binding_;
- mojo::AssociatedBindingSet<mojom::AssociatedInterfaceProvider, int32_t>
+ mojo::AssociatedBindingSet<blink::mojom::AssociatedInterfaceProvider, int32_t>
associated_interface_provider_bindings_;
// These fields are cached values that are updated in
@@ -662,6 +702,10 @@ class CONTENT_EXPORT RenderProcessHostImpl
// widgets the lowest depth of all hidden clients. Initialized to max depth
// when there are no clients.
unsigned int frame_depth_ = kMaxFrameDepthForPriority;
+ // |intersects_viewport_| similar to |frame_depth_| can be used to rank
+ // processes of same visibility. It indicates process has frames that
+ // intersect with the viewport.
+ bool intersects_viewport_ = false;
#if defined(OS_ANDROID)
// Highest importance of all clients that contribute priority.
ChildProcessImportance effective_importance_ = ChildProcessImportance::NORMAL;
@@ -715,7 +759,7 @@ class CONTENT_EXPORT RenderProcessHostImpl
StoragePartitionImpl* storage_partition_impl_;
// The observers watching our lifetime.
- base::ObserverList<RenderProcessHostObserver> observers_;
+ base::ObserverList<RenderProcessHostObserver>::Unchecked observers_;
// True if the process can be shut down suddenly. If this is true, then we're
// sure that all the RenderViews in the process can be shutdown suddenly. If
@@ -757,7 +801,7 @@ class CONTENT_EXPORT RenderProcessHostImpl
BrowserThread::DeleteOnIOThread>
audio_output_stream_factory_context_;
- scoped_refptr<P2PSocketDispatcherHost> p2p_socket_dispatcher_host_;
+ std::unique_ptr<P2PSocketDispatcherHost> p2p_socket_dispatcher_host_;
// Must be accessed on UI thread.
std::vector<int> aec_dump_consumers_;
@@ -771,6 +815,8 @@ class CONTENT_EXPORT RenderProcessHostImpl
std::unique_ptr<MediaStreamTrackMetricsHost, BrowserThread::DeleteOnIOThread>
media_stream_track_metrics_host_;
+ std::unique_ptr<VideoDecoderProxy> video_decoder_proxy_;
+
// Forwards messages between WebRTCInternals in the browser process
// and PeerConnectionTracker in the renderer process.
// It holds a raw pointer to webrtc_eventlog_host_, and therefore should be
@@ -808,7 +854,9 @@ class CONTENT_EXPORT RenderProcessHostImpl
#endif
scoped_refptr<ResourceMessageFilter> resource_message_filter_;
- std::unique_ptr<GpuClientImpl, BrowserThread::DeleteOnIOThread> gpu_client_;
+ std::unique_ptr<FileSystemManagerImpl, BrowserThread::DeleteOnIOThread>
+ file_system_manager_impl_;
+ std::unique_ptr<viz::GpuClient, BrowserThread::DeleteOnIOThread> gpu_client_;
std::unique_ptr<PushMessagingManager, BrowserThread::DeleteOnIOThread>
push_messaging_manager_;
@@ -837,6 +885,8 @@ class CONTENT_EXPORT RenderProcessHostImpl
std::unique_ptr<mojo::Binding<viz::mojom::CompositingModeReporter>>
compositing_mode_reporter_;
+ bool cleanup_corb_exception_for_plugin_upon_destruction_ = false;
+
base::WeakPtrFactory<RenderProcessHostImpl> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(RenderProcessHostImpl);
diff --git a/chromium/content/browser/renderer_host/render_process_host_unittest.cc b/chromium/content/browser/renderer_host/render_process_host_unittest.cc
index b036f1a9a31..9a91cd8279e 100644
--- a/chromium/content/browser/renderer_host/render_process_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/render_process_host_unittest.cc
@@ -42,12 +42,16 @@ TEST_F(RenderProcessHostUnitTest, GuestsAreNotSuitableHosts) {
MockRenderProcessHost guest_host(browser_context());
guest_host.set_is_for_guests_only(true);
+ scoped_refptr<SiteInstanceImpl> site_instance =
+ SiteInstanceImpl::CreateForURL(browser_context(), test_url);
EXPECT_FALSE(RenderProcessHostImpl::IsSuitableHost(
- &guest_host, browser_context(), test_url));
+ &guest_host, browser_context(), site_instance->GetSiteURL(),
+ site_instance->lock_url()));
EXPECT_TRUE(RenderProcessHostImpl::IsSuitableHost(
- process(), browser_context(), test_url));
- EXPECT_EQ(process(), RenderProcessHostImpl::GetExistingProcessHost(
- browser_context(), test_url));
+ process(), browser_context(), site_instance->GetSiteURL(),
+ site_instance->lock_url()));
+ EXPECT_EQ(process(),
+ RenderProcessHostImpl::GetExistingProcessHost(site_instance.get()));
}
#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
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 1f491537c8f..a25a92f7eb0 100644
--- a/chromium/content/browser/renderer_host/render_view_host_impl.cc
+++ b/chromium/content/browser/renderer_host/render_view_host_impl.cc
@@ -481,11 +481,18 @@ WebPreferences RenderViewHostImpl::ComputeWebkitPrefs() {
NOTREACHED();
}
+ // On Android, Touch event feature detection is enabled by default,
+ // Otherwise default is disabled.
+ std::string touch_enabled_default_switch =
+ switches::kTouchEventFeatureDetectionDisabled;
+#if defined(OS_ANDROID)
+ touch_enabled_default_switch = switches::kTouchEventFeatureDetectionEnabled;
+#endif // defined(OS_ANDROID)
const std::string touch_enabled_switch =
command_line.HasSwitch(switches::kTouchEventFeatureDetection)
? command_line.GetSwitchValueASCII(
switches::kTouchEventFeatureDetection)
- : switches::kTouchEventFeatureDetectionAuto;
+ : touch_enabled_default_switch;
prefs.touch_event_feature_detection_enabled =
(touch_enabled_switch == switches::kTouchEventFeatureDetectionAuto)
? (ui::GetTouchScreensAvailability() ==
@@ -493,6 +500,7 @@ WebPreferences RenderViewHostImpl::ComputeWebkitPrefs() {
: (touch_enabled_switch.empty() ||
touch_enabled_switch ==
switches::kTouchEventFeatureDetectionEnabled);
+
std::tie(prefs.available_pointer_types, prefs.available_hover_types) =
ui::GetAvailablePointerAndHoverTypes();
prefs.primary_pointer_type =
@@ -906,14 +914,14 @@ void RenderViewHostImpl::OnFocus() {
void RenderViewHostImpl::RenderWidgetDidForwardMouseEvent(
const blink::WebMouseEvent& mouse_event) {
if (mouse_event.GetType() == WebInputEvent::kMouseWheel &&
- GetWidget()->ignore_input_events()) {
+ GetWidget()->IsIgnoringInputEvents()) {
delegate_->OnIgnoredUIEvent();
}
}
bool RenderViewHostImpl::MayRenderWidgetForwardKeyboardEvent(
const NativeWebKeyboardEvent& key_event) {
- if (GetWidget()->ignore_input_events()) {
+ if (GetWidget()->IsIgnoringInputEvents()) {
if (key_event.GetType() == WebInputEvent::kRawKeyDown)
delegate_->OnIgnoredUIEvent();
return false;
diff --git a/chromium/content/browser/renderer_host/render_widget_host_delegate.cc b/chromium/content/browser/renderer_host/render_widget_host_delegate.cc
index 00c3a8c727d..aa01d7b2207 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_delegate.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_delegate.cc
@@ -17,11 +17,20 @@ KeyboardEventProcessingResult RenderWidgetHostDelegate::PreHandleKeyboardEvent(
return KeyboardEventProcessingResult::NOT_HANDLED;
}
+bool RenderWidgetHostDelegate::PreHandleMouseEvent(
+ const blink::WebMouseEvent& event) {
+ return false;
+}
+
bool RenderWidgetHostDelegate::HandleWheelEvent(
const blink::WebMouseWheelEvent& event) {
return false;
}
+bool RenderWidgetHostDelegate::ShouldIgnoreInputEvents() {
+ return false;
+}
+
bool RenderWidgetHostDelegate::PreHandleGestureEvent(
const blink::WebGestureEvent& event) {
return false;
diff --git a/chromium/content/browser/renderer_host/render_widget_host_delegate.h b/chromium/content/browser/renderer_host/render_widget_host_delegate.h
index b054514ea74..387c81db0e0 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_delegate.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_delegate.h
@@ -23,6 +23,7 @@
#include "ui/gfx/range/range.h"
namespace blink {
+class WebMouseEvent;
class WebMouseWheelEvent;
class WebGestureEvent;
}
@@ -89,6 +90,13 @@ class CONTENT_EXPORT RenderWidgetHostDelegate {
virtual KeyboardEventProcessingResult PreHandleKeyboardEvent(
const NativeWebKeyboardEvent& event);
+ // Callback to give the browser a chance to handle the specified mouse
+ // event before sending it to the renderer.
+ // Returns true if the |event| was handled.
+ // TODO(carlosil, nasko): remove once committed interstitial pages are
+ // fully implemented.
+ virtual bool PreHandleMouseEvent(const blink::WebMouseEvent& event);
+
// Callback to inform the browser that the renderer did not process the
// specified events. This gives an opportunity to the browser to process the
// event (used for keyboard shortcuts).
@@ -104,6 +112,9 @@ class CONTENT_EXPORT RenderWidgetHostDelegate {
virtual void DidReceiveInputEvent(RenderWidgetHostImpl* render_widget_host,
const blink::WebInputEvent::Type type) {}
+ // Asks whether the page is in a state of ignoring input events.
+ virtual bool ShouldIgnoreInputEvents();
+
// Callback to give the browser a chance to handle the specified gesture
// event before sending it to the renderer.
// Returns true if the |event| was handled.
@@ -138,7 +149,8 @@ class CONTENT_EXPORT RenderWidgetHostDelegate {
#if defined(OS_MACOSX)
virtual void DidChangeTextSelection(const base::string16& text,
- const gfx::Range& range) {}
+ const gfx::Range& range,
+ size_t offset) {}
#endif
// Request the renderer to Move the caret to the new position.
@@ -272,6 +284,7 @@ class CONTENT_EXPORT RenderWidgetHostDelegate {
// Get the UKM source ID for current content. This is used for providing
// data about the content to the URL-keyed metrics service.
+ // Note: This is also exposed by the RenderFrameHostDelegate.
virtual ukm::SourceId GetUkmSourceIdForLastCommittedSource() const;
// Notifies the delegate that a focused editable element has been touched
@@ -283,9 +296,6 @@ class CONTENT_EXPORT RenderWidgetHostDelegate {
// not a WebContents, returns nullptr.
virtual WebContents* GetAsWebContents();
- // Notifies that a CompositorFrame was received from the renderer.
- virtual void DidReceiveCompositorFrame() {}
-
// Gets the size set by a top-level frame with auto-resize enabled.
virtual gfx::Size GetAutoResizeSize();
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 9ab96c3f933..437b43ade73 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_impl.cc
@@ -27,7 +27,7 @@
#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/default_tick_clock.h"
#include "base/trace_event/trace_event.h"
@@ -292,7 +292,8 @@ class UnboundWidgetInputHandler : public mojom::WidgetInputHandler {
void ImeCommitText(const base::string16& text,
const std::vector<ui::ImeTextSpan>& ime_text_spans,
const gfx::Range& range,
- int32_t relative_cursor_position) override {
+ int32_t relative_cursor_position,
+ ImeCommitTextCallback callback) override {
DLOG(WARNING) << "Input request on unbound interface";
}
void ImeFinishComposingText(bool keep_selection) override {
@@ -350,7 +351,6 @@ RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
is_unresponsive_(false),
in_flight_event_count_(0),
in_get_backing_store_(false),
- ignore_input_events_(false),
text_direction_updated_(false),
text_direction_(blink::kWebTextDirectionLeftToRight),
text_direction_canceled_(false),
@@ -407,8 +407,8 @@ RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
const auto* command_line = base::CommandLine::ForCurrentProcess();
if (!command_line->HasSwitch(switches::kDisableHangMonitor)) {
input_event_ack_timeout_.reset(new TimeoutMonitor(
- base::Bind(&RenderWidgetHostImpl::RendererIsUnresponsive,
- weak_factory_.GetWeakPtr())));
+ base::BindRepeating(&RenderWidgetHostImpl::OnInputEventAckTimeout,
+ weak_factory_.GetWeakPtr())));
}
if (!command_line->HasSwitch(switches::kDisableNewContentRenderingTimeout)) {
@@ -570,6 +570,14 @@ void RenderWidgetHostImpl::SetFrameDepth(unsigned int depth) {
UpdatePriority();
}
+void RenderWidgetHostImpl::SetIntersectsViewport(bool intersects) {
+ if (intersects_viewport_ == intersects)
+ return;
+
+ intersects_viewport_ = intersects;
+ UpdatePriority();
+}
+
void RenderWidgetHostImpl::UpdatePriority() {
if (!destroyed_)
process_->UpdateClientPriority(this);
@@ -672,8 +680,6 @@ bool RenderWidgetHostImpl::OnMessageReceived(const IPC::Message &msg) {
OnTextInputStateChanged)
IPC_MESSAGE_HANDLER(ViewHostMsg_LockMouse, OnLockMouse)
IPC_MESSAGE_HANDLER(ViewHostMsg_UnlockMouse, OnUnlockMouse)
- IPC_MESSAGE_HANDLER(ViewHostMsg_ShowDisambiguationPopup,
- OnShowDisambiguationPopup)
IPC_MESSAGE_HANDLER(ViewHostMsg_SelectionBoundsChanged,
OnSelectionBoundsChanged)
IPC_MESSAGE_HANDLER(ViewHostMsg_FocusedNodeTouched, OnFocusedNodeTouched)
@@ -1189,19 +1195,8 @@ void RenderWidgetHostImpl::DidNavigate(uint32_t next_source_id) {
// |visual_properties_ack_pending_| and make sure the next resize will be
// acked if the last resize before navigation was supposed to be acked.
visual_properties_ack_pending_ = false;
- viz::LocalSurfaceId old_surface_id = view_->GetLocalSurfaceId();
if (view_)
view_->DidNavigate();
- viz::LocalSurfaceId new_surface_id = view_->GetLocalSurfaceId();
- // If |view_| didn't allocate a new surface id, then don't start
- // |new_content_rendering_timeout_|. Two reasons:
- // 1. It's not needed (because this was the first navigation event)
- // 2. If we don't change the surface id, then we will not get the call to
- // OnFirstSurfaceActivation, and not stop the timer (even if we get new
- // frames).
- // https://crbug.com/853651, https://crbug.com/535375
- if (old_surface_id == new_surface_id)
- return;
} else {
// It is possible for a compositor frame to arrive before the browser is
// notified about the page being committed, in which case no timer is
@@ -1247,7 +1242,11 @@ void RenderWidgetHostImpl::ForwardMouseEventWithLatencyInfo(
return;
}
- if (ShouldDropInputEvents())
+ if (IsIgnoringInputEvents())
+ return;
+
+ // Delegate must be non-null, due to |IsIgnoringInputEvents()| test.
+ if (delegate_->PreHandleMouseEvent(mouse_event))
return;
auto* touch_emulator = GetExistingTouchEmulator();
@@ -1273,7 +1272,7 @@ void RenderWidgetHostImpl::ForwardWheelEventWithLatencyInfo(
TRACE_EVENT2("input", "RenderWidgetHostImpl::ForwardWheelEvent", "dx",
wheel_event.delta_x, "dy", wheel_event.delta_y);
- if (ShouldDropInputEvents())
+ if (IsIgnoringInputEvents())
return;
auto* touch_emulator = GetExistingTouchEmulator();
@@ -1304,7 +1303,7 @@ void RenderWidgetHostImpl::ForwardGestureEventWithLatencyInfo(
TRACE_EVENT1("input", "RenderWidgetHostImpl::ForwardGestureEvent", "type",
WebInputEvent::GetName(gesture_event.GetType()));
// Early out if necessary, prior to performing latency logic.
- if (ShouldDropInputEvents())
+ if (IsIgnoringInputEvents())
return;
bool scroll_update_needs_wrapping = false;
@@ -1393,7 +1392,7 @@ void RenderWidgetHostImpl::ForwardGestureEventWithLatencyInfo(
gesture_event));
}
- // Delegate must be non-null, due to |ShouldDropInputEvents()| test.
+ // Delegate must be non-null, due to |IsIgnoringInputEvents()| test.
if (delegate_->PreHandleGestureEvent(gesture_event))
return;
@@ -1459,7 +1458,7 @@ void RenderWidgetHostImpl::ForwardKeyboardEventWithCommands(
return;
}
- if (ShouldDropInputEvents())
+ if (IsIgnoringInputEvents())
return;
if (!process_->IsInitializedAndNotDead())
@@ -1722,6 +1721,7 @@ RenderProcessHost::Priority RenderWidgetHostImpl::GetPriority() {
RenderProcessHost::Priority priority = {
is_hidden_,
frame_depth_,
+ intersects_viewport_,
#if defined(OS_ANDROID)
importance_,
#endif
@@ -1982,8 +1982,9 @@ void RenderWidgetHostImpl::ImeCommitText(
const std::vector<ui::ImeTextSpan>& ime_text_spans,
const gfx::Range& replacement_range,
int relative_cursor_pos) {
- GetWidgetInputHandler()->ImeCommitText(
- text, ime_text_spans, replacement_range, relative_cursor_pos);
+ GetWidgetInputHandler()->ImeCommitText(text, ime_text_spans,
+ replacement_range, relative_cursor_pos,
+ base::OnceClosure());
}
void RenderWidgetHostImpl::ImeFinishComposingText(bool keep_selection) {
@@ -2077,18 +2078,24 @@ void RenderWidgetHostImpl::Destroy(bool also_delete) {
}
}
-void RenderWidgetHostImpl::RendererIsUnresponsive() {
+void RenderWidgetHostImpl::OnInputEventAckTimeout() {
+ RendererIsUnresponsive(base::BindRepeating(
+ &RenderWidgetHostImpl::RestartInputEventAckTimeoutIfNecessary,
+ weak_factory_.GetWeakPtr()));
+}
+
+void RenderWidgetHostImpl::RendererIsUnresponsive(
+ base::RepeatingClosure restart_hang_monitor_timeout) {
NotificationService::current()->Notify(
NOTIFICATION_RENDER_WIDGET_HOST_HANG,
Source<RenderWidgetHost>(this),
NotificationService::NoDetails());
is_unresponsive_ = true;
- if (delegate_)
- delegate_->RendererUnresponsive(
- this, base::BindRepeating(
- &RenderWidgetHostImpl::RestartInputEventAckTimeoutIfNecessary,
- weak_factory_.GetWeakPtr()));
+ if (delegate_) {
+ delegate_->RendererUnresponsive(this,
+ std::move(restart_hang_monitor_timeout));
+ }
// Do not add code after this since the Delegate may delete this
// RenderWidgetHostImpl in RendererUnresponsive.
@@ -2104,8 +2111,12 @@ void RenderWidgetHostImpl::RendererIsResponsive() {
void RenderWidgetHostImpl::ClearDisplayedGraphics() {
NotifyNewContentRenderingTimeoutForTesting();
- if (view_)
- view_->ClearCompositorFrame();
+ if (view_) {
+ if (enable_surface_synchronization_)
+ view_->ResetFallbackToFirstNavigationSurface();
+ else
+ view_->ClearCompositorFrame();
+ }
}
void RenderWidgetHostImpl::OnRenderProcessGone(int status, int exit_code) {
@@ -2225,7 +2236,7 @@ void RenderWidgetHostImpl::DidUpdateVisualProperties(
NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_VISUAL_PROPERTIES,
Source<RenderWidgetHost>(this), NotificationService::NoDetails());
- if (!view_ || is_hidden_)
+ if (!view_)
return;
viz::ScopedSurfaceIdAllocator scoped_allocator =
@@ -2321,8 +2332,10 @@ bool RenderWidgetHostImpl::IsWheelScrollInProgress() {
}
void RenderWidgetHostImpl::SetMouseCapture(bool capture) {
- if (delegate_)
- delegate_->GetInputEventRouter()->SetMouseCaptureTarget(GetView(), capture);
+ if (!delegate_ || !delegate_->GetInputEventRouter())
+ return;
+
+ delegate_->GetInputEventRouter()->SetMouseCaptureTarget(GetView(), capture);
}
void RenderWidgetHostImpl::OnInvalidFrameToken(uint32_t frame_token) {
@@ -2417,39 +2430,6 @@ RenderWidgetHostImpl::GetKeyboardLayoutMap() {
return view_->GetKeyboardLayoutMap();
}
-void RenderWidgetHostImpl::OnShowDisambiguationPopup(
- const gfx::Rect& rect_pixels,
- const gfx::Size& size,
- base::SharedMemoryHandle handle) {
- DCHECK(!rect_pixels.IsEmpty());
- DCHECK(!size.IsEmpty());
-
- SkImageInfo info = SkImageInfo::MakeN32Premul(size.width(), size.height());
- size_t shm_size = info.computeMinByteSize();
-
- base::SharedMemory shm(handle, false /* read_only */);
- if (shm_size == 0 || !shm.Map(shm_size)) {
- bad_message::ReceivedBadMessage(GetProcess(),
- bad_message::RWH_SHARED_BITMAP);
- return;
- }
-
- SkBitmap zoomed_bitmap;
- zoomed_bitmap.installPixels(info, shm.memory(), info.minRowBytes());
-
- // Note that |rect| is in coordinates of pixels relative to the window origin.
- // Aura-based systems will want to convert this to DIPs.
- if (view_)
- view_->ShowDisambiguationPopup(rect_pixels, zoomed_bitmap);
-
- // It is assumed that the disambiguation popup will make a copy of the
- // provided zoomed image, so we delete |zoomed_bitmap| and free shared memory.
-}
-
-void RenderWidgetHostImpl::SetIgnoreInputEvents(bool ignore_input_events) {
- ignore_input_events_ = ignore_input_events;
-}
-
bool RenderWidgetHostImpl::KeyPressListenersHandleEvent(
const NativeWebKeyboardEvent& event) {
if (event.skip_in_browser || event.GetType() != WebKeyboardEvent::kRawKeyDown)
@@ -2477,7 +2457,7 @@ InputEventAckState RenderWidgetHostImpl::FilterInputEvent(
// Don't ignore touch cancel events, since they may be sent while input
// events are being ignored in order to keep the renderer from getting
// confused about how many touches are active.
- if (ShouldDropInputEvents() && event.GetType() != WebInputEvent::kTouchCancel)
+ if (IsIgnoringInputEvents() && event.GetType() != WebInputEvent::kTouchCancel)
return INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS;
if (!process_->IsInitializedAndNotDead())
@@ -2626,13 +2606,16 @@ void RenderWidgetHostImpl::OnTouchEventAck(
for (auto& input_event_observer : input_event_observers_)
input_event_observer.OnInputEventAck(ack_source, ack_result, event.event);
- auto* touch_emulator = GetExistingTouchEmulator();
- if (touch_emulator &&
- touch_emulator->HandleTouchEventAck(event.event, ack_result)) {
- return;
- }
+ auto* input_event_router =
+ delegate() ? delegate()->GetInputEventRouter() : nullptr;
- if (view_)
+ // At present interstitial pages might not have an input event router, so we
+ // just have the view process the ack directly in that case; the view is
+ // guaranteed to be a top-level view with an appropriate implementation of
+ // ProcessAckedTouchEvent().
+ if (input_event_router)
+ input_event_router->ProcessAckedTouchEvent(event, ack_result, view_.get());
+ else if (view_)
view_->ProcessAckedTouchEvent(event, ack_result);
}
@@ -2644,8 +2627,9 @@ void RenderWidgetHostImpl::OnUnexpectedEventAck(UnexpectedEventAckType type) {
}
}
-bool RenderWidgetHostImpl::ShouldDropInputEvents() const {
- return ignore_input_events_ || process_->IgnoreInputEvents() || !delegate_;
+bool RenderWidgetHostImpl::IsIgnoringInputEvents() const {
+ return process_->IgnoreInputEvents() || !delegate_ ||
+ delegate_->ShouldIgnoreInputEvents();
}
void RenderWidgetHostImpl::SetBackgroundOpaque(bool opaque) {
@@ -2988,9 +2972,6 @@ void RenderWidgetHostImpl::SubmitCompositorFrame(
}
}
}
-
- if (delegate_)
- delegate_->DidReceiveCompositorFrame();
}
void RenderWidgetHostImpl::DidProcessFrame(uint32_t frame_token) {
@@ -3075,16 +3056,6 @@ void RenderWidgetHostImpl::ProgressFlingIfNeeded(TimeTicks current_time) {
fling_scheduler_->ProgressFlingOnBeginFrameIfneeded(current_time);
}
-void RenderWidgetHostImpl::DidReceiveFirstFrameAfterNavigation() {
- DCHECK(enable_surface_synchronization_);
- did_receive_first_frame_after_navigation_ = true;
- if (!new_content_rendering_timeout_ ||
- !new_content_rendering_timeout_->IsRunning()) {
- return;
- }
- new_content_rendering_timeout_->Stop();
-}
-
void RenderWidgetHostImpl::ForceFirstFrameAfterNavigationTimeout() {
if (did_receive_first_frame_after_navigation_ ||
!new_content_rendering_timeout_) {
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 4af5870e7c4..c2d8cd56243 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_impl.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_impl.h
@@ -199,7 +199,6 @@ class CONTENT_EXPORT RenderWidgetHostImpl
RenderWidgetHostViewBase* GetView() const override;
bool IsLoading() const override;
bool IsCurrentlyUnresponsive() const override;
- void SetIgnoreInputEvents(bool ignore_input_events) override;
bool SynchronizeVisualProperties() override;
void AddKeyPressEventCallback(const KeyPressEventCallback& callback) override;
void RemoveKeyPressEventCallback(
@@ -288,6 +287,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl
}
void SetFrameDepth(unsigned int depth);
+ void SetIntersectsViewport(bool intersects);
void UpdatePriority();
// Tells the renderer to die and optionally delete |this|.
@@ -479,12 +479,8 @@ class CONTENT_EXPORT RenderWidgetHostImpl
// Cancels an ongoing composition.
void ImeCancelComposition();
- bool ignore_input_events() const {
- return ignore_input_events_;
- }
-
- // Whether forwarded WebInputEvents should be dropped.
- bool ShouldDropInputEvents() const;
+ // Whether forwarded WebInputEvents are being ignored.
+ bool IsIgnoringInputEvents() const;
bool has_touch_handler() const { return has_touch_handler_; }
@@ -683,8 +679,6 @@ class CONTENT_EXPORT RenderWidgetHostImpl
bool FlingCancellationIsDeferred() const;
void SetNeedsBeginFrameForFlingProgress();
- void DidReceiveFirstFrameAfterNavigation();
-
// The RenderWidgetHostImpl will keep showing the old page (for a while) after
// navigation until the first frame of the new page arrives. This reduces
// flicker. However, if for some reason it is known that the frames won't be
@@ -712,10 +706,21 @@ class CONTENT_EXPORT RenderWidgetHostImpl
// Returns the keyboard layout mapping.
base::flat_map<std::string, std::string> GetKeyboardLayoutMap();
- void DidStopFlinging() override;
+ void DidStopFlinging();
void GetContentRenderingTimeoutFrom(RenderWidgetHostImpl* other);
+ // Called on delayed response from the renderer by either
+ // 1) |hang_monitor_timeout_| (slow to ack input events) or
+ // 2) NavigationHandle::OnCommitTimeout (slow to commit).
+ void RendererIsUnresponsive(
+ base::RepeatingClosure restart_hang_monitor_timeout);
+
+ // Called if we know the renderer is responsive. When we currently think the
+ // renderer is unresponsive, this will clear that state and call
+ // NotifyRendererResponsive.
+ void RendererIsResponsive();
+
protected:
// ---------------------------------------------------------------------------
// The following method is overridden by RenderViewHost to send upwards to
@@ -793,18 +798,10 @@ class CONTENT_EXPORT RenderWidgetHostImpl
// destructor is called as well.
void Destroy(bool also_delete);
- // Called by |input_event_ack_timeout_| on delayed response from the renderer.
- void RendererIsUnresponsive();
-
// Called by |new_content_rendering_timeout_| if a renderer has loaded new
// content but failed to produce a compositor frame in a defined time.
void ClearDisplayedGraphics();
- // Called if we know the renderer is responsive. When we currently think the
- // renderer is unresponsive, this will clear that state and call
- // NotifyRendererResponsive.
- void RendererIsResponsive();
-
// IPC message handlers
void OnRenderProcessGone(int status, int error_code);
void OnClose();
@@ -821,9 +818,6 @@ class CONTENT_EXPORT RenderWidgetHostImpl
void OnLockMouse(bool user_gesture,
bool privileged);
void OnUnlockMouse();
- void OnShowDisambiguationPopup(const gfx::Rect& rect_pixels,
- const gfx::Size& size,
- base::SharedMemoryHandle handle);
void OnSelectionBoundsChanged(
const ViewHostMsg_SelectionBounds_Params& params);
void OnSetNeedsBeginFrames(bool needs_begin_frames);
@@ -890,6 +884,10 @@ class CONTENT_EXPORT RenderWidgetHostImpl
// was noticed because of input event ack timeout.
void RestartInputEventAckTimeoutIfNecessary();
+ // Called by |input_event_ack_timeout_| when an input event timed out without
+ // getting an ack from the renderer.
+ void OnInputEventAckTimeout();
+
void SetupInputRouter();
// Start intercepting system keyboard events.
@@ -951,6 +949,11 @@ class CONTENT_EXPORT RenderWidgetHostImpl
// is depth 1, ie just below the root widget.
unsigned int frame_depth_ = 1u;
+ // Indicates that widget has a frame that intersects with the viewport. Note
+ // this is independent of |is_hidden_|. For widgets not associated with
+ // RenderFrame/View, assume false.
+ bool intersects_viewport_ = false;
+
#if defined(OS_ANDROID)
// Tracks the current importance of widget.
ChildProcessImportance importance_ = ChildProcessImportance::NORMAL;
@@ -983,11 +986,11 @@ class CONTENT_EXPORT RenderWidgetHostImpl
std::vector<MouseEventCallback> mouse_event_callbacks_;
// Input event callbacks.
- base::ObserverList<RenderWidgetHost::InputEventObserver>
+ base::ObserverList<RenderWidgetHost::InputEventObserver>::Unchecked
input_event_observers_;
// The observers watching us.
- base::ObserverList<RenderWidgetHostObserver> observers_;
+ base::ObserverList<RenderWidgetHostObserver>::Unchecked observers_;
// If true, then we should repaint when restoring even if we have a
// backingstore. This flag is set to true if we receive a paint message
@@ -1009,9 +1012,6 @@ class CONTENT_EXPORT RenderWidgetHostImpl
// operation to finish.
base::TimeTicks repaint_start_time_;
- // Set to true if we shouldn't send input events from the render widget.
- bool ignore_input_events_;
-
// Set when we update the text direction of the selected input element.
bool text_direction_updated_;
blink::WebTextDirection text_direction_;
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 52a1434b1b4..e3d18fefaf8 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
@@ -154,6 +154,9 @@ void RenderWidgetHostInputEventRouter::OnRenderWidgetHostViewBaseDestroyed(
if (view == last_fling_start_target_)
last_fling_start_target_ = nullptr;
+ if (view == last_fling_start_bubbled_target_)
+ last_fling_start_bubbled_target_ = nullptr;
+
event_targeter_->ViewWillBeDestroyed(view);
}
@@ -173,7 +176,7 @@ RenderWidgetHostInputEventRouter::HittestDelegate::HittestDelegate(
bool RenderWidgetHostInputEventRouter::HittestDelegate::RejectHitTarget(
const viz::SurfaceDrawQuad* surface_quad,
const gfx::Point& point_in_quad_space) {
- auto it = hittest_data_.find(surface_quad->primary_surface_id);
+ auto it = hittest_data_.find(surface_quad->surface_range.end());
if (it != hittest_data_.end() && it->second.ignored_for_hittest)
return true;
return false;
@@ -182,7 +185,7 @@ bool RenderWidgetHostInputEventRouter::HittestDelegate::RejectHitTarget(
bool RenderWidgetHostInputEventRouter::HittestDelegate::AcceptHitTarget(
const viz::SurfaceDrawQuad* surface_quad,
const gfx::Point& point_in_quad_space) {
- auto it = hittest_data_.find(surface_quad->primary_surface_id);
+ auto it = hittest_data_.find(surface_quad->surface_range.end());
if (it != hittest_data_.end() && !it->second.ignored_for_hittest)
return true;
return false;
@@ -573,9 +576,12 @@ void RenderWidgetHostInputEventRouter::DispatchTouchEvent(
// of the touch sequence, though this could be wrong; a better approach
// might be to always transform each point to the |touch_target_.target|
// for the duration of the sequence.
- DCHECK(target_location.has_value());
- touch_target_.delta =
- target_location.value() - touch_event.touches[0].PositionInWidget();
+ if (target_location.has_value()) {
+ touch_target_.delta =
+ target_location.value() - touch_event.touches[0].PositionInWidget();
+ } else {
+ touch_target_.delta = gfx::Vector2dF();
+ }
DCHECK(touchscreen_gesture_target_map_.find(
touch_event.unique_touch_event_id) ==
@@ -596,6 +602,14 @@ void RenderWidgetHostInputEventRouter::DispatchTouchEvent(
}
DCHECK_GE(active_touches_, 0);
+ // Debugging for crbug.com/814674.
+ if (touch_target_.target && !IsViewInMap(touch_target_.target)) {
+ NOTREACHED() << "Touch events should not be routed to a destroyed target "
+ "View.";
+ touch_target_.target = nullptr;
+ base::debug::DumpWithoutCrashing();
+ }
+
if (!touch_target_.target) {
TouchEventWithLatencyInfo touch_with_latency(touch_event, latency);
root_view->ProcessAckedTouchEvent(touch_with_latency,
@@ -619,6 +633,28 @@ void RenderWidgetHostInputEventRouter::DispatchTouchEvent(
touch_target_.target = nullptr;
}
+void RenderWidgetHostInputEventRouter::ProcessAckedTouchEvent(
+ const TouchEventWithLatencyInfo& event,
+ InputEventAckState ack_result,
+ RenderWidgetHostViewBase* view) {
+ // TODO(wjmaclean): Eventually we will keep track of which outgoing touch
+ // events are emulated and which aren't, so the decision to hand off to the
+ // touch emulator won't just rely on the existence of the touch emulator.
+ if (touch_emulator_ &&
+ touch_emulator_->HandleTouchEventAck(event.event, ack_result)) {
+ return;
+ }
+
+ if (!view)
+ return;
+
+ auto* root_view = view->GetRootView();
+ if (!root_view)
+ return;
+
+ root_view->ProcessAckedTouchEvent(event, ack_result);
+}
+
void RenderWidgetHostInputEventRouter::RouteTouchEvent(
RenderWidgetHostViewBase* root_view,
blink::WebTouchEvent* event,
@@ -795,7 +831,8 @@ void RenderWidgetHostInputEventRouter::BubbleScrollEvent(
DCHECK(event.GetType() == blink::WebInputEvent::kGestureScrollBegin ||
event.GetType() == blink::WebInputEvent::kGestureScrollUpdate ||
event.GetType() == blink::WebInputEvent::kGestureScrollEnd ||
- event.GetType() == blink::WebInputEvent::kGestureFlingStart);
+ event.GetType() == blink::WebInputEvent::kGestureFlingStart ||
+ event.GetType() == blink::WebInputEvent::kGestureFlingCancel);
ui::LatencyInfo latency_info =
ui::WebInputEventTraits::CreateLatencyInfoForWebGestureEvent(event);
@@ -824,7 +861,26 @@ void RenderWidgetHostInputEventRouter::BubbleScrollEvent(
}
bubbling_gesture_scroll_target_.target = target_view;
+ } else if (event.GetType() == blink::WebInputEvent::kGestureFlingCancel) {
+ // TODO(828422): Remove once this issue no longer occurs.
+ if (resending_view == last_fling_start_bubbled_target_) {
+ ReportBubblingScrollToSameView(event, resending_view);
+ last_fling_start_bubbled_target_ = nullptr;
+ return;
+ }
+ // GFC event must get bubbled to the same target view that the last GFS has
+ // been bubbled.
+ if (last_fling_start_bubbled_target_) {
+ last_fling_start_bubbled_target_->ProcessGestureEvent(
+ GestureEventInTarget(event, last_fling_start_bubbled_target_),
+ latency_info);
+ last_fling_start_bubbled_target_ = nullptr;
+ }
+ return;
} else { // !(event.GetType() == blink::WebInputEvent::kGestureScrollBegin)
+ // && !(event.GetType() ==
+ // blink::WebInputEvent::kGestureFlingCancel)
+
if (!bubbling_gesture_scroll_target_.target) {
// The GestureScrollBegin event is not bubbled, don't bubble the rest of
// the scroll events.
@@ -856,6 +912,12 @@ void RenderWidgetHostInputEventRouter::BubbleScrollEvent(
bubbling_gesture_scroll_target_.target->ProcessGestureEvent(
GestureEventInTarget(event, bubbling_gesture_scroll_target_.target),
latency_info);
+
+ // The GFC should be sent to the view that handles the GFS.
+ if (event.GetType() == blink::WebInputEvent::kGestureFlingStart) {
+ last_fling_start_bubbled_target_ = bubbling_gesture_scroll_target_.target;
+ }
+
if (event.GetType() == blink::WebInputEvent::kGestureScrollEnd ||
event.GetType() == blink::WebInputEvent::kGestureFlingStart) {
first_bubbling_scroll_target_.target = nullptr;
@@ -1061,6 +1123,9 @@ void RenderWidgetHostInputEventRouter::DispatchTouchscreenGestureEvent(
if (target_allowed_touch_action.value() &
cc::TouchAction::kTouchActionPinchZoom) {
gesture_pinch_did_send_scroll_begin_ = true;
+ // The pinch gesture will be sent to the root view and it may not have a
+ // valid touch action yet. In this case, set the touch action to auto.
+ rwhi->input_router()->ForceSetTouchActionAuto();
SendGestureScrollBegin(root_view, gesture_event);
} else {
// When target does not allow touch-action: pinch, instead of sending
@@ -1197,6 +1262,11 @@ void RenderWidgetHostInputEventRouter::DispatchTouchscreenGestureEvent(
map_size_key,
base::StringPrintf("%u", static_cast<int>(owner_map_.size())));
+ if (events_being_flushed_) {
+ touchscreen_gesture_target_.target->host()
+ ->input_router()
+ ->ForceSetTouchActionAuto();
+ }
touchscreen_gesture_target_.target->ProcessGestureEvent(event, latency);
if (gesture_event.GetType() == blink::WebInputEvent::kGestureFlingStart)
@@ -1368,6 +1438,11 @@ RenderWidgetHostInputEventRouter::FindTargetSynchronously(
return RenderWidgetTargetResult();
}
+void RenderWidgetHostInputEventRouter::SetEventsBeingFlushed(
+ bool events_being_flushed) {
+ events_being_flushed_ = events_being_flushed;
+}
+
void RenderWidgetHostInputEventRouter::DispatchEventToTarget(
RenderWidgetHostViewBase* root_view,
RenderWidgetHostViewBase* target,
diff --git a/chromium/content/browser/renderer_host/render_widget_host_input_event_router.h b/chromium/content/browser/renderer_host/render_widget_host_input_event_router.h
index 68d7cf064c2..f32c2cee069 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_input_event_router.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_input_event_router.h
@@ -15,17 +15,27 @@
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
+#include "build/build_config.h"
#include "components/viz/common/surfaces/surface_id.h"
#include "components/viz/host/hit_test/hit_test_query.h"
#include "components/viz/service/surfaces/surface_hittest_delegate.h"
+#include "content/browser/renderer_host/event_with_latency_info.h"
#include "content/browser/renderer_host/input/touch_emulator_client.h"
#include "content/browser/renderer_host/render_widget_host_view_base_observer.h"
#include "content/browser/renderer_host/render_widget_targeter.h"
#include "content/common/content_export.h"
+#include "content/public/common/input_event_ack_state.h"
#include "ui/gfx/geometry/vector2d_conversions.h"
struct FrameHostMsg_HittestData_Params;
+#if defined(OS_WIN)
+// Flaky on Windows. https://crbug.com/868308
+#define MAYBE_TouchpadPinchOverOOPIF DISABLED_TouchpadPinchOverOOPIF
+#else
+#define MAYBE_TouchpadPinchOverOOPIF TouchpadPinchOverOOPIF
+#endif // OS_WIN
+
namespace blink {
class WebGestureEvent;
class WebInputEvent;
@@ -78,6 +88,9 @@ class CONTENT_EXPORT RenderWidgetHostInputEventRouter
blink::WebGestureEvent* event,
const ui::LatencyInfo& latency);
void OnHandledTouchStartOrFirstTouchMove(uint32_t unique_touch_event_id);
+ void ProcessAckedTouchEvent(const TouchEventWithLatencyInfo& event,
+ InputEventAckState ack_result,
+ RenderWidgetHostViewBase* view);
void RouteTouchEvent(RenderWidgetHostViewBase* root_view,
blink::WebTouchEvent *event,
const ui::LatencyInfo& latency);
@@ -272,6 +285,9 @@ class CONTENT_EXPORT RenderWidgetHostInputEventRouter
const blink::WebInputEvent& event,
const ui::LatencyInfo& latency,
const base::Optional<gfx::PointF>& target_location) override;
+ // Notify whether the events in the queue are being flushed due to touch ack
+ // timeout, or the flushing has completed.
+ void SetEventsBeingFlushed(bool events_being_flushed) override;
FrameSinkIdOwnerMap owner_map_;
TargetMap touchscreen_gesture_target_map_;
@@ -295,6 +311,12 @@ class CONTENT_EXPORT RenderWidgetHostInputEventRouter
// Tracked for the purpose of targeting subsequent fling cancel events.
RenderWidgetHostViewBase* last_fling_start_target_ = nullptr;
+ // During scroll bubbling we bubble the GFS to the target view so that its
+ // fling controller takes care of flinging. In this case we should also send
+ // the GFC to the bubbling target so that the fling controller currently in
+ // charge of the fling progress could handle the fling cancellelation as well.
+ RenderWidgetHostViewBase* last_fling_start_bubbled_target_ = nullptr;
+
// Tracked for the purpose of providing a root_view when dispatching emulated
// touch/gesture events.
RenderWidgetHostViewBase* last_emulated_event_root_view_;
@@ -311,6 +333,7 @@ class CONTENT_EXPORT RenderWidgetHostInputEventRouter
std::unique_ptr<RenderWidgetTargeter> event_targeter_;
bool use_viz_hit_test_ = false;
+ bool events_being_flushed_ = false;
std::unique_ptr<TouchEmulator> touch_emulator_;
@@ -327,7 +350,7 @@ class CONTENT_EXPORT RenderWidgetHostInputEventRouter
FRIEND_TEST_ALL_PREFIXES(SitePerProcessHitTestBrowserTest,
InputEventRouterTouchpadGestureTargetTest);
FRIEND_TEST_ALL_PREFIXES(SitePerProcessHitTestBrowserTest,
- TouchpadPinchOverOOPIF);
+ MAYBE_TouchpadPinchOverOOPIF);
FRIEND_TEST_ALL_PREFIXES(SitePerProcessMouseWheelHitTestBrowserTest,
InputEventRouterWheelTargetTest);
FRIEND_TEST_ALL_PREFIXES(SitePerProcessMacBrowserTest,
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 f25a7637f5c..310d80202ed 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
@@ -4,9 +4,17 @@
#include "content/browser/renderer_host/render_widget_host_input_event_router.h"
+#include <vector>
+
#include "base/run_loop.h"
#include "base/test/scoped_task_environment.h"
#include "build/build_config.h"
+#include "components/viz/common/features.h"
+#include "components/viz/common/hit_test/aggregated_hit_test_region.h"
+#include "components/viz/host/hit_test/hit_test_query.h"
+#include "components/viz/host/host_frame_sink_manager.h"
+#include "components/viz/test/host_frame_sink_manager_test_api.h"
+#include "content/browser/compositor/surface_utils.h"
#include "content/browser/compositor/test/test_image_transport_factory.h"
#include "content/browser/renderer_host/frame_connector_delegate.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
@@ -53,6 +61,7 @@ class TestRenderWidgetHostViewChildFrame
public:
explicit TestRenderWidgetHostViewChildFrame(RenderWidgetHost* widget)
: RenderWidgetHostViewChildFrame(widget),
+ frame_sink_id_(2, 1),
last_gesture_seen_(blink::WebInputEvent::kUndefined) {}
~TestRenderWidgetHostViewChildFrame() override = default;
@@ -66,12 +75,22 @@ class TestRenderWidgetHostViewChildFrame
unique_id_for_last_touch_ack_ = touch.event.unique_touch_event_id;
}
+ void SetBounds(const gfx::Rect& rect) override { bounds_ = rect; }
+
+ gfx::Rect GetViewBounds() const override { return bounds_; }
+
+ const viz::FrameSinkId& GetFrameSinkId() const override {
+ return frame_sink_id_;
+ }
+
blink::WebInputEvent::Type last_gesture_seen() { return last_gesture_seen_; }
uint32_t last_id_for_touch_ack() { return unique_id_for_last_touch_ack_; }
void Reset() { last_gesture_seen_ = blink::WebInputEvent::kUndefined; }
private:
+ gfx::Rect bounds_;
+ viz::FrameSinkId frame_sink_id_;
blink::WebInputEvent::Type last_gesture_seen_;
uint32_t unique_id_for_last_touch_ack_ = 0;
};
@@ -85,6 +104,7 @@ class MockRootRenderWidgetHostView : public TestRenderWidgetHostView {
RenderWidgetHost* rwh,
std::map<RenderWidgetHostViewBase*, viz::FrameSinkId>& frame_sink_id_map)
: TestRenderWidgetHostView(rwh),
+ frame_sink_id_(1, 1),
frame_sink_id_map_(frame_sink_id_map),
current_hittest_result_(nullptr),
force_query_renderer_on_hit_test_(false),
@@ -120,6 +140,16 @@ class MockRootRenderWidgetHostView : public TestRenderWidgetHostView {
unique_id_for_last_touch_ack_ = touch.event.unique_touch_event_id;
}
+ void SetBounds(const gfx::Rect& rect) override { bounds_ = rect; }
+
+ gfx::Rect GetViewBounds() const override { return bounds_; }
+
+ const viz::FrameSinkId& GetFrameSinkId() const override {
+ return frame_sink_id_;
+ }
+
+ viz::FrameSinkId GetRootFrameSinkId() override { return frame_sink_id_; }
+
blink::WebInputEvent::Type last_gesture_seen() { return last_gesture_seen_; }
uint32_t last_id_for_touch_ack() { return unique_id_for_last_touch_ack_; }
@@ -134,6 +164,8 @@ class MockRootRenderWidgetHostView : public TestRenderWidgetHostView {
void Reset() { last_gesture_seen_ = blink::WebInputEvent::kUndefined; }
private:
+ gfx::Rect bounds_;
+ viz::FrameSinkId frame_sink_id_;
std::map<RenderWidgetHostViewBase*, viz::FrameSinkId>& frame_sink_id_map_;
RenderWidgetHostViewBase* current_hittest_result_;
bool force_query_renderer_on_hit_test_;
@@ -147,6 +179,12 @@ class RenderWidgetHostInputEventRouterTest : public testing::Test {
public:
RenderWidgetHostInputEventRouterTest() {}
+ // Initializes the hit testing data required when
+ // features::IsVizHitTestingEnabled. Where both |view_root_flags| and
+ // |view_other_flags| are viz::HitTestRegionFlags, representing the type of
+ // events to be responded to by each view, along with how they are processed.
+ void InitVizHitTestData(int view_root_flags, int view_other_flags);
+
protected:
// testing::Test:
void SetUp() override {
@@ -189,8 +227,8 @@ class RenderWidgetHostInputEventRouterTest : public testing::Test {
// Set up the RWHIER's FrameSinkId to RWHV map so that we can control the
// result of RWHIER's hittesting.
- frame_sink_id_map_ = {{view_root_.get(), viz::FrameSinkId(1, 1)},
- {view_other_.get(), viz::FrameSinkId(2, 2)}};
+ frame_sink_id_map_ = {{view_root_.get(), view_root_->GetFrameSinkId()},
+ {view_other_.get(), view_other_->GetFrameSinkId()}};
rwhier_.AddFrameSinkIdOwner(frame_sink_id_map_[view_root_.get()],
view_root_.get());
rwhier_.AddFrameSinkIdOwner(frame_sink_id_map_[view_other_.get()],
@@ -217,6 +255,8 @@ class RenderWidgetHostInputEventRouterTest : public testing::Test {
MockRenderWidgetHostDelegate delegate_;
std::unique_ptr<BrowserContext> browser_context_;
+ std::unique_ptr<viz::HostFrameSinkManagerTestApi>
+ host_frame_sink_manager_test_api_;
std::unique_ptr<MockRenderProcessHost> process_host1_;
std::unique_ptr<MockRenderProcessHost> process_host2_;
std::unique_ptr<MockWidgetImpl> widget_impl1_;
@@ -236,6 +276,42 @@ class RenderWidgetHostInputEventRouterTest : public testing::Test {
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostInputEventRouterTest);
};
+void RenderWidgetHostInputEventRouterTest::InitVizHitTestData(
+ int view_root_flags,
+ int view_other_flags) {
+ if (!features::IsVizHitTestingEnabled())
+ return;
+ DCHECK(GetHostFrameSinkManager());
+ // Bounds chosen so that both |view_root_| and |view_other_| occupy (0, 0);
+ // the default position in WebPointerProperties. This is done as the test
+ // suite overrides enough of the classic hit testing path that there the
+ // bounds do not matter. However Viz hit-testing always performs a contains
+ // check on input events. This allows both views to handle the input
+ // targetting in the tests below.
+ view_root_->SetBounds(gfx::Rect(0, 0, 10, 10));
+ view_other_->SetBounds(gfx::Rect(0, 0, 10, 5));
+
+ host_frame_sink_manager_test_api_ =
+ std::make_unique<viz::HostFrameSinkManagerTestApi>(
+ GetHostFrameSinkManager());
+ viz::HostFrameSinkManager::DisplayHitTestQueryMap hit_test_map;
+ hit_test_map[view_root_->GetFrameSinkId()] =
+ std::make_unique<viz::HitTestQuery>();
+
+ std::vector<viz::AggregatedHitTestRegion> hit_test_data;
+ hit_test_data.push_back(viz::AggregatedHitTestRegion(
+ view_root_->GetFrameSinkId(), view_root_flags,
+ view_root_->GetViewBounds(), gfx::Transform(), 1));
+ hit_test_data.push_back(viz::AggregatedHitTestRegion(
+ view_other_->GetFrameSinkId(), view_other_flags,
+ view_other_->GetViewBounds(), gfx::Transform(), 0));
+ hit_test_map[view_root_->GetFrameSinkId()]
+ ->OnAggregatedHitTestRegionListUpdated(hit_test_data);
+
+ host_frame_sink_manager_test_api_->SetDisplayHitTestQuery(
+ std::move(hit_test_map));
+}
+
// Make sure that when a touch scroll crosses out of the area for a
// RenderWidgetHostView, the RenderWidgetHostInputEventRouter continues to
// route gesture events to the same RWHV until the end of the gesture.
@@ -247,6 +323,11 @@ TEST_F(RenderWidgetHostInputEventRouterTest,
// We start the touch in the area for |view_other_|.
view_root_->SetHittestResult(view_other_.get());
+ // Each view will want to process the touch event.
+ InitVizHitTestData(viz::HitTestRegionFlags::kHitTestTouch |
+ viz::HitTestRegionFlags::kHitTestMine,
+ viz::HitTestRegionFlags::kHitTestTouch |
+ viz::HitTestRegionFlags::kHitTestMine);
blink::WebTouchEvent touch_event(
blink::WebInputEvent::kTouchStart, blink::WebInputEvent::kNoModifiers,
@@ -299,9 +380,20 @@ TEST_F(RenderWidgetHostInputEventRouterTest,
rwhier_.RouteGestureEvent(view_root_.get(), &gesture_event,
ui::LatencyInfo(ui::SourceEventType::TOUCH));
- // Now the touch moves out of |view_other_| and into |view_root_|, but
- // |view_other_| should continue to be the target for gesture events.
+ // The continuation of the touch moves should maintain their current target of
+ // |view_other_|, even if they move outside of that view, and into
+ // |view_root_|.
+ //
+ // Since this test is not using actual view sizes, nor event positions, we
+ // need to setup our hit testing overrides to prevent targeting |view_other_|.
+ //
+ // If the target is maintained through the gesture this will pass. If instead
+ // the hit testing logic is refered to, then this test will fail.
view_root_->SetHittestResult(view_root_.get());
+ InitVizHitTestData(viz::HitTestRegionFlags::kHitTestTouch |
+ viz::HitTestRegionFlags::kHitTestMine,
+ viz::HitTestRegionFlags::kHitTestTouch |
+ viz::HitTestRegionFlags::kHitTestIgnore);
view_root_->Reset();
view_other_->Reset();
@@ -369,6 +461,13 @@ TEST_F(RenderWidgetHostInputEventRouterTest, DoNotCoalesceTouchEvents) {
RenderWidgetTargeter* targeter = rwhier_.GetRenderWidgetTargeterForTests();
view_root_->SetHittestResult(view_root_.get());
view_root_->set_force_query_renderer_on_hit_test(true);
+ // Also force the renderer to be queried.
+ InitVizHitTestData(viz::HitTestRegionFlags::kHitTestTouch |
+ viz::HitTestRegionFlags::kHitTestMine |
+ viz::HitTestRegionFlags::kHitTestAsk,
+ viz::HitTestRegionFlags::kHitTestTouch |
+ viz::HitTestRegionFlags::kHitTestMine |
+ viz::HitTestRegionFlags::kHitTestAsk);
// We need to set up a comm pipe, or else the targeter will crash when it
// tries to query the renderer. It doesn't matter that the pipe isn't
@@ -423,6 +522,13 @@ TEST_F(RenderWidgetHostInputEventRouterTest, DoNotCoalesceGestureEvents) {
RenderWidgetTargeter* targeter = rwhier_.GetRenderWidgetTargeterForTests();
view_root_->SetHittestResult(view_root_.get());
view_root_->set_force_query_renderer_on_hit_test(true);
+ // Also force the renderer to be queried.
+ InitVizHitTestData(viz::HitTestRegionFlags::kHitTestTouch |
+ viz::HitTestRegionFlags::kHitTestMine |
+ viz::HitTestRegionFlags::kHitTestAsk,
+ viz::HitTestRegionFlags::kHitTestTouch |
+ viz::HitTestRegionFlags::kHitTestMine |
+ viz::HitTestRegionFlags::kHitTestAsk);
// We need to set up a comm pipe, or else the targeter will crash when it
// tries to query the renderer. It doesn't matter that the pipe isn't
diff --git a/chromium/content/browser/renderer_host/render_widget_host_ns_view_client.h b/chromium/content/browser/renderer_host/render_widget_host_ns_view_client.h
index 92f4fd7407f..5efb19f2379 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_ns_view_client.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_ns_view_client.h
@@ -13,6 +13,7 @@ namespace blink {
class WebGestureEvent;
class WebMouseEvent;
class WebMouseWheelEvent;
+class WebTouchEvent;
} // namespace blink
namespace ui {
@@ -53,6 +54,8 @@ class RenderWidgetHostNSViewLocalClient {
// Forward events to the renderer or the input router, as appropriate.
virtual void RouteOrProcessMouseEvent(
const blink::WebMouseEvent& web_event) = 0;
+ virtual void RouteOrProcessTouchEvent(
+ const blink::WebTouchEvent& web_event) = 0;
virtual void RouteOrProcessWheelEvent(
const blink::WebMouseWheelEvent& web_event) = 0;
diff --git a/chromium/content/browser/renderer_host/render_widget_host_unittest.cc b/chromium/content/browser/renderer_host/render_widget_host_unittest.cc
index e5de66d7b7c..138cac8c271 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_unittest.cc
@@ -524,6 +524,7 @@ class MockRenderWidgetHostDelegate : public RenderWidgetHostDelegate {
handle_wheel_event_(false),
handle_wheel_event_called_(false),
unresponsive_timer_fired_(false),
+ ignore_input_events_(false),
render_view_host_delegate_view_(new MockRenderViewHostDelegateView()) {}
~MockRenderWidgetHostDelegate() override {}
@@ -582,6 +583,10 @@ class MockRenderWidgetHostDelegate : public RenderWidgetHostDelegate {
return mock_delegate_view();
}
+ void SetIgnoreInputEvents(bool ignore_input_events) {
+ ignore_input_events_ = ignore_input_events;
+ }
+
protected:
KeyboardEventProcessingResult PreHandleKeyboardEvent(
const NativeWebKeyboardEvent& event) override {
@@ -610,6 +615,8 @@ class MockRenderWidgetHostDelegate : public RenderWidgetHostDelegate {
unresponsive_timer_fired_ = true;
}
+ bool ShouldIgnoreInputEvents() override { return ignore_input_events_; }
+
void ExecuteEditCommand(
const std::string& command,
const base::Optional<base::string16>& value) override {}
@@ -633,6 +640,8 @@ class MockRenderWidgetHostDelegate : public RenderWidgetHostDelegate {
bool unresponsive_timer_fired_;
+ bool ignore_input_events_;
+
std::unique_ptr<MockRenderViewHostDelegateView>
render_view_host_delegate_view_;
@@ -1694,7 +1703,7 @@ TEST_F(RenderWidgetHostTest, SwapCompositorFrameWithBadSourceId) {
TEST_F(RenderWidgetHostTest, IgnoreInputEvent) {
host_->SetupForInputRouterTest();
- host_->SetIgnoreInputEvents(true);
+ delegate_->SetIgnoreInputEvents(true);
SimulateKeyboardEvent(WebInputEvent::kRawKeyDown);
EXPECT_FALSE(host_->mock_input_router()->sent_keyboard_event_);
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 f56a9746443..c0460f053f2 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
@@ -21,6 +21,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/sys_info.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "cc/base/math_util.h"
#include "cc/layers/layer.h"
#include "cc/layers/surface_layer.h"
#include "cc/trees/latency_info_swap_promise.h"
@@ -40,7 +41,6 @@
#include "content/browser/android/overscroll_controller_android.h"
#include "content/browser/android/selection/selection_popup_controller.h"
#include "content/browser/android/synchronous_compositor_host.h"
-#include "content/browser/android/tap_disambiguator.h"
#include "content/browser/android/text_suggestion_host_android.h"
#include "content/browser/bad_message.h"
#include "content/browser/compositor/surface_utils.h"
@@ -48,6 +48,7 @@
#include "content/browser/gpu/gpu_process_host.h"
#include "content/browser/media/android/media_web_contents_observer_android.h"
#include "content/browser/renderer_host/compositor_impl_android.h"
+#include "content/browser/renderer_host/delegated_frame_host_client_android.h"
#include "content/browser/renderer_host/dip_util.h"
#include "content/browser/renderer_host/frame_metadata_util.h"
#include "content/browser/renderer_host/input/input_router.h"
@@ -148,12 +149,8 @@ void RecordToolTypeForActionDown(const ui::MotionEventAndroid& event) {
}
}
-bool FloatEquals(float a, float b) {
- return std::abs(a - b) < FLT_EPSILON;
-}
-
void WakeUpGpu(GpuProcessHost* host) {
- if (host && host->wake_up_gpu_before_drawing()) {
+ if (host && host->gpu_host()->wake_up_gpu_before_drawing()) {
host->gpu_service()->WakeUpGpu();
}
}
@@ -171,7 +168,6 @@ RenderWidgetHostViewAndroid::RenderWidgetHostViewAndroid(
is_window_activity_started_(true),
is_in_vr_(false),
ime_adapter_android_(nullptr),
- tap_disambiguator_(nullptr),
selection_popup_controller_(nullptr),
text_suggestion_host_(nullptr),
gesture_listener_manager_(nullptr),
@@ -198,9 +194,12 @@ RenderWidgetHostViewAndroid::RenderWidgetHostViewAndroid(
view_.set_event_handler(this);
if (using_browser_compositor_) {
+ delegated_frame_host_client_ =
+ std::make_unique<DelegatedFrameHostClientAndroid>(this);
delegated_frame_host_ = std::make_unique<ui::DelegatedFrameHostAndroid>(
- &view_, CompositorImpl::GetHostFrameSinkManager(), this,
- host()->GetFrameSinkId(), features::IsSurfaceSynchronizationEnabled());
+ &view_, CompositorImpl::GetHostFrameSinkManager(),
+ delegated_frame_host_client_.get(), host()->GetFrameSinkId(),
+ features::IsSurfaceSynchronizationEnabled());
if (is_showing_) {
delegated_frame_host_->WasShown(
local_surface_id_allocator_.GetCurrentLocalSurfaceId(),
@@ -218,7 +217,14 @@ RenderWidgetHostViewAndroid::RenderWidgetHostViewAndroid(
host()->SetView(this);
touch_selection_controller_client_manager_ =
std::make_unique<TouchSelectionControllerClientManagerAndroid>(this);
+
UpdateNativeViewTree(parent_native_view);
+ // This RWHVA may have been created speculatively. We should give any
+ // existing RWHVAs priority for receiving input events, otherwise a
+ // speculative RWHVA could be sent input events intended for the currently
+ // showing RWHVA.
+ if (parent_native_view)
+ parent_native_view->MoveToBack(&view_);
CreateOverscrollControllerIfPossible();
@@ -387,7 +393,7 @@ void RenderWidgetHostViewAndroid::OnRenderFrameMetadataChangedBeforeActivation(
float top_content_offset_dip = IsUseZoomForDSFEnabled()
? top_content_offset / dip_scale
: top_content_offset;
- view_.UpdateFrameInfo({scrollable_viewport_size_dip, top_content_offset});
+ view_.UpdateFrameInfo({scrollable_viewport_size_dip, top_content_offset_dip});
bool controls_changed = UpdateControls(
view_.GetDipScale(), metadata.top_controls_height,
metadata.top_controls_shown_ratio, metadata.bottom_controls_height,
@@ -415,6 +421,7 @@ void RenderWidgetHostViewAndroid::OnRenderFrameMetadataChangedBeforeActivation(
page_scale_ = metadata.page_scale_factor;
min_page_scale_ = metadata.min_page_scale_factor;
max_page_scale_ = metadata.max_page_scale_factor;
+ current_surface_size_ = metadata.viewport_size_in_pixels;
}
void RenderWidgetHostViewAndroid::Focus() {
@@ -820,6 +827,8 @@ void RenderWidgetHostViewAndroid::ResetGestureDetection() {
}
void RenderWidgetHostViewAndroid::OnDidNavigateMainFrameToNewPage() {
+ if (view_.parent())
+ view_.parent()->MoveToFront(&view_);
ResetGestureDetection();
}
@@ -871,12 +880,17 @@ void RenderWidgetHostViewAndroid::UpdateBackgroundColor() {
view_.OnBackgroundColorChanged(color);
}
+bool RenderWidgetHostViewAndroid::HasFallbackSurface() const {
+ return delegated_frame_host_ && delegated_frame_host_->HasFallbackSurface();
+}
+
void RenderWidgetHostViewAndroid::CopyFromSurface(
const gfx::Rect& src_subrect,
const gfx::Size& output_size,
base::OnceCallback<void(const SkBitmap&)> callback) {
TRACE_EVENT0("cc", "RenderWidgetHostViewAndroid::CopyFromSurface");
- if (!IsSurfaceAvailableForCopy()) {
+ if (!features::IsSurfaceSynchronizationEnabled() &&
+ !IsSurfaceAvailableForCopy()) {
std::move(callback).Run(SkBitmap());
return;
}
@@ -915,12 +929,9 @@ uint32_t RenderWidgetHostViewAndroid::GetCaptureSequenceNumber() const {
return latest_capture_sequence_number_;
}
-void RenderWidgetHostViewAndroid::ShowDisambiguationPopup(
- const gfx::Rect& rect_pixels, const SkBitmap& zoomed_bitmap) {
- if (!tap_disambiguator_)
- return;
-
- tap_disambiguator_->ShowPopup(rect_pixels, zoomed_bitmap);
+void RenderWidgetHostViewAndroid::OnInterstitialPageAttached() {
+ if (view_.parent())
+ view_.parent()->MoveToFront(&view_);
}
void RenderWidgetHostViewAndroid::OnInterstitialPageGoingAway() {
@@ -957,14 +968,6 @@ void RenderWidgetHostViewAndroid::ReclaimResources(
renderer_compositor_frame_sink_->ReclaimResources(resources);
}
-void RenderWidgetHostViewAndroid::OnFrameTokenChanged(uint32_t frame_token) {
- OnFrameTokenChangedForView(frame_token);
-}
-
-void RenderWidgetHostViewAndroid::DidReceiveFirstFrameAfterNavigation() {
- host_->DidReceiveFirstFrameAfterNavigation();
-}
-
void RenderWidgetHostViewAndroid::DidCreateNewRendererCompositorFrameSink(
viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) {
if (!delegated_frame_host_) {
@@ -1039,6 +1042,11 @@ void RenderWidgetHostViewAndroid::ClearCompositorFrame() {
EvictDelegatedFrame();
}
+void RenderWidgetHostViewAndroid::ResetFallbackToFirstNavigationSurface() {
+ if (delegated_frame_host_)
+ delegated_frame_host_->ResetFallbackToFirstNavigationSurface();
+}
+
bool RenderWidgetHostViewAndroid::RequestRepaintForTesting() {
return SynchronizeVisualProperties(cc::DeadlinePolicy::UseDefaultDeadline(),
base::nullopt);
@@ -1333,7 +1341,8 @@ bool RenderWidgetHostViewAndroid::UpdateControls(
float top_content_offset = top_controls_height * top_controls_shown_ratio;
float top_shown_pix = top_content_offset * to_pix;
float top_translate = top_shown_pix - top_controls_pix;
- bool top_changed = !FloatEquals(top_shown_pix, prev_top_shown_pix_);
+ bool top_changed =
+ !cc::MathUtil::IsFloatNearlyTheSame(top_shown_pix, prev_top_shown_pix_);
// TODO(mthiesse, https://crbug.com/853686): Remove the IsInVR check once
// there are no use cases for ignoring the initial update.
if (top_changed || (!controls_initialized_ && IsInVR()))
@@ -1343,7 +1352,8 @@ bool RenderWidgetHostViewAndroid::UpdateControls(
float bottom_controls_pix = bottom_controls_height * to_pix;
float bottom_shown_pix = bottom_controls_pix * bottom_controls_shown_ratio;
- bool bottom_changed = !FloatEquals(bottom_shown_pix, prev_bottom_shown_pix_);
+ bool bottom_changed = !cc::MathUtil::IsFloatNearlyTheSame(
+ bottom_shown_pix, prev_bottom_shown_pix_);
float bottom_translate = bottom_controls_pix - bottom_shown_pix;
if (bottom_changed || (!controls_initialized_ && IsInVR()))
view_.OnBottomControlsChanged(bottom_translate, bottom_shown_pix);
@@ -1357,6 +1367,9 @@ void RenderWidgetHostViewAndroid::OnDidUpdateVisualPropertiesComplete(
const cc::RenderFrameMetadata& metadata) {
SynchronizeVisualProperties(cc::DeadlinePolicy::UseDefaultDeadline(),
metadata.local_surface_id);
+ // We've just processed new RenderFrameMetadata and potentially embedded a
+ // new surface for that data. Check if we need to evict it.
+ EvictFrameIfNecessary();
}
void RenderWidgetHostViewAndroid::ShowInternal() {
@@ -1848,17 +1861,6 @@ bool RenderWidgetHostViewAndroid::ShowSelectionMenu(
GetTouchHandleHeight());
}
-void RenderWidgetHostViewAndroid::ResolveTapDisambiguation(
- double timestamp_seconds,
- gfx::Point tap_viewport_offset,
- bool is_long_press) {
- DCHECK(host());
- host()->Send(new ViewMsg_ResolveTapDisambiguation(
- host()->GetRoutingID(),
- base::TimeTicks() + base::TimeDelta::FromSecondsD(timestamp_seconds),
- tap_viewport_offset, is_long_press));
-}
-
void RenderWidgetHostViewAndroid::MoveCaret(const gfx::Point& point) {
if (host() && host()->delegate())
host()->delegate()->MoveCaret(point);
@@ -2076,8 +2078,6 @@ bool RenderWidgetHostViewAndroid::RequiresDoubleTapGestureEvents() const {
void RenderWidgetHostViewAndroid::OnSizeChanged() {
if (ime_adapter_android_)
ime_adapter_android_->UpdateAfterViewSizeChanged();
- if (tap_disambiguator_)
- tap_disambiguator_->HidePopup();
}
void RenderWidgetHostViewAndroid::OnPhysicalBackingSizeChanged() {
@@ -2329,8 +2329,6 @@ void RenderWidgetHostViewAndroid::CreateOverscrollControllerIfPossible() {
// If window_android is null here, this is bad because we don't listen for it
// being set, so we won't be able to construct the OverscrollController at the
// proper time.
- // TODO(rlanday): once we get WindowAndroid from ViewAndroid instead of
- // ContentViewCore, listen for WindowAndroid being set and create the
ui::WindowAndroid* window_android = view_.GetWindowAndroid();
if (!window_android)
return;
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 ae59220401e..6d3920e20e8 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
@@ -53,7 +53,6 @@ class OverscrollControllerAndroid;
class SelectionPopupController;
class SynchronousCompositorHost;
class SynchronousCompositorClient;
-class TapDisambiguator;
class TextSuggestionHostAndroid;
class TouchSelectionControllerClientManagerAndroid;
class WebContentsAccessibilityAndroid;
@@ -67,7 +66,6 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
: public RenderWidgetHostViewBase,
public StylusTextSelectorClient,
public content::TextInputManager::Observer,
- public ui::DelegatedFrameHostAndroid::Client,
public ui::EventHandlerAndroid,
public ui::GestureProviderClient,
public ui::TouchSelectionControllerClient,
@@ -156,13 +154,13 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
base::Optional<viz::HitTestRegionList> hit_test_region_list) override;
void OnDidNotProduceFrame(const viz::BeginFrameAck& ack) override;
void ClearCompositorFrame() override;
+ void ResetFallbackToFirstNavigationSurface() override;
bool RequestRepaintForTesting() override;
void SetIsInVR(bool is_in_vr) override;
bool IsInVR() const override;
void DidOverscroll(const ui::DidOverscrollParams& params) override;
void DidStopFlinging() override;
- void ShowDisambiguationPopup(const gfx::Rect& rect_pixels,
- const SkBitmap& zoomed_bitmap) override;
+ void OnInterstitialPageAttached() override;
void OnInterstitialPageGoingAway() override;
std::unique_ptr<SyntheticGestureTarget> CreateSyntheticGestureTarget()
override;
@@ -235,17 +233,13 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
std::unique_ptr<ui::TouchHandleDrawable> CreateDrawable() override;
void DidScroll() override;
- // DelegatedFrameHostAndroid::Client implementation.
- void SetBeginFrameSource(viz::BeginFrameSource* begin_frame_source) override;
- void DidPresentCompositorFrame(
- uint32_t presentation_token,
- const gfx::PresentationFeedback& feedback) override;
+ // Used by DelegatedFrameHostClientAndroid.
+ void SetBeginFrameSource(viz::BeginFrameSource* begin_frame_source);
+ void DidPresentCompositorFrame(uint32_t presentation_token,
+ const gfx::PresentationFeedback& feedback);
void DidReceiveCompositorFrameAck(
- const std::vector<viz::ReturnedResource>& resources) override;
- void ReclaimResources(
- const std::vector<viz::ReturnedResource>& resources) override;
- void OnFrameTokenChanged(uint32_t frame_token) override;
- void DidReceiveFirstFrameAfterNavigation() override;
+ const std::vector<viz::ReturnedResource>& resources);
+ void ReclaimResources(const std::vector<viz::ReturnedResource>& resources);
// viz::BeginFrameObserver implementation.
void OnBeginFrame(const viz::BeginFrameArgs& args) override;
@@ -264,15 +258,9 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
void SendMouseWheelEvent(const blink::WebMouseWheelEvent& event);
void SendGestureEvent(const blink::WebGestureEvent& event);
bool ShowSelectionMenu(const ContextMenuParams& params);
- void ResolveTapDisambiguation(double timestamp_seconds,
- gfx::Point tap_viewport_offset,
- bool is_long_press);
void set_ime_adapter(ImeAdapterAndroid* ime_adapter) {
ime_adapter_android_ = ime_adapter;
}
- void set_tap_disambiguator(TapDisambiguator* tap_disambiguator) {
- tap_disambiguator_ = tap_disambiguator;
- }
void set_selection_popup_controller(SelectionPopupController* controller) {
selection_popup_controller_ = controller;
}
@@ -348,6 +336,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
protected:
// RenderWidgetHostViewBase:
void UpdateBackgroundColor() override;
+ bool HasFallbackSurface() const override;
private:
MouseWheelPhaseHandler* GetMouseWheelPhaseHandler() override;
@@ -449,13 +438,15 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
bool handles_hidden_by_selection_ui_ = false;
ImeAdapterAndroid* ime_adapter_android_;
- TapDisambiguator* tap_disambiguator_;
SelectionPopupController* selection_popup_controller_;
TextSuggestionHostAndroid* text_suggestion_host_;
GestureListenerManager* gesture_listener_manager_;
mutable ui::ViewAndroid view_;
+ std::unique_ptr<ui::DelegatedFrameHostAndroid::Client>
+ delegated_frame_host_client_;
+
// Manages the Compositor Frames received from the renderer.
std::unique_ptr<ui::DelegatedFrameHostAndroid> delegated_frame_host_;
@@ -482,7 +473,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
std::unique_ptr<TouchSelectionControllerClientManagerAndroid>
touch_selection_controller_client_manager_;
- // Bounds to use if we have no backing ContentViewCore
+ // Bounds to use if we have no backing WebContents.
gfx::Rect default_bounds_;
const bool using_browser_compositor_;
@@ -508,7 +499,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink_ =
nullptr;
- base::ObserverList<DestructionObserver> destruction_observers_;
+ base::ObserverList<DestructionObserver>::Unchecked destruction_observers_;
MouseWheelPhaseHandler mouse_wheel_phase_handler_;
uint32_t latest_capture_sequence_number_ = 0u;
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 09168578786..b01698c8111 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
@@ -22,7 +22,6 @@
#include "components/viz/common/features.h"
#include "components/viz/common/frame_sinks/copy_output_request.h"
#include "components/viz/common/frame_sinks/copy_output_result.h"
-#include "components/viz/common/gl_helper.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/browser/accessibility/browser_accessibility_state_impl.h"
#include "content/browser/bad_message.h"
@@ -55,8 +54,8 @@
#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/ui/common/switches.h"
-#include "services/ui/public/interfaces/window_tree_constants.mojom.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/platform/aura_window_properties.h"
@@ -365,7 +364,7 @@ RenderWidgetHostViewAura::RenderWidgetHostViewAura(
is_guest_view_hack_(is_guest_view_hack),
device_scale_factor_(0.0f),
event_handler_(new RenderWidgetHostViewEventHandler(host(), this, this)),
- frame_sink_id_(!features::IsAshInBrowserProcess()
+ frame_sink_id_(features::IsUsingWindowService()
? viz::FrameSinkId()
: is_guest_view_hack_
? AllocateFrameSinkIdForGuestViewHack()
@@ -756,9 +755,13 @@ void RenderWidgetHostViewAura::FocusedNodeTouched(bool editable) {
return;
auto* controller = input_method->GetInputMethodKeyboardController();
if (editable && host()->GetView() && host()->delegate()) {
- keyboard_observer_.reset(new WinScreenKeyboardObserver(this));
- if (!controller->DisplayVirtualKeyboard())
+ if (last_pointer_type_ == ui::EventPointerType::POINTER_TYPE_TOUCH) {
+ keyboard_observer_.reset(new WinScreenKeyboardObserver(this));
+ if (!controller->DisplayVirtualKeyboard())
+ keyboard_observer_.reset(nullptr);
+ } else {
keyboard_observer_.reset(nullptr);
+ }
virtual_keyboard_requested_ = keyboard_observer_.get();
} else {
virtual_keyboard_requested_ = false;
@@ -886,6 +889,11 @@ void RenderWidgetHostViewAura::ClearCompositorFrame() {
delegated_frame_host_->ClearDelegatedFrame();
}
+void RenderWidgetHostViewAura::ResetFallbackToFirstNavigationSurface() {
+ if (delegated_frame_host_)
+ delegated_frame_host_->ResetFallbackToFirstNavigationSurface();
+}
+
bool RenderWidgetHostViewAura::RequestRepaintForTesting() {
return SynchronizeVisualProperties(cc::DeadlinePolicy::UseDefaultDeadline(),
base::nullopt);
@@ -1643,6 +1651,10 @@ bool RenderWidgetHostViewAura::TransformPointToLocalCoordSpaceLegacy(
return true;
}
+bool RenderWidgetHostViewAura::HasFallbackSurface() const {
+ return delegated_frame_host_ && delegated_frame_host_->HasFallbackSurface();
+}
+
bool RenderWidgetHostViewAura::TransformPointToCoordSpaceForView(
const gfx::PointF& point,
RenderWidgetHostViewBase* target_view,
@@ -1656,8 +1668,10 @@ bool RenderWidgetHostViewAura::TransformPointToCoordSpaceForView(
// In TransformPointToLocalCoordSpace() there is a Point-to-Pixel conversion,
// but it is not necessary here because the final target view is responsible
// for converting before computing the final transform.
- return delegated_frame_host_->TransformPointToCoordSpaceForView(
- point, target_view, transformed_point, source);
+ if (!HasFallbackSurface())
+ return false;
+ return target_view->TransformPointToLocalCoordSpace(
+ point, GetCurrentSurfaceId(), transformed_point, source);
}
viz::FrameSinkId RenderWidgetHostViewAura::GetRootFrameSinkId() {
@@ -1698,9 +1712,9 @@ void RenderWidgetHostViewAura::FocusedNodeChanged(
}
void RenderWidgetHostViewAura::ScheduleEmbed(
- ui::mojom::WindowTreeClientPtr client,
+ ws::mojom::WindowTreeClientPtr client,
base::OnceCallback<void(const base::UnguessableToken&)> callback) {
- DCHECK(!features::IsAshInBrowserProcess());
+ DCHECK(features::IsUsingWindowService());
aura::Env::GetInstance()->ScheduleEmbed(std::move(client),
std::move(callback));
}
@@ -1749,7 +1763,7 @@ void RenderWidgetHostViewAura::OnWindowFocused(aura::Window* gained_focus,
// We need to honor input bypass if the associated tab is does not want
// input. This gives the current focused window a chance to be the text
// input client and handle events.
- if (host()->ignore_input_events())
+ if (host()->IsIgnoringInputEvents())
return;
host()->GotFocus();
@@ -1922,7 +1936,7 @@ void RenderWidgetHostViewAura::CreateAuraWindow(aura::client::WindowType type) {
if (frame_sink_id_.is_valid())
window_->SetEmbedFrameSinkId(frame_sink_id_);
- if (features::IsAshInBrowserProcess())
+ if (!features::IsUsingWindowService())
return;
// Embed the renderer into the Window.
@@ -1930,8 +1944,8 @@ void RenderWidgetHostViewAura::CreateAuraWindow(aura::client::WindowType type) {
// the visibility of |window_|.
aura::WindowPortMus::Get(window_)->Embed(
GetWindowTreeClientFromRenderer(),
- ui::mojom::kEmbedFlagEmbedderInterceptsEvents |
- ui::mojom::kEmbedFlagEmbedderControlsVisibility,
+ ws::mojom::kEmbedFlagEmbedderInterceptsEvents |
+ ws::mojom::kEmbedFlagEmbedderControlsVisibility,
base::BindOnce(&EmbedCallback));
}
@@ -1941,10 +1955,8 @@ void RenderWidgetHostViewAura::CreateDelegatedFrameHostClient() {
delegated_frame_host_client_ =
std::make_unique<DelegatedFrameHostClientAura>(this);
- const bool enable_viz =
- base::FeatureList::IsEnabled(features::kVizDisplayCompositor);
delegated_frame_host_ = std::make_unique<DelegatedFrameHost>(
- frame_sink_id_, delegated_frame_host_client_.get(), enable_viz,
+ frame_sink_id_, delegated_frame_host_client_.get(),
false /* should_register_frame_sink_id */);
// Let the page-level input event router know about our surface ID
@@ -2226,7 +2238,7 @@ void RenderWidgetHostViewAura::AddedToRootWindow() {
#endif
if (delegated_frame_host_)
- delegated_frame_host_->SetCompositor(window_->GetHost()->compositor());
+ delegated_frame_host_->AttachToCompositor(window_->GetHost()->compositor());
}
void RenderWidgetHostViewAura::RemovingFromRootWindow() {
@@ -2239,7 +2251,7 @@ void RenderWidgetHostViewAura::RemovingFromRootWindow() {
window_->GetHost()->RemoveObserver(this);
if (delegated_frame_host_)
- delegated_frame_host_->ResetCompositor();
+ delegated_frame_host_->DetachFromCompositor();
#if defined(OS_WIN)
// Update the legacy window's parent temporarily to the hidden window. It
@@ -2315,7 +2327,7 @@ void RenderWidgetHostViewAura::CreateSelectionController() {
}
void RenderWidgetHostViewAura::OnDidNavigateMainFrameToNewPage() {
- ui::GestureRecognizer::Get()->CancelActiveTouches(window_);
+ window_->env()->gesture_recognizer()->CancelActiveTouches(window_);
}
const viz::FrameSinkId& RenderWidgetHostViewAura::GetFrameSinkId() const {
@@ -2339,11 +2351,21 @@ void RenderWidgetHostViewAura::OnUpdateTextInputStateCalled(
GetInputMethod()->OnTextInputTypeChanged(this);
const TextInputState* state = text_input_manager_->GetTextInputState();
- if (state && state->show_ime_if_needed &&
- state->type != ui::TEXT_INPUT_TYPE_NONE &&
- state->mode != ui::TEXT_INPUT_MODE_NONE &&
- GetInputMethod()->GetTextInputClient() == this) {
- GetInputMethod()->ShowVirtualKeyboardIfEnabled();
+ if (state && state->type != ui::TEXT_INPUT_TYPE_NONE &&
+ state->mode != ui::TEXT_INPUT_MODE_NONE) {
+ bool show_virtual_keyboard = true;
+#if defined(OS_WIN)
+ show_virtual_keyboard =
+ last_pointer_type_ == ui::EventPointerType::POINTER_TYPE_TOUCH;
+#endif
+ if (state->show_ime_if_needed &&
+ GetInputMethod()->GetTextInputClient() == this &&
+ show_virtual_keyboard) {
+ GetInputMethod()->ShowVirtualKeyboardIfEnabled();
+ }
+ // Ensure that accessibility events are fired when the selection location
+ // moves from UI back to content.
+ text_input_manager->NotifySelectionBoundsChanged(updated_view);
}
if (auto* render_widget_host = updated_view->host()) {
@@ -2370,33 +2392,11 @@ void RenderWidgetHostViewAura::OnImeCancelComposition(
void RenderWidgetHostViewAura::OnSelectionBoundsChanged(
TextInputManager* text_input_manager,
RenderWidgetHostViewBase* updated_view) {
+ // Note: accessibility caret move events are no longer fired directly here,
+ // because they were redundant with the events fired by the top level window
+ // by HWNDMessageHandler::OnCaretBoundsChanged().
if (GetInputMethod())
GetInputMethod()->OnCaretBoundsChanged(this);
-
-#if defined(OS_WIN)
- RenderWidgetHostViewBase* focused_view = GetFocusedViewForTextSelection();
- if (!focused_view || !GetTextInputManager()->IsRegistered(focused_view))
- return;
-
- // Some assistive software need to track the location of the caret.
- if (!GetRenderWidgetHost() || !legacy_render_widget_host_HWND_)
- return;
-
- // Not using |GetCaretBounds| because it includes the whole of the selection,
- // not just the focus.
- const TextInputManager::SelectionRegion* region =
- GetTextInputManager()->GetSelectionRegion(focused_view);
- if (!region)
- return;
-
- const gfx::Rect caret_rect = ConvertRectToScreen(gfx::Rect(
- region->focus.edge_top_rounded().x(),
- region->focus.edge_top_rounded().y(), 1, region->focus.GetHeight()));
- gfx::Rect dip_caret_rect = display::win::ScreenWin::DIPToScreenRect(
- legacy_render_widget_host_HWND_->hwnd(), caret_rect);
- dip_caret_rect.set_width(1); // Collapse any selection.
- legacy_render_widget_host_HWND_->MoveCaretTo(dip_caret_rect);
-#endif // defined(OS_WIN)
}
void RenderWidgetHostViewAura::OnTextSelectionChanged(
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 5f75e19c4a9..f237a3d5651 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
@@ -178,6 +178,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
base::Optional<viz::HitTestRegionList> hit_test_region_list) override;
void OnDidNotProduceFrame(const viz::BeginFrameAck& ack) override;
void ClearCompositorFrame() override;
+ void ResetFallbackToFirstNavigationSurface() override;
bool RequestRepaintForTesting() override;
void DidStopFlinging() override;
void OnDidNavigateMainFrameToNewPage() override;
@@ -197,7 +198,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
void FocusedNodeChanged(bool is_editable_node,
const gfx::Rect& node_bounds_in_screen) override;
- void ScheduleEmbed(ui::mojom::WindowTreeClientPtr client,
+ void ScheduleEmbed(ws::mojom::WindowTreeClientPtr client,
base::OnceCallback<void(const base::UnguessableToken&)>
callback) override;
void OnSynchronizedDisplayPropertiesChanged() override;
@@ -342,6 +343,12 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
void ScrollFocusedEditableNodeIntoRect(const gfx::Rect& rect);
+ // TODO(lanwei): Use TestApi interface to write functions that are used in
+ // tests and remove FRIEND_TEST_ALL_PREFIXES.
+ void SetLastPointerType(ui::EventPointerType last_pointer_type) {
+ last_pointer_type_ = last_pointer_type;
+ }
+
protected:
~RenderWidgetHostViewAura() override;
@@ -354,6 +361,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
// RenderWidgetHostViewBase:
void UpdateBackgroundColor() override;
+ bool HasFallbackSurface() const override;
private:
friend class DelegatedFrameHostClientAura;
@@ -408,6 +416,8 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
DiscardDelegatedFramesWithMemoryPressure);
FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraKeyboardTest,
KeyboardObserverDestroyed);
+ FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraKeyboardTest,
+ KeyboardObserverForOnlyTouchInput);
FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
DropFallbackWhenHidden);
FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
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 9aac9b4c740..dba7c7d3e47 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
@@ -296,7 +296,7 @@ class FakeRenderWidgetHostViewAura : public RenderWidgetHostViewAura {
return GetDelegatedFrameHost()->HasPrimarySurface();
}
- bool HasFallbackSurface() const {
+ bool HasFallbackSurface() const override {
return GetDelegatedFrameHost()->HasFallbackSurface();
}
@@ -304,8 +304,6 @@ class FakeRenderWidgetHostViewAura : public RenderWidgetHostViewAura {
GetDelegatedFrameHost()->ReclaimResources(resources);
}
- void ResetCompositor() { GetDelegatedFrameHost()->ResetCompositor(); }
-
const ui::MotionEventAura& pointer_state() {
return event_handler()->pointer_state();
}
@@ -498,13 +496,16 @@ class RenderWidgetHostViewAuraTest : public testing::Test {
static void InstallDelegatedFrameHostClient(
RenderWidgetHostViewAura* view,
std::unique_ptr<DelegatedFrameHostClient> delegated_frame_host_client) {
+ // Follow RWHVAura code that does not create DelegateFrameHost when there is
+ // no valid frame sink id.
+ if (!view->frame_sink_id_.is_valid())
+ return;
+
view->delegated_frame_host_client_ = std::move(delegated_frame_host_client);
- const bool enable_viz =
- base::FeatureList::IsEnabled(features::kVizDisplayCompositor);
view->delegated_frame_host_ = nullptr;
view->delegated_frame_host_ = std::make_unique<DelegatedFrameHost>(
view->frame_sink_id_, view->delegated_frame_host_client_.get(),
- enable_viz, false /* should_register_frame_sink_id */);
+ false /* should_register_frame_sink_id */);
}
FakeRenderWidgetHostViewAura* CreateView(bool is_guest_view_hack) {
@@ -2230,15 +2231,22 @@ TEST_F(RenderWidgetHostViewAuraTest, TouchpadFlingStartResetsWheelPhaseState) {
EXPECT_EQ(15U, gesture_event->data.scroll_update.delta_y);
// A GFS is received showing that the user has lifted their fingers. This will
- // reset the scroll state of the wheel phase handler.
+ // reset the scroll state of the wheel phase handler. The velocity should be
+ // big enough to make sure that fling is still active while sending the scroll
+ // event.
ui::ScrollEvent fling_start(ui::ET_SCROLL_FLING_START, gfx::Point(2, 2),
- ui::EventTimeForNow(), 0, 0, 10, 0, 10, 2);
+ ui::EventTimeForNow(), 0, 0, 1000, 0, 1000, 2);
view_->OnScrollEvent(&fling_start);
base::RunLoop().RunUntilIdle();
events = GetAndResetDispatchedMessages();
- // A GFS with touchpad source won't get dispatched to the renderer.
- EXPECT_EQ(0U, events.size());
+ // A GFS with touchpad source won't get dispatched to the renderer. However,
+ // since progressFling is called right away after processing the GFS, it is
+ // possible that a progress event is sent if the time delta between GFS
+ // timestamp and the time that it gets processed is large enough.
+ bool progress_event_sent = events.size();
+ if (progress_event_sent)
+ EXPECT_EQ("MouseWheel GestureScrollUpdate", GetMessageNames(events));
// Handling the next ui::ET_SCROLL event will generate a GFC which resets the
// phase state. The fling controller processes GFC and generates a wheel event
@@ -2248,13 +2256,12 @@ TEST_F(RenderWidgetHostViewAuraTest, TouchpadFlingStartResetsWheelPhaseState) {
ui::EventTimeForNow(), 0, 0, 15, 0, 15, 2);
view_->OnScrollEvent(&scroll2);
base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(widget_host_->FlingCancellationIsDeferred());
events = GetAndResetDispatchedMessages();
- EXPECT_EQ("MouseWheel GestureScrollEnd MouseWheel", GetMessageNames(events));
+ EXPECT_EQ("MouseWheel", GetMessageNames(events));
wheel_event = static_cast<const WebMouseWheelEvent*>(
events[0]->ToEvent()->Event()->web_event.get());
- EXPECT_EQ(WebMouseWheelEvent::kPhaseEnded, wheel_event->momentum_phase);
- wheel_event = static_cast<const WebMouseWheelEvent*>(
- events[2]->ToEvent()->Event()->web_event.get());
EXPECT_EQ(WebMouseWheelEvent::kPhaseBegan, wheel_event->phase);
}
@@ -3035,7 +3042,7 @@ viz::CompositorFrame MakeDelegatedFrame(float scale_factor,
// This test verifies that returned resources do not require a pending ack.
TEST_F(RenderWidgetHostViewAuraTest, ReturnedResources) {
// TODO: fix for mash.
- if (!features::IsAshInBrowserProcess())
+ if (features::IsUsingWindowService())
return;
gfx::Size view_size(100, 100);
@@ -3069,7 +3076,7 @@ TEST_F(RenderWidgetHostViewAuraTest, TwoOutputSurfaces) {
// TODO(jonross): Delete this test once Viz launches as it will be obsolete.
// https://crbug.com/844469
if (base::FeatureList::IsEnabled(features::kVizDisplayCompositor) ||
- !features::IsAshInBrowserProcess()) {
+ features::IsUsingWindowService()) {
return;
}
@@ -3211,7 +3218,7 @@ TEST_F(RenderWidgetHostViewAuraTest, ZeroSizeStillGetsLocalSurfaceId) {
TEST_F(RenderWidgetHostViewAuraTest, BackgroundColorMatchesCompositorFrame) {
// TODO: fix for mash.
- if (!features::IsAshInBrowserProcess())
+ if (features::IsUsingWindowService())
return;
gfx::Size frame_size(100, 100);
@@ -3376,7 +3383,7 @@ TEST_F(RenderWidgetHostViewAuraTest, OutputSurfaceIdChange) {
// TODO(jonross): Delete this test once Viz launches as it will be obsolete.
// https://crbug.com/844469
if (base::FeatureList::IsEnabled(features::kVizDisplayCompositor) ||
- !features::IsAshInBrowserProcess()) {
+ features::IsUsingWindowService()) {
return;
}
@@ -3436,6 +3443,10 @@ TEST_F(RenderWidgetHostViewAuraTest, OutputSurfaceIdChange) {
// then the fallback is dropped.
TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
DropFallbackWhenHidden) {
+ // Early out because DelegatedFrameHost is not used in mash.
+ if (features::IsUsingWindowService())
+ return;
+
view_->InitAsChild(nullptr);
aura::client::ParentWindowWithContext(
view_->GetNativeView(), parent_view_->GetNativeView()->GetRootWindow(),
@@ -3460,6 +3471,10 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
// This test verifies that the primary SurfaceId is populated on resize and
// the fallback SurfaceId is populated in OnFirstSurfaceActivation.
TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest, SurfaceChanges) {
+ // Early out because DelegatedFrameHost is not used in mash.
+ if (features::IsUsingWindowService())
+ return;
+
view_->InitAsChild(nullptr);
aura::client::ParentWindowWithContext(
view_->GetNativeView(), parent_view_->GetNativeView()->GetRootWindow(),
@@ -3477,7 +3492,7 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest, SurfaceChanges) {
// Resizing should update the primary SurfaceId.
view_->SetSize(gfx::Size(400, 400));
EXPECT_EQ(gfx::Size(400, 400), view_->window_->layer()->size());
- EXPECT_FALSE(view_->window_->layer()->GetFallbackSurfaceId()->is_valid());
+ EXPECT_EQ(nullptr, view_->window_->layer()->GetFallbackSurfaceId());
EXPECT_EQ(gfx::Size(400, 400),
view_->delegated_frame_host_->CurrentFrameSizeInDipForTesting());
@@ -3496,7 +3511,7 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest, SurfaceChanges) {
TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
DeviceScaleFactorChanges) {
// TODO: fix for mash.
- if (!features::IsAshInBrowserProcess())
+ if (features::IsUsingWindowService())
return;
view_->InitAsChild(nullptr);
@@ -3509,7 +3524,7 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
EXPECT_EQ(gfx::Size(300, 300), view_->window_->layer()->size());
viz::SurfaceId initial_surface_id =
*view_->window_->layer()->GetPrimarySurfaceId();
- EXPECT_FALSE(view_->window_->layer()->GetFallbackSurfaceId()->is_valid());
+ EXPECT_EQ(nullptr, view_->window_->layer()->GetFallbackSurfaceId());
// Resizing should update the primary SurfaceId.
aura_test_helper_->test_screen()->SetDeviceScaleFactor(2.0f);
@@ -3526,7 +3541,7 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
// TODO(jonross): Delete this test once Viz launches as it will be obsolete.
// https://crbug.com/844469
if (base::FeatureList::IsEnabled(features::kVizDisplayCompositor) ||
- !features::IsAshInBrowserProcess()) {
+ features::IsUsingWindowService()) {
return;
}
@@ -3560,6 +3575,10 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
// RenderWidgetHostViewAuraTest.DiscardDelegatedFrame.
TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
DiscardDelegatedFrames) {
+ // Early out because DelegatedFrameHost is not used in mash.
+ if (features::IsUsingWindowService())
+ return;
+
view_->InitAsChild(nullptr);
size_t max_renderer_frames =
@@ -3696,6 +3715,10 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
}
TEST_F(RenderWidgetHostViewAuraTest, DiscardDelegatedFramesWithLocking) {
+ // Early out because DelegatedFrameHost is not used in mash.
+ if (features::IsUsingWindowService())
+ return;
+
view_->InitAsChild(nullptr);
size_t max_renderer_frames =
@@ -3766,6 +3789,10 @@ TEST_F(RenderWidgetHostViewAuraTest, DiscardDelegatedFramesWithLocking) {
// 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::IsUsingWindowService())
+ return;
+
view_->InitAsChild(nullptr);
// The test logic below relies on having max_renderer_frames > 2. By default,
@@ -3870,7 +3897,7 @@ TEST_F(RenderWidgetHostViewAuraTest, ForwardsBeginFrameAcks) {
// TODO(jonross): Delete this test once Viz launches as it will be obsolete.
// https://crbug.com/844469
if (base::FeatureList::IsEnabled(features::kVizDisplayCompositor) ||
- !features::IsAshInBrowserProcess()) {
+ features::IsUsingWindowService()) {
return;
}
@@ -4244,13 +4271,19 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest,
// Send a fling start, but with a small velocity, the fling controller handles
// GFS with touchpad source and the event doesn't get queued in gesture event
- // queue. The overscroll state doesn't get reset till the first ProgressFling
- // call.
+ // queue. The overscroll state doesn't get reset till the fling progress sends
+ // the fling end event.
SimulateGestureFlingStartEvent(0.f, 0.1f, blink::kWebGestureDeviceTouchpad);
events = GetAndResetDispatchedMessages();
- EXPECT_EQ(0U, events.size());
- EXPECT_EQ(OVERSCROLL_EAST, overscroll_mode());
- EXPECT_EQ(OverscrollSource::TOUCHPAD, overscroll_source());
+ bool fling_end_event_sent_ = events.size();
+ if (fling_end_event_sent_) {
+ EXPECT_EQ("MouseWheel GestureScrollEnd", GetMessageNames(events));
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
+ EXPECT_EQ(OverscrollSource::NONE, overscroll_source());
+ } else {
+ EXPECT_EQ(OVERSCROLL_EAST, overscroll_mode());
+ EXPECT_EQ(OverscrollSource::TOUCHPAD, overscroll_source());
+ }
base::TimeTicks progress_time =
base::TimeTicks::Now() + base::TimeDelta::FromMilliseconds(17);
@@ -5699,9 +5732,33 @@ TEST_F(RenderWidgetHostViewAuraTest, ForwardMouseEvent) {
view_ = nullptr;
}
+class TouchpadRenderWidgetHostViewAuraTest
+ : public RenderWidgetHostViewAuraTest,
+ public testing::WithParamInterface<bool> {
+ public:
+ TouchpadRenderWidgetHostViewAuraTest() {
+ if (GetParam()) {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kTouchpadAsyncPinchEvents);
+ } else {
+ scoped_feature_list_.InitAndDisableFeature(
+ features::kTouchpadAsyncPinchEvents);
+ }
+ }
+ ~TouchpadRenderWidgetHostViewAuraTest() override = default;
+
+ private:
+ base::test::ScopedFeatureList scoped_feature_list_;
+ DISALLOW_COPY_AND_ASSIGN(TouchpadRenderWidgetHostViewAuraTest);
+};
+
+INSTANTIATE_TEST_CASE_P(,
+ TouchpadRenderWidgetHostViewAuraTest,
+ testing::Bool());
+
// Test that we elide touchpad pinch gesture steams consisting of only begin
// and end events.
-TEST_F(RenderWidgetHostViewAuraTest, ElideEmptyTouchpadPinchSequence) {
+TEST_P(TouchpadRenderWidgetHostViewAuraTest, ElideEmptyTouchpadPinchSequence) {
ui::GestureEventDetails begin_details(ui::ET_GESTURE_PINCH_BEGIN);
begin_details.set_device_type(ui::GestureDeviceType::DEVICE_TOUCHPAD);
ui::GestureEvent begin_event(0, 0, 0, ui::EventTimeForNow(), begin_details);
@@ -5740,7 +5797,7 @@ TEST_F(RenderWidgetHostViewAuraTest, ElideEmptyTouchpadPinchSequence) {
// Since we have not sent any GesturePinchUpdates by the time we get to the
// end of the pinch, the GesturePinchBegin and GesturePinchEnd events should
// be elided.
- EXPECT_EQ(0U, events.size());
+ EXPECT_EQ("MouseWheel", GetMessageNames(events));
}
TEST_F(RenderWidgetHostViewAuraTest, GestureTapFromStylusHasPointerType) {
@@ -5781,7 +5838,7 @@ TEST_F(RenderWidgetHostViewAuraTest, HitTestRegionListSubmitted) {
// TODO(jonross): Delete this test once Viz launches as it will be obsolete.
// https://crbug.com/844469
if (base::FeatureList::IsEnabled(features::kVizDisplayCompositor) ||
- !features::IsAshInBrowserProcess()) {
+ features::IsUsingWindowService()) {
return;
}
@@ -5823,7 +5880,7 @@ TEST_F(RenderWidgetHostViewAuraTest, HitTestRegionListSubmitted) {
TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
NewContentRenderingTimeout) {
// TODO: fix for mash.
- if (!features::IsAshInBrowserProcess())
+ if (features::IsUsingWindowService())
return;
constexpr base::TimeDelta kTimeout = base::TimeDelta::FromMicroseconds(10);
@@ -5849,15 +5906,8 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
FROM_HERE, run_loop.QuitClosure(), 2 * kTimeout);
run_loop.Run();
}
- if (base::FeatureList::IsEnabled(features::kEnableSurfaceSynchronization)) {
- // When using surface sync, the timer should not fire, because the surface
- // id did not change.
- EXPECT_FALSE(widget_host_->new_content_rendering_timeout_fired());
- } else {
- // When not using surface sync, the timer will fire because the source id
- // changed.
- EXPECT_TRUE(widget_host_->new_content_rendering_timeout_fired());
- }
+
+ EXPECT_TRUE(widget_host_->new_content_rendering_timeout_fired());
widget_host_->reset_new_content_rendering_timeout_fired();
// Start the timer. Verify that a new LocalSurfaceId is allocated.
@@ -5879,29 +5929,13 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
}
EXPECT_TRUE(widget_host_->new_content_rendering_timeout_fired());
widget_host_->reset_new_content_rendering_timeout_fired();
-
- // Start the timer again. A new LocalSurfaceId should be allocated.
- widget_host_->DidNavigate(10);
- viz::LocalSurfaceId id3 = view_->GetLocalSurfaceId();
- EXPECT_LT(id2.parent_sequence_number(), id3.parent_sequence_number());
-
- // Submit to |id3|. Timer should not fire.
- view_->delegated_frame_host_->OnFirstSurfaceActivation(viz::SurfaceInfo(
- viz::SurfaceId(view_->GetFrameSinkId(), id3), 1, gfx::Size(20, 20)));
- {
- base::RunLoop run_loop;
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, run_loop.QuitClosure(), 2 * kTimeout);
- run_loop.Run();
- }
- EXPECT_FALSE(widget_host_->new_content_rendering_timeout_fired());
}
// If a tab is evicted, allocate a new LocalSurfaceId next time it's shown.
TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
AllocateLocalSurfaceIdOnEviction) {
// TODO: fix for mash.
- if (!features::IsAshInBrowserProcess())
+ if (features::IsUsingWindowService())
return;
view_->InitAsChild(nullptr);
@@ -5923,6 +5957,10 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
// visible we show blank.
TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
DropFallbackIfResizedWhileHidden) {
+ // Early out because DelegatedFrameHost is not used in mash.
+ if (features::IsUsingWindowService())
+ return;
+
view_->InitAsChild(nullptr);
aura::client::ParentWindowWithContext(
view_->GetNativeView(), parent_view_->GetNativeView()->GetRootWindow(),
@@ -5935,13 +5973,17 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
view_->Hide();
view_->SetSize(gfx::Size(54, 32));
view_->Show();
- EXPECT_FALSE(view_->window_->layer()->GetFallbackSurfaceId()->is_valid());
+ EXPECT_EQ(nullptr, view_->window_->layer()->GetFallbackSurfaceId());
}
// If a tab is hidden and shown without being resized in the meantime, the
// fallback SurfaceId has to be preserved.
TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
DontDropFallbackIfNotResizedWhileHidden) {
+ // Early out because DelegatedFrameHost is not used in mash.
+ if (features::IsUsingWindowService())
+ return;
+
view_->InitAsChild(nullptr);
aura::client::ParentWindowWithContext(
view_->GetNativeView(), parent_view_->GetNativeView()->GetRootWindow(),
@@ -5960,6 +6002,10 @@ 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::IsUsingWindowService())
+ return;
+
// Initialize the first view.
view_->InitAsChild(nullptr);
aura::client::ParentWindowWithContext(
@@ -6735,6 +6781,7 @@ class RenderWidgetHostViewAuraKeyboardTest
};
TEST_F(RenderWidgetHostViewAuraKeyboardTest, KeyboardObserverDestroyed) {
+ parent_view_->SetLastPointerType(ui::EventPointerType::POINTER_TYPE_TOUCH);
parent_view_->FocusedNodeTouched(true);
EXPECT_NE(parent_view_->keyboard_observer_.get(), nullptr);
EXPECT_EQ(keyboard_controller_observer_count(), 1u);
@@ -6744,6 +6791,20 @@ TEST_F(RenderWidgetHostViewAuraKeyboardTest, KeyboardObserverDestroyed) {
EXPECT_EQ(keyboard_controller_observer_count(), 0u);
}
+TEST_F(RenderWidgetHostViewAuraKeyboardTest,
+ KeyboardObserverForOnlyTouchInput) {
+ // Show virtual keyboard for touch inputs.
+ parent_view_->SetLastPointerType(ui::EventPointerType::POINTER_TYPE_TOUCH);
+ parent_view_->FocusedNodeTouched(true);
+ EXPECT_NE(parent_view_->keyboard_observer_.get(), nullptr);
+ EXPECT_EQ(keyboard_controller_observer_count(), 1u);
+ // Do not show virtual keyboard for mouse inputs.
+ parent_view_->SetLastPointerType(ui::EventPointerType::POINTER_TYPE_MOUSE);
+ parent_view_->FocusedNodeTouched(true);
+ EXPECT_EQ(parent_view_->keyboard_observer_.get(), nullptr);
+ EXPECT_EQ(keyboard_controller_observer_count(), 0u);
+}
+
#endif // defined(OS_WIN)
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_base.cc b/chromium/content/browser/renderer_host/render_widget_host_view_base.cc
index 5561b7a1f38..fae4c74c977 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
@@ -161,6 +161,10 @@ int RenderWidgetHostViewBase::GetMouseWheelMinimumGranularity() const {
return 0;
}
+RenderWidgetHostViewBase* RenderWidgetHostViewBase::GetRootView() {
+ return this;
+}
+
void RenderWidgetHostViewBase::SelectionChanged(const base::string16& text,
size_t offset,
const gfx::Range& range) {
@@ -233,6 +237,12 @@ gfx::Range RenderWidgetHostViewBase::GetSelectedRange() {
return GetTextInputManager()->GetTextSelection(this)->range();
}
+size_t RenderWidgetHostViewBase::GetOffsetForSurroundingText() {
+ if (!GetTextInputManager())
+ return 0;
+ return GetTextInputManager()->GetTextSelection(this)->offset();
+}
+
void RenderWidgetHostViewBase::SetBackgroundColor(SkColor color) {
DCHECK(SkColorGetA(color) == SK_AlphaOPAQUE ||
SkColorGetA(color) == SK_AlphaTRANSPARENT);
@@ -346,6 +356,11 @@ void RenderWidgetHostViewBase::ForwardTouchpadPinchIfNecessary(
}
}
+bool RenderWidgetHostViewBase::HasFallbackSurface() const {
+ NOTREACHED();
+ return false;
+}
+
void RenderWidgetHostViewBase::SetPopupType(blink::WebPopupType popup_type) {
popup_type_ = popup_type;
}
@@ -385,6 +400,12 @@ bool RenderWidgetHostViewBase::RequestRepaintForTesting() {
return false;
}
+void RenderWidgetHostViewBase::ProcessAckedTouchEvent(
+ const TouchEventWithLatencyInfo& touch,
+ InputEventAckState ack_result) {
+ NOTREACHED();
+}
+
void RenderWidgetHostViewBase::UpdateScreenInfo(gfx::NativeView view) {
if (host() && host()->delegate())
host()->delegate()->SendScreenRects();
@@ -488,12 +509,6 @@ void RenderWidgetHostViewBase::DidReceiveRendererFrame() {
++renderer_frame_number_;
}
-void RenderWidgetHostViewBase::ShowDisambiguationPopup(
- const gfx::Rect& rect_pixels,
- const SkBitmap& zoomed_bitmap) {
- NOTIMPLEMENTED_LOG_ONCE();
-}
-
void RenderWidgetHostViewBase::OnAutoscrollStart() {
if (!GetMouseWheelPhaseHandler())
return;
@@ -719,7 +734,7 @@ RenderWidgetHostViewBase::GetTouchSelectionControllerClientManager() {
void RenderWidgetHostViewBase::EmbedChildFrameRendererWindowTreeClient(
RenderWidgetHostViewBase* root_view,
int routing_id,
- ui::mojom::WindowTreeClientPtr renderer_window_tree_client) {
+ ws::mojom::WindowTreeClientPtr renderer_window_tree_client) {
RenderWidgetHost* render_widget_host = GetRenderWidgetHost();
if (!render_widget_host)
return;
@@ -761,19 +776,19 @@ void RenderWidgetHostViewBase::OnDidScheduleEmbed(
}
void RenderWidgetHostViewBase::ScheduleEmbed(
- ui::mojom::WindowTreeClientPtr client,
+ ws::mojom::WindowTreeClientPtr client,
base::OnceCallback<void(const base::UnguessableToken&)> callback) {
NOTREACHED();
}
-ui::mojom::WindowTreeClientPtr
+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);
- ui::mojom::WindowTreeClientPtr window_tree_client;
+ ws::mojom::WindowTreeClientPtr window_tree_client;
factory->CreateWindowTreeClientForRenderWidget(
render_widget_host->GetRoutingID(),
mojo::MakeRequest(&window_tree_client),
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 8ed6ffd3a28..08454f68a01 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
@@ -46,9 +46,8 @@
#if defined(USE_AURA)
#include "base/containers/flat_map.h"
#include "content/common/render_widget_window_tree_client_factory.mojom.h"
-#include "services/ui/public/interfaces/window_tree.mojom.h"
+#include "services/ws/public/mojom/window_tree.mojom.h"
#endif
-class SkBitmap;
struct ViewHostMsg_SelectionBounds_Params;
@@ -118,6 +117,7 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
base::string16 GetSelectedText() override;
base::string16 GetSurroundingText() override;
gfx::Range GetSelectedRange() override;
+ size_t GetOffsetForSurroundingText() override;
bool IsMouseLocked() override;
bool LockKeyboard(base::Optional<base::flat_set<ui::DomCode>> codes) override;
void SetBackgroundColor(SkColor color) override;
@@ -199,6 +199,10 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
//----------------------------------------------------------------------------
// The following methods can be overridden by derived classes.
+ // Returns the root-view associated with this view. Always returns |this| for
+ // non-embeddable derived views.
+ virtual RenderWidgetHostViewBase* GetRootView();
+
// Notifies the View that the renderer text selection has changed.
virtual void SelectionChanged(const base::string16& text,
size_t offset,
@@ -296,6 +300,9 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
// with what is visible on screen.
virtual void ClearCompositorFrame() = 0;
+ // This method will reset the fallback to the first surface after navigation.
+ virtual void ResetFallbackToFirstNavigationSurface() = 0;
+
// Requests a new CompositorFrame from the renderer. This is done by
// allocating a new viz::LocalSurfaceId which forces a commit and draw.
virtual bool RequestRepaintForTesting();
@@ -308,7 +315,7 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
// |touch|'s coordinates are in the coordinate space of the view to which it
// was targeted.
virtual void ProcessAckedTouchEvent(const TouchEventWithLatencyInfo& touch,
- InputEventAckState ack_result) {}
+ InputEventAckState ack_result);
virtual void DidOverscroll(const ui::DidOverscrollParams& params) {}
@@ -373,9 +380,11 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
const gfx::PointF& point,
const viz::SurfaceId& original_surface,
gfx::PointF* transformed_point);
-
- // Transform a point that is in the coordinate space for the current
- // RenderWidgetHostView to the coordinate space of the target_view.
+ // Given a RenderWidgetHostViewBase that renders to a Surface that is
+ // contained within this class' Surface, find the relative transform between
+ // the Surfaces and apply it to a point. Returns false if a Surface has not
+ // yet been created or if |target_view| is not a descendant RWHV from our
+ // client.
virtual bool TransformPointToCoordSpaceForView(
const gfx::PointF& point,
RenderWidgetHostViewBase* target_view,
@@ -413,6 +422,9 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
// Returns true if this view's size have been initialized.
virtual bool HasSize() const;
+ // Informs the view that the assocaited InterstitialPage was attached.
+ virtual void OnInterstitialPageAttached() {}
+
// Tells the view that the assocaited InterstitialPage will going away (but is
// not yet destroyed, as InterstitialPage destruction is asynchronous). The
// view may use this notification to clean up associated resources. This
@@ -495,11 +507,6 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
// Gets the bounds of the top-level window, in screen coordinates.
virtual gfx::Rect GetBoundsInRootWindow() = 0;
- // Called by the RenderWidgetHost when an ambiguous gesture is detected to
- // show the disambiguation popup bubble.
- virtual void ShowDisambiguationPopup(const gfx::Rect& rect_pixels,
- const SkBitmap& zoomed_bitmap);
-
// Called by the WebContentsImpl when a user tries to navigate a new page on
// main frame.
virtual void OnDidNavigateMainFrameToNewPage();
@@ -553,7 +560,7 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
void EmbedChildFrameRendererWindowTreeClient(
RenderWidgetHostViewBase* root_view,
int routing_id,
- ui::mojom::WindowTreeClientPtr renderer_window_tree_client);
+ ws::mojom::WindowTreeClientPtr renderer_window_tree_client);
void OnChildFrameDestroyed(int routing_id);
#endif
@@ -591,10 +598,10 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
#if defined(USE_AURA)
virtual void ScheduleEmbed(
- ui::mojom::WindowTreeClientPtr client,
+ ws::mojom::WindowTreeClientPtr client,
base::OnceCallback<void(const base::UnguessableToken&)> callback);
- ui::mojom::WindowTreeClientPtr GetWindowTreeClientFromRenderer();
+ ws::mojom::WindowTreeClientPtr GetWindowTreeClientFromRenderer();
#endif
// If |event| is a touchpad pinch event for which we've sent a synthetic
@@ -604,6 +611,8 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
const blink::WebGestureEvent& event,
InputEventAckState ack_result);
+ virtual bool HasFallbackSurface() const;
+
// The model object. Members will become private when
// RenderWidgetHostViewGuest is removed.
RenderWidgetHostImpl* host_;
@@ -686,7 +695,7 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
uint32_t renderer_frame_number_;
- base::ObserverList<RenderWidgetHostViewBaseObserver> observers_;
+ base::ObserverList<RenderWidgetHostViewBaseObserver>::Unchecked observers_;
#if defined(USE_AURA)
mojom::RenderWidgetWindowTreeClientPtr render_widget_window_tree_client_;
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 08e68296f2a..ef607a087cd 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
@@ -49,7 +49,7 @@
#include "ui/touch_selection/touch_selection_controller.h"
#if defined(USE_AURA)
-#include "services/ui/public/interfaces/window_tree.mojom.h"
+#include "services/ws/public/mojom/window_tree.mojom.h"
#include "ui/aura/env.h"
#endif
@@ -74,7 +74,7 @@ RenderWidgetHostViewChildFrame::RenderWidgetHostViewChildFrame(
enable_viz_(
base::FeatureList::IsEnabled(features::kVizDisplayCompositor)),
weak_factory_(this) {
- if (!features::IsAshInBrowserProcess()) {
+ if (features::IsUsingWindowService()) {
// 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();
@@ -93,7 +93,7 @@ RenderWidgetHostViewChildFrame::~RenderWidgetHostViewChildFrame() {
if (frame_connector_)
DetachFromTouchSelectionClientManagerIfNecessary();
- if (features::IsAshInBrowserProcess()) {
+ if (!features::IsUsingWindowService()) {
ResetCompositorFrameSinkSupport();
if (GetHostFrameSinkManager())
GetHostFrameSinkManager()->InvalidateFrameSinkId(frame_sink_id_);
@@ -147,7 +147,7 @@ void RenderWidgetHostViewChildFrame::SetFrameConnectorDelegate(
if (parent_view) {
DCHECK(parent_view->GetFrameSinkId().is_valid() ||
- !features::IsAshInBrowserProcess());
+ features::IsUsingWindowService());
SetParentFrameSinkId(parent_view->GetFrameSinkId());
}
@@ -168,7 +168,7 @@ void RenderWidgetHostViewChildFrame::SetFrameConnectorDelegate(
}
#if defined(USE_AURA)
- if (!features::IsAshInBrowserProcess()) {
+ if (features::IsUsingWindowService()) {
frame_connector_->EmbedRendererWindowTreeClientInParent(
GetWindowTreeClientFromRenderer());
}
@@ -180,7 +180,7 @@ void RenderWidgetHostViewChildFrame::SetFrameConnectorDelegate(
#if defined(USE_AURA)
void RenderWidgetHostViewChildFrame::SetFrameSinkId(
const viz::FrameSinkId& frame_sink_id) {
- if (!features::IsAshInBrowserProcess())
+ if (features::IsUsingWindowService())
frame_sink_id_ = frame_sink_id;
}
#endif // defined(USE_AURA)
@@ -375,6 +375,11 @@ gfx::Size RenderWidgetHostViewChildFrame::GetCompositorViewportPixelSize()
return gfx::Size();
}
+RenderWidgetHostViewBase* RenderWidgetHostViewChildFrame::GetRootView() {
+ return frame_connector_ ? frame_connector_->GetRootRenderWidgetHostView()
+ : nullptr;
+}
+
void RenderWidgetHostViewChildFrame::InitAsPopup(
RenderWidgetHostView* parent_host_view,
const gfx::Rect& bounds) {
@@ -472,11 +477,13 @@ void RenderWidgetHostViewChildFrame::UnregisterFrameSinkId() {
void RenderWidgetHostViewChildFrame::UpdateViewportIntersection(
const gfx::Rect& viewport_intersection,
- const gfx::Rect& compositor_visible_rect) {
+ const gfx::Rect& compositor_visible_rect,
+ bool occluded_or_obscured) {
if (host()) {
- host()->Send(new ViewMsg_SetViewportIntersection(host()->GetRoutingID(),
- viewport_intersection,
- compositor_visible_rect));
+ host()->SetIntersectsViewport(!viewport_intersection.IsEmpty());
+ host()->Send(new ViewMsg_SetViewportIntersection(
+ host()->GetRoutingID(), viewport_intersection, compositor_visible_rect,
+ occluded_or_obscured));
}
}
@@ -517,6 +524,37 @@ void RenderWidgetHostViewChildFrame::GestureEventAck(
ack_result == INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS ||
ack_result == INPUT_EVENT_ACK_STATE_CONSUMED_SHOULD_BUBBLE;
+ bool touchpad_fling_start_bubbles = false;
+// GSU events with inertial phase are generated from touchpad fling only on
+// ChromeOS. Other platforms either don't have touchpad-based GSUs with inertial
+// phase (e.g., Linux/Android, or Windows with low precision touchpads) or
+// generate them from the OS rather than the fling controller (e.g., Mac, or
+// Windows with high precision touchpads). |touchpad_fling_start_bubbles| is
+// true on ChromeOS to show that on this platform we do not need to bubble
+// touchpad-based GSU events with inertial phase, since touchpad-based fling
+// start gets bubbled instead and the fling controller of the parent will take
+// care of touchpad-based inertial GSUs event creation from the bubbled touchpad
+// fling.
+#if defined(CHROMEOS)
+ touchpad_fling_start_bubbles = true;
+#endif // defined(CHROMEOS)
+
+ // When a GFS is bubbled, we still send it to the fling controller of the
+ // child view to finish the scroll sequence. However the GSU and GSE events
+ // that are generated by the child view's fling controller do not need to get
+ // bubbled since the GFS event itself is bubbled and the target's fling
+ // controller will take care of flinging.
+ if (((event.GetType() == blink::WebInputEvent::kGestureScrollEnd &&
+ event.data.scroll_end.inertial_phase ==
+ blink::WebGestureEvent::kMomentumPhase) ||
+ (event.GetType() == blink::WebInputEvent::kGestureScrollUpdate &&
+ event.data.scroll_update.inertial_phase ==
+ blink::WebGestureEvent::kMomentumPhase)) &&
+ (event.SourceDevice() != blink::kWebGestureDeviceTouchpad ||
+ touchpad_fling_start_bubbles)) {
+ return;
+ }
+
if ((event.GetType() == blink::WebInputEvent::kGestureScrollBegin) &&
should_bubble) {
DCHECK(!is_scroll_sequence_bubbling_);
@@ -535,7 +573,8 @@ void RenderWidgetHostViewChildFrame::GestureEventAck(
should_bubble) ||
event.GetType() == blink::WebInputEvent::kGestureScrollUpdate ||
event.GetType() == blink::WebInputEvent::kGestureScrollEnd ||
- event.GetType() == blink::WebInputEvent::kGestureFlingStart) {
+ event.GetType() == blink::WebInputEvent::kGestureFlingStart ||
+ event.GetType() == blink::WebInputEvent::kGestureFlingCancel) {
frame_connector_->BubbleScrollEvent(event);
}
}
@@ -580,7 +619,7 @@ void RenderWidgetHostViewChildFrame::DidCreateNewRendererCompositorFrameSink(
void RenderWidgetHostViewChildFrame::SetParentFrameSinkId(
const viz::FrameSinkId& parent_frame_sink_id) {
if (parent_frame_sink_id_ == parent_frame_sink_id ||
- !features::IsAshInBrowserProcess())
+ features::IsUsingWindowService())
return;
auto* host_frame_sink_manager = GetHostFrameSinkManager();
@@ -601,7 +640,7 @@ void RenderWidgetHostViewChildFrame::SetParentFrameSinkId(
}
void RenderWidgetHostViewChildFrame::SendSurfaceInfoToEmbedder() {
- if (!features::IsAshInBrowserProcess())
+ if (features::IsUsingWindowService())
return;
if (!last_activated_surface_info_.is_valid())
return;
@@ -661,15 +700,6 @@ gfx::Rect RenderWidgetHostViewChildFrame::GetBoundsInRootWindow() {
return rect;
}
-void RenderWidgetHostViewChildFrame::ProcessAckedTouchEvent(
- const TouchEventWithLatencyInfo& touch,
- InputEventAckState ack_result) {
- if (!frame_connector_)
- return;
-
- frame_connector_->ForwardProcessAckedTouchEvent(touch, ack_result);
-}
-
void RenderWidgetHostViewChildFrame::DidStopFlinging() {
if (selection_controller_client_)
selection_controller_client_->DidStopFlinging();
@@ -812,7 +842,8 @@ void RenderWidgetHostViewChildFrame::WillSendScreenRects() {
// until somebody figures that out. RWHVCF::Init() is too early.
if (frame_connector_) {
UpdateViewportIntersection(frame_connector_->viewport_intersection_rect(),
- frame_connector_->compositor_visible_rect());
+ frame_connector_->compositor_visible_rect(),
+ frame_connector_->occluded_or_obscured());
SetIsInert();
UpdateInheritedEffectiveTouchAction();
UpdateRenderThrottlingStatus();
@@ -1067,7 +1098,7 @@ RenderWidgetHostViewChildFrame::DidUpdateVisualProperties(
}
void RenderWidgetHostViewChildFrame::CreateCompositorFrameSinkSupport() {
- if (!features::IsAshInBrowserProcess() || enable_viz_)
+ if (features::IsUsingWindowService() || 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 f5a326cdc98..ba8c25a4021 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
@@ -114,6 +114,7 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
void TakeFallbackContentFrom(RenderWidgetHostView* view) override;
// RenderWidgetHostViewBase implementation.
+ RenderWidgetHostViewBase* GetRootView() override;
void InitAsPopup(RenderWidgetHostView* parent_host_view,
const gfx::Rect& bounds) override;
void InitAsFullscreen(RenderWidgetHostView* reference_host_view) override;
@@ -136,10 +137,10 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
// Since the URL of content rendered by this class is not displayed in
// the URL bar, this method does not need an implementation.
void ClearCompositorFrame() override {}
+ void ResetFallbackToFirstNavigationSurface() override{};
+
void TransformPointToRootSurface(gfx::PointF* point) override;
gfx::Rect GetBoundsInRootWindow() override;
- void ProcessAckedTouchEvent(const TouchEventWithLatencyInfo& touch,
- InputEventAckState ack_result) override;
void DidStopFlinging() override;
bool LockMouse() override;
void UnlockMouse() override;
@@ -225,7 +226,8 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
void UnregisterFrameSinkId();
void UpdateViewportIntersection(const gfx::Rect& viewport_intersection,
- const gfx::Rect& compositor_visible_rect);
+ const gfx::Rect& compositor_visible_rect,
+ bool occluded_or_obscured);
// TODO(sunxd): Rename SetIsInert to UpdateIsInert.
void SetIsInert();
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 6c9a0a1bc04..96d0d44860b 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
@@ -160,7 +160,7 @@ IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewChildFrameTest,
IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewChildFrameTest, ChildFrameSinkId) {
// Only when mus hosts viz do we expect a RenderFrameProxy to provide the
// FrameSinkId.
- if (features::IsAshInBrowserProcess())
+ if (!features::IsUsingWindowService())
return;
GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html"));
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc b/chromium/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc
index d888709145d..4eff713dfc4 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc
@@ -230,7 +230,7 @@ TEST_F(RenderWidgetHostViewChildFrameTest, ViewportIntersectionUpdated) {
process->sink().GetUniqueMessageMatching(
ViewMsg_SetViewportIntersection::ID);
ASSERT_TRUE(intersection_update);
- std::tuple<gfx::Rect, gfx::Rect> sent_rects;
+ std::tuple<gfx::Rect, gfx::Rect, bool> sent_rects;
ViewMsg_SetViewportIntersection::Read(intersection_update, &sent_rects);
EXPECT_EQ(intersection_rect, std::get<0>(sent_rects));
@@ -282,7 +282,7 @@ TEST_F(RenderWidgetHostViewChildFrameTest, WasResizedOncePerChange) {
constexpr gfx::Size compositor_viewport_pixel_size(100, 100);
constexpr gfx::Rect screen_space_rect(compositor_viewport_pixel_size);
viz::ParentLocalSurfaceIdAllocator allocator;
- viz::LocalSurfaceId local_surface_id = allocator.GenerateId();
+ viz::LocalSurfaceId local_surface_id = allocator.GetCurrentLocalSurfaceId();
constexpr viz::FrameSinkId frame_sink_id(1, 1);
const viz::SurfaceId surface_id(frame_sink_id, local_surface_id);
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_cocoa.h b/chromium/content/browser/renderer_host/render_widget_host_view_cocoa.h
index b2d9cecb8e2..83af25a5814 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_cocoa.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_cocoa.h
@@ -189,6 +189,12 @@ struct DidOverscrollParams;
// The filter used to guide touch events towards a horizontal or vertical
// orientation.
content::MouseWheelRailsFilterMac mouseWheelFilter_;
+
+ // Whether the direct manipulation feature is enabled.
+ bool direct_manipulation_enabled_;
+
+ // Whether the pen's tip is in contact with the stylus digital tablet.
+ bool has_pen_contact_;
}
@property(nonatomic, assign) NSRange markedRange;
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_cocoa.mm b/chromium/content/browser/renderer_host/render_widget_host_view_cocoa.mm
index 8b84322baa8..92f940ef023 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_cocoa.mm
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_cocoa.mm
@@ -24,6 +24,7 @@
#import "ui/base/clipboard/clipboard_util_mac.h"
#import "ui/base/cocoa/appkit_utils.h"
#include "ui/base/cocoa/cocoa_base_utils.h"
+#include "ui/base/ui_base_features.h"
#include "ui/display/screen.h"
#include "ui/events/event_utils.h"
#include "ui/events/keycodes/dom/dom_code.h"
@@ -41,10 +42,12 @@ using content::RenderWidgetHostViewMacEditCommandHelper;
using content::WebGestureEventBuilder;
using content::WebMouseEventBuilder;
using content::WebMouseWheelEventBuilder;
+using content::WebTouchEventBuilder;
using blink::WebInputEvent;
using blink::WebMouseEvent;
using blink::WebMouseWheelEvent;
using blink::WebGestureEvent;
+using blink::WebTouchEvent;
namespace {
@@ -87,6 +90,10 @@ class ForwardingLocalClient : public RenderWidgetHostNSViewLocalClient {
const blink::WebMouseEvent& web_event) override {
client_->RouteOrProcessMouseEvent(TranslateEvent(web_event));
}
+ void RouteOrProcessTouchEvent(
+ const blink::WebTouchEvent& web_event) override {
+ client_->RouteOrProcessTouchEvent(TranslateEvent(web_event));
+ }
void RouteOrProcessWheelEvent(
const blink::WebMouseWheelEvent& web_event) override {
client_->RouteOrProcessWheelEvent(TranslateEvent(web_event));
@@ -223,6 +230,9 @@ void ExtractUnderlines(NSAttributedString* string,
isStylusEnteringProximity_ = false;
keyboardLockActive_ = false;
textInputType_ = ui::TEXT_INPUT_TYPE_NONE;
+ direct_manipulation_enabled_ =
+ base::FeatureList::IsEnabled(features::kDirectManipulationStylus);
+ has_pen_contact_ = false;
}
return self;
}
@@ -542,9 +552,37 @@ void ExtractUnderlines(NSAttributedString* string,
if (type == NSMouseMoved)
cursorHidden_ = NO;
- WebMouseEvent event =
- WebMouseEventBuilder::Build(theEvent, self, pointerType_);
- localClient_->RouteOrProcessMouseEvent(event);
+ bool send_touch =
+ direct_manipulation_enabled_ &&
+ pointerType_ == blink::WebPointerProperties::PointerType::kPen;
+
+ // Send touch events when the pen is in contact with the tablet.
+ if (send_touch) {
+ // Because the NSLeftMouseUp event's buttonMask is not
+ // NSEventButtonMaskPenTip, we read |has_pen_contact_| to ensure a
+ // TouchRelease is sent appropriately at the end when the stylus is
+ // no longer in contact with the digitizer.
+ send_touch = has_pen_contact_;
+ if (type == NSLeftMouseDown || type == NSLeftMouseUp ||
+ type == NSLeftMouseDragged) {
+ NSEventButtonMask buttonMask = [theEvent buttonMask];
+ if (buttonMask == NSEventButtonMaskPenTip) {
+ DCHECK(type != NSLeftMouseUp);
+ send_touch = has_pen_contact_ = true;
+ } else {
+ has_pen_contact_ = false;
+ }
+ }
+ }
+
+ if (!send_touch) {
+ WebMouseEvent event =
+ WebMouseEventBuilder::Build(theEvent, self, pointerType_);
+ localClient_->RouteOrProcessMouseEvent(event);
+ } else {
+ WebTouchEvent event = WebTouchEventBuilder::Build(theEvent, self);
+ localClient_->RouteOrProcessTouchEvent(event);
+ }
}
- (void)tabletEvent:(NSEvent*)theEvent {
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 052bcb2791c..e25f39d32e7 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
@@ -149,6 +149,7 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
base::Optional<viz::HitTestRegionList> hit_test_region_list) override;
void OnDidNotProduceFrame(const viz::BeginFrameAck& ack) override;
void ClearCompositorFrame() override;
+ void ResetFallbackToFirstNavigationSurface() override;
bool RequestRepaintForTesting() override;
BrowserAccessibilityManager* CreateBrowserAccessibilityManager(
BrowserAccessibilityDelegate* delegate, bool for_root_frame) override;
@@ -308,6 +309,7 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
const ui::LatencyInfo& latency_info,
const std::vector<EditCommand>& commands) override;
void RouteOrProcessMouseEvent(const blink::WebMouseEvent& web_event) override;
+ void RouteOrProcessTouchEvent(const blink::WebTouchEvent& web_event) override;
void RouteOrProcessWheelEvent(
const blink::WebMouseWheelEvent& web_event) override;
void ForwardMouseEvent(const blink::WebMouseEvent& web_event) override;
@@ -339,6 +341,7 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
bool skip_in_browser,
const std::vector<EditCommand>& commands) override;
void RouteOrProcessMouseEvent(std::unique_ptr<InputEvent> event) override;
+ void RouteOrProcessTouchEvent(std::unique_ptr<InputEvent> event) override;
void RouteOrProcessWheelEvent(std::unique_ptr<InputEvent> event) override;
void ForwardMouseEvent(std::unique_ptr<InputEvent> event) override;
void ForwardWheelEvent(std::unique_ptr<InputEvent> event) override;
@@ -392,7 +395,6 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
SkColor BrowserCompositorMacGetGutterColor() const override;
void BrowserCompositorMacOnBeginFrame(base::TimeTicks frame_time) override;
void OnFrameTokenChanged(uint32_t frame_token) override;
- void DidReceiveFirstFrameAfterNavigation() override;
void DestroyCompositorForShutdown() override;
bool SynchronizeVisualProperties(
const base::Optional<viz::LocalSurfaceId>&
@@ -488,6 +490,7 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
// RenderWidgetHostViewBase:
void UpdateBackgroundColor() override;
+ bool HasFallbackSurface() const override;
// Gets a textual view of the page's contents, and passes it to the callback
// provided.
@@ -535,11 +538,6 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
// Display link for getting vsync info.
scoped_refptr<ui::DisplayLinkMac> display_link_;
- // The current VSync timebase and interval. This is zero until the first call
- // to SendVSyncParametersToRenderer(), and refreshed regularly thereafter.
- base::TimeTicks vsync_timebase_;
- base::TimeDelta vsync_interval_;
-
// Whether a request for begin frames has been issued.
bool needs_begin_frames_;
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 0703dd02c90..7e3a9aa6adc 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
@@ -91,10 +91,6 @@ void RenderWidgetHostViewMac::OnFrameTokenChanged(uint32_t frame_token) {
OnFrameTokenChangedForView(frame_token);
}
-void RenderWidgetHostViewMac::DidReceiveFirstFrameAfterNavigation() {
- host()->DidReceiveFirstFrameAfterNavigation();
-}
-
void RenderWidgetHostViewMac::DestroyCompositorForShutdown() {
// When RenderWidgetHostViewMac was owned by an NSView, this function was
// necessary to ensure that the ui::Compositor did not outlive the
@@ -138,8 +134,13 @@ void RenderWidgetHostViewMac::AcceleratedWidgetCALayerParamsUpdated() {
if (ca_layer_params)
ns_view_bridge_->SetCALayerParams(*ca_layer_params);
- if (display_link_)
- display_link_->NotifyCurrentTime(base::TimeTicks::Now());
+ // Take this opportunity to update the VSync parameters, if needed.
+ if (display_link_) {
+ base::TimeTicks timebase;
+ base::TimeDelta interval;
+ if (display_link_->GetVSyncParameters(&timebase, &interval))
+ browser_compositor_->UpdateVSyncParameters(timebase, interval);
+ }
}
///////////////////////////////////////////////////////////////////////////////
@@ -293,19 +294,6 @@ void RenderWidgetHostViewMac::InitAsFullscreen(
NOTREACHED();
}
-void RenderWidgetHostViewMac::UpdateDisplayVSyncParameters() {
- if (!host() || !display_link_.get())
- return;
-
- if (!display_link_->GetVSyncParameters(&vsync_timebase_, &vsync_interval_)) {
- vsync_timebase_ = base::TimeTicks();
- vsync_interval_ = base::TimeDelta();
- return;
- }
-
- browser_compositor_->UpdateVSyncParameters(vsync_timebase_, vsync_interval_);
-}
-
RenderWidgetHostViewBase*
RenderWidgetHostViewMac::GetFocusedViewForTextSelection() {
// We obtain the TextSelection from focused RWH which is obtained from the
@@ -338,16 +326,11 @@ RenderWidgetHostImpl* RenderWidgetHostViewMac::GetWidgetForIme() {
}
void RenderWidgetHostViewMac::UpdateNSViewAndDisplayProperties() {
- static bool is_frame_rate_limit_disabled =
- base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableFrameRateLimit);
- if (!is_frame_rate_limit_disabled) {
- display_link_ = ui::DisplayLinkMac::GetForDisplay(display_.id());
- if (!display_link_.get()) {
- // Note that on some headless systems, the display link will fail to be
- // created, so this should not be a fatal error.
- LOG(ERROR) << "Failed to create display link.";
- }
+ display_link_ = ui::DisplayLinkMac::GetForDisplay(display_.id());
+ if (!display_link_) {
+ // Note that on some headless systems, the display link will fail to be
+ // created, so this should not be a fatal error.
+ LOG(ERROR) << "Failed to create display link.";
}
if (features::IsViewsBrowserCocoa())
@@ -592,8 +575,8 @@ void RenderWidgetHostViewMac::OnTextSelectionChanged(
ns_view_bridge_->SetTextSelection(selection->text(), selection->offset(),
selection->range());
if (host() && host()->delegate())
- host()->delegate()->DidChangeTextSelection(selection->text(),
- selection->range());
+ host()->delegate()->DidChangeTextSelection(
+ selection->text(), selection->range(), selection->offset());
}
bool RenderWidgetHostViewMac::ShouldWaitInPreCommit() {
@@ -1027,8 +1010,6 @@ void RenderWidgetHostViewMac::SubmitCompositorFrame(
browser_compositor_->GetDelegatedFrameHost()->SubmitCompositorFrame(
local_surface_id, std::move(frame), std::move(hit_test_region_list));
-
- UpdateDisplayVSyncParameters();
}
void RenderWidgetHostViewMac::OnDidNotProduceFrame(
@@ -1040,6 +1021,11 @@ void RenderWidgetHostViewMac::ClearCompositorFrame() {
browser_compositor_->ClearCompositorFrame();
}
+void RenderWidgetHostViewMac::ResetFallbackToFirstNavigationSurface() {
+ browser_compositor_->GetDelegatedFrameHost()
+ ->ResetFallbackToFirstNavigationSurface();
+}
+
bool RenderWidgetHostViewMac::RequestRepaintForTesting() {
return browser_compositor_->RequestRepaintForTesting();
}
@@ -1183,7 +1169,7 @@ void RenderWidgetHostViewMac::SendGesturePinchEvent(WebGestureEvent* event) {
DCHECK(event->SourceDevice() ==
blink::WebGestureDevice::kWebGestureDeviceTouchpad);
host()->delegate()->GetInputEventRouter()->RouteGestureEvent(
- this, event, ui::LatencyInfo(ui::SourceEventType::WHEEL));
+ this, event, ui::LatencyInfo(ui::SourceEventType::TOUCHPAD));
return;
}
host()->ForwardGestureEvent(*event);
@@ -1222,6 +1208,10 @@ bool RenderWidgetHostViewMac::TransformPointToLocalCoordSpaceLegacy(
return true;
}
+bool RenderWidgetHostViewMac::HasFallbackSurface() const {
+ return browser_compositor_->GetDelegatedFrameHost()->HasFallbackSurface();
+}
+
bool RenderWidgetHostViewMac::TransformPointToCoordSpaceForView(
const gfx::PointF& point,
RenderWidgetHostViewBase* target_view,
@@ -1232,9 +1222,10 @@ bool RenderWidgetHostViewMac::TransformPointToCoordSpaceForView(
return true;
}
- return browser_compositor_->GetDelegatedFrameHost()
- ->TransformPointToCoordSpaceForView(point, target_view, transformed_point,
- source);
+ if (!HasFallbackSurface())
+ return false;
+ return target_view->TransformPointToLocalCoordSpace(
+ point, GetCurrentSurfaceId(), transformed_point, source);
}
viz::FrameSinkId RenderWidgetHostViewMac::GetRootFrameSinkId() {
@@ -1488,6 +1479,24 @@ void RenderWidgetHostViewMac::RouteOrProcessMouseEvent(
}
}
+void RenderWidgetHostViewMac::RouteOrProcessTouchEvent(
+ const blink::WebTouchEvent& const_web_event) {
+ blink::WebTouchEvent web_event = const_web_event;
+ ui::FilteredGestureProvider::TouchHandlingResult result =
+ gesture_provider_.OnTouchEvent(MotionEventWeb(web_event));
+ if (!result.succeeded)
+ return;
+
+ ui::LatencyInfo latency_info(ui::SourceEventType::OTHER);
+ latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT);
+ if (ShouldRouteEvent(web_event)) {
+ host()->delegate()->GetInputEventRouter()->RouteTouchEvent(this, &web_event,
+ latency_info);
+ } else {
+ ProcessTouchEvent(web_event, latency_info);
+ }
+}
+
void RenderWidgetHostViewMac::RouteOrProcessWheelEvent(
const blink::WebMouseWheelEvent& const_web_event) {
blink::WebMouseWheelEvent web_event = const_web_event;
@@ -1850,6 +1859,7 @@ void RenderWidgetHostViewMac::ForwardKeyboardEventWithCommands(
ForwardKeyboardEventWithCommands(native_event, input_event->latency_info,
commands);
}
+
void RenderWidgetHostViewMac::RouteOrProcessMouseEvent(
std::unique_ptr<InputEvent> input_event) {
if (!input_event || !input_event->web_event ||
@@ -1863,6 +1873,19 @@ void RenderWidgetHostViewMac::RouteOrProcessMouseEvent(
RouteOrProcessMouseEvent(mouse_event);
}
+void RenderWidgetHostViewMac::RouteOrProcessTouchEvent(
+ std::unique_ptr<InputEvent> input_event) {
+ if (!input_event || !input_event->web_event ||
+ !blink::WebInputEvent::IsTouchEventType(
+ input_event->web_event->GetType())) {
+ DLOG(ERROR) << "Absent or non-TouchEventType event.";
+ return;
+ }
+ const blink::WebTouchEvent& touch_event =
+ static_cast<const blink::WebTouchEvent&>(*input_event->web_event);
+ RouteOrProcessTouchEvent(touch_event);
+}
+
void RenderWidgetHostViewMac::RouteOrProcessWheelEvent(
std::unique_ptr<InputEvent> input_event) {
if (!input_event || !input_event->web_event ||
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 4fceb1ab71c..8e31dddeb00 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
@@ -22,6 +22,7 @@
#include "base/test/simple_test_tick_clock.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/viz/common/surfaces/child_local_surface_id_allocator.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"
@@ -51,6 +52,8 @@
#include "ui/base/cocoa/secure_password_input.h"
#import "ui/base/test/cocoa_helper.h"
#import "ui/base/test/scoped_fake_nswindow_focus.h"
+#include "ui/base/ui_base_features.h"
+#include "ui/compositor/recyclable_compositor_mac.h"
#include "ui/events/base_event_utils.h"
#include "ui/events/blink/blink_features.h"
#include "ui/events/blink/web_input_event_traits.h"
@@ -132,20 +135,30 @@ std::string GetMessageNames(
for (auto& event : events)
result.push_back(event->name());
return base::JoinString(result, " ");
- }
+}
+
+blink::WebPointerProperties::PointerType GetPointerType(
+ const MockWidgetInputHandler::MessageVector& events) {
+ EXPECT_EQ(events.size(), 1U);
+ MockWidgetInputHandler::DispatchedEventMessage* event = events[0]->ToEvent();
+ if (!event)
+ return blink::WebPointerProperties::PointerType::kUnknown;
+
+ if (blink::WebInputEvent::IsMouseEventType(
+ event->Event()->web_event->GetType())) {
+ return static_cast<const blink::WebMouseEvent*>(
+ event->Event()->web_event.get())
+ ->pointer_type;
+ }
- blink::WebPointerProperties::PointerType GetPointerType(
- const MockWidgetInputHandler::MessageVector& events) {
- EXPECT_EQ(events.size(), 1U);
- MockWidgetInputHandler::DispatchedEventMessage* event =
- events[0]->ToEvent();
- if (event && blink::WebInputEvent::IsMouseEventType(
- event->Event()->web_event->GetType())) {
- return static_cast<const blink::WebMouseEvent*>(
- event->Event()->web_event.get())
- ->pointer_type;
- }
- return blink::WebPointerProperties::PointerType::kUnknown;
+ if (blink::WebInputEvent::IsTouchEventType(
+ event->Event()->web_event->GetType())) {
+ return static_cast<const blink::WebTouchEvent*>(
+ event->Event()->web_event.get())
+ ->touches[0]
+ .pointer_type;
+ }
+ return blink::WebPointerProperties::PointerType::kUnknown;
}
NSEvent* MockTabletEventWithParams(CGEventType type,
@@ -166,12 +179,20 @@ NSEvent* MockMouseEventWithParams(CGEventType mouse_type,
CGPoint location,
CGMouseButton button,
CGEventMouseSubtype subtype,
- bool is_entering_proximity = false) {
+ bool is_entering_proximity = false,
+ bool is_pen_tip = false) {
CGEventRef cg_event =
CGEventCreateMouseEvent(NULL, mouse_type, location, button);
CGEventSetIntegerValueField(cg_event, kCGMouseEventSubtype, subtype);
CGEventSetIntegerValueField(cg_event, kCGTabletProximityEventEnterProximity,
is_entering_proximity);
+ CGEventSetIntegerValueField(cg_event, kCGTabletEventRotation, 300);
+ if (is_pen_tip)
+ CGEventSetIntegerValueField(cg_event, kCGTabletEventPointButtons, 1);
+ CGEventTimestamp timestamp =
+ (ui::EventTimeForNow() - base::TimeTicks()).InMicroseconds() *
+ base::Time::kNanosecondsPerMicrosecond;
+ CGEventSetTimestamp(cg_event, timestamp);
NSEvent* event = [NSEvent eventWithCGEvent:cg_event];
CFRelease(cg_event);
return event;
@@ -358,7 +379,8 @@ class RenderWidgetHostViewMacTest : public RenderViewHostImplTestHarness {
void SetUp() override {
RenderViewHostImplTestHarness::SetUp();
- gpu::ImageTransportSurface::SetAllowOSMesaForTesting(true);
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndEnableFeature(features::kDirectManipulationStylus);
browser_context_ = std::make_unique<TestBrowserContext>();
process_host_ =
@@ -944,6 +966,77 @@ TEST_F(RenderWidgetHostViewMacTest, PointerEventWithMouseType) {
GetPointerType(events));
}
+TEST_F(RenderWidgetHostViewMacTest, PointerEventWithPenTypeSendAsTouch) {
+ // Send a NSEvent of NSTabletProximity type which has a device type of pen.
+ NSEvent* event = MockTabletEventWithParams(kCGEventTabletProximity, true,
+ NSPenPointingDevice);
+ [rwhv_mac_->cocoa_view() tabletEvent:event];
+ // Flush and clear other messages (e.g. begin frames) the RWHVMac also sends.
+ base::RunLoop().RunUntilIdle();
+ static_cast<RenderWidgetHostImpl*>(rwhv_mac_->GetRenderWidgetHost())
+ ->input_router()
+ ->ForceSetTouchActionAuto();
+
+ event = MockMouseEventWithParams(
+ kCGEventLeftMouseDown, {6, 9}, kCGMouseButtonLeft,
+ kCGEventMouseSubtypeTabletPoint, false, true);
+ [rwhv_mac_->cocoa_view() mouseEvent:event];
+ base::RunLoop().RunUntilIdle();
+ MockWidgetInputHandler::MessageVector events =
+ host_->GetAndResetDispatchedMessages();
+ ASSERT_EQ("TouchStart", GetMessageNames(events));
+ EXPECT_EQ(blink::WebPointerProperties::PointerType::kPen,
+ GetPointerType(events));
+ events.clear();
+ base::RunLoop().RunUntilIdle();
+ events = host_->GetAndResetDispatchedMessages();
+
+ event = MockMouseEventWithParams(
+ kCGEventLeftMouseDragged, {16, 29}, kCGMouseButtonLeft,
+ kCGEventMouseSubtypeTabletPoint, false, true);
+ [rwhv_mac_->cocoa_view() mouseEvent:event];
+ base::RunLoop().RunUntilIdle();
+ events = host_->GetAndResetDispatchedMessages();
+ ASSERT_EQ("TouchMove", GetMessageNames(events));
+ EXPECT_EQ(blink::WebPointerProperties::PointerType::kPen,
+ GetPointerType(events));
+
+ events.clear();
+ base::RunLoop().RunUntilIdle();
+ events = host_->GetAndResetDispatchedMessages();
+
+ event = MockMouseEventWithParams(kCGEventLeftMouseUp, {16, 29},
+ kCGMouseButtonLeft,
+ kCGEventMouseSubtypeTabletPoint, false);
+ [rwhv_mac_->cocoa_view() mouseEvent:event];
+ base::RunLoop().RunUntilIdle();
+ events = host_->GetAndResetDispatchedMessages();
+ ASSERT_EQ("TouchEnd GestureScrollEnd", GetMessageNames(events));
+ EXPECT_EQ(blink::WebPointerProperties::PointerType::kPen,
+ static_cast<const blink::WebTouchEvent*>(
+ events[0]->ToEvent()->Event()->web_event.get())
+ ->touches[0]
+ .pointer_type);
+
+ events.clear();
+ base::RunLoop().RunUntilIdle();
+ events = host_->GetAndResetDispatchedMessages();
+
+ event =
+ MockMouseEventWithParams(kCGEventLeftMouseDown, {6, 9},
+ kCGMouseButtonLeft, kCGEventMouseSubtypeDefault);
+ [rwhv_mac_->cocoa_view() mouseEvent:event];
+ base::RunLoop().RunUntilIdle();
+ events = host_->GetAndResetDispatchedMessages();
+ ASSERT_EQ("MouseDown", GetMessageNames(events));
+ EXPECT_EQ(blink::WebPointerProperties::PointerType::kMouse,
+ GetPointerType(events));
+
+ events.clear();
+ base::RunLoop().RunUntilIdle();
+ events = host_->GetAndResetDispatchedMessages();
+}
+
TEST_F(RenderWidgetHostViewMacTest, SendMouseMoveOnShowingContextMenu) {
rwhv_mac_->SetShowingContextMenu(true);
base::RunLoop().RunUntilIdle();
@@ -1308,9 +1401,19 @@ TEST_F(RenderWidgetHostViewMacTest,
host->ShutdownAndDestroyWidget(true);
}
-class RenderWidgetHostViewMacPinchTest : public RenderWidgetHostViewMacTest {
+class RenderWidgetHostViewMacPinchTest
+ : public RenderWidgetHostViewMacTest,
+ public testing::WithParamInterface<bool> {
public:
- RenderWidgetHostViewMacPinchTest() = default;
+ RenderWidgetHostViewMacPinchTest() : async_events_enabled_(GetParam()) {
+ if (async_events_enabled_) {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kTouchpadAsyncPinchEvents);
+ } else {
+ scoped_feature_list_.InitAndDisableFeature(
+ features::kTouchpadAsyncPinchEvents);
+ }
+ }
bool ShouldSendGestureEvents() {
#if defined(MAC_OS_X_VERSION_10_11) && \
@@ -1334,11 +1437,16 @@ class RenderWidgetHostViewMacPinchTest : public RenderWidgetHostViewMacTest {
[rwhv_cocoa_ endGestureWithEvent:pinchEndEvent];
}
+ const bool async_events_enabled_;
+
private:
+ base::test::ScopedFeatureList scoped_feature_list_;
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewMacPinchTest);
};
-TEST_F(RenderWidgetHostViewMacPinchTest, PinchThresholding) {
+INSTANTIATE_TEST_CASE_P(, RenderWidgetHostViewMacPinchTest, testing::Bool());
+
+TEST_P(RenderWidgetHostViewMacPinchTest, PinchThresholding) {
// Do a gesture that crosses the threshold.
{
NSEvent* pinchUpdateEvents[3] = {
@@ -1372,28 +1480,38 @@ TEST_F(RenderWidgetHostViewMacPinchTest, PinchThresholding) {
[rwhv_cocoa_ magnifyWithEvent:pinchUpdateEvents[1]];
base::RunLoop().RunUntilIdle();
events = host_->GetAndResetDispatchedMessages();
- EXPECT_EQ("MouseWheel", GetMessageNames(events));
- // Now acking the synthetic mouse wheel does produce GesturePinch events.
- events[0]->ToEvent()->CallCallback(
- INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
- events = host_->GetAndResetDispatchedMessages();
- EXPECT_EQ("GesturePinchBegin GesturePinchUpdate", GetMessageNames(events));
+ if (async_events_enabled_) {
+ EXPECT_EQ("MouseWheel GesturePinchBegin GesturePinchUpdate",
+ GetMessageNames(events));
+ } else {
+ EXPECT_EQ("MouseWheel", GetMessageNames(events));
+ // Now acking the synthetic mouse wheel does produce GesturePinch events.
+ events[0]->ToEvent()->CallCallback(
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+ events = host_->GetAndResetDispatchedMessages();
+ EXPECT_EQ("GesturePinchBegin GesturePinchUpdate",
+ GetMessageNames(events));
+ }
// The third update still has zoom enabled.
[rwhv_cocoa_ magnifyWithEvent:pinchUpdateEvents[2]];
base::RunLoop().RunUntilIdle();
events = host_->GetAndResetDispatchedMessages();
- EXPECT_EQ("MouseWheel", GetMessageNames(events));
- events[0]->ToEvent()->CallCallback(
- INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
- events = host_->GetAndResetDispatchedMessages();
- EXPECT_EQ("GesturePinchUpdate", GetMessageNames(events));
+ if (async_events_enabled_) {
+ EXPECT_EQ("MouseWheel GesturePinchUpdate", GetMessageNames(events));
+ } else {
+ EXPECT_EQ("MouseWheel", GetMessageNames(events));
+ events[0]->ToEvent()->CallCallback(
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+ events = host_->GetAndResetDispatchedMessages();
+ EXPECT_EQ("GesturePinchUpdate", GetMessageNames(events));
+ }
SendEndPinchEvent();
base::RunLoop().RunUntilIdle();
events = host_->GetAndResetDispatchedMessages();
- EXPECT_EQ("GesturePinchEnd", GetMessageNames(events));
+ EXPECT_EQ("MouseWheel GesturePinchEnd", GetMessageNames(events));
}
// Do a gesture that doesn't cross the threshold, but happens when we're not
@@ -1422,7 +1540,7 @@ TEST_F(RenderWidgetHostViewMacPinchTest, PinchThresholding) {
SendEndPinchEvent();
base::RunLoop().RunUntilIdle();
events = host_->GetAndResetDispatchedMessages();
- EXPECT_EQ("GesturePinchEnd", GetMessageNames(events));
+ EXPECT_EQ("MouseWheel GesturePinchEnd", GetMessageNames(events));
}
// Do a gesture again, after the page scale is no longer at one, and ensure
@@ -1458,7 +1576,7 @@ TEST_F(RenderWidgetHostViewMacPinchTest, PinchThresholding) {
SendEndPinchEvent();
base::RunLoop().RunUntilIdle();
events = host_->GetAndResetDispatchedMessages();
- EXPECT_EQ(0U, events.size());
+ EXPECT_EQ("MouseWheel", GetMessageNames(events));
}
}
@@ -1837,11 +1955,11 @@ TEST_F(InputMethodMacTest, MonitorCompositionRangeForActiveWidget) {
TEST_F(RenderWidgetHostViewMacTest, ClearCompositorFrame) {
BrowserCompositorMac* browser_compositor = rwhv_mac_->BrowserCompositor();
- ui::Compositor* ui_compositor = browser_compositor->GetCompositorForTesting();
+ ui::Compositor* ui_compositor = browser_compositor->GetCompositor();
EXPECT_NE(ui_compositor, nullptr);
EXPECT_TRUE(ui_compositor->IsLocked());
rwhv_mac_->ClearCompositorFrame();
- EXPECT_EQ(browser_compositor->GetCompositorForTesting(), ui_compositor);
+ EXPECT_EQ(browser_compositor->GetCompositor(), ui_compositor);
EXPECT_FALSE(ui_compositor->IsLocked());
}
@@ -1904,4 +2022,30 @@ TEST_F(RenderWidgetHostViewMacTest, ConflictingAllocationsResolve) {
EXPECT_EQ(local_surface_id4, merged_local_surface_id);
}
+TEST_F(RenderWidgetHostViewMacTest, TransformToRootNoParentLayer) {
+ gfx::PointF point(10, 20);
+ rwhv_mac_->TransformPointToRootSurface(&point);
+ EXPECT_EQ(point, gfx::PointF(10, 20));
+}
+
+TEST_F(RenderWidgetHostViewMacTest, TransformToRootWithParentLayer) {
+ std::unique_ptr<ui::RecyclableCompositorMac> compositor =
+ ui::RecyclableCompositorMacFactory::Get()->CreateCompositor(
+ ImageTransportFactory::GetInstance()->GetContextFactory(),
+ ImageTransportFactory::GetInstance()->GetContextFactoryPrivate());
+ std::unique_ptr<ui::Layer> root_surface_layer =
+ std::make_unique<ui::Layer>(ui::LAYER_SOLID_COLOR);
+ std::unique_ptr<ui::Layer> parent_layer =
+ std::make_unique<ui::Layer>(ui::LAYER_SOLID_COLOR);
+
+ compositor->compositor()->SetRootLayer(root_surface_layer.get());
+ root_surface_layer->SetBounds(gfx::Rect(-5, -10, 1000, 2000));
+ parent_layer->SetBounds(gfx::Rect(100, 300, 500, 400));
+ root_surface_layer->Add(parent_layer.get());
+ gfx::PointF point(10, 20);
+ rwhv_mac_->SetParentUiLayer(parent_layer.get());
+ rwhv_mac_->TransformPointToRootSurface(&point);
+ EXPECT_EQ(point, gfx::PointF(105, 310));
+}
+
} // 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 4a5acc5f53b..eef715fc681 100644
--- a/chromium/content/browser/renderer_host/render_widget_targeter.cc
+++ b/chromium/content/browser/renderer_host/render_widget_targeter.cc
@@ -153,10 +153,7 @@ void RenderWidgetTargeter::FindTargetAndDispatch(
RenderWidgetHostViewBase* target = result.view;
auto* event_ptr = &event;
async_depth_ = 0;
- // TODO(kenrb, wjmaclean): Asynchronous hit tests don't work properly with
- // GuestViews, so rely on the synchronous result.
- // See https://crbug.com/802378.
- if (result.should_query_view && !target->IsRenderWidgetHostViewGuest()) {
+ if (result.should_query_view) {
// TODO(kenrb, sadrul): When all event types support asynchronous hit
// testing, we should be able to have FindTargetSynchronously return the
// view and location to use for the renderer hit test query.
@@ -215,6 +212,7 @@ void RenderWidgetTargeter::QueryClient(
}
void RenderWidgetTargeter::FlushEventQueue() {
+ bool events_being_flushed = false;
while (!request_in_flight_ && !requests_.empty()) {
auto request = std::move(requests_.front());
requests_.pop();
@@ -224,9 +222,16 @@ void RenderWidgetTargeter::FlushEventQueue() {
continue;
}
request.tracker->Stop();
+ // Only notify the delegate once that the current event queue is being
+ // flushed. Once all the events are flushed, notify the delegate again.
+ if (!events_being_flushed) {
+ delegate_->SetEventsBeingFlushed(true);
+ events_being_flushed = true;
+ }
FindTargetAndDispatch(request.root_view.get(), *request.event,
request.latency);
}
+ delegate_->SetEventsBeingFlushed(false);
}
void RenderWidgetTargeter::FoundFrameSinkId(
@@ -237,7 +242,8 @@ void RenderWidgetTargeter::FoundFrameSinkId(
uint32_t request_id,
const gfx::PointF& target_location,
TracingUmaTracker tracker,
- const viz::FrameSinkId& frame_sink_id) {
+ const viz::FrameSinkId& frame_sink_id,
+ const gfx::PointF& transformed_location) {
tracker.Stop();
if (request_id != last_request_id_ || !request_in_flight_) {
// This is a response to a request that already timed out, so the event
@@ -259,10 +265,8 @@ void RenderWidgetTargeter::FoundFrameSinkId(
unresponsive_views_.find(view) != unresponsive_views_.end()) {
FoundTarget(root_view.get(), view, *event, latency, target_location, false);
} else {
- gfx::PointF location = target_location;
- target->TransformPointToCoordSpaceForView(location, view, &location);
- QueryClient(root_view.get(), view, *event, latency, location, target.get(),
- target_location);
+ QueryClient(root_view.get(), view, *event, latency, transformed_location,
+ target.get(), target_location);
}
}
diff --git a/chromium/content/browser/renderer_host/render_widget_targeter.h b/chromium/content/browser/renderer_host/render_widget_targeter.h
index e9b3e2addf4..5e6dda1dbc3 100644
--- a/chromium/content/browser/renderer_host/render_widget_targeter.h
+++ b/chromium/content/browser/renderer_host/render_widget_targeter.h
@@ -70,6 +70,8 @@ class RenderWidgetTargeter {
const ui::LatencyInfo& latency,
const base::Optional<gfx::PointF>& target_location) = 0;
+ virtual void SetEventsBeingFlushed(bool events_being_flushed) = 0;
+
virtual RenderWidgetHostViewBase* FindViewFromFrameSinkId(
const viz::FrameSinkId& frame_sink_id) const = 0;
};
@@ -115,6 +117,11 @@ class RenderWidgetTargeter {
// |event| is in the coordinate space of |root_view|. |target_location|, if
// set, is the location in |target|'s coordinate space.
+ // |target| is the current target that will be queried using its
+ // InputTargetClient interface.
+ // |frame_sink_id| is returned from the InputTargetClient to indicate where
+ // the event should be routed, and |transformed_location| is the point in
+ // that new target's coordinate space.
void FoundFrameSinkId(base::WeakPtr<RenderWidgetHostViewBase> root_view,
base::WeakPtr<RenderWidgetHostViewBase> target,
ui::WebScopedInputEvent event,
@@ -122,7 +129,8 @@ class RenderWidgetTargeter {
uint32_t request_id,
const gfx::PointF& target_location,
TracingUmaTracker tracker,
- const viz::FrameSinkId& frame_sink_id);
+ const viz::FrameSinkId& frame_sink_id,
+ const gfx::PointF& transformed_location);
// |event| is in the coordinate space of |root_view|. |target_location|, if
// set, is the location in |target|'s coordinate space. If |latched_target| is
diff --git a/chromium/content/browser/renderer_host/text_input_manager.cc b/chromium/content/browser/renderer_host/text_input_manager.cc
index 24f32e7228a..ce3a5ff83cf 100644
--- a/chromium/content/browser/renderer_host/text_input_manager.cc
+++ b/chromium/content/browser/renderer_host/text_input_manager.cc
@@ -209,6 +209,11 @@ void TextInputManager::SelectionBoundsChanged(
selection_region_map_[view].first_selection_rect.set_size(
params.anchor_rect.size());
+ NotifySelectionBoundsChanged(view);
+}
+
+void TextInputManager::NotifySelectionBoundsChanged(
+ RenderWidgetHostViewBase* view) {
for (auto& observer : observer_list_)
observer.OnSelectionBoundsChanged(this, view);
}
diff --git a/chromium/content/browser/renderer_host/text_input_manager.h b/chromium/content/browser/renderer_host/text_input_manager.h
index 8e4ecfe5be2..b715544c7a2 100644
--- a/chromium/content/browser/renderer_host/text_input_manager.h
+++ b/chromium/content/browser/renderer_host/text_input_manager.h
@@ -184,6 +184,10 @@ class CONTENT_EXPORT TextInputManager {
void SelectionBoundsChanged(RenderWidgetHostViewBase* view,
const ViewHostMsg_SelectionBounds_Params& params);
+ // Notify observers that the selection bounds have been updated. This is also
+ // called when a view with a selection is reactivated.
+ void NotifySelectionBoundsChanged(RenderWidgetHostViewBase* view);
+
// Called when the composition range and/or character bounds have changed.
void ImeCompositionRangeChanged(
RenderWidgetHostViewBase* view,
@@ -255,7 +259,7 @@ class CONTENT_EXPORT TextInputManager {
// user.
bool should_do_learning_;
- base::ObserverList<Observer> observer_list_;
+ base::ObserverList<Observer>::Unchecked observer_list_;
DISALLOW_COPY_AND_ASSIGN(TextInputManager);
};
diff --git a/chromium/content/browser/renderer_host/ui_events_helper.cc b/chromium/content/browser/renderer_host/ui_events_helper.cc
index 6ea4ed53dbe..8b3330f22c9 100644
--- a/chromium/content/browser/renderer_host/ui_events_helper.cc
+++ b/chromium/content/browser/renderer_host/ui_events_helper.cc
@@ -65,8 +65,7 @@ bool MakeUITouchEventsFromWebTouchEvents(
int flags = ui::WebEventModifiersToEventFlags(touch.GetModifiers());
base::TimeTicks timestamp = touch.TimeStamp();
- unsigned count = 0;
- for (unsigned i = 0; i < blink::WebTouchEvent::kTouchesLengthCap; ++i) {
+ for (unsigned i = 0; i < touch.touches_length; ++i) {
const blink::WebTouchPoint& point = touch.touches[i];
if (WebTouchPointStateToEventType(point.state) != type)
continue;
@@ -85,8 +84,6 @@ bool MakeUITouchEventsFromWebTouchEvents(
uievent->set_root_location_f(location);
uievent->set_latency(touch_with_latency.latency);
list->push_back(std::move(uievent));
- if (++count >= touch.touches_length)
- break;
}
return true;
}
diff --git a/chromium/content/browser/renderer_host/web_database_host_impl.cc b/chromium/content/browser/renderer_host/web_database_host_impl.cc
index 99612d10417..da7a48e8903 100644
--- a/chromium/content/browser/renderer_host/web_database_host_impl.cc
+++ b/chromium/content/browser/renderer_host/web_database_host_impl.cc
@@ -9,6 +9,7 @@
#include "base/metrics/histogram_macros.h"
#include "base/strings/utf_string_conversions.h"
+#include "content/browser/child_process_security_policy_impl.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/origin_util.h"
@@ -33,15 +34,6 @@ namespace {
const int kNumDeleteRetries = 2;
// The delay between each retry to delete the SQLite database.
const int kDelayDeleteRetryMs = 100;
-
-bool ValidateOrigin(const url::Origin& origin) {
- if (origin.unique()) {
- mojo::ReportBadMessage("Invalid Origin.");
- return false;
- }
- return true;
-}
-
} // namespace
WebDatabaseHostImpl::WebDatabaseHostImpl(
@@ -80,6 +72,9 @@ void WebDatabaseHostImpl::OpenFile(const base::string16& vfs_file_name,
int32_t desired_flags,
OpenFileCallback callback) {
DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence());
+ if (!ValidateOrigin(vfs_file_name))
+ return;
+
base::File file;
const base::File* tracked_file = nullptr;
std::string origin_identifier;
@@ -130,6 +125,9 @@ void WebDatabaseHostImpl::DeleteFile(const base::string16& vfs_file_name,
bool sync_dir,
DeleteFileCallback callback) {
DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence());
+ if (!ValidateOrigin(vfs_file_name))
+ return;
+
DatabaseDeleteFile(vfs_file_name, sync_dir, std::move(callback),
kNumDeleteRetries);
}
@@ -138,6 +136,9 @@ void WebDatabaseHostImpl::GetFileAttributes(
const base::string16& vfs_file_name,
GetFileAttributesCallback callback) {
DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence());
+ if (!ValidateOrigin(vfs_file_name))
+ return;
+
int32_t attributes = -1;
base::FilePath db_file =
DatabaseUtil::GetFullFilePathForVfsFile(db_tracker_.get(), vfs_file_name);
@@ -150,6 +151,9 @@ void WebDatabaseHostImpl::GetFileAttributes(
void WebDatabaseHostImpl::GetFileSize(const base::string16& vfs_file_name,
GetFileSizeCallback callback) {
DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence());
+ if (!ValidateOrigin(vfs_file_name))
+ return;
+
int64_t size = 0LL;
base::FilePath db_file =
DatabaseUtil::GetFullFilePathForVfsFile(db_tracker_.get(), vfs_file_name);
@@ -163,6 +167,9 @@ void WebDatabaseHostImpl::SetFileSize(const base::string16& vfs_file_name,
int64_t expected_size,
SetFileSizeCallback callback) {
DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence());
+ if (!ValidateOrigin(vfs_file_name))
+ return;
+
bool success = false;
base::FilePath db_file =
DatabaseUtil::GetFullFilePathForVfsFile(db_tracker_.get(), vfs_file_name);
@@ -177,13 +184,12 @@ void WebDatabaseHostImpl::GetSpaceAvailable(
GetSpaceAvailableCallback callback) {
// QuotaManager is only available on the IO thread.
DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence());
- DCHECK(db_tracker_->quota_manager_proxy());
if (!ValidateOrigin(origin)) {
- std::move(callback).Run(0);
return;
}
+ DCHECK(db_tracker_->quota_manager_proxy());
db_tracker_->quota_manager_proxy()->GetUsageAndQuota(
db_tracker_->task_runner(), origin, blink::mojom::StorageType::kTemporary,
base::BindOnce(
@@ -367,4 +373,37 @@ blink::mojom::WebDatabase& WebDatabaseHostImpl::GetWebDatabase() {
return *database_provider_;
}
+bool WebDatabaseHostImpl::ValidateOrigin(const url::Origin& origin) {
+ if (origin.unique()) {
+ mojo::ReportBadMessage("Invalid origin.");
+ return false;
+ }
+
+ if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanAccessDataForOrigin(
+ process_id_, origin.GetURL())) {
+ mojo::ReportBadMessage("Unauthorized origin.");
+ return false;
+ }
+ return true;
+}
+
+bool WebDatabaseHostImpl::ValidateOrigin(const base::string16& vfs_file_name) {
+ std::string origin_identifier;
+ if (vfs_file_name.empty())
+ return true;
+
+ if (!DatabaseUtil::CrackVfsFileName(vfs_file_name, &origin_identifier,
+ nullptr, nullptr)) {
+ return true;
+ }
+
+ if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanAccessDataForOrigin(
+ process_id_,
+ storage::GetOriginURLFromIdentifier(origin_identifier))) {
+ mojo::ReportBadMessage("Unauthorized origin.");
+ return false;
+ }
+ return true;
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/web_database_host_impl.h b/chromium/content/browser/renderer_host/web_database_host_impl.h
index 21bf6dc9b23..c57d2fcbf80 100644
--- a/chromium/content/browser/renderer_host/web_database_host_impl.h
+++ b/chromium/content/browser/renderer_host/web_database_host_impl.h
@@ -8,6 +8,7 @@
#include <string>
#include "base/strings/string16.h"
+#include "build/build_config.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "storage/browser/database/database_tracker.h"
#include "third_party/blink/public/platform/modules/webdatabase/web_database.mojom.h"
@@ -18,10 +19,11 @@ class Origin;
namespace content {
-class WebDatabaseHostImpl : public blink::mojom::WebDatabaseHost,
- public storage::DatabaseTracker::Observer {
+class CONTENT_EXPORT WebDatabaseHostImpl
+ : public blink::mojom::WebDatabaseHost,
+ public storage::DatabaseTracker::Observer {
public:
- WebDatabaseHostImpl(int proess_id,
+ WebDatabaseHostImpl(int process_id,
scoped_refptr<storage::DatabaseTracker> db_tracker);
~WebDatabaseHostImpl() override;
@@ -30,6 +32,9 @@ class WebDatabaseHostImpl : public blink::mojom::WebDatabaseHost,
blink::mojom::WebDatabaseHostRequest request);
private:
+ FRIEND_TEST_ALL_PREFIXES(WebDatabaseHostImplTest, BadMessagesUnauthorized);
+ FRIEND_TEST_ALL_PREFIXES(WebDatabaseHostImplTest, BadMessagesInvalid);
+
// blink::mojom::WebDatabaseHost:
void OpenFile(const base::string16& vfs_file_name,
int32_t desired_flags,
@@ -85,6 +90,17 @@ class WebDatabaseHostImpl : public blink::mojom::WebDatabaseHost,
// exist.
blink::mojom::WebDatabase& GetWebDatabase();
+ // Check that an IPC call has permission to access the passed origin. Must
+ // be called from within the context of a mojo call. Invalid calls will
+ // report a bad message, which will terminate the calling process. If this
+ // returns false, the caller should return immediately without invoking
+ // callbacks.
+ bool ValidateOrigin(const url::Origin& origin);
+
+ // As above, but for calls where the origin is embedded in a VFS filename.
+ // Empty filenames signalling a temp file are permitted.
+ bool ValidateOrigin(const base::string16& vfs_file_name);
+
// Our render process host ID, used to bind to the correct render process.
const int process_id_;
diff --git a/chromium/content/browser/renderer_host/web_database_host_impl_unittest.cc b/chromium/content/browser/renderer_host/web_database_host_impl_unittest.cc
new file mode 100644
index 00000000000..c46954787e2
--- /dev/null
+++ b/chromium/content/browser/renderer_host/web_database_host_impl_unittest.cc
@@ -0,0 +1,178 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/web_database_host_impl.h"
+
+#include "base/strings/utf_string_conversions.h"
+#include "content/browser/child_process_security_policy_impl.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "mojo/core/embedder/embedder.h"
+#include "storage/common/database/database_identifier.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+namespace {
+base::string16 ConstructVfsFileName(const url::Origin& origin,
+ const base::string16& name,
+ const base::string16& suffix) {
+ std::string identifier = storage::GetIdentifierFromOrigin(origin);
+ return base::UTF8ToUTF16(identifier) + base::ASCIIToUTF16("/") + name +
+ base::ASCIIToUTF16("#") + suffix;
+}
+
+class BadMessageObserver {
+ public:
+ BadMessageObserver()
+ : dummy_message_(0, 0, 0, 0, nullptr), context_(&dummy_message_) {
+ mojo::core::SetDefaultProcessErrorCallback(base::BindRepeating(
+ &BadMessageObserver::ReportBadMessage, base::Unretained(this)));
+ }
+
+ ~BadMessageObserver() {
+ mojo::core::SetDefaultProcessErrorCallback(
+ mojo::core::ProcessErrorCallback());
+ }
+
+ const std::string& last_error() const { return last_error_; }
+
+ private:
+ void ReportBadMessage(const std::string& error) { last_error_ = error; }
+
+ mojo::Message dummy_message_;
+ mojo::internal::MessageDispatchContext context_;
+ std::string last_error_;
+
+ DISALLOW_COPY_AND_ASSIGN(BadMessageObserver);
+};
+} // namespace
+
+class WebDatabaseHostImplTest : public ::testing::Test {
+ protected:
+ WebDatabaseHostImplTest() = default;
+ ~WebDatabaseHostImplTest() override = default;
+
+ void SetUp() override {
+ scoped_refptr<storage::DatabaseTracker> db_tracker =
+ base::MakeRefCounted<storage::DatabaseTracker>(
+ base::FilePath(), /*is_incognito=*/false,
+ /*special_storage_policy=*/nullptr,
+ /*quota_manager_proxy=*/nullptr);
+ db_tracker->set_task_runner_for_testing(
+ base::ThreadTaskRunnerHandle::Get());
+
+ host_ = std::make_unique<WebDatabaseHostImpl>(process_id(),
+ std::move(db_tracker));
+ }
+
+ template <typename Callable>
+ void CheckUnauthorizedOrigin(const Callable& func) {
+ BadMessageObserver bad_message_observer;
+ func();
+ EXPECT_EQ("Unauthorized origin.", bad_message_observer.last_error());
+ }
+
+ template <typename Callable>
+ void CheckInvalidOrigin(const Callable& func) {
+ BadMessageObserver bad_message_observer;
+ func();
+ EXPECT_EQ("Invalid origin.", bad_message_observer.last_error());
+ }
+
+ WebDatabaseHostImpl* host() { return host_.get(); }
+ int process_id() { return kProcessId; }
+
+ private:
+ static constexpr int kProcessId = 1234;
+ TestBrowserThreadBundle thread_bundle_;
+ std::unique_ptr<WebDatabaseHostImpl> host_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebDatabaseHostImplTest);
+};
+
+TEST_F(WebDatabaseHostImplTest, BadMessagesUnauthorized) {
+ const url::Origin correct_origin =
+ url::Origin::Create(GURL("http://correct.com"));
+ const url::Origin incorrect_origin =
+ url::Origin::Create(GURL("http://incorrect.net"));
+ const base::string16 db_name(base::ASCIIToUTF16("db_name"));
+ const base::string16 suffix(base::ASCIIToUTF16("suffix"));
+ const base::string16 bad_vfs_file_name =
+ ConstructVfsFileName(incorrect_origin, db_name, suffix);
+
+ auto* security_policy = ChildProcessSecurityPolicyImpl::GetInstance();
+ security_policy->Add(process_id());
+ security_policy->AddIsolatedOrigins({correct_origin, incorrect_origin});
+ security_policy->LockToOrigin(process_id(), correct_origin.GetURL());
+ ASSERT_TRUE(security_policy->CanAccessDataForOrigin(process_id(),
+ correct_origin.GetURL()));
+ ASSERT_FALSE(security_policy->CanAccessDataForOrigin(
+ process_id(), incorrect_origin.GetURL()));
+
+ CheckUnauthorizedOrigin([&]() {
+ host()->OpenFile(bad_vfs_file_name,
+ /*desired_flags=*/0, base::BindOnce([](base::File) {}));
+ });
+
+ CheckUnauthorizedOrigin([&]() {
+ host()->DeleteFile(bad_vfs_file_name,
+ /*sync_dir=*/false, base::BindOnce([](int32_t) {}));
+ });
+
+ CheckUnauthorizedOrigin([&]() {
+ host()->GetFileAttributes(bad_vfs_file_name,
+ base::BindOnce([](int32_t) {}));
+ });
+
+ CheckUnauthorizedOrigin([&]() {
+ host()->GetFileSize(bad_vfs_file_name, base::BindOnce([](int64_t) {}));
+ });
+
+ CheckUnauthorizedOrigin([&]() {
+ host()->SetFileSize(bad_vfs_file_name, /*expected_size=*/0,
+ base::BindOnce([](bool) {}));
+ });
+
+ CheckUnauthorizedOrigin([&]() {
+ host()->GetSpaceAvailable(incorrect_origin, base::BindOnce([](int64_t) {}));
+ });
+
+ CheckUnauthorizedOrigin([&]() {
+ host()->Opened(incorrect_origin, db_name, base::ASCIIToUTF16("description"),
+ /*estimated_size=*/0);
+ });
+
+ CheckUnauthorizedOrigin(
+ [&]() { host()->Modified(incorrect_origin, db_name); });
+
+ CheckUnauthorizedOrigin([&]() { host()->Closed(incorrect_origin, db_name); });
+
+ CheckUnauthorizedOrigin([&]() {
+ host()->HandleSqliteError(incorrect_origin, db_name, /*error=*/0);
+ });
+}
+
+TEST_F(WebDatabaseHostImplTest, BadMessagesInvalid) {
+ const url::Origin opaque_origin;
+ const base::string16 db_name(base::ASCIIToUTF16("db_name"));
+
+ CheckInvalidOrigin([&]() {
+ host()->GetSpaceAvailable(opaque_origin, base::BindOnce([](int64_t) {}));
+ });
+
+ CheckInvalidOrigin([&]() {
+ host()->Opened(opaque_origin, db_name, base::ASCIIToUTF16("description"),
+ /*estimated_size=*/0);
+ });
+
+ CheckInvalidOrigin([&]() { host()->Modified(opaque_origin, db_name); });
+
+ CheckInvalidOrigin([&]() { host()->Closed(opaque_origin, db_name); });
+
+ CheckInvalidOrigin([&]() {
+ host()->HandleSqliteError(opaque_origin, db_name, /*error=*/0);
+ });
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_interface_binders.cc b/chromium/content/browser/renderer_interface_binders.cc
index 896f1b27ded..c3a8bdc572d 100644
--- a/chromium/content/browser/renderer_interface_binders.cc
+++ b/chromium/content/browser/renderer_interface_binders.cc
@@ -171,7 +171,7 @@ void RendererInterfaceBinders::InitializeParameterizedBinderRegistry() {
->CreateService(origin, std::move(request));
}));
parameterized_binder_registry_.AddInterface(
- base::BindRepeating(&BackgroundFetchServiceImpl::Create));
+ base::BindRepeating(&BackgroundFetchServiceImpl::CreateForWorker));
parameterized_binder_registry_.AddInterface(
base::BindRepeating(GetRestrictedCookieManager));
parameterized_binder_registry_.AddInterface(
diff --git a/chromium/content/browser/resolve_proxy_msg_helper.cc b/chromium/content/browser/resolve_proxy_msg_helper.cc
index 08885d871bb..41a3408c313 100644
--- a/chromium/content/browser/resolve_proxy_msg_helper.cc
+++ b/chromium/content/browser/resolve_proxy_msg_helper.cc
@@ -5,25 +5,28 @@
#include "content/browser/resolve_proxy_msg_helper.h"
#include "base/bind.h"
-#include "base/bind_helpers.h"
#include "base/compiler_specific.h"
#include "content/common/view_messages.h"
-#include "net/base/net_errors.h"
-#include "net/log/net_log_with_source.h"
-#include "net/url_request/url_request_context.h"
-#include "net/url_request/url_request_context_getter.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/storage_partition.h"
+#include "mojo/public/cpp/bindings/interface_request.h"
+#include "net/proxy_resolution/proxy_info.h"
+#include "services/network/public/mojom/network_context.mojom.h"
namespace content {
-ResolveProxyMsgHelper::ResolveProxyMsgHelper(
- net::URLRequestContextGetter* getter)
+ResolveProxyMsgHelper::ResolveProxyMsgHelper(int render_process_host_id)
: BrowserMessageFilter(ViewMsgStart),
- context_getter_(getter),
- proxy_resolution_service_(nullptr) {}
-
-ResolveProxyMsgHelper::ResolveProxyMsgHelper(
- net::ProxyResolutionService* proxy_resolution_service)
- : BrowserMessageFilter(ViewMsgStart), proxy_resolution_service_(proxy_resolution_service) {}
+ render_process_host_id_(render_process_host_id),
+ binding_(this) {}
+
+void ResolveProxyMsgHelper::OverrideThreadForMessage(
+ const IPC::Message& message,
+ BrowserThread::ID* thread) {
+ if (message.type() == ViewHostMsg_ResolveProxy::ID)
+ *thread = BrowserThread::UI;
+}
bool ResolveProxyMsgHelper::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
@@ -36,68 +39,97 @@ bool ResolveProxyMsgHelper::OnMessageReceived(const IPC::Message& message) {
void ResolveProxyMsgHelper::OnResolveProxy(const GURL& url,
IPC::Message* reply_msg) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
// Enqueue the pending request.
pending_requests_.push_back(PendingRequest(url, reply_msg));
// If nothing is in progress, start.
- if (pending_requests_.size() == 1)
+ if (!binding_.is_bound()) {
+ DCHECK_EQ(1u, pending_requests_.size());
StartPendingRequest();
+ }
}
ResolveProxyMsgHelper::~ResolveProxyMsgHelper() {
- // Clear all pending requests if the ProxyResolutionService is still alive (if
- // we have a default request context or override).
- if (!pending_requests_.empty()) {
- PendingRequest req = pending_requests_.front();
- proxy_resolution_service_->CancelRequest(req.request);
- }
+ DCHECK(!owned_self_);
+ DCHECK(!binding_.is_bound());
+}
+
+void ResolveProxyMsgHelper::StartPendingRequest() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(!binding_.is_bound());
+ DCHECK(!pending_requests_.empty());
- for (PendingRequestList::iterator it = pending_requests_.begin();
- it != pending_requests_.end();
- ++it) {
- delete it->reply_msg;
+ // Start the request.
+ network::mojom::ProxyLookupClientPtr proxy_lookup_client;
+ binding_.Bind(mojo::MakeRequest(&proxy_lookup_client));
+ binding_.set_connection_error_handler(
+ base::BindOnce(&ResolveProxyMsgHelper::OnProxyLookupComplete,
+ base::Unretained(this), base::nullopt));
+ owned_self_ = this;
+ if (!SendRequestToNetworkService(pending_requests_.front().url,
+ std::move(proxy_lookup_client))) {
+ OnProxyLookupComplete(base::nullopt);
}
+}
- pending_requests_.clear();
+bool ResolveProxyMsgHelper::SendRequestToNetworkService(
+ const GURL& url,
+ network::mojom::ProxyLookupClientPtr proxy_lookup_client) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ RenderProcessHost* render_process_host =
+ RenderProcessHost::FromID(render_process_host_id_);
+ // Fail the request if there's no such RenderProcessHost;
+ if (!render_process_host)
+ return false;
+ render_process_host->GetStoragePartition()
+ ->GetNetworkContext()
+ ->LookUpProxyForURL(url, std::move(proxy_lookup_client));
+ return true;
}
-void ResolveProxyMsgHelper::OnResolveProxyCompleted(int result) {
- CHECK(!pending_requests_.empty());
+void ResolveProxyMsgHelper::OnProxyLookupComplete(
+ const base::Optional<net::ProxyInfo>& proxy_info) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(!pending_requests_.empty());
- const PendingRequest& completed_req = pending_requests_.front();
- ViewHostMsg_ResolveProxy::WriteReplyParams(
- completed_req.reply_msg, result == net::OK, proxy_info_.ToPacString());
- Send(completed_req.reply_msg);
+ binding_.Close();
+
+ // If all references except |owned_self_| have been released, just release
+ // the last reference, without doing anything.
+ if (HasOneRef()) {
+ scoped_refptr<ResolveProxyMsgHelper> self = std::move(owned_self_);
+ return;
+ }
+
+ owned_self_ = nullptr;
// Clear the current (completed) request.
+ PendingRequest completed_req = std::move(pending_requests_.front());
pending_requests_.pop_front();
+ ViewHostMsg_ResolveProxy::WriteReplyParams(
+ completed_req.reply_msg.get(), !!proxy_info,
+ proxy_info ? proxy_info->ToPacString() : std::string());
+ Send(completed_req.reply_msg.release());
+
// Start the next request.
if (!pending_requests_.empty())
StartPendingRequest();
}
-void ResolveProxyMsgHelper::StartPendingRequest() {
- PendingRequest& req = pending_requests_.front();
+ResolveProxyMsgHelper::PendingRequest::PendingRequest(const GURL& url,
+ IPC::Message* reply_msg)
+ : url(url), reply_msg(reply_msg) {}
- // Verify the request wasn't started yet.
- DCHECK(nullptr == req.request);
+ResolveProxyMsgHelper::PendingRequest::PendingRequest(
+ PendingRequest&& pending_request) noexcept = default;
- if (context_getter_.get()) {
- proxy_resolution_service_ = context_getter_->GetURLRequestContext()->proxy_resolution_service();
- context_getter_ = nullptr;
- }
+ResolveProxyMsgHelper::PendingRequest::~PendingRequest() noexcept = default;
- // Start the request.
- int result = proxy_resolution_service_->ResolveProxy(
- req.url, std::string(), &proxy_info_,
- base::Bind(&ResolveProxyMsgHelper::OnResolveProxyCompleted,
- base::Unretained(this)),
- &req.request, nullptr, net::NetLogWithSource());
-
- // Completed synchronously.
- if (result != net::ERR_IO_PENDING)
- OnResolveProxyCompleted(result);
-}
+ResolveProxyMsgHelper::PendingRequest& ResolveProxyMsgHelper::PendingRequest::
+operator=(PendingRequest&& pending_request) noexcept = default;
} // namespace content
diff --git a/chromium/content/browser/resolve_proxy_msg_helper.h b/chromium/content/browser/resolve_proxy_msg_helper.h
index 8eacab90e7d..8034af85184 100644
--- a/chromium/content/browser/resolve_proxy_msg_helper.h
+++ b/chromium/content/browser/resolve_proxy_msg_helper.h
@@ -8,21 +8,24 @@
#include <string>
#include "base/containers/circular_deque.h"
+#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/optional.h"
+#include "base/sequenced_task_runner_helpers.h"
#include "content/common/content_export.h"
#include "content/public/browser/browser_message_filter.h"
-#include "net/base/completion_callback.h"
-#include "net/proxy_resolution/proxy_resolution_service.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "services/network/public/mojom/proxy_lookup_client.mojom.h"
#include "url/gurl.h"
namespace net {
-class URLRequestContextGetter;
+class ProxyInfo;
}
namespace content {
-// Responds to ChildProcessHostMsg_ResolveProxy, kicking off a ProxyResolve
-// request on the IO thread using the specified proxy service. Completion is
+// Responds to ChildProcessHostMsg_ResolveProxy, kicking off a proxy lookup
+// request on the UI thread using the specified proxy service. Completion is
// notified through the delegate. If multiple requests are started at the same
// time, they will run in FIFO order, with only 1 being outstanding at a time.
//
@@ -30,15 +33,18 @@ namespace content {
// outstanding proxy resolve requests with the proxy service. It also deletes
// the stored IPC::Message pointers for pending requests.
//
-// This object is expected to live on the IO thread.
-class CONTENT_EXPORT ResolveProxyMsgHelper : public BrowserMessageFilter {
+// This object does most of its work on the UI thread. It holds onto a
+// self-reference as long as there's a pending Mojo call, as losing its last
+// reference on the IO thread with an open mojo pipe that lives on the UI
+// thread leads to problems.
+class CONTENT_EXPORT ResolveProxyMsgHelper : public BrowserMessageFilter,
+ network::mojom::ProxyLookupClient {
public:
- explicit ResolveProxyMsgHelper(net::URLRequestContextGetter* getter);
- // Constructor used by unittests.
- explicit ResolveProxyMsgHelper(
- net::ProxyResolutionService* proxy_resolution_service);
+ explicit ResolveProxyMsgHelper(int render_process_host_id);
// BrowserMessageFilter implementation
+ void OverrideThreadForMessage(const IPC::Message& message,
+ BrowserThread::ID* thread) override;
bool OnMessageReceived(const IPC::Message& message) override;
void OnResolveProxy(const GURL& url, IPC::Message* reply_msg);
@@ -49,37 +55,57 @@ class CONTENT_EXPORT ResolveProxyMsgHelper : public BrowserMessageFilter {
~ResolveProxyMsgHelper() override;
private:
- // Callback for the ProxyResolutionService (bound to |callback_|).
- void OnResolveProxyCompleted(int result);
+ // Used to destroy the |ResolveProxyMsgHelper| on the UI thread.
+ friend class base::DeleteHelper<ResolveProxyMsgHelper>;
// Starts the first pending request.
void StartPendingRequest();
+ // Virtual for testing. Returns false if unable to get a network service, due
+ // to the RenderProcessHost no longer existing.
+ virtual bool SendRequestToNetworkService(
+ const GURL& url,
+ network::mojom::ProxyLookupClientPtr proxy_lookup_client);
+
+ // network::mojom::ProxyLookupClient implementation.
+ void OnProxyLookupComplete(
+ const base::Optional<net::ProxyInfo>& proxy_info) override;
+
// A PendingRequest is a resolve request that is in progress, or queued.
struct PendingRequest {
public:
- PendingRequest(const GURL& url, IPC::Message* reply_msg)
- : url(url), reply_msg(reply_msg), request(NULL) {}
+ PendingRequest(const GURL& url, IPC::Message* reply_msg);
+ PendingRequest(PendingRequest&& pending_request) noexcept;
+ ~PendingRequest();
+
+ PendingRequest& operator=(PendingRequest&& pending_request) noexcept;
// The URL of the request.
GURL url;
// Data to pass back to the delegate on completion (we own it until then).
- IPC::Message* reply_msg;
+ std::unique_ptr<IPC::Message> reply_msg;
- // Handle for cancelling the current request if it has started (else NULL).
- net::ProxyResolutionService::Request* request;
+ private:
+ DISALLOW_COPY_AND_ASSIGN(PendingRequest);
};
- // Info about the current outstanding proxy request.
- net::ProxyInfo proxy_info_;
+ const int render_process_host_id_;
// FIFO queue of pending requests. The first entry is always the current one.
using PendingRequestList = base::circular_deque<PendingRequest>;
PendingRequestList pending_requests_;
- scoped_refptr<net::URLRequestContextGetter> context_getter_;
- net::ProxyResolutionService* proxy_resolution_service_;
+ // Self-reference. Owned as long as there's an outstanding proxy lookup.
+ // Needed to shut down safely, since this class is refcounted, with some
+ // references owned on multiple threads, while |binding_| lives on the UI
+ // thread, and may receive callbacks there whenever there's a pending request.
+ scoped_refptr<ResolveProxyMsgHelper> owned_self_;
+
+ // Binding for the currently in-progress request, if any.
+ mojo::Binding<network::mojom::ProxyLookupClient> binding_;
+
+ DISALLOW_COPY_AND_ASSIGN(ResolveProxyMsgHelper);
};
} // namespace content
diff --git a/chromium/content/browser/resolve_proxy_msg_helper_unittest.cc b/chromium/content/browser/resolve_proxy_msg_helper_unittest.cc
index d9e5b3e3f90..92975535fc9 100644
--- a/chromium/content/browser/resolve_proxy_msg_helper_unittest.cc
+++ b/chromium/content/browser/resolve_proxy_msg_helper_unittest.cc
@@ -7,47 +7,68 @@
#include <tuple>
#include "base/memory/ptr_util.h"
+#include "base/run_loop.h"
#include "content/common/view_messages.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "ipc/ipc_test_sink.h"
#include "net/base/net_errors.h"
-#include "net/proxy_resolution/mock_proxy_resolver.h"
-#include "net/proxy_resolution/proxy_config_service.h"
-#include "net/proxy_resolution/proxy_resolution_service.h"
+#include "net/proxy_resolution/proxy_info.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
+#include "services/network/public/mojom/proxy_lookup_client.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
-// This ProxyConfigService always returns "http://pac" as the PAC url to use.
-class MockProxyConfigService : public net::ProxyConfigService {
- public:
- void AddObserver(Observer* observer) override {}
- void RemoveObserver(Observer* observer) override {}
- ConfigAvailability GetLatestProxyConfig(
- net::ProxyConfigWithAnnotation* results) override {
- *results = net::ProxyConfigWithAnnotation(
- net::ProxyConfig::CreateFromCustomPacURL(GURL("http://pac")),
- TRAFFIC_ANNOTATION_FOR_TESTS);
- return CONFIG_VALID;
- }
-};
-
class TestResolveProxyMsgHelper : public ResolveProxyMsgHelper {
public:
- TestResolveProxyMsgHelper(net::ProxyResolutionService* proxy_resolution_service,
- IPC::Listener* listener)
- : ResolveProxyMsgHelper(proxy_resolution_service), listener_(listener) {}
+ // Incoming ProxyLookupClientPtrs are written to |proxy_lookup_client|.
+ explicit TestResolveProxyMsgHelper(
+ IPC::Listener* listener,
+ network::mojom::ProxyLookupClientPtr* proxy_lookup_client)
+ : ResolveProxyMsgHelper(0 /* renderer_process_host_id */),
+ listener_(listener),
+ proxy_lookup_client_(proxy_lookup_client) {}
+
bool Send(IPC::Message* message) override {
+ // Shouldn't be calling Send() if there are no live references to |this|.
+ EXPECT_TRUE(HasAtLeastOneRef());
+
listener_->OnMessageReceived(*message);
delete message;
return true;
}
+ bool SendRequestToNetworkService(
+ const GURL& url,
+ network::mojom::ProxyLookupClientPtr proxy_lookup_client) override {
+ // Only one request should be send at a time.
+ EXPECT_FALSE(*proxy_lookup_client_);
+
+ if (fail_to_send_request_)
+ return false;
+
+ pending_url_ = url;
+ *proxy_lookup_client_ = std::move(proxy_lookup_client);
+ return true;
+ }
+
+ const GURL& pending_url() const { return pending_url_; }
+
+ void set_fail_to_send_request(bool fail_to_send_request) {
+ fail_to_send_request_ = fail_to_send_request;
+ }
+
protected:
~TestResolveProxyMsgHelper() override {}
IPC::Listener* listener_;
+
+ bool fail_to_send_request_ = false;
+
+ network::mojom::ProxyLookupClientPtr* proxy_lookup_client_;
+ GURL pending_url_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestResolveProxyMsgHelper);
};
class ResolveProxyMsgHelperTest : public testing::Test, public IPC::Listener {
@@ -63,12 +84,9 @@ class ResolveProxyMsgHelperTest : public testing::Test, public IPC::Listener {
};
ResolveProxyMsgHelperTest()
- : resolver_factory_(new net::MockAsyncProxyResolverFactory(false)),
- service_(new net::ProxyResolutionService(
- base::WrapUnique(new MockProxyConfigService),
- base::WrapUnique(resolver_factory_),
- nullptr)),
- helper_(new TestResolveProxyMsgHelper(service_.get(), this)) {
+ : helper_(base::MakeRefCounted<TestResolveProxyMsgHelper>(
+ this,
+ &proxy_lookup_client_)) {
test_sink_.AddFilter(this);
}
@@ -86,13 +104,6 @@ class ResolveProxyMsgHelperTest : public testing::Test, public IPC::Listener {
return IPC::SyncMessage::GenerateReply(&message);
}
- net::MockAsyncProxyResolverFactory* resolver_factory_;
- net::MockAsyncProxyResolver resolver_;
- std::unique_ptr<net::ProxyResolutionService> service_;
- scoped_refptr<ResolveProxyMsgHelper> helper_;
- std::unique_ptr<PendingResult> pending_result_;
-
- private:
bool OnMessageReceived(const IPC::Message& msg) override {
ViewHostMsg_ResolveProxy::ReplyParam reply_data;
EXPECT_TRUE(ViewHostMsg_ResolveProxy::ReadReplyParam(&msg, &reply_data));
@@ -104,6 +115,12 @@ class ResolveProxyMsgHelperTest : public testing::Test, public IPC::Listener {
}
TestBrowserThreadBundle thread_bundle_;
+
+ scoped_refptr<TestResolveProxyMsgHelper> helper_;
+ std::unique_ptr<PendingResult> pending_result_;
+
+ network::mojom::ProxyLookupClientPtr proxy_lookup_client_;
+
IPC::TestSink test_sink_;
};
@@ -123,15 +140,14 @@ TEST_F(ResolveProxyMsgHelperTest, Sequential) {
helper_->OnResolveProxy(url1, msg1);
- // Finish ProxyResolutionService's initialization.
- ASSERT_EQ(1u, resolver_factory_->pending_requests().size());
- resolver_factory_->pending_requests()[0]->CompleteNowWithForwarder(
- net::OK, &resolver_);
-
- ASSERT_EQ(1u, resolver_.pending_jobs().size());
- EXPECT_EQ(url1, resolver_.pending_jobs()[0]->url());
- resolver_.pending_jobs()[0]->results()->UseNamedProxy("result1:80");
- resolver_.pending_jobs()[0]->CompleteNow(net::OK);
+ // There should be a pending proxy lookup request. Respond to it.
+ EXPECT_EQ(url1, helper_->pending_url());
+ ASSERT_TRUE(proxy_lookup_client_);
+ net::ProxyInfo proxy_info;
+ proxy_info.UseNamedProxy("result1:80");
+ proxy_lookup_client_->OnProxyLookupComplete(proxy_info);
+ proxy_lookup_client_.reset();
+ base::RunLoop().RunUntilIdle();
// Check result.
EXPECT_EQ(true, pending_result()->result);
@@ -140,10 +156,12 @@ TEST_F(ResolveProxyMsgHelperTest, Sequential) {
helper_->OnResolveProxy(url2, msg2);
- ASSERT_EQ(1u, resolver_.pending_jobs().size());
- EXPECT_EQ(url2, resolver_.pending_jobs()[0]->url());
- resolver_.pending_jobs()[0]->results()->UseNamedProxy("result2:80");
- resolver_.pending_jobs()[0]->CompleteNow(net::OK);
+ EXPECT_EQ(url2, helper_->pending_url());
+ ASSERT_TRUE(proxy_lookup_client_);
+ proxy_info.UseNamedProxy("result2:80");
+ proxy_lookup_client_->OnProxyLookupComplete(proxy_info);
+ proxy_lookup_client_.reset();
+ base::RunLoop().RunUntilIdle();
// Check result.
EXPECT_EQ(true, pending_result()->result);
@@ -152,10 +170,11 @@ TEST_F(ResolveProxyMsgHelperTest, Sequential) {
helper_->OnResolveProxy(url3, msg3);
- ASSERT_EQ(1u, resolver_.pending_jobs().size());
- EXPECT_EQ(url3, resolver_.pending_jobs()[0]->url());
- resolver_.pending_jobs()[0]->results()->UseNamedProxy("result3:80");
- resolver_.pending_jobs()[0]->CompleteNow(net::OK);
+ EXPECT_EQ(url3, helper_->pending_url());
+ ASSERT_TRUE(proxy_lookup_client_);
+ proxy_info.UseNamedProxy("result3:80");
+ proxy_lookup_client_->OnProxyLookupComplete(proxy_info);
+ base::RunLoop().RunUntilIdle();
// Check result.
EXPECT_EQ(true, pending_result()->result);
@@ -173,48 +192,45 @@ TEST_F(ResolveProxyMsgHelperTest, QueueRequests) {
IPC::Message* msg2 = GenerateReply();
IPC::Message* msg3 = GenerateReply();
- // Start three requests. Since the proxy resolver is async, all the
- // requests will be pending.
+ // Start three requests. All the requests will be pending.
helper_->OnResolveProxy(url1, msg1);
-
- // Finish ProxyResolutionService's initialization.
- ASSERT_EQ(1u, resolver_factory_->pending_requests().size());
- resolver_factory_->pending_requests()[0]->CompleteNowWithForwarder(
- net::OK, &resolver_);
-
helper_->OnResolveProxy(url2, msg2);
helper_->OnResolveProxy(url3, msg3);
- // ResolveProxyHelper only keeps 1 request outstanding in
- // ProxyResolutionService at a time.
- ASSERT_EQ(1u, resolver_.pending_jobs().size());
- EXPECT_EQ(url1, resolver_.pending_jobs()[0]->url());
-
- resolver_.pending_jobs()[0]->results()->UseNamedProxy("result1:80");
- resolver_.pending_jobs()[0]->CompleteNow(net::OK);
+ // Complete first request.
+ EXPECT_EQ(url1, helper_->pending_url());
+ ASSERT_TRUE(proxy_lookup_client_);
+ net::ProxyInfo proxy_info;
+ proxy_info.UseNamedProxy("result1:80");
+ proxy_lookup_client_->OnProxyLookupComplete(proxy_info);
+ proxy_lookup_client_.reset();
+ base::RunLoop().RunUntilIdle();
// Check result.
EXPECT_EQ(true, pending_result()->result);
EXPECT_EQ("PROXY result1:80", pending_result()->proxy_list);
clear_pending_result();
- ASSERT_EQ(1u, resolver_.pending_jobs().size());
- EXPECT_EQ(url2, resolver_.pending_jobs()[0]->url());
-
- resolver_.pending_jobs()[0]->results()->UseNamedProxy("result2:80");
- resolver_.pending_jobs()[0]->CompleteNow(net::OK);
+ // Complete second request.
+ EXPECT_EQ(url2, helper_->pending_url());
+ ASSERT_TRUE(proxy_lookup_client_);
+ proxy_info.UseNamedProxy("result2:80");
+ proxy_lookup_client_->OnProxyLookupComplete(proxy_info);
+ proxy_lookup_client_.reset();
+ base::RunLoop().RunUntilIdle();
// Check result.
EXPECT_EQ(true, pending_result()->result);
EXPECT_EQ("PROXY result2:80", pending_result()->proxy_list);
clear_pending_result();
- ASSERT_EQ(1u, resolver_.pending_jobs().size());
- EXPECT_EQ(url3, resolver_.pending_jobs()[0]->url());
-
- resolver_.pending_jobs()[0]->results()->UseNamedProxy("result3:80");
- resolver_.pending_jobs()[0]->CompleteNow(net::OK);
+ // Complete third request.
+ EXPECT_EQ(url3, helper_->pending_url());
+ ASSERT_TRUE(proxy_lookup_client_);
+ proxy_info.UseNamedProxy("result3:80");
+ proxy_lookup_client_->OnProxyLookupComplete(proxy_info);
+ base::RunLoop().RunUntilIdle();
// Check result.
EXPECT_EQ(true, pending_result()->result);
@@ -222,7 +238,7 @@ TEST_F(ResolveProxyMsgHelperTest, QueueRequests) {
clear_pending_result();
}
-// Delete the helper while a request is in progress, and others are pending.
+// Delete the helper while a request is in progress and others are pending.
TEST_F(ResolveProxyMsgHelperTest, CancelPendingRequests) {
GURL url1("http://www.google1.com/");
GURL url2("http://www.google2.com/");
@@ -237,32 +253,133 @@ TEST_F(ResolveProxyMsgHelperTest, CancelPendingRequests) {
// requests will be pending.
helper_->OnResolveProxy(url1, msg1);
-
- // Finish ProxyResolutionService's initialization.
- ASSERT_EQ(1u, resolver_factory_->pending_requests().size());
- resolver_factory_->pending_requests()[0]->CompleteNowWithForwarder(
- net::OK, &resolver_);
-
helper_->OnResolveProxy(url2, msg2);
helper_->OnResolveProxy(url3, msg3);
- // ResolveProxyHelper only keeps 1 request outstanding in
- // ProxyResolutionService at a time.
- ASSERT_EQ(1u, resolver_.pending_jobs().size());
- EXPECT_EQ(url1, resolver_.pending_jobs()[0]->url());
+ // Check the first request is pending.
+ EXPECT_EQ(url1, helper_->pending_url());
+ ASSERT_TRUE(proxy_lookup_client_);
- // Delete the underlying ResolveProxyMsgHelper -- this should cancel all
- // the requests which are outstanding.
+ // Release a reference. The |helper_| will not be deleted, since there's a
+ // pending resolution.
helper_ = nullptr;
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(proxy_lookup_client_.is_bound());
+ EXPECT_FALSE(proxy_lookup_client_.encountered_error());
+
+ // Send Mojo message on the pipe.
+ net::ProxyInfo proxy_info;
+ proxy_info.UseNamedProxy("result1:80");
+ proxy_lookup_client_->OnProxyLookupComplete(proxy_info);
+
+ // Spinning the message loop results in the helper being destroyed and closing
+ // the pipe.
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(!proxy_lookup_client_.is_bound() ||
+ proxy_lookup_client_.encountered_error());
+ // The result should not have been sent.
+ EXPECT_FALSE(pending_result());
- // The pending requests sent to the proxy resolver should have been cancelled.
+ // It should also be the case that msg1, msg2, msg3 were deleted by the
+ // cancellation. (Else will show up as a leak).
+}
- EXPECT_EQ(0u, resolver_.pending_jobs().size());
+// Issue a request that fails.
+TEST_F(ResolveProxyMsgHelperTest, RequestFails) {
+ GURL url("http://www.google.com/");
- EXPECT_TRUE(pending_result() == nullptr);
+ // Message will be deleted by the sink.
+ IPC::Message* msg = GenerateReply();
- // It should also be the case that msg1, msg2, msg3 were deleted by the
- // cancellation. (Else will show up as a leak in Valgrind).
+ helper_->OnResolveProxy(url, msg);
+
+ // There should be a pending proxy lookup request. Respond to it.
+ EXPECT_EQ(url, helper_->pending_url());
+ ASSERT_TRUE(proxy_lookup_client_);
+ proxy_lookup_client_->OnProxyLookupComplete(base::nullopt);
+ base::RunLoop().RunUntilIdle();
+
+ // Check result.
+ EXPECT_EQ(false, pending_result()->result);
+ EXPECT_EQ("", pending_result()->proxy_list);
+ clear_pending_result();
+}
+
+// Issue a request, only to have the Mojo pipe closed.
+TEST_F(ResolveProxyMsgHelperTest, PipeClosed) {
+ GURL url("http://www.google.com/");
+
+ // Message will be deleted by the sink.
+ IPC::Message* msg = GenerateReply();
+
+ helper_->OnResolveProxy(url, msg);
+
+ // There should be a pending proxy lookup request. Respond to it by closing
+ // the pipe.
+ EXPECT_EQ(url, helper_->pending_url());
+ ASSERT_TRUE(proxy_lookup_client_);
+ proxy_lookup_client_.reset();
+ base::RunLoop().RunUntilIdle();
+
+ // Check result.
+ EXPECT_EQ(false, pending_result()->result);
+ EXPECT_EQ("", pending_result()->proxy_list);
+ clear_pending_result();
+}
+
+// Fail to send a request to the network service.
+TEST_F(ResolveProxyMsgHelperTest, FailToSendRequest) {
+ GURL url("http://www.google.com/");
+
+ // Message will be deleted by the sink.
+ IPC::Message* msg = GenerateReply();
+
+ helper_->set_fail_to_send_request(true);
+
+ helper_->OnResolveProxy(url, msg);
+ // No request should be pending.
+ EXPECT_TRUE(helper_->pending_url().is_empty());
+
+ // Check result.
+ EXPECT_EQ(false, pending_result()->result);
+ EXPECT_EQ("", pending_result()->proxy_list);
+ clear_pending_result();
+}
+
+// Make sure if mojo callback is invoked after last externally owned reference
+// is released, there is no crash.
+// Regression test for https://crbug.com/870675
+TEST_F(ResolveProxyMsgHelperTest, Lifetime) {
+ GURL url("http://www.google1.com/");
+
+ // Messages are deleted by the sink.
+ IPC::Message* msg = GenerateReply();
+
+ helper_->OnResolveProxy(url, msg);
+
+ // There should be a pending proxy lookup request. Respond to it.
+ EXPECT_EQ(url, helper_->pending_url());
+ ASSERT_TRUE(proxy_lookup_client_);
+
+ // Release the |helper_| pointer. The object should keep a reference to
+ // itself, so should not be deleted.
+ helper_ = nullptr;
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(proxy_lookup_client_.is_bound());
+ EXPECT_FALSE(proxy_lookup_client_.encountered_error());
+
+ // Send Mojo message on the pipe.
+ net::ProxyInfo proxy_info;
+ proxy_info.UseNamedProxy("result1:80");
+ proxy_lookup_client_->OnProxyLookupComplete(proxy_info);
+
+ // Spinning the message loop results in the helper being destroyed and closing
+ // the pipe.
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(!proxy_lookup_client_.is_bound() ||
+ proxy_lookup_client_.encountered_error());
+ // The result should not have been sent.
+ EXPECT_FALSE(pending_result());
}
} // namespace content
diff --git a/chromium/content/browser/resources/accessibility/OWNERS b/chromium/content/browser/resources/accessibility/OWNERS
deleted file mode 100644
index 697dba28c57..00000000000
--- a/chromium/content/browser/resources/accessibility/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-file://ui/accessibility/OWNERS
-
-# TEAM: chromium-accessibility@chromium.org
-# COMPONENT: Internals>Accessibility
diff --git a/chromium/content/browser/resources/accessibility/accessibility.css b/chromium/content/browser/resources/accessibility/accessibility.css
deleted file mode 100644
index 45ade4f058d..00000000000
--- a/chromium/content/browser/resources/accessibility/accessibility.css
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2013 The Chromium Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-body {
- font-family: Arial, sans-serif;
- font-size: 12px;
- margin: 10px 20px;
- min-width: 47em;
- padding-bottom: 65px;
-}
-
-img {
- float: left;
- height: 16px;
- padding-right: 5px;
- width: 16px;
-}
-
-.row {
- border-bottom: 1px solid #A0A0A0;
- padding: 5px;
-}
-
-.url {
- color: #A0A0A0;
-}
-
-p {
- line-height: 1.2em;
-}
-
-.columns {
- display: flex;
-}
-
-.column {
- flex-basis: 50%;
-}
-
-.checkbox_row {
- display: flex;
- align-items: center;
-}
-
-.checkbox_wrapper {
- width: 32px;
- margin: 0 0 2px 0;
- padding: 0;
- flex-grow: 0;
-}
-
-.secondary {
- margin: 0 0 12px 32px;
- color: #696969;
-}
-
-a {
- margin: 10px 20px;
-}
-
-label {
- margin: 0 0 2px 0;
- padding: 0;
- flex-grow: 1;
-}
-
-label.disabled {
- color: #696969;
-}
-
-label input[type="checkbox"] {
- margin-right: 6px;
-}
diff --git a/chromium/content/browser/resources/accessibility/accessibility.html b/chromium/content/browser/resources/accessibility/accessibility.html
deleted file mode 100644
index 80e7b7a665b..00000000000
--- a/chromium/content/browser/resources/accessibility/accessibility.html
+++ /dev/null
@@ -1,147 +0,0 @@
-<!doctype html>
-<html>
-<!--
-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.
--->
-<head>
- <meta charset="utf-8">
- <title>Accessibility Internals</title>
- <link rel="stylesheet" href="chrome://resources/css/chrome_shared.css">
- <link rel="stylesheet" href="accessibility.css">
- <script src="chrome://resources/js/cr.js"></script>
- <script src="chrome://resources/js/load_time_data.js"></script>
- <script src="chrome://resources/js/action_link.js"></script>
- <script src="chrome://resources/js/util.js"></script>
- <script src="strings.js"></script>
- <script src="accessibility.js"></script>
-</head>
-<body>
- <h1>Accessibility Internals</h1>
-
- <div class="columns">
- <div class="column">
- <h2>Global accessibility mode:</h2>
-
- <div class="checkbox_row">
- <span class="checkbox_wrapper">
- <input type="checkbox" id="native"
- aria-describedby="native_secondary">
- </span>
- <label for="native">
- Native accessibility API support
- </label>
- </div>
- <div id="native_secondary" class="secondary">
- Allows Chrome to be controlled via native accessibility APIs
- specific to this platform.
- </div>
-
- <div class="checkbox_row">
- <span class="checkbox_wrapper">
- <input type="checkbox" id="web"
- aria-describedby="web_secondary">
- </span>
- <label for="web">
- Web accessibility
- </label>
- </div>
- <div id="web_secondary" class="secondary">
- Accessibility support is enabled for web content.
- </div>
-
- <div class="checkbox_row">
- <span class="checkbox_wrapper">
- <input type="checkbox" id="text"
- aria-describedby="text_secondary">
- </span>
- <label for="text">
- Text metrics
- </label>
- </div>
- <div id="text_secondary" class="secondary">
- Enables support for querying line breaks and the bounding
- box of arbitrary character ranges.
- </div>
-
- <div class="checkbox_row">
- <span class="checkbox_wrapper">
- <input type="checkbox" id="screenreader"
- aria-describedby="screenreader_secondary">
- </span>
- <label for="screenreader">
- Screen reader support
- </label>
- </div>
- <div id="screenreader_secondary" class="secondary">
- Exposes accessibility APIs typically needed only by
- screen readers.
- </div>
-
- <div class="checkbox_row">
- <span class="checkbox_wrapper">
- <input type="checkbox" id="html"
- aria-describedby="html_secondary">
- </span>
- <label for="html">
- HTML
- </label>
- </div>
- <div id="html_secondary" class="secondary">
- Exposes HTML tag names and attributes via accessibility APIs.
- </div>
-
- <h2>Options:</h2>
-
- <div class="checkbox_row">
- <span class="checkbox_wrapper">
- <input type="checkbox" id="internal"
- aria-describedby="internal_secondary">
- </span>
- <label for="internal">
- Internal
- </label>
- </div>
- <div id="internal_secondary" class="secondary">
- Show internal accessibility tree instead of native
- </div>
-
- </div>
- <div class="column">
- <p>
- Accessibility features in Chrome are off by default and enabled
- automatically on-demand. Changes to this page only take effect
- until the next time Chrome is restarted.
- </p>
- <p>
- To force accessibility to be enabled at launch, run Chrome with this
- command-line flag:
- <pre>--force-renderer-accessibility</pre>
- </p>
- <p>
- To disable accessibility, run Chrome with this flag:
- <pre>--disable-renderer-accessibility</pre>
- </p>
- </div>
- </div>
-
- <!--
- <div id="global" class="row">Global accessibility mode:
- <a is="action-link" role="button" id="toggle_global" aria-labelledby="global"></a>
- </div>
-
- <div id="internal" class="row">Show internal accessibility tree instead of native:
- <a is="action-link" role="button" id="toggle_internal" aria-labelledby="internal"></a>
- </div>
--->
- <h2>Chrome Native UI:</h2>
- <div id="native_ui">
- <a is="action-link" tabindex="0" role="button" id="showNativeUI">show accessibility tree</a>
- </div>
-
- <h2>Pages:</h2>
- <div id="pages" class="list"></div>
- <script src="chrome://resources/js/i18n_template.js"></script>
-</body>
-</html>
diff --git a/chromium/content/browser/resources/accessibility/accessibility.js b/chromium/content/browser/resources/accessibility/accessibility.js
deleted file mode 100644
index 979aa311c22..00000000000
--- a/chromium/content/browser/resources/accessibility/accessibility.js
+++ /dev/null
@@ -1,272 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-cr.define('accessibility', function() {
- 'use strict';
-
- // Note: keep these values in sync with the values in
- // content/common/accessibility_mode_enums.h
- const AXMode = {
- kNativeAPIs: 1 << 0,
- kWebContents: 1 << 1,
- kInlineTextBoxes: 1 << 2,
- kScreenReader: 1 << 3,
- kHTML: 1 << 4,
-
- get kAXModeWebContentsOnly() {
- return AXMode.kWebContents |
- AXMode.kInlineTextBoxes | AXMode.kScreenReader |
- AXMode.kHTML;
- },
-
- get kAXModeComplete() {
- return AXMode.kNativeAPIs | AXMode.kWebContents |
- AXMode.kInlineTextBoxes | AXMode.kScreenReader |
- AXMode.kHTML;
- }
- };
-
- function requestData() {
- var xhr = new XMLHttpRequest();
- xhr.open('GET', 'targets-data.json', false);
- xhr.send(null);
- if (xhr.status === 200) {
- console.log(xhr.responseText);
- return JSON.parse(xhr.responseText);
- }
- return [];
- }
-
- function toggleAccessibility(data, element, mode) {
- chrome.send('toggleAccessibility',
- [String(data.processId), String(data.routeId), mode]);
- document.location.reload();
- }
-
- function requestWebContentsTree(data, element) {
- chrome.send('requestWebContentsTree',
- [String(data.processId), String(data.routeId)]);
- }
-
- function initialize() {
- console.log('initialize');
- var data = requestData();
-
- bindCheckbox('native', data['native']);
- bindCheckbox('web', data['web']);
- bindCheckbox('text', data['text']);
- bindCheckbox('screenreader', data['screenreader']);
- bindCheckbox('html', data['html']);
- bindCheckbox('internal', data['internal']);
-
- $('pages').textContent = '';
-
- var list = data['list'];
- for (var i = 0; i < list.length; i++) {
- addToPagesList(list[i]);
- }
-
- var showNativeUI = $('showNativeUI');
- showNativeUI.addEventListener('click', function() {
- chrome.send('requestNativeUITree', []);
- });
- }
-
- function bindCheckbox(name, value) {
- if (value == 'on')
- $(name).checked = true;
- if (value == 'disabled') {
- $(name).disabled = true;
- $(name).labels[0].classList.add('disabled');
- }
- $(name).addEventListener('change', function() {
- chrome.send('setGlobalFlag', [name, $(name).checked]);
- document.location.reload();
- });
- }
-
- function addToPagesList(data) {
- // TODO: iterate through data and pages rows instead
- var id = data['processId'] + '.' + data['routeId'];
- var row = document.createElement('div');
- row.className = 'row';
- row.id = id;
- formatRow(row, data);
-
- row.processId = data.processId;
- row.routeId = data.routeId;
-
- var list = $('pages');
- list.appendChild(row);
- }
-
- function formatRow(row, data) {
- if (!('url' in data)) {
- if ('error' in data) {
- row.appendChild(createErrorMessageElement(data, row));
- return;
- }
- }
-
- var siteInfo = document.createElement('div');
- var properties = ['favicon_url', 'name', 'url'];
- for (var j = 0; j < properties.length; j++)
- siteInfo.appendChild(formatValue(data, properties[j]));
- row.appendChild(siteInfo);
-
- row.appendChild(createModeElement(AXMode.kNativeAPIs, data))
- row.appendChild(createModeElement(AXMode.kWebContents, data))
- row.appendChild(createModeElement(AXMode.kInlineTextBoxes,
- data))
- row.appendChild(createModeElement(AXMode.kScreenReader, data))
- row.appendChild(createModeElement(AXMode.kHTML, data))
-
- row.appendChild(document.createTextNode(' | '));
-
- if ('tree' in data) {
- row.appendChild(createShowAccessibilityTreeElement(data, row, true));
- row.appendChild(createHideAccessibilityTreeElement(row.id));
- row.appendChild(createAccessibilityTreeElement(data));
- }
- else {
- row.appendChild(createShowAccessibilityTreeElement(data, row, false));
- if ('error' in data)
- row.appendChild(createErrorMessageElement(data, row));
- }
- }
-
- function formatValue(data, property) {
- var value = data[property];
-
- if (property == 'favicon_url') {
- var faviconElement = document.createElement('img');
- if (value)
- faviconElement.src = value;
- faviconElement.alt = "";
- return faviconElement;
- }
-
- var text = value ? String(value) : '';
- if (text.length > 100)
- text = text.substring(0, 100) + '\u2026'; // ellipsis
-
- var span = document.createElement('span');
- span.textContent = ' ' + text + ' ';
- span.className = property;
- return span;
- }
-
- function getNameForAccessibilityMode(mode) {
- switch (mode) {
- case AXMode.kNativeAPIs:
- return "native"
- case AXMode.kWebContents:
- return "web"
- case AXMode.kInlineTextBoxes:
- return "inline text"
- case AXMode.kScreenReader:
- return "screen reader"
- case AXMode.kHTML:
- return "html"
- }
- return "unknown"
- }
-
- function createModeElement(mode, data) {
- var currentMode = data['a11y_mode'];
- var link = document.createElement('a', 'action-link');
- link.setAttribute('role', 'button');
-
- var stateText = ((currentMode & mode) != 0) ? 'true' : 'false';
- link.textContent = getNameForAccessibilityMode(mode) + ": " + stateText;
- link.setAttribute('aria-pressed', stateText);
- link.addEventListener('click',
- toggleAccessibility.bind(this, data, link, mode));
- return link;
- }
-
- function createShowAccessibilityTreeElement(data, row, opt_refresh) {
- var link = document.createElement('a', 'action-link');
- link.setAttribute('role', 'button');
- if (opt_refresh)
- link.textContent = 'refresh accessibility tree';
- else
- link.textContent = 'show accessibility tree';
- link.id = row.id + ':showTree';
- link.addEventListener('click',
- requestWebContentsTree.bind(this, data, link));
- return link;
- }
-
- function createHideAccessibilityTreeElement(id) {
- var link = document.createElement('a', 'action-link');
- link.setAttribute('role', 'button');
- link.textContent = 'hide accessibility tree';
- link.addEventListener('click',
- function() {
- $(id + ':showTree').textContent = 'show accessibility tree';
- var existingTreeElements = $(id).getElementsByTagName('pre');
- for (var i = 0; i < existingTreeElements.length; i++)
- $(id).removeChild(existingTreeElements[i]);
- var row = $(id);
- while (row.lastChild != $(id + ':showTree'))
- row.removeChild(row.lastChild);
- });
- return link;
- }
-
- function createErrorMessageElement(data) {
- var errorMessageElement = document.createElement('div');
- var errorMessage = data.error;
- errorMessageElement.innerHTML = errorMessage + '&nbsp;';
- var closeLink = document.createElement('a');
- closeLink.href='#';
- closeLink.textContent = '[close]';
- closeLink.addEventListener('click', function() {
- var parentElement = errorMessageElement.parentElement;
- parentElement.removeChild(errorMessageElement);
- if (parentElement.childElementCount == 0)
- parentElement.parentElement.removeChild(parentElement);
- });
- errorMessageElement.appendChild(closeLink);
- return errorMessageElement;
- }
-
- // Called from C++
- function showTree(data) {
- var id = data.processId + '.' + data.routeId;
- var row = $(id);
- if (!row)
- return;
-
- row.textContent = '';
- formatRow(row, data);
- }
-
- // Called from C++
- function showNativeUITree(data) {
- var treeElement = document.querySelector('#native_ui pre');
- if (!treeElement) {
- var treeElement = document.createElement('pre');
- $('native_ui').appendChild(treeElement);
- }
- treeElement.textContent = data.tree;
- }
-
- function createAccessibilityTreeElement(data) {
- var treeElement = document.createElement('pre');
- var tree = data.tree;
- treeElement.textContent = tree;
- return treeElement;
- }
-
- // These are the functions we export so they can be called from C++.
- return {
- initialize: initialize,
- showTree: showTree,
- showNativeUITree: showNativeUITree
- };
-});
-
-document.addEventListener('DOMContentLoaded', accessibility.initialize);
diff --git a/chromium/content/browser/resources/indexed_db/indexeddb_internals.html b/chromium/content/browser/resources/indexed_db/indexeddb_internals.html
index 692219c2667..2c87cd9d3a3 100644
--- a/chromium/content/browser/resources/indexed_db/indexeddb_internals.html
+++ b/chromium/content/browser/resources/indexed_db/indexeddb_internals.html
@@ -48,6 +48,10 @@
jsvalues=".idb_origin_url:url;.idb_partition_path:$partition_path">Force close</a>
<a href="#" class="download"
jsvalues=".idb_origin_url:url;.idb_partition_path:$partition_path">Download</a>
+ <a href="#" class="force-schema-downgrade"
+ jsvalues=".idb_origin_url:url;.idb_partition_path:$partition_path">Force schema downgrade</a>
+ <a href="https://crbug.com/829141"
+ target="_blank">?</a>
<span class="download-status" style="display: none">Loading...</span>
</div>
<div class="indexeddb-database" jsselect="$this.databases">
diff --git a/chromium/content/browser/resources/indexed_db/indexeddb_internals.js b/chromium/content/browser/resources/indexed_db/indexeddb_internals.js
index fc80a25d024..9051fe7f35b 100644
--- a/chromium/content/browser/resources/indexed_db/indexeddb_internals.js
+++ b/chromium/content/browser/resources/indexed_db/indexeddb_internals.js
@@ -29,6 +29,14 @@ cr.define('indexeddb', function() {
return false;
}
+ function forceSchemaDowngrade(event) {
+ var link = event.target;
+ progressNodeFor(link).style.display = 'inline';
+ chrome.send('forceSchemaDowngrade', [link.idb_partition_path,
+ link.idb_origin_url]);
+ return false;
+ }
+
function withNode(selector, partition_path, origin_url, callback) {
var links = document.querySelectorAll(selector);
for (var i = 0; i < links.length; ++i) {
@@ -59,6 +67,18 @@ cr.define('indexeddb', function() {
});
}
+ function onForcedSchemaDowngrade(partition_path,
+ origin_url,
+ connection_count) {
+ withNode('a.force-schema-downgrade', partition_path, origin_url,
+ function(link) {
+ progressNodeFor(link).style.display = 'none';
+ });
+ withNode('.connection-count', partition_path, origin_url, function(span) {
+ span.innerText = connection_count;
+ });
+ }
+
// Fired from the backend with a single partition's worth of
// IndexedDB metadata.
function onOriginsReady(origins, partition_path) {
@@ -76,11 +96,18 @@ cr.define('indexeddb', function() {
for (i = 0; i < forceCloseLinks.length; ++i) {
forceCloseLinks[i].addEventListener('click', forceClose, false);
}
+ var forceSchemaDowngradeLinks =
+ container.querySelectorAll('a.force-schema-downgrade');
+ for (i = 0; i < forceSchemaDowngradeLinks.length; ++i) {
+ forceSchemaDowngradeLinks[i].addEventListener(
+ 'click', forceSchemaDowngrade, false);
+ }
}
return {
initialize: initialize,
onForcedClose: onForcedClose,
+ onForcedSchemaDowngrade: onForcedSchemaDowngrade,
onOriginDownloadReady: onOriginDownloadReady,
onOriginsReady: onOriginsReady,
};
diff --git a/chromium/content/browser/resources/media/client_renderer.js b/chromium/content/browser/resources/media/client_renderer.js
index 0b5413e8ae7..5d04e38d678 100644
--- a/chromium/content/browser/resources/media/client_renderer.js
+++ b/chromium/content/browser/resources/media/client_renderer.js
@@ -16,6 +16,8 @@ var ClientRenderer = (function() {
this.logTable = logElement.querySelector('tbody');
this.graphElement = document.getElementById('graphs');
this.audioPropertyName = document.getElementById('audio-property-name');
+ this.audioFocusSessionListElement_ =
+ document.getElementById('audio-focus-session-list');
this.players = null;
this.selectedPlayer = null;
@@ -139,6 +141,19 @@ var ClientRenderer = (function() {
},
/**
+ * Called when the list of audio focus sessions has changed.
+ * @param sessions A list of media sessions that contain the current state.
+ */
+ audioFocusSessionUpdated: function(sessions) {
+ removeChildren(this.audioFocusSessionListElement_);
+
+ sessions.forEach(session => {
+ this.audioFocusSessionListElement_.appendChild(
+ this.createAudioFocusSessionRow_(session));
+ });
+ },
+
+ /**
* Called when an audio component is removed from the collection.
* @param componentType Integer AudioComponent enum value; must match values
* from the AudioLogFactory::AudioComponent enum.
@@ -358,7 +373,7 @@ var ClientRenderer = (function() {
var label = document.createElement('label');
var name_text = p.url || 'Player ' + player.id;
- var name_node = document.createElement('span');
+ var name_node = document.createElement('div');
name_node.appendChild(document.createTextNode(name_text));
name_node.className = 'player-name';
label.appendChild(name_node);
@@ -370,8 +385,7 @@ var ClientRenderer = (function() {
frame.push(p.frame_url);
var frame_text = frame.join(' - ');
if (frame_text) {
- label.appendChild(document.createElement('br'));
- var frame_node = document.createElement('span');
+ var frame_node = document.createElement('div');
frame_node.className = 'player-frame';
frame_node.appendChild(document.createTextNode(frame_text));
label.appendChild(frame_node);
@@ -390,8 +404,7 @@ var ClientRenderer = (function() {
desc.push('(' + p.event + ')');
var desc_text = desc.join(' ');
if (desc_text) {
- label.appendChild(document.createElement('br'));
- var desc_node = document.createElement('span');
+ var desc_node = document.createElement('div');
desc_node.className = 'player-desc';
desc_node.appendChild(document.createTextNode(desc_text));
label.appendChild(desc_node);
@@ -528,6 +541,15 @@ var ClientRenderer = (function() {
this.drawLog_();
}
},
+
+ createAudioFocusSessionRow_: function(session) {
+ const template = $('audio-focus-session-row');
+ const span = template.content.querySelectorAll('span');
+ span[0].textContent = session.name;
+ span[1].textContent = session.owner;
+ span[2].textContent = session.state;
+ return document.importNode(template.content, true);
+ },
};
return ClientRenderer;
diff --git a/chromium/content/browser/resources/media/main.js b/chromium/content/browser/resources/media/main.js
index add25a1fc38..9a25be49b7e 100644
--- a/chromium/content/browser/resources/media/main.js
+++ b/chromium/content/browser/resources/media/main.js
@@ -27,6 +27,13 @@ var media = (function() {
manager.updateVideoCaptureCapabilities(videoCaptureCapabilities);
};
+ media.onReceiveAudioFocusState = function(audioFocusState) {
+ if (!audioFocusState)
+ return;
+
+ manager.updateAudioFocusSessions(audioFocusState.sessions);
+ };
+
media.updateAudioComponent = function(component) {
var uniqueComponentId = component.owner_id + ':' + component.component_id;
switch (component.status) {
diff --git a/chromium/content/browser/resources/media/manager.js b/chromium/content/browser/resources/media/manager.js
index 590a78c1e37..994df2b5bfe 100644
--- a/chromium/content/browser/resources/media/manager.js
+++ b/chromium/content/browser/resources/media/manager.js
@@ -41,6 +41,14 @@ var Manager = (function() {
Manager.prototype = {
/**
+ * Updates the audio focus state.
+ * @param sessions A list of media sessions that contain the current state.
+ */
+ updateAudioFocusSessions: function(sessions) {
+ this.clientRenderer_.audioFocusSessionUpdated(sessions);
+ },
+
+ /**
* Updates an audio-component.
* @param componentType Integer AudioComponent enum value; must match values
* from the AudioLogFactory::AudioComponent enum.
diff --git a/chromium/content/browser/resources/media/media_internals.css b/chromium/content/browser/resources/media/media_internals.css
index 7daaa773c62..a86c5c996cb 100644
--- a/chromium/content/browser/resources/media/media_internals.css
+++ b/chromium/content/browser/resources/media/media_internals.css
@@ -178,11 +178,9 @@ h3 {
color: rgba(0, 0, 0, .5);
}
+label.audio-focus-session,
label.selectable-button {
- -webkit-user-select: none;
- display: inline-block;
- background: #BDF;
- cursor: pointer;
+ display: block;
border: solid 1px #999;
border-radius: 3px;
padding: 6px;
@@ -191,6 +189,12 @@ label.selectable-button {
word-break: break-all;
}
+label.selectable-button {
+ background: #BDF;
+ cursor: pointer;
+ user-select: none;
+}
+
input.selectable-button {
display: none;
}
@@ -205,6 +209,7 @@ input.selectable-button:hover + label.selectable-button {
border-color: #666;
}
+label.audio-focus-session,
label.destructed-player {
background-color: #EEE;
}
@@ -215,6 +220,9 @@ label.destructed-player {
.player-frame {
font-style: italic;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
}
.no-players-selected #players .property-wrapper,
@@ -226,3 +234,6 @@ label.destructed-player {
display: none;
}
+#audio-focus-session-list {
+ list-style: none;
+}
diff --git a/chromium/content/browser/resources/media/media_internals.html b/chromium/content/browser/resources/media/media_internals.html
index e624b5a2419..6df11b93b5c 100644
--- a/chromium/content/browser/resources/media/media_internals.html
+++ b/chromium/content/browser/resources/media/media_internals.html
@@ -25,6 +25,7 @@ found in the LICENSE file.
<tab>Players</tab>
<tab>Audio</tab>
<tab>Video Capture</tab>
+ <tab>Audio Focus</tab>
</tabs>
<tabpanels>
<tabpanel id="players">
@@ -120,6 +121,21 @@ found in the LICENSE file.
</table>
</div>
</tabpanel>
+ <tabpanel id="players">
+ <div id="list-wrapper">
+ <h2>Active Sessions</h2>
+ <ul id="audio-focus-session-list" class="show-none-if-empty"></ul>
+ </div>
+ <template id="audio-focus-session-row">
+ <li>
+ <label class="audio-focus-session">
+ <span class="player-name"></span><br />
+ <span class="player-frame"></span><br />
+ <span class="player-desc"></span>
+ </label>
+ </li>
+ </template>
+ </tabpanel>
</tabpanels>
</tabbox>
<dialog id="clipboard-dialog">
diff --git a/chromium/content/browser/scheduler/responsiveness/OWNERS b/chromium/content/browser/scheduler/responsiveness/OWNERS
new file mode 100644
index 00000000000..8b3b15dc071
--- /dev/null
+++ b/chromium/content/browser/scheduler/responsiveness/OWNERS
@@ -0,0 +1,2 @@
+erikchen@chromium.org
+tdresser@chromium.org
diff --git a/chromium/content/browser/scheduler/responsiveness/README b/chromium/content/browser/scheduler/responsiveness/README
new file mode 100644
index 00000000000..68ee4d93be7
--- /dev/null
+++ b/chromium/content/browser/scheduler/responsiveness/README
@@ -0,0 +1,35 @@
+The classes in this folder estimate the responsiveness of Chrome by measuring
+execution latency on the UI and IO threads of the browser process.
+
+There are four types of work executed on the UI and IO threads.
+1) Both the UI and IO threads can have tasks posted to them via the Task
+ Scheduler [e.g. via content::BrowserThread::PostTask].
+2) The UI thread processes native events directly from the message loop
+ [NSEvents on macOS, MSGs on Windows, InputEvents on Android, XEvents on
+ X11, etc.]
+3) The IO thread's message pump processes IPCs by listening on data channels
+ [e.g. fds] and waking up on available data.
+4) The UI thread's message loop may process other platform-specific sources.
+
+Execution latency is a measure of the duration between when a task or event is
+scheduled or created, and when it finishes executing. We measure this for (1)
+and (2) but not (3) and (4). More details:
+
+1) Record TimeTicks::Now() when the event is scheduled and compare to
+ TimeTicks::Now() when the event finishes execution.
+2) All native events have a creation timestamp. Compare that to
+ TimeTicks::Now() when the event finishes execution.
+3) There's no good solution here, since the current wire format for IPCs does
+ not record the time at which the IPC was written to the data channel. The
+ time between reading from the data channel and finishing execution is
+ typically small, as heavy tasks are supposed to be dispatched off the IO
+ thread.
+4) There is no consistent way to measure the execution latency of work that
+ is neither a task nor an event. If individual sources prove to be
+ a source of non-responsiveness, they will need to be addressed on a
+ case-by-case basis.
+
+Note: As long as there are any tasks or events queued, jank caused by (3) or
+(4) will be accounted for, as it will show up as increased queueing time.
+
+Design doc: https://docs.google.com/document/d/1vDSGFvJblh7yJ3U3RVB_7qZLubyfTbQdQjuN1GoUNkc/edit
diff --git a/chromium/content/browser/scheduler/responsiveness/calculator.cc b/chromium/content/browser/scheduler/responsiveness/calculator.cc
new file mode 100644
index 00000000000..2c82001f04e
--- /dev/null
+++ b/chromium/content/browser/scheduler/responsiveness/calculator.cc
@@ -0,0 +1,216 @@
+// 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/responsiveness/calculator.h"
+
+#include <algorithm>
+#include <set>
+
+#include "base/metrics/histogram_macros.h"
+#include "content/public/browser/browser_thread.h"
+
+namespace content {
+namespace responsiveness {
+
+namespace {
+
+// We divide the measurement interval into discretized time slices.
+// Each slice is marked as janky if it contained a janky task. A janky task is
+// one whose execution latency is greater than kJankThreshold.
+constexpr base::TimeDelta kMeasurementInterval =
+ base::TimeDelta::FromSeconds(30);
+
+// A task or event longer than kJankThreshold is considered janky.
+constexpr base::TimeDelta kJankThreshold =
+ base::TimeDelta::FromMilliseconds(100);
+
+// If there have been no events/tasks on the UI thread for a significant period
+// of time, it's likely because Chrome was suspended.
+// This value is copied from queueing_time_estimator.cc:kInvalidPeriodThreshold.
+constexpr base::TimeDelta kSuspendInterval = base::TimeDelta::FromSeconds(30);
+
+// Given a |jank|, finds each janky slice between |start_time| and |end_time|,
+// and adds it to |janky_slices|.
+void AddJankySlices(std::set<int>* janky_slices,
+ const Calculator::Jank& jank,
+ base::TimeTicks start_time,
+ base::TimeTicks end_time) {
+ // Ignore the first jank threshold, since that's the part of the task/event
+ // that wasn't janky.
+ base::TimeTicks jank_start = jank.start_time + kJankThreshold;
+
+ // Bound by |start_time| and |end_time|.
+ jank_start = std::max(jank_start, start_time);
+ base::TimeTicks jank_end = std::min(jank.end_time, end_time);
+
+ // Find each janky slice, and add it to |janky_slices|.
+ while (jank_start < jank_end) {
+ // Convert |jank_start| to a slice label.
+ int label = (jank_start - start_time) / kJankThreshold;
+ janky_slices->insert(label);
+
+ jank_start += kJankThreshold;
+ }
+}
+
+} // namespace
+
+Calculator::Jank::Jank(base::TimeTicks start_time, base::TimeTicks end_time)
+ : start_time(start_time), end_time(end_time) {
+ DCHECK_LE(start_time, end_time);
+}
+
+Calculator::Calculator()
+ : last_calculation_time_(base::TimeTicks::Now()),
+ most_recent_activity_time_(last_calculation_time_) {}
+Calculator::~Calculator() = default;
+
+void Calculator::TaskOrEventFinishedOnUIThread(base::TimeTicks schedule_time,
+ base::TimeTicks finish_time) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ if (finish_time - schedule_time >= kJankThreshold) {
+ GetJanksOnUIThread().emplace_back(schedule_time, finish_time);
+ }
+
+ // We rely on the assumption that |finish_time| is the current time.
+ CalculateResponsivenessIfNecessary(/*current_time=*/finish_time);
+}
+
+void Calculator::TaskOrEventFinishedOnIOThread(base::TimeTicks schedule_time,
+ base::TimeTicks finish_time) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ if (finish_time - schedule_time >= kJankThreshold) {
+ base::AutoLock lock(io_thread_lock_);
+ GetJanksOnIOThread().emplace_back(schedule_time, finish_time);
+ }
+}
+
+void Calculator::EmitResponsiveness(int janky_slices) {
+ UMA_HISTOGRAM_COUNTS_1000(
+ "Browser.Responsiveness.JankyIntervalsPerThirtySeconds", janky_slices);
+}
+
+base::TimeTicks Calculator::GetLastCalculationTime() {
+ return last_calculation_time_;
+}
+
+void Calculator::CalculateResponsivenessIfNecessary(
+ base::TimeTicks current_time) {
+ base::TimeTicks last_activity_time = most_recent_activity_time_;
+ most_recent_activity_time_ = current_time;
+
+ // We intentionally dump all data if it appears that Chrome was suspended.
+ // [e.g. machine is asleep, process is backgrounded on Android]. We don't have
+ // an explicit signal for this. Instead, we rely on the assumption that when
+ // Chrome is not suspended, there is a steady stream of tasks and events on
+ // the UI thread. If there's been a significant amount of time since the last
+ // calculation, then it's likely because Chrome was suspended.
+ if (current_time - last_activity_time > kSuspendInterval) {
+ last_calculation_time_ = current_time;
+ GetJanksOnUIThread().clear();
+ {
+ base::AutoLock lock(io_thread_lock_);
+ GetJanksOnIOThread().clear();
+ }
+ return;
+ }
+
+ base::TimeDelta time_since_last_calculation =
+ current_time - last_calculation_time_;
+ if (time_since_last_calculation <= kMeasurementInterval)
+ return;
+
+ // At least |kMeasurementInterval| time has passed, so we want to move forward
+ // |last_calculation_time_| and make measurements based on janks in that
+ // interval.
+ int number_of_measurement_intervals =
+ time_since_last_calculation / kMeasurementInterval;
+ DCHECK(number_of_measurement_intervals >= 1);
+
+ base::TimeTicks new_calculation_time =
+ last_calculation_time_ +
+ number_of_measurement_intervals * kMeasurementInterval;
+
+ // Acquire the janks in the measurement interval from the UI and IO threads.
+ std::vector<JankList> janks_from_multiple_threads;
+ janks_from_multiple_threads.push_back(
+ TakeJanksOlderThanTime(&GetJanksOnUIThread(), new_calculation_time));
+ {
+ base::AutoLock lock(io_thread_lock_);
+ janks_from_multiple_threads.push_back(
+ TakeJanksOlderThanTime(&GetJanksOnIOThread(), new_calculation_time));
+ }
+
+ CalculateResponsiveness(std::move(janks_from_multiple_threads),
+ last_calculation_time_, new_calculation_time);
+
+ last_calculation_time_ = new_calculation_time;
+}
+
+void Calculator::CalculateResponsiveness(
+ std::vector<JankList> janks_from_multiple_threads,
+ base::TimeTicks start_time,
+ base::TimeTicks end_time) {
+ while (start_time < end_time) {
+ base::TimeTicks current_interval_end_time =
+ start_time + kMeasurementInterval;
+
+ // We divide the current measurement interval into slices. Each slice is
+ // given a monotonically increasing label, from 0 to |kNumberOfSlices - 1|.
+ // Example [all times in milliseconds since UNIX epoch]:
+ // The measurement interval is [50135, 80135].
+ // The slice [50135, 50235] is labeled 0.
+ // The slice [50235, 50335] is labeled 1.
+ // ...
+ // The slice [80035, 80135] is labeled 299.
+ std::set<int> janky_slices;
+
+ for (const JankList& janks : janks_from_multiple_threads) {
+ for (const Jank& jank : janks) {
+ AddJankySlices(&janky_slices, jank, start_time,
+ current_interval_end_time);
+ }
+ }
+
+ EmitResponsiveness(janky_slices.size());
+
+ start_time = current_interval_end_time;
+ }
+}
+
+Calculator::JankList& Calculator::GetJanksOnUIThread() {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ return janks_on_ui_thread_;
+}
+
+Calculator::JankList& Calculator::GetJanksOnIOThread() {
+ io_thread_lock_.AssertAcquired();
+ return janks_on_io_thread_;
+}
+
+Calculator::JankList Calculator::TakeJanksOlderThanTime(
+ JankList* janks,
+ base::TimeTicks end_time) {
+ // Find all janks with Jank.start_time < |end_time|.
+ auto it = std::partition(
+ janks->begin(), janks->end(),
+ [&end_time](const Jank& jank) { return jank.start_time < end_time; });
+
+ // Early exit. We don't need to remove any Janks either, since Jank.end_time
+ // >= Jank.start_time.
+ if (it == janks->begin())
+ return JankList();
+
+ JankList janks_to_return(janks->begin(), it);
+
+ // Remove all janks with Jank.end_time < |end_time|.
+ auto first_jank_to_keep = std::partition(
+ janks->begin(), janks->end(),
+ [&end_time](const Jank& jank) { return jank.end_time < end_time; });
+ janks->erase(janks->begin(), first_jank_to_keep);
+ return janks_to_return;
+}
+
+} // namespace responsiveness
+} // namespace content
diff --git a/chromium/content/browser/scheduler/responsiveness/calculator.h b/chromium/content/browser/scheduler/responsiveness/calculator.h
new file mode 100644
index 00000000000..a5c7c406362
--- /dev/null
+++ b/chromium/content/browser/scheduler/responsiveness/calculator.h
@@ -0,0 +1,130 @@
+// 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_RESPONSIVENESS_CALCULATOR_H_
+#define CONTENT_BROWSER_SCHEDULER_RESPONSIVENESS_CALCULATOR_H_
+
+#include <vector>
+
+#include "base/macros.h"
+#include "base/synchronization/lock.h"
+#include "base/time/time.h"
+#include "content/common/content_export.h"
+
+namespace content {
+namespace responsiveness {
+
+// This class receives execution latency on events and tasks, and uses that to
+// estimate responsiveness.
+//
+// All members are UI-thread affine, with the exception of
+// |janks_on_io_thread_| which is protected by |io_thread_lock_|.
+class CONTENT_EXPORT Calculator {
+ public:
+ Calculator();
+ virtual ~Calculator();
+
+ // Must be called from the UI thread.
+ // virtual for testing.
+ // The implementation will gracefully handle calls where finish_time <
+ // schedule_time.
+ // The implementation will gracefully handle successive calls with
+ // |schedule_times| that are out of order.
+ virtual void TaskOrEventFinishedOnUIThread(base::TimeTicks schedule_time,
+ base::TimeTicks finish_time);
+
+ // Must be called from the IO thread.
+ // virtual for testing.
+ virtual void TaskOrEventFinishedOnIOThread(base::TimeTicks schedule_time,
+ base::TimeTicks finish_time);
+
+ // Each janking task/event is fully defined by |start_time| and |end_time|.
+ // Note that |duration| = |end_time| - |start_time|.
+ struct Jank {
+ Jank(base::TimeTicks start_time, base::TimeTicks end_time);
+
+ base::TimeTicks start_time;
+ base::TimeTicks end_time;
+ };
+
+ protected:
+ // Emits an UMA metric for responsiveness of a single measurement interval.
+ // Exposed for testing.
+ virtual void EmitResponsiveness(int janky_slices);
+
+ // Exposed for testing.
+ base::TimeTicks GetLastCalculationTime();
+
+ private:
+ using JankList = std::vector<Jank>;
+
+ // If sufficient time has passed since the last calculation, then calculate
+ // responsiveness again and update |last_calculation_time_|.
+ //
+ // We only trigger this from the UI thread since triggering it from the IO
+ // thread would require us to grab the lock, which could cause contention. We
+ // only need this to trigger every 30s or so, and we generally expect there to
+ // be some activity on the UI thread if Chrome is actually in use.
+ void CalculateResponsivenessIfNecessary(base::TimeTicks current_time);
+
+ // Responsiveness is calculated by:
+ // 1) Discretizing time into small intervals.
+ // 2) In each interval, looking to see if there is a Janky event. If so, the
+ // interval is marked as |janky|.
+ // 3) Computing the percentage of intervals that are janky.
+ // The caller guarantees that Jank.end_time < |end_time|.
+ //
+ // This method intentionally takes a std::vector<JankList>, as we may want to
+ // extend it in the future to take JankLists from other threads/processes.
+ void CalculateResponsiveness(
+ std::vector<JankList> janks_from_multiple_threads,
+ base::TimeTicks start_time,
+ base::TimeTicks end_time);
+
+ // Accessor for |janks_on_ui_thread_|. Must be called from the UI thread.
+ JankList& GetJanksOnUIThread();
+
+ // Accessor for |janks_on_io_thread_|. Requires that |io_thread_lock_| has
+ // already been taken. May be called from any thread.
+ JankList& GetJanksOnIOThread();
+
+ // This method:
+ // 1) Removes all Janks with Jank.end_time < |end_time| from |janks|.
+ // 2) Returns all Janks with Jank.start_time < |end_time|.
+ JankList TakeJanksOlderThanTime(JankList* janks, base::TimeTicks end_time);
+
+ // This should only be accessed via the accessor, which checks that the caller
+ // is on the UI thread.
+ JankList janks_on_ui_thread_;
+
+ // We expect there to be low contention and this lock to cause minimal
+ // overhead. If performance of this lock proves to be a problem, we can move
+ // to a lock-free data structure.
+ base::Lock io_thread_lock_;
+
+ // This should only be accessed via the accessor, which checks that
+ // |io_thread_lock_| has been acquired.
+ JankList janks_on_io_thread_;
+
+ // The last time at which metrics were emitted. All janks older than this time
+ // have been consumed. Newer janks are still in their JankLists waiting to be
+ // consumed.
+ base::TimeTicks last_calculation_time_;
+
+ // This class keeps track of the time at which any activity occurred on the UI
+ // thread. If a sufficiently long period of time passes without any activity,
+ // then it's assumed that the process was suspended. In this case, we should
+ // not emit any responsiveness metrics.
+ //
+ // Note that the process may be suspended while a task or event is being
+ // executed, so a very long execution time should be treated similarly.
+ base::TimeTicks most_recent_activity_time_;
+
+ DISALLOW_COPY_AND_ASSIGN(Calculator);
+};
+
+} // namespace responsiveness
+} // namespace content
+
+#endif // CONTENT_BROWSER_SCHEDULER_RESPONSIVENESS_CALCULATOR_H_
diff --git a/chromium/content/browser/scheduler/responsiveness/calculator_unittest.cc b/chromium/content/browser/scheduler/responsiveness/calculator_unittest.cc
new file mode 100644
index 00000000000..25f81ad24fe
--- /dev/null
+++ b/chromium/content/browser/scheduler/responsiveness/calculator_unittest.cc
@@ -0,0 +1,235 @@
+// 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/responsiveness/calculator.h"
+
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+namespace responsiveness {
+
+namespace {
+// Copied from calculator.cc.
+constexpr int kMeasurementIntervalInMs = 30 * 1000;
+constexpr int kJankThresholdInMs = 100;
+
+class FakeCalculator : public Calculator {
+ public:
+ std::vector<int>& Emissions() { return janky_slices_; }
+
+ void EmitResponsiveness(int janky_slices) override {
+ janky_slices_.push_back(janky_slices);
+ }
+
+ using Calculator::GetLastCalculationTime;
+
+ private:
+ std::vector<int> janky_slices_;
+};
+
+} // namespace
+
+class ResponsivenessCalculatorTest : public testing::Test {
+ public:
+ void SetUp() override {
+ calculator_ = std::make_unique<FakeCalculator>();
+ last_calculation_time_ = calculator_->GetLastCalculationTime();
+ }
+
+ void AddEventUI(int schedule_time_in_ms, int finish_time_in_ms) {
+ calculator_->TaskOrEventFinishedOnUIThread(
+ last_calculation_time_ +
+ base::TimeDelta::FromMilliseconds(schedule_time_in_ms),
+ last_calculation_time_ +
+ base::TimeDelta::FromMilliseconds(finish_time_in_ms));
+ }
+
+ void AddEventIO(int schedule_time_in_ms, int finish_time_in_ms) {
+ calculator_->TaskOrEventFinishedOnIOThread(
+ last_calculation_time_ +
+ base::TimeDelta::FromMilliseconds(schedule_time_in_ms),
+ last_calculation_time_ +
+ base::TimeDelta::FromMilliseconds(finish_time_in_ms));
+ }
+
+ void TriggerCalculation() {
+ AddEventUI(kMeasurementIntervalInMs + 1, kMeasurementIntervalInMs + 2);
+ last_calculation_time_ = calculator_->GetLastCalculationTime();
+ }
+
+ protected:
+ // This member sets up BrowserThread::IO and BrowserThread::UI. It must be the
+ // first member, as other members may depend on these abstractions.
+ content::TestBrowserThreadBundle test_browser_thread_bundle_;
+
+ std::unique_ptr<FakeCalculator> calculator_;
+ base::TimeTicks last_calculation_time_;
+};
+
+// A single event of length slightly longer than kJankThresholdInMs.
+TEST_F(ResponsivenessCalculatorTest, ShortJank) {
+ AddEventUI(40, 40 + kJankThresholdInMs + 5);
+ TriggerCalculation();
+
+ ASSERT_EQ(1u, calculator_->Emissions().size());
+ EXPECT_EQ(1, calculator_->Emissions()[0]);
+}
+
+// A single event of length slightly longer than 10 * kJankThresholdInMs.
+TEST_F(ResponsivenessCalculatorTest, LongJank) {
+ AddEventUI(40, 40 + 10 * kJankThresholdInMs + 5);
+ TriggerCalculation();
+
+ ASSERT_EQ(1u, calculator_->Emissions().size());
+ EXPECT_EQ(10, calculator_->Emissions()[0]);
+}
+
+// Events that last less than 100ms do not jank, regardless of start time.
+TEST_F(ResponsivenessCalculatorTest, NoJank) {
+ int base_time = 30;
+ for (int i = 0; i < kJankThresholdInMs; ++i) {
+ AddEventUI(base_time, base_time + i);
+ }
+
+ base_time += kJankThresholdInMs;
+ for (int i = 0; i < kJankThresholdInMs; ++i) {
+ AddEventUI(base_time + i, base_time + 2 * i);
+ }
+
+ TriggerCalculation();
+ ASSERT_EQ(1u, calculator_->Emissions().size());
+ EXPECT_EQ(0, calculator_->Emissions()[0]);
+}
+
+// 10 Jank events, but very closely overlapping. Time slices are discretized and
+// fixed, e.g. [0 100] [100 200] [200 300]. In this test, the events all start
+// in the [0 100] slice and end in the [100 200] slice. All of them end up
+// marking the [100 200] slice as janky.
+TEST_F(ResponsivenessCalculatorTest, OverlappingJank) {
+ int base_time = 30;
+ for (int i = 0; i < 10; ++i) {
+ AddEventUI(base_time, base_time + kJankThresholdInMs + 10);
+ }
+
+ TriggerCalculation();
+ ASSERT_EQ(1u, calculator_->Emissions().size());
+ EXPECT_EQ(1, calculator_->Emissions()[0]);
+}
+
+// UI thread has 3 jank events on slices 1, 2, 3
+// IO thread has 3 jank events on slices 3, 4, 5,
+// There should be a total of 5 jank events.
+TEST_F(ResponsivenessCalculatorTest, OverlappingJankMultipleThreads) {
+ int base_time = 105;
+ for (int i = 0; i < 3; ++i) {
+ AddEventUI(base_time + i * kJankThresholdInMs,
+ base_time + (i + 1) * kJankThresholdInMs + 10);
+ }
+
+ base_time = 305;
+ for (int i = 0; i < 3; ++i) {
+ AddEventIO(base_time + i * kJankThresholdInMs,
+ base_time + (i + 1) * kJankThresholdInMs + 10);
+ }
+
+ TriggerCalculation();
+ ASSERT_EQ(1u, calculator_->Emissions().size());
+ EXPECT_EQ(5, calculator_->Emissions()[0]);
+}
+
+// Three janks, each of length 2, separated by some shorter events.
+TEST_F(ResponsivenessCalculatorTest, SeparatedJanks) {
+ int base_time = 105;
+
+ for (int i = 0; i < 3; ++i) {
+ AddEventUI(base_time, base_time + 1);
+ AddEventUI(base_time, base_time + 2 * kJankThresholdInMs + 1);
+ base_time += 10 * kJankThresholdInMs;
+ }
+ TriggerCalculation();
+
+ ASSERT_EQ(1u, calculator_->Emissions().size());
+ EXPECT_EQ(6, calculator_->Emissions()[0]);
+}
+
+TEST_F(ResponsivenessCalculatorTest, MultipleTrigger) {
+ int base_time = 105;
+
+ // 3 Janks, then trigger, then repeat.
+ for (int i = 0; i < 10; ++i) {
+ for (int j = 0; j < 3; ++j) {
+ AddEventUI(base_time, base_time + 3 * kJankThresholdInMs + 1);
+ base_time += 3 * kJankThresholdInMs;
+ }
+ TriggerCalculation();
+ }
+
+ ASSERT_EQ(10u, calculator_->Emissions().size());
+ for (int i = 0; i < 10; ++i) {
+ EXPECT_EQ(9, calculator_->Emissions()[i]);
+ }
+}
+
+// A long delay means that the machine likely went to sleep.
+TEST_F(ResponsivenessCalculatorTest, LongDelay) {
+ int base_time = 105;
+ AddEventUI(base_time, base_time + 3 * kJankThresholdInMs + 1);
+ base_time += 10 * kMeasurementIntervalInMs;
+ AddEventUI(base_time, base_time + 1);
+
+ ASSERT_EQ(0u, calculator_->Emissions().size());
+}
+
+// A long event means that the machine likely went to sleep.
+TEST_F(ResponsivenessCalculatorTest, LongEvent) {
+ int base_time = 105;
+ AddEventUI(base_time, base_time + 10 * kMeasurementIntervalInMs);
+
+ ASSERT_EQ(0u, calculator_->Emissions().size());
+}
+
+// An event that crosses a measurement interval boundary should count towards
+// both measurement intervals.
+TEST_F(ResponsivenessCalculatorTest, EventCrossesBoundary) {
+ // Dummy event so that Calculator doesn't think the process is suspended.
+ AddEventUI(0.5 * kMeasurementIntervalInMs, 0.5 * kMeasurementIntervalInMs);
+
+ // The event goes from [29801, 30150]. It should count as 1 jank in the first
+ // measurement interval and 2 in the second.
+ AddEventUI(kMeasurementIntervalInMs - 2 * kJankThresholdInMs + 1,
+ kMeasurementIntervalInMs + 1.5 * kJankThresholdInMs);
+
+ // Dummy event so that Calculator doesn't think the process is suspended.
+ AddEventUI(1.5 * kMeasurementIntervalInMs, 1.5 * kMeasurementIntervalInMs);
+
+ // Trigger another calculation.
+ AddEventUI(2 * kMeasurementIntervalInMs + 1,
+ 2 * kMeasurementIntervalInMs + 1);
+ ASSERT_EQ(2u, calculator_->Emissions().size());
+ EXPECT_EQ(1, calculator_->Emissions()[0]);
+ EXPECT_EQ(2, calculator_->Emissions()[1]);
+}
+
+// Events may not be ordered by start or end time.
+TEST_F(ResponsivenessCalculatorTest, UnorderedEvents) {
+ // We add the following events:
+ // [100, 250]
+ // [150, 300]
+ // [50, 200]
+ // [50, 390]
+ // The event [50, 400] subsumes all previous events.
+ AddEventUI(kJankThresholdInMs, 2.5 * kJankThresholdInMs);
+ AddEventUI(1.5 * kJankThresholdInMs, 3 * kJankThresholdInMs);
+ AddEventUI(0.5 * kJankThresholdInMs, 2 * kJankThresholdInMs);
+ AddEventUI(0.5 * kJankThresholdInMs, 3.9 * kJankThresholdInMs);
+
+ TriggerCalculation();
+
+ ASSERT_EQ(1u, calculator_->Emissions().size());
+ EXPECT_EQ(3, calculator_->Emissions()[0]);
+}
+
+} // namespace responsiveness
+} // namespace content
diff --git a/chromium/content/browser/scheduler/responsiveness/message_loop_observer.cc b/chromium/content/browser/scheduler/responsiveness/message_loop_observer.cc
new file mode 100644
index 00000000000..01284022732
--- /dev/null
+++ b/chromium/content/browser/scheduler/responsiveness/message_loop_observer.cc
@@ -0,0 +1,34 @@
+// 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/responsiveness/message_loop_observer.h"
+
+namespace content {
+namespace responsiveness {
+
+MessageLoopObserver::MessageLoopObserver(TaskCallback will_run_task_callback,
+ TaskCallback did_run_task_callback)
+ : will_run_task_callback_(will_run_task_callback),
+ did_run_task_callback_(did_run_task_callback) {
+ base::MessageLoopCurrent::Get()->SetAddQueueTimeToTasks(true);
+ base::MessageLoopCurrent::Get()->AddTaskObserver(this);
+}
+
+MessageLoopObserver::~MessageLoopObserver() {
+ base::MessageLoopCurrent::Get()->RemoveTaskObserver(this);
+ base::MessageLoopCurrent::Get()->SetAddQueueTimeToTasks(false);
+}
+
+void MessageLoopObserver::WillProcessTask(
+ const base::PendingTask& pending_task) {
+ will_run_task_callback_.Run(&pending_task);
+}
+
+void MessageLoopObserver::DidProcessTask(
+ const base::PendingTask& pending_task) {
+ did_run_task_callback_.Run(&pending_task);
+}
+
+} // namespace responsiveness
+} // namespace content
diff --git a/chromium/content/browser/scheduler/responsiveness/message_loop_observer.h b/chromium/content/browser/scheduler/responsiveness/message_loop_observer.h
new file mode 100644
index 00000000000..e6eed71be4e
--- /dev/null
+++ b/chromium/content/browser/scheduler/responsiveness/message_loop_observer.h
@@ -0,0 +1,47 @@
+// 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_RESPONSIVENESS_MESSAGE_LOOP_OBSERVER_H_
+#define CONTENT_BROWSER_SCHEDULER_RESPONSIVENESS_MESSAGE_LOOP_OBSERVER_H_
+
+#include "base/macros.h"
+#include "base/message_loop/message_loop_current.h"
+#include "content/common/content_export.h"
+
+namespace base {
+struct PendingTask;
+} // namespace base
+
+namespace content {
+namespace responsiveness {
+
+// This object is not thread safe. It must be constructed and destroyed on the
+// same thread. The callbacks will occur synchronously from WillProcessTask()
+// and DidProcessTask().
+class CONTENT_EXPORT MessageLoopObserver
+ : base::MessageLoopCurrent::TaskObserver {
+ public:
+ using TaskCallback =
+ base::RepeatingCallback<void(const base::PendingTask* task)>;
+
+ // The constructor will register the object as an observer of the current
+ // MessageLoop. The destructor will unregister the object.
+ MessageLoopObserver(TaskCallback will_run_task_callback,
+ TaskCallback did_run_task_callback);
+ ~MessageLoopObserver() override;
+
+ private:
+ void WillProcessTask(const base::PendingTask& pending_task) override;
+ void DidProcessTask(const base::PendingTask& pending_task) override;
+
+ TaskCallback will_run_task_callback_;
+ TaskCallback did_run_task_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(MessageLoopObserver);
+};
+
+} // namespace responsiveness
+} // namespace content
+
+#endif // CONTENT_BROWSER_SCHEDULER_RESPONSIVENESS_MESSAGE_LOOP_OBSERVER_H_
diff --git a/chromium/content/browser/scheduler/responsiveness/native_event_observer.cc b/chromium/content/browser/scheduler/responsiveness/native_event_observer.cc
new file mode 100644
index 00000000000..4225e9aa6df
--- /dev/null
+++ b/chromium/content/browser/scheduler/responsiveness/native_event_observer.cc
@@ -0,0 +1,157 @@
+// 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.
+
+// Needed for defined(OS_WIN)
+#include "build/build_config.h"
+
+// Windows headers must come first.
+#if defined(OS_WIN)
+#include <windows.h>
+
+#include <timeapi.h>
+#endif
+
+// Proceed with header includes in usual order.
+#include "content/browser/scheduler/responsiveness/native_event_observer.h"
+
+#include "ui/events/platform/platform_event_source.h"
+
+#if defined(USE_X11)
+#include "ui/events/platform/x11/x11_event_source.h" // nogncheck
+#elif defined(USE_OZONE)
+#include "ui/events/event.h"
+#endif
+
+#if defined(OS_LINUX)
+#include "ui/events/platform_event.h"
+#endif
+
+#if defined(OS_WIN)
+#include "base/message_loop/message_loop_current.h"
+#endif
+
+namespace content {
+namespace responsiveness {
+
+#if defined(OS_WIN) || (defined(OS_LINUX) && defined(USE_X11))
+
+namespace {
+
+// Clamps a TimeDelta to be within [0 seconds, 30 seconds].
+// Relies on the assumption that |delta| is >= 0 seconds.
+base::TimeDelta ClampDeltaFromExternalSource(const base::TimeDelta& delta) {
+ DCHECK_GE(delta, base::TimeDelta());
+
+ // Ignore pathologically long deltas. External source is probably having
+ // issues.
+ constexpr base::TimeDelta pathologically_long_duration =
+ base::TimeDelta::FromSeconds(30);
+ if (delta > pathologically_long_duration)
+ return base::TimeDelta();
+
+ return delta;
+}
+
+} // namespace
+
+#endif // defined(OS_WIN) || (defined(OS_LINUX) && defined(USE_X11))
+
+NativeEventObserver::NativeEventObserver(
+ WillRunEventCallback will_run_event_callback,
+ DidRunEventCallback did_run_event_callback)
+ : will_run_event_callback_(will_run_event_callback),
+ did_run_event_callback_(did_run_event_callback) {
+ RegisterObserver();
+}
+
+NativeEventObserver::~NativeEventObserver() {
+ DeregisterObserver();
+}
+
+#if defined(OS_LINUX)
+void NativeEventObserver::RegisterObserver() {
+ ui::PlatformEventSource::GetInstance()->AddPlatformEventObserver(this);
+}
+void NativeEventObserver::DeregisterObserver() {
+ ui::PlatformEventSource::GetInstance()->RemovePlatformEventObserver(this);
+}
+
+void NativeEventObserver::WillProcessEvent(const ui::PlatformEvent& event) {
+ will_run_event_callback_.Run(&event);
+}
+
+void NativeEventObserver::DidProcessEvent(const ui::PlatformEvent& event) {
+#if defined(USE_OZONE)
+ did_run_event_callback_.Run(&event, event->time_stamp());
+#elif defined(USE_X11)
+ // X11 uses a uint32_t on the wire protocol. Xlib casts this to an unsigned
+ // long by prepending with 0s. We cast back to a uint32_t so that subtraction
+ // works properly when the timestamp overflows back to 0.
+ uint32_t event_server_time_ms =
+ static_cast<uint32_t>(ui::X11EventSource::GetInstance()->GetTimestamp());
+ uint32_t current_server_time_ms = static_cast<uint32_t>(
+ ui::X11EventSource::GetInstance()->GetCurrentServerTime());
+
+ // On X11, event times are in X11 Server time. To convert to base::TimeTicks,
+ // we perform a round-trip to the X11 Server, subtract the two times to get a
+ // TimeDelta, and then subtract that from base::TimeTicks::Now(). Since we're
+ // working with units of time from an external source, we clamp the TimeDelta
+ // to reasonable values.
+ uint32_t delta_ms = current_server_time_ms - event_server_time_ms;
+ base::TimeDelta delta = base::TimeDelta::FromMilliseconds(delta_ms);
+ base::TimeDelta sanitized = ClampDeltaFromExternalSource(delta);
+
+ did_run_event_callback_.Run(&event, base::TimeTicks::Now() - sanitized);
+#else
+#error
+#endif
+}
+#endif // defined(OS_LINUX)
+
+#if defined(OS_WIN)
+void NativeEventObserver::RegisterObserver() {
+ base::MessageLoopCurrentForUI::Get()->AddMessagePumpObserver(this);
+}
+void NativeEventObserver::DeregisterObserver() {
+ base::MessageLoopCurrentForUI::Get()->RemoveMessagePumpObserver(this);
+}
+void NativeEventObserver::WillDispatchMSG(const MSG& msg) {
+ will_run_event_callback_.Run(&msg);
+}
+void NativeEventObserver::DidDispatchMSG(const MSG& msg) {
+ // On Windows, MSG.time is in units of milliseconds since system started. It
+ // uses the timer exposed by ::GetTickCount().
+ // https://blogs.msdn.microsoft.com/oldnewthing/20140122-00/?p=2013
+ //
+ // This timer has ~16ms granularity. This is okay for us since we require
+ // ~100ms granularity.
+ // https://randomascii.wordpress.com/2013/05/09/timegettime-versus-gettickcount/
+ //
+ // To convert MSG.time to TimeTicks, we subtract MSG.time from
+ // ::GetTickCount() to create a TimeDelta, and then subtract that from
+ // TimeTicks::Now().
+ //
+ // We cast both values to DWORD [uint32], perform subtraction to get a uint32,
+ // and then shove that into a TimeDelta.
+ //
+ // Note: Both measurements of time can experience rollover. If one of them has
+ // rolled over but the other has not, then the result will be very large.
+ // ClampDeltaFromExternalSource takes care of this, in addition to any other
+ // odd timing issues that may come up [e.g. MSG.time time-traveling to give a
+ // larger value than ::timeGetTime() -- this has not been observed in practice
+ // but since we don't control the code in question, we trust nothing].
+ base::TimeDelta delta = base::TimeDelta::FromMilliseconds(
+ ::GetTickCount() - static_cast<DWORD>(msg.time));
+ base::TimeDelta sanitized = ClampDeltaFromExternalSource(delta);
+ did_run_event_callback_.Run(&msg, base::TimeTicks::Now() - sanitized);
+}
+#endif // defined(OS_WIN)
+
+#if defined(OS_ANDROID) || defined(OS_FUCHSIA)
+void NativeEventObserver::RegisterObserver() {}
+void NativeEventObserver::DeregisterObserver() {}
+#endif // defined(OS_ANDROID) || defined(OS_FUCHSIA)
+
+} // namespace responsiveness
+} // namespace content
diff --git a/chromium/content/browser/scheduler/responsiveness/native_event_observer.h b/chromium/content/browser/scheduler/responsiveness/native_event_observer.h
new file mode 100644
index 00000000000..5aaefd3daf5
--- /dev/null
+++ b/chromium/content/browser/scheduler/responsiveness/native_event_observer.h
@@ -0,0 +1,99 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_SCHEDULER_RESPONSIVENESS_NATIVE_EVENT_OBSERVER_H_
+#define CONTENT_BROWSER_SCHEDULER_RESPONSIVENESS_NATIVE_EVENT_OBSERVER_H_
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "build/build_config.h"
+#include "content/common/content_export.h"
+
+#if defined(OS_MACOSX)
+#include "content/public/browser/native_event_processor_observer_mac.h"
+#endif
+
+#if defined(OS_LINUX)
+#include "ui/events/platform/platform_event_observer.h"
+#endif
+
+#if defined(OS_WIN)
+#include "base/message_loop/message_pump_win.h"
+#endif
+
+namespace content {
+namespace responsiveness {
+
+// This class must only be used from the UI thread.
+//
+// This class hooks itself into the native event processor for the platform and
+// forwards will_run/did_run callbacks to Watcher. Native events are processed
+// at different layers for each platform, so the interface for this class is
+// necessarily messy.
+//
+// On macOS, the hook should be in -[BrowserCrApplication sendEvent:].
+// On Linux, the hook should be in ui::PlatformEventSource::DispatchEvent.
+// On Windows, the hook should be in MessagePumpForUI::ProcessMessageHelper.
+// On Android, the hook should be in <TBD>.
+class CONTENT_EXPORT NativeEventObserver
+#if defined(OS_MACOSX)
+ : public NativeEventProcessorObserver
+#elif defined(OS_LINUX)
+ : public ui::PlatformEventObserver
+#elif defined(OS_WIN)
+ : public base::MessagePumpForUI::Observer
+#endif
+{
+ public:
+ using WillRunEventCallback =
+ base::RepeatingCallback<void(const void* opaque_identifier)>;
+
+ // |creation_time| refers to the time at which the native event was created.
+ using DidRunEventCallback =
+ base::RepeatingCallback<void(const void* opaque_identifier,
+ base::TimeTicks creation_time)>;
+
+ // The constructor will register the object as an observer of the native event
+ // processor. The destructor will unregister the object.
+ NativeEventObserver(WillRunEventCallback will_run_event_callback,
+ DidRunEventCallback did_run_event_callback);
+
+#if defined(OS_LINUX)
+ ~NativeEventObserver() override;
+#else
+ virtual ~NativeEventObserver();
+#endif
+
+ protected:
+#if defined(OS_MACOSX)
+ // NativeEventProcessorObserver overrides:
+ // Exposed for tests.
+ void WillRunNativeEvent(const void* opaque_identifier) override;
+ void DidRunNativeEvent(const void* opaque_identifier,
+ base::TimeTicks creation_time) override;
+#elif defined(OS_LINUX)
+ // PlatformEventObserver overrides:
+ // Exposed for tests.
+ void WillProcessEvent(const ui::PlatformEvent& event) override;
+ void DidProcessEvent(const ui::PlatformEvent& event) override;
+#elif defined(OS_WIN)
+ // base::MessagePumpForUI::Observer overrides:
+ void WillDispatchMSG(const MSG& msg) override;
+ void DidDispatchMSG(const MSG& msg) override;
+#endif
+
+ private:
+ void RegisterObserver();
+ void DeregisterObserver();
+
+ WillRunEventCallback will_run_event_callback_;
+ DidRunEventCallback did_run_event_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(NativeEventObserver);
+};
+
+} // namespace responsiveness
+} // namespace content
+
+#endif // CONTENT_BROWSER_SCHEDULER_RESPONSIVENESS_NATIVE_EVENT_OBSERVER_H_
diff --git a/chromium/content/browser/scheduler/responsiveness/native_event_observer_browsertest.mm b/chromium/content/browser/scheduler/responsiveness/native_event_observer_browsertest.mm
new file mode 100644
index 00000000000..e62074265b4
--- /dev/null
+++ b/chromium/content/browser/scheduler/responsiveness/native_event_observer_browsertest.mm
@@ -0,0 +1,72 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/scheduler/responsiveness/native_event_observer.h"
+
+#include "base/bind_helpers.h"
+#include "content/public/test/content_browser_test.h"
+#include "ui/events/test/cocoa_test_event_utils.h"
+
+#import <Carbon/Carbon.h>
+
+namespace content {
+namespace responsiveness {
+
+namespace {
+
+class FakeNativeEventObserver : public NativeEventObserver {
+ public:
+ FakeNativeEventObserver()
+ : NativeEventObserver(base::DoNothing(), base::DoNothing()) {}
+ ~FakeNativeEventObserver() override = default;
+
+ void WillRunNativeEvent(const void* opaque_identifier) override {
+ ASSERT_FALSE(will_run_id_);
+ will_run_id_ = opaque_identifier;
+ }
+ void DidRunNativeEvent(const void* opaque_identifier,
+ base::TimeTicks creation_time) override {
+ ASSERT_FALSE(did_run_id_);
+ did_run_id_ = opaque_identifier;
+ creation_time_ = creation_time;
+ }
+
+ const void* will_run_id() { return will_run_id_; }
+ const void* did_run_id() { return did_run_id_; }
+ base::TimeTicks creation_time() { return creation_time_; }
+
+ private:
+ const void* will_run_id_ = nullptr;
+ const void* did_run_id_ = nullptr;
+ base::TimeTicks creation_time_;
+};
+
+} // namespace
+
+class ResponsivenessNativeEventObserverBrowserTest : public ContentBrowserTest {
+};
+
+IN_PROC_BROWSER_TEST_F(ResponsivenessNativeEventObserverBrowserTest,
+ EventForwarding) {
+ FakeNativeEventObserver observer;
+
+ EXPECT_FALSE(observer.will_run_id());
+ EXPECT_FALSE(observer.did_run_id());
+ base::TimeTicks time_at_creation = base::TimeTicks::Now();
+ NSEvent* event = cocoa_test_event_utils::KeyEventWithKeyCode(kVK_Return, '\r',
+ NSKeyDown, 0);
+ [NSApp sendEvent:event];
+
+ EXPECT_EQ(observer.will_run_id(), event);
+ EXPECT_EQ(observer.did_run_id(), event);
+
+ // time_at_creation should be really similar to creation_time. As a sanity
+ // check, make sure they're within a second of each other.
+ EXPECT_LT(
+ fabs((observer.creation_time() - time_at_creation).InMilliseconds()),
+ 1000);
+}
+
+} // namespace responsiveness
+} // namespace content
diff --git a/chromium/content/browser/scheduler/responsiveness/native_event_observer_browsertest_win.cc b/chromium/content/browser/scheduler/responsiveness/native_event_observer_browsertest_win.cc
new file mode 100644
index 00000000000..426ec6ff5ee
--- /dev/null
+++ b/chromium/content/browser/scheduler/responsiveness/native_event_observer_browsertest_win.cc
@@ -0,0 +1,76 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/scheduler/responsiveness/native_event_observer.h"
+
+#include "base/bind_helpers.h"
+#include "base/win/message_window.h"
+#include "content/public/test/content_browser_test.h"
+
+namespace content {
+namespace responsiveness {
+
+namespace {
+
+bool HandleMessage(UINT message,
+ WPARAM wparam,
+ LPARAM lparam,
+ LRESULT* result) {
+ return false;
+}
+
+} // namespace
+
+class ResponsivenessNativeEventObserverBrowserTest : public ContentBrowserTest {
+ public:
+ void WillRunEvent(const void* opaque_id) {
+ ASSERT_FALSE(will_run_id_);
+ will_run_id_ = opaque_id;
+ }
+ void DidRunEvent(const void* opaque_id, base::TimeTicks creation_time) {
+ ASSERT_FALSE(did_run_id_);
+ did_run_id_ = opaque_id;
+ creation_time_ = creation_time;
+ std::move(quit_closure_).Run();
+ }
+
+ protected:
+ const void* will_run_id_ = nullptr;
+ const void* did_run_id_ = nullptr;
+ base::TimeTicks creation_time_;
+ base::OnceClosure quit_closure_;
+};
+
+IN_PROC_BROWSER_TEST_F(ResponsivenessNativeEventObserverBrowserTest,
+ EventForwarding) {
+ base::win::MessageWindow window;
+ EXPECT_TRUE(window.Create(base::BindRepeating(&HandleMessage)));
+
+ NativeEventObserver observer(
+ base::BindRepeating(
+ &ResponsivenessNativeEventObserverBrowserTest::WillRunEvent,
+ base::Unretained(this)),
+ base::BindRepeating(
+ &ResponsivenessNativeEventObserverBrowserTest::DidRunEvent,
+ base::Unretained(this)));
+ base::TimeTicks time_at_creation = base::TimeTicks::Now();
+
+ EXPECT_FALSE(will_run_id_);
+ EXPECT_FALSE(did_run_id_);
+
+ EXPECT_NE(PostMessage(window.hwnd(), WM_USER, 100, 0), 0);
+ base::RunLoop run_loop;
+ quit_closure_ = run_loop.QuitClosure();
+ run_loop.Run();
+
+ EXPECT_EQ(will_run_id_, did_run_id_);
+ EXPECT_NE(will_run_id_, nullptr);
+
+ // time_at_creation should be really similar to creation_time_. As a sanity
+ // check, make sure they're within a second of each other.
+ EXPECT_LT(fabs((creation_time_ - time_at_creation).InMilliseconds()), 1000);
+}
+
+} // namespace responsiveness
+} // namespace content
diff --git a/chromium/content/browser/scheduler/responsiveness/native_event_observer_mac.mm b/chromium/content/browser/scheduler/responsiveness/native_event_observer_mac.mm
new file mode 100644
index 00000000000..a074d87741d
--- /dev/null
+++ b/chromium/content/browser/scheduler/responsiveness/native_event_observer_mac.mm
@@ -0,0 +1,36 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/scheduler/responsiveness/native_event_observer.h"
+
+#import <AppKit/AppKit.h>
+
+#import "content/public/browser/native_event_processor_mac.h"
+
+namespace content {
+namespace responsiveness {
+
+void NativeEventObserver::RegisterObserver() {
+ DCHECK([NSApp conformsToProtocol:@protocol(NativeEventProcessor)]);
+ id<NativeEventProcessor> processor =
+ static_cast<id<NativeEventProcessor>>(NSApp);
+ [processor addNativeEventProcessorObserver:this];
+}
+void NativeEventObserver::DeregisterObserver() {
+ DCHECK([NSApp conformsToProtocol:@protocol(NativeEventProcessor)]);
+ id<NativeEventProcessor> processor =
+ static_cast<id<NativeEventProcessor>>(NSApp);
+ [processor removeNativeEventProcessorObserver:this];
+}
+
+void NativeEventObserver::WillRunNativeEvent(const void* opaque_identifier) {
+ will_run_event_callback_.Run(opaque_identifier);
+}
+void NativeEventObserver::DidRunNativeEvent(const void* opaque_identifier,
+ base::TimeTicks creation_time) {
+ did_run_event_callback_.Run(opaque_identifier, creation_time);
+}
+
+} // namespace responsiveness
+} // namespace content
diff --git a/chromium/content/browser/scheduler/responsiveness/watcher.cc b/chromium/content/browser/scheduler/responsiveness/watcher.cc
new file mode 100644
index 00000000000..2e61f5db182
--- /dev/null
+++ b/chromium/content/browser/scheduler/responsiveness/watcher.cc
@@ -0,0 +1,257 @@
+// 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/responsiveness/watcher.h"
+
+#include "base/pending_task.h"
+#include "content/browser/scheduler/responsiveness/calculator.h"
+#include "content/browser/scheduler/responsiveness/message_loop_observer.h"
+#include "content/browser/scheduler/responsiveness/native_event_observer.h"
+#include "content/public/browser/browser_thread.h"
+
+namespace content {
+namespace responsiveness {
+
+Watcher::Metadata::Metadata(const void* identifier) : identifier(identifier) {}
+
+Watcher::Watcher() {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+}
+
+void Watcher::SetUp() {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+ // Destroy() has the corresponding call to Release().
+ // We need this additional reference to make sure the object stays alive
+ // through hops to the IO thread, which are necessary both during construction
+ // and destruction.
+ AddRef();
+
+ calculator_ = CreateCalculator();
+ native_event_observer_ui_ = CreateNativeEventObserver();
+
+ RegisterMessageLoopObserverUI();
+
+ content::BrowserThread::PostTask(
+ content::BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&Watcher::SetUpOnIOThread, base::Unretained(this),
+ calculator_.get()));
+}
+
+void Watcher::Destroy() {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+ DCHECK(!destroy_was_called_);
+ destroy_was_called_ = true;
+
+ message_loop_observer_ui_.reset();
+ native_event_observer_ui_.reset();
+
+ content::BrowserThread::PostTask(
+ content::BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&Watcher::TearDownOnIOThread, base::Unretained(this)));
+}
+
+std::unique_ptr<Calculator> Watcher::CreateCalculator() {
+ return std::make_unique<Calculator>();
+}
+
+std::unique_ptr<NativeEventObserver> Watcher::CreateNativeEventObserver() {
+ NativeEventObserver::WillRunEventCallback will_run_callback =
+ base::BindRepeating(&Watcher::WillRunEventOnUIThread,
+ base::Unretained(this));
+ NativeEventObserver::DidRunEventCallback did_run_callback =
+ base::BindRepeating(&Watcher::DidRunEventOnUIThread,
+ base::Unretained(this));
+ return std::make_unique<NativeEventObserver>(std::move(will_run_callback),
+ std::move(did_run_callback));
+}
+
+Watcher::~Watcher() {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ DCHECK(destroy_was_called_);
+}
+
+void Watcher::RegisterMessageLoopObserverUI() {
+ // We must use base::Unretained(this) to prevent ownership cycle.
+ MessageLoopObserver::TaskCallback will_run_callback = base::BindRepeating(
+ &Watcher::WillRunTaskOnUIThread, base::Unretained(this));
+ MessageLoopObserver::TaskCallback did_run_callback = base::BindRepeating(
+ &Watcher::DidRunTaskOnUIThread, base::Unretained(this));
+ message_loop_observer_ui_.reset(new MessageLoopObserver(
+ std::move(will_run_callback), std::move(did_run_callback)));
+}
+
+void Watcher::RegisterMessageLoopObserverIO() {
+ // We must use base::Unretained(this) to prevent ownership cycle.
+ MessageLoopObserver::TaskCallback will_run_callback = base::BindRepeating(
+ &Watcher::WillRunTaskOnIOThread, base::Unretained(this));
+ MessageLoopObserver::TaskCallback did_run_callback = base::BindRepeating(
+ &Watcher::DidRunTaskOnIOThread, base::Unretained(this));
+ message_loop_observer_io_.reset(new MessageLoopObserver(
+ std::move(will_run_callback), std::move(did_run_callback)));
+}
+
+void Watcher::SetUpOnIOThread(Calculator* calculator) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+
+ RegisterMessageLoopObserverIO();
+ calculator_io_ = calculator;
+}
+
+void Watcher::TearDownOnIOThread() {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+
+ message_loop_observer_io_.reset();
+
+ calculator_io_ = nullptr;
+ content::BrowserThread::PostTask(
+ content::BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&Watcher::TearDownOnUIThread, base::Unretained(this)));
+}
+
+void Watcher::TearDownOnUIThread() {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+ // Corresponding call to AddRef() is in the constructor.
+ Release();
+}
+
+void Watcher::WillRunTaskOnUIThread(const base::PendingTask* task) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+ WillRunTask(task, &currently_running_metadata_ui_);
+}
+
+void Watcher::DidRunTaskOnUIThread(const base::PendingTask* task) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+ // It's safe to use base::Unretained since the callback will be synchronously
+ // invoked.
+ TaskOrEventFinishedCallback callback =
+ base::BindOnce(&Calculator::TaskOrEventFinishedOnUIThread,
+ base::Unretained(calculator_.get()));
+
+ DidRunTask(task, &currently_running_metadata_ui_,
+ &mismatched_task_identifiers_ui_, std::move(callback));
+}
+
+void Watcher::WillRunTaskOnIOThread(const base::PendingTask* task) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+
+ WillRunTask(task, &currently_running_metadata_io_);
+}
+
+void Watcher::DidRunTaskOnIOThread(const base::PendingTask* task) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+
+ // It's safe to use base::Unretained since the callback will be synchronously
+ // invoked.
+ TaskOrEventFinishedCallback callback =
+ base::BindOnce(&Calculator::TaskOrEventFinishedOnIOThread,
+ base::Unretained(calculator_io_));
+ DidRunTask(task, &currently_running_metadata_io_,
+ &mismatched_task_identifiers_io_, std::move(callback));
+}
+
+void Watcher::WillRunTask(const base::PendingTask* task,
+ std::stack<Metadata>* currently_running_metadata) {
+ // Reentrancy should be rare.
+ if (UNLIKELY(!currently_running_metadata->empty())) {
+ currently_running_metadata->top().caused_reentrancy = true;
+ }
+
+ currently_running_metadata->emplace(task);
+
+ // For delayed tasks, record the time right before the task is run.
+ if (!task->delayed_run_time.is_null()) {
+ currently_running_metadata->top().delayed_task_start =
+ base::TimeTicks::Now();
+ }
+}
+
+void Watcher::DidRunTask(const base::PendingTask* task,
+ std::stack<Metadata>* currently_running_metadata,
+ int* mismatched_task_identifiers,
+ TaskOrEventFinishedCallback callback) {
+ // Calls to DidRunTask should always be paired with WillRunTask. The only time
+ // the identifier should differ is when Watcher is first constructed. The
+ // TaskRunner Observers may be added while a task is being run, which means
+ // that there was no corresponding WillRunTask.
+ if (UNLIKELY(currently_running_metadata->empty() ||
+ (task != currently_running_metadata->top().identifier))) {
+ *mismatched_task_identifiers += 1;
+ DCHECK_LE(*mismatched_task_identifiers, 1);
+ return;
+ }
+
+ bool caused_reentrancy = currently_running_metadata->top().caused_reentrancy;
+ base::TimeTicks delayed_task_start =
+ currently_running_metadata->top().delayed_task_start;
+ currently_running_metadata->pop();
+
+ // Ignore tasks that caused reentrancy, since their execution latency will
+ // be very large, but Chrome was still responsive.
+ if (UNLIKELY(caused_reentrancy))
+ return;
+
+ // For delayed tasks, measure the duration of the task itself, rather than the
+ // duration from schedule time to finish time.
+ base::TimeTicks schedule_time;
+ if (delayed_task_start.is_null()) {
+ // Tasks which were posted before the MessageLoopObserver was created will
+ // not have a queue_time, and should be ignored. This doesn't affect delayed
+ // tasks.
+ if (UNLIKELY(!task->queue_time))
+ return;
+
+ schedule_time = task->queue_time.value();
+ } else {
+ schedule_time = delayed_task_start;
+ }
+
+ std::move(callback).Run(schedule_time, base::TimeTicks::Now());
+}
+
+void Watcher::WillRunEventOnUIThread(const void* opaque_identifier) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ // Reentrancy should be rare.
+ if (UNLIKELY(!currently_running_metadata_ui_.empty())) {
+ currently_running_metadata_ui_.top().caused_reentrancy = true;
+ }
+
+ currently_running_metadata_ui_.emplace(opaque_identifier);
+}
+
+void Watcher::DidRunEventOnUIThread(const void* opaque_identifier,
+ base::TimeTicks creation_time) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+ // Calls to DidRunEventOnUIThread should always be paired with
+ // WillRunEventOnUIThread. The only time the identifier should differ is when
+ // Watcher is first constructed. The TaskRunner Observers may be added while a
+ // task is being run, which means that there was no corresponding WillRunTask.
+ if (UNLIKELY(currently_running_metadata_ui_.empty() ||
+ (opaque_identifier !=
+ currently_running_metadata_ui_.top().identifier))) {
+ mismatched_event_identifiers_ui_ += 1;
+ DCHECK_LE(mismatched_event_identifiers_ui_, 1);
+ return;
+ }
+
+ bool caused_reentrancy =
+ currently_running_metadata_ui_.top().caused_reentrancy;
+ currently_running_metadata_ui_.pop();
+
+ // Ignore events that caused reentrancy, since their execution latency will
+ // be very large, but Chrome was still responsive.
+ if (UNLIKELY(caused_reentrancy))
+ return;
+
+ calculator_->TaskOrEventFinishedOnUIThread(creation_time,
+ base::TimeTicks::Now());
+}
+
+} // namespace responsiveness
+} // namespace content
diff --git a/chromium/content/browser/scheduler/responsiveness/watcher.h b/chromium/content/browser/scheduler/responsiveness/watcher.h
new file mode 100644
index 00000000000..0e6d3edfce7
--- /dev/null
+++ b/chromium/content/browser/scheduler/responsiveness/watcher.h
@@ -0,0 +1,156 @@
+// 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_RESPONSIVENESS_WATCHER_H_
+#define CONTENT_BROWSER_SCHEDULER_RESPONSIVENESS_WATCHER_H_
+
+#include <memory>
+#include <stack>
+
+#include "base/callback.h"
+#include "base/gtest_prod_util.h"
+#include "base/macros.h"
+#include "base/time/time.h"
+#include "content/common/content_export.h"
+
+namespace base {
+struct PendingTask;
+} // namespace base
+
+namespace content {
+namespace responsiveness {
+
+class Calculator;
+class MessageLoopObserver;
+class NativeEventObserver;
+
+// This class watches events and tasks processed on the UI and IO threads of the
+// browser process. It forwards stats on execution latency to Calculator, which
+// emits UMA metrics.
+//
+// This class must only be constructed/destroyed on the UI thread. It has some
+// private members that are affine to the IO thread. It takes care of deleting
+// them appropriately.
+//
+// TODO(erikchen): Once the browser scheduler is implemented, this entire class
+// should become simpler, as either BrowserUIThreadScheduler or
+// BrowserIOThreadScheduler should implement much of the same functionality.
+class CONTENT_EXPORT Watcher : public base::RefCounted<Watcher> {
+ public:
+ Watcher();
+
+ // Must be called immediately after the constructor. This cannot be called
+ // from the constructor because subclasses [for tests] need to be able to
+ // override functions.
+ void SetUp();
+
+ // Destruction requires a thread-hop to the IO thread, so cannot be completed
+ // synchronously. Owners of this class should call this method, and then
+ // release their reference.
+ void Destroy();
+
+ protected:
+ // Exposed for tests.
+ virtual std::unique_ptr<Calculator> CreateCalculator();
+ virtual std::unique_ptr<NativeEventObserver> CreateNativeEventObserver();
+ virtual ~Watcher();
+ virtual void RegisterMessageLoopObserverUI();
+ virtual void RegisterMessageLoopObserverIO();
+
+ private:
+ friend class base::RefCounted<Watcher>;
+ FRIEND_TEST_ALL_PREFIXES(ResponsivenessWatcherTest, TaskForwarding);
+ FRIEND_TEST_ALL_PREFIXES(ResponsivenessWatcherTest, TaskNesting);
+
+ // Metadata for currently running tasks and events is needed to track whether
+ // or not they caused reentrancy.
+ struct Metadata {
+ explicit Metadata(const void* identifier);
+
+ // An opaque identifier for the task or event.
+ const void* identifier = nullptr;
+
+ // Whether the task or event has caused reentrancy.
+ bool caused_reentrancy = false;
+
+ // For delayed tasks, the time at which the event is scheduled to run
+ // is only loosely coupled to the time that the task actually runs. The
+ // difference between these is not interesting for computing responsiveness.
+ // Instead of measuring the duration between |queue_time| and |finish_time|,
+ // we measure the duration of execution itself.
+ base::TimeTicks delayed_task_start;
+ };
+
+ void SetUpOnIOThread(Calculator*);
+ void TearDownOnIOThread();
+ void TearDownOnUIThread();
+
+ // These methods are called by the MessageLoopObserver of the UI thread to
+ // allow Watcher to collect metadata about the tasks being run.
+ void WillRunTaskOnUIThread(const base::PendingTask* task);
+ void DidRunTaskOnUIThread(const base::PendingTask* task);
+
+ // These methods are called by the MessageLoopObserver of the IO thread to
+ // allow Watcher to collect metadata about the tasks being run.
+ void WillRunTaskOnIOThread(const base::PendingTask* task);
+ void DidRunTaskOnIOThread(const base::PendingTask* task);
+
+ // Common implementations for the thread-specific methods.
+ void WillRunTask(const base::PendingTask* task,
+ std::stack<Metadata>* currently_running_metadata);
+
+ // |callback| will either be synchronously invoked, or else never invoked.
+ using TaskOrEventFinishedCallback =
+ base::OnceCallback<void(base::TimeTicks, base::TimeTicks)>;
+ void DidRunTask(const base::PendingTask* task,
+ std::stack<Metadata>* currently_running_metadata,
+ int* mismatched_task_identifiers,
+ TaskOrEventFinishedCallback callback);
+
+ // These methods are called by the NativeEventObserver of the UI thread to
+ // allow Watcher to collect metadata about the events being run.
+ void WillRunEventOnUIThread(const void* opaque_identifier);
+ void DidRunEventOnUIThread(const void* opaque_identifier,
+ base::TimeTicks creation_time);
+
+ // The following members are all affine to the UI thread.
+ std::unique_ptr<Calculator> calculator_;
+ std::unique_ptr<MessageLoopObserver> message_loop_observer_ui_;
+ std::unique_ptr<NativeEventObserver> native_event_observer_ui_;
+
+ // Metadata for currently running tasks and events on the UI thread.
+ std::stack<Metadata> currently_running_metadata_ui_;
+
+ // Task identifiers should only be mismatched once, since the Watcher may
+ // register itself during a Task execution, and thus doesn't capture the
+ // initial WillRunTask() callback.
+ int mismatched_task_identifiers_ui_ = 0;
+
+ // Event identifiers should be mismatched at most once, since the Watcher may
+ // register itself during an event execution, and thus doesn't capture the
+ // initial WillRunEventOnUIThread callback.
+ int mismatched_event_identifiers_ui_ = 0;
+
+ // The following members are all affine to the IO thread.
+ std::stack<Metadata> currently_running_metadata_io_;
+ int mismatched_task_identifiers_io_ = 0;
+ std::unique_ptr<MessageLoopObserver> message_loop_observer_io_;
+
+ // The implementation of this class guarantees that |calculator_io_| will be
+ // non-nullptr and point to a valid object any time it is used on the IO
+ // thread. To ensure this, the first task that this class posts onto the IO
+ // thread sets |calculator_io_|. On destruction, this class first tears down
+ // all consumers of |calculator_io_|, and then clears the member and destroys
+ // Calculator.
+ Calculator* calculator_io_ = nullptr;
+
+ bool destroy_was_called_ = false;
+
+ DISALLOW_COPY_AND_ASSIGN(Watcher);
+};
+
+} // namespace responsiveness
+} // namespace content
+
+#endif // CONTENT_BROWSER_SCHEDULER_RESPONSIVENESS_WATCHER_H_
diff --git a/chromium/content/browser/scheduler/responsiveness/watcher_unittest.cc b/chromium/content/browser/scheduler/responsiveness/watcher_unittest.cc
new file mode 100644
index 00000000000..c80be85babb
--- /dev/null
+++ b/chromium/content/browser/scheduler/responsiveness/watcher_unittest.cc
@@ -0,0 +1,236 @@
+// 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/responsiveness/watcher.h"
+
+#include "base/location.h"
+#include "base/pending_task.h"
+#include "base/run_loop.h"
+#include "base/synchronization/lock.h"
+#include "build/build_config.h"
+#include "content/browser/scheduler/responsiveness/calculator.h"
+#include "content/browser/scheduler/responsiveness/native_event_observer.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+namespace responsiveness {
+
+namespace {
+
+class FakeCalculator : public Calculator {
+ public:
+ void TaskOrEventFinishedOnUIThread(base::TimeTicks schedule_time,
+ base::TimeTicks finish_time) override {
+ queue_times_ui_.push_back(schedule_time);
+ }
+
+ void TaskOrEventFinishedOnIOThread(base::TimeTicks schedule_time,
+ base::TimeTicks finish_time) override {
+ base::AutoLock l(io_thread_lock_);
+ queue_times_io_.push_back(schedule_time);
+ }
+
+ int NumTasksOnUIThread() { return static_cast<int>(queue_times_ui_.size()); }
+ std::vector<base::TimeTicks>& QueueTimesUIThread() { return queue_times_ui_; }
+ int NumTasksOnIOThread() {
+ base::AutoLock l(io_thread_lock_);
+ return static_cast<int>(queue_times_io_.size());
+ }
+ std::vector<base::TimeTicks>& QueueTimesIOThread() {
+ base::AutoLock l(io_thread_lock_);
+ return queue_times_io_;
+ }
+
+ private:
+ std::vector<base::TimeTicks> queue_times_ui_;
+ base::Lock io_thread_lock_;
+ std::vector<base::TimeTicks> queue_times_io_;
+};
+
+class FakeWatcher : public Watcher {
+ public:
+ std::unique_ptr<Calculator> CreateCalculator() override {
+ std::unique_ptr<FakeCalculator> calculator =
+ std::make_unique<FakeCalculator>();
+ calculator_ = calculator.get();
+ return calculator;
+ }
+
+ std::unique_ptr<NativeEventObserver> CreateNativeEventObserver() override {
+ return nullptr;
+ }
+
+ void RegisterMessageLoopObserverUI() override {
+ if (register_message_loop_observer_)
+ Watcher::RegisterMessageLoopObserverUI();
+ }
+ void RegisterMessageLoopObserverIO() override {
+ if (register_message_loop_observer_)
+ Watcher::RegisterMessageLoopObserverIO();
+ }
+
+ FakeWatcher(bool register_message_loop_observer)
+ : Watcher(),
+ register_message_loop_observer_(register_message_loop_observer) {}
+
+ int NumTasksOnUIThread() { return calculator_->NumTasksOnUIThread(); }
+ std::vector<base::TimeTicks>& QueueTimesUIThread() {
+ return calculator_->QueueTimesUIThread();
+ }
+ std::vector<base::TimeTicks>& QueueTimesIOThread() {
+ return calculator_->QueueTimesIOThread();
+ }
+ int NumTasksOnIOThread() { return calculator_->NumTasksOnIOThread(); }
+
+ private:
+ ~FakeWatcher() override{};
+ FakeCalculator* calculator_ = nullptr;
+ bool register_message_loop_observer_ = false;
+};
+
+} // namespace
+
+class ResponsivenessWatcherTest : public testing::Test {
+ public:
+ void SetUp() override {
+ // Watcher's constructor posts a task to IO thread, which in the unit test
+ // is also this thread. Regardless, we need to let those tasks finish.
+ watcher_ = scoped_refptr<FakeWatcher>(
+ new FakeWatcher(/*register_message_loop_observer=*/false));
+ watcher_->SetUp();
+ test_browser_thread_bundle_.RunUntilIdle();
+ }
+
+ void TearDown() override {
+ watcher_->Destroy();
+ watcher_.reset();
+ }
+
+ protected:
+ // This member sets up BrowserThread::IO and BrowserThread::UI. It must be the
+ // first member, as other members may depend on these abstractions.
+ content::TestBrowserThreadBundle test_browser_thread_bundle_;
+
+ scoped_refptr<FakeWatcher> watcher_;
+};
+
+// Test that tasks are forwarded to calculator.
+TEST_F(ResponsivenessWatcherTest, TaskForwarding) {
+ for (int i = 0; i < 3; ++i) {
+ base::PendingTask task(FROM_HERE, base::OnceClosure());
+ task.queue_time = base::TimeTicks::Now();
+ watcher_->WillRunTaskOnUIThread(&task);
+ watcher_->DidRunTaskOnUIThread(&task);
+ }
+ EXPECT_EQ(3, watcher_->NumTasksOnUIThread());
+ EXPECT_EQ(0, watcher_->NumTasksOnIOThread());
+
+ for (int i = 0; i < 4; ++i) {
+ base::PendingTask task(FROM_HERE, base::OnceClosure());
+ task.queue_time = base::TimeTicks::Now();
+ watcher_->WillRunTaskOnIOThread(&task);
+ watcher_->DidRunTaskOnIOThread(&task);
+ }
+ EXPECT_EQ(3, watcher_->NumTasksOnUIThread());
+ EXPECT_EQ(4, watcher_->NumTasksOnIOThread());
+}
+
+// Test that nested tasks are not forwarded to the calculator.
+TEST_F(ResponsivenessWatcherTest, TaskNesting) {
+ base::TimeTicks now = base::TimeTicks::Now();
+
+ base::PendingTask task1(FROM_HERE, base::OnceClosure());
+ task1.queue_time = now + base::TimeDelta::FromMilliseconds(1);
+ base::PendingTask task2(FROM_HERE, base::OnceClosure());
+ task2.queue_time = now + base::TimeDelta::FromMilliseconds(2);
+ base::PendingTask task3(FROM_HERE, base::OnceClosure());
+ task3.queue_time = now + base::TimeDelta::FromMilliseconds(3);
+
+ watcher_->WillRunTaskOnUIThread(&task1);
+ watcher_->WillRunTaskOnUIThread(&task2);
+ watcher_->WillRunTaskOnUIThread(&task3);
+ watcher_->DidRunTaskOnUIThread(&task3);
+ watcher_->DidRunTaskOnUIThread(&task2);
+ watcher_->DidRunTaskOnUIThread(&task1);
+
+ ASSERT_EQ(1, watcher_->NumTasksOnUIThread());
+
+ // The innermost task should be the one that is passed through, as it didn't
+ // cause reentrancy.
+ EXPECT_EQ(now + base::TimeDelta::FromMilliseconds(3),
+ watcher_->QueueTimesUIThread()[0]);
+ EXPECT_EQ(0, watcher_->NumTasksOnIOThread());
+}
+
+class ResponsivenessWatcherRealIOThreadTest : public testing::Test {
+ public:
+ ResponsivenessWatcherRealIOThreadTest()
+ : test_browser_thread_bundle_(
+ content::TestBrowserThreadBundle::REAL_IO_THREAD) {}
+
+ void SetUp() override {
+ // Watcher's constructor posts a task to IO thread. We need to let those
+ // tasks finish.
+ watcher_ = scoped_refptr<FakeWatcher>(
+ new FakeWatcher(/*register_message_loop_observer=*/true));
+ watcher_->SetUp();
+ test_browser_thread_bundle_.RunIOThreadUntilIdle();
+ }
+
+ void TearDown() override {
+ watcher_->Destroy();
+ watcher_.reset();
+
+ // Destroy a task onto the IO thread, which posts back to the UI thread
+ // to complete destruction.
+ test_browser_thread_bundle_.RunIOThreadUntilIdle();
+ test_browser_thread_bundle_.RunUntilIdle();
+ }
+
+ protected:
+ // This member sets up BrowserThread::IO and BrowserThread::UI. It must be the
+ // first member, as other members may depend on these abstractions.
+ content::TestBrowserThreadBundle test_browser_thread_bundle_;
+
+ scoped_refptr<FakeWatcher> watcher_;
+};
+
+// Flaky on Linux TSAN. https://crbug.com/876561
+#if defined(OS_LINUX) && defined(THREAD_SANITIZER)
+#define MAYBE_MessageLoopObserver DISABLED_MessageLoopObserver
+#else
+#define MAYBE_MessageLoopObserver MessageLoopObserver
+#endif
+TEST_F(ResponsivenessWatcherRealIOThreadTest, MAYBE_MessageLoopObserver) {
+ // Post a do-nothing task onto the UI thread.
+ content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
+ base::BindOnce([]() {}));
+
+ // Post a do-nothing task onto the IO thread.
+ content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
+ base::BindOnce([]() {}));
+
+ // Post a task onto the IO thread that hops back to the UI thread. This
+ // guarantees that both of the do-nothing tasks have already been processed.
+ base::RunLoop run_loop;
+ content::BrowserThread::PostTask(
+ content::BrowserThread::IO, FROM_HERE,
+ base::BindOnce(
+ [](base::OnceClosure quit_closure) {
+ content::BrowserThread::PostTask(
+ content::BrowserThread::UI, FROM_HERE, std::move(quit_closure));
+ },
+ run_loop.QuitClosure()));
+ run_loop.Run();
+
+ ASSERT_GE(watcher_->NumTasksOnUIThread(), 1);
+ EXPECT_FALSE(watcher_->QueueTimesUIThread()[0].is_null());
+ ASSERT_GE(watcher_->NumTasksOnIOThread(), 1);
+ EXPECT_FALSE(watcher_->QueueTimesIOThread()[0].is_null());
+}
+
+} // namespace responsiveness
+} // namespace content
diff --git a/chromium/content/browser/security_exploit_browsertest.cc b/chromium/content/browser/security_exploit_browsertest.cc
index e3b04edb5a3..e9cb49ebc81 100644
--- a/chromium/content/browser/security_exploit_browsertest.cc
+++ b/chromium/content/browser/security_exploit_browsertest.cc
@@ -6,6 +6,7 @@
#include "base/command_line.h"
#include "base/containers/hash_tables.h"
+#include "base/feature_list.h"
#include "base/macros.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
@@ -14,7 +15,6 @@
#include "content/browser/dom_storage/session_storage_namespace_impl.h"
#include "content/browser/frame_host/navigator.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
-#include "content/browser/loader/resource_message_filter.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/renderer_host/render_view_host_factory.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
@@ -50,6 +50,7 @@
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/url_request/url_request_slow_download_job.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
+#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/network_switches.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/mojom/url_loader.mojom.h"
@@ -182,20 +183,6 @@ class SecurityExploitBrowserTest : public ContentBrowserTest {
base::BindOnce(&net::URLRequestSlowDownloadJob::AddUrlHandler));
}
- static void CreateLoaderAndStartOnIOThread(
- scoped_refptr<ResourceMessageFilter> filter,
- network::mojom::URLLoaderRequest request,
- int route_id,
- int request_id,
- const network::ResourceRequest& resource_request,
- network::mojom::URLLoaderClientPtrInfo client) {
- filter->CreateLoaderAndStart(
- std::move(request), route_id, request_id,
- network::mojom::kURLLoadOptionNone, resource_request,
- network::mojom::URLLoaderClientPtr(std::move(client)),
- net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
- }
-
static void CreateLoaderAndStart(
RenderProcessHost* process,
int route_id,
@@ -215,13 +202,13 @@ class SecurityExploitBrowserTest : public ContentBrowserTest {
int request_id,
const network::ResourceRequest& resource_request,
network::mojom::URLLoaderClientPtrInfo client) {
- RenderProcessHostImpl* impl = static_cast<RenderProcessHostImpl*>(process);
- auto filter = impl->resource_message_filter_;
-
- process->GetChannel()->ipc_task_runner()->PostTask(
- FROM_HERE, base::BindOnce(CreateLoaderAndStartOnIOThread, filter,
- std::move(request), route_id, request_id,
- resource_request, std::move(client)));
+ network::mojom::URLLoaderFactoryPtr factory;
+ process->CreateURLLoaderFactory(mojo::MakeRequest(&factory));
+ factory->CreateLoaderAndStart(
+ std::move(request), route_id, request_id,
+ network::mojom::kURLLoadOptionNone, resource_request,
+ network::mojom::URLLoaderClientPtr(std::move(client)),
+ net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
}
void TryCreateDuplicateRequestIds(Shell* shell, bool block_loaders) {
@@ -467,6 +454,10 @@ void OnHttpHeaderReceived(const std::string& header,
// Renderer processes should not be able to spoof Origin HTTP headers.
IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, InvalidOriginHeaders) {
+ // https://crbug.com/862176
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService))
+ return;
+
// Create a set of IPC messages with various Origin headers.
network::ResourceRequest chrome_origin_msg(
CreateXHRRequestWithOrigin("chrome://settings"));
@@ -529,11 +520,21 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, InvalidOriginHeaders) {
// Renderer process should not be able to create multiple requests with the same
// id.
IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, InvalidRequestId) {
+ // This test is specific to the ResourceDispatcherHost implementation, which
+ // is not used with network service enabled.
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService))
+ return;
+
// Existing loader in pending_loaders_.
TryCreateDuplicateRequestIds(shell(), false);
}
IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, InvalidBlockedRequestId) {
+ // This test is specific to the ResourceDispatcherHost implementation, which
+ // is not used with network service enabled.
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService))
+ return;
+
// Existing loader in blocked_loaders_map_.
TryCreateDuplicateRequestIds(shell(), true);
}
@@ -623,13 +624,18 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
EXPECT_TRUE(NavigateToURL(shell(), start_url));
- RenderProcessHostKillWaiter kill_waiter(
- shell()->web_contents()->GetMainFrame()->GetProcess());
+ RenderFrameHostImpl* frame = static_cast<RenderFrameHostImpl*>(
+ shell()->web_contents()->GetMainFrame());
+ RenderProcessHostKillWaiter kill_waiter(frame->GetProcess());
ScopedInterfaceProviderRequestReplacer replacer(shell()->web_contents(),
nullptr);
NavigateToURLAndExpectNoCommit(shell(), non_same_document_url);
EXPECT_EQ(bad_message::RFH_INTERFACE_PROVIDER_MISSING, kill_waiter.Wait());
+
+ // Verify that the death of the renderer process doesn't leave behing and leak
+ // NavigationRequests - see https://crbug.com/869193.
+ EXPECT_EQ(0u, frame->GetNavigationEntryIdsPendingCommit().size());
}
// Test that a compromised renderer cannot ask to upload an arbitrary file in
@@ -648,7 +654,7 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
root->current_frame_host()->GetProcess());
// Prepare a file to upload.
- base::ThreadRestrictions::ScopedAllowIO allow_io_for_temp_dir;
+ base::ScopedAllowBlockingForTesting allow_blocking;
base::ScopedTempDir temp_dir;
base::FilePath file_path;
std::string file_content("test-file-content");
diff --git a/chromium/content/browser/service_manager/common_browser_interfaces.cc b/chromium/content/browser/service_manager/common_browser_interfaces.cc
index ea58b9e3599..f537f90fa48 100644
--- a/chromium/content/browser/service_manager/common_browser_interfaces.cc
+++ b/chromium/content/browser/service_manager/common_browser_interfaces.cc
@@ -11,12 +11,13 @@
#include "base/callback.h"
#include "base/command_line.h"
#include "base/memory/ref_counted.h"
+#include "base/task/post_task.h"
#include "base/task_runner.h"
-#include "base/task_scheduler/post_task.h"
#include "build/build_config.h"
#include "components/discardable_memory/service/discardable_shared_memory_manager.h"
+#include "components/viz/host/gpu_client.h"
#include "content/browser/browser_main_loop.h"
-#include "content/browser/gpu/gpu_client_impl.h"
+#include "content/browser/gpu/browser_gpu_client_delegate.h"
#include "content/common/child_process_host_impl.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/connection_filter.h"
@@ -24,7 +25,7 @@
#include "content/public/common/service_names.mojom.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "services/service_manager/public/cpp/binder_registry.h"
-#include "services/ui/public/interfaces/gpu.mojom.h"
+#include "services/ws/public/mojom/gpu.mojom.h"
#include "ui/base/ui_base_features.h"
#if defined(OS_WIN)
@@ -50,7 +51,7 @@ class ConnectionFilterImpl : public ConnectionFilter {
#elif defined(OS_MACOSX)
registry_.AddInterface(base::BindRepeating(&FontLoaderDispatcher::Create));
#endif
- if (features::IsAshInBrowserProcess()) {
+ if (!features::IsUsingWindowService()) {
// 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();
@@ -62,8 +63,6 @@ class ConnectionFilterImpl : public ConnectionFilter {
base::Unretained(manager)));
}
}
- }
- if (features::IsAshInBrowserProcess()) {
registry_.AddInterface(base::BindRepeating(
&ConnectionFilterImpl::BindGpuRequest, base::Unretained(this)));
}
@@ -82,16 +81,16 @@ class ConnectionFilterImpl : public ConnectionFilter {
const std::string& interface_name,
mojo::ScopedMessagePipeHandle* interface_pipe,
service_manager::Connector* connector) override {
- // Ignore ui::mojom::Gpu interface request from Renderer process.
+ // Ignore ws::mojom::Gpu interface request from Renderer process.
// The request will be handled in RenderProcessHostImpl.
if (source_info.identity.name() == mojom::kRendererServiceName &&
- interface_name == ui::mojom::Gpu::Name_)
+ interface_name == ws::mojom::Gpu::Name_)
return;
registry_.TryBindInterface(interface_name, interface_pipe, source_info);
}
- void BindGpuRequest(ui::mojom::GpuRequest request,
+ void BindGpuRequest(ws::mojom::GpuRequest request,
const service_manager::BindSourceInfo& source_info) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -104,8 +103,9 @@ class ConnectionFilterImpl : public ConnectionFilter {
const uint64_t gpu_client_tracing_id =
ChildProcessHostImpl::ChildProcessUniqueIdToTracingProcessId(
gpu_client_id);
- auto gpu_client = std::make_unique<GpuClientImpl>(
- gpu_client_id, gpu_client_tracing_id,
+ auto gpu_client = std::make_unique<viz::GpuClient>(
+ std::make_unique<BrowserGpuClientDelegate>(), gpu_client_id,
+ gpu_client_tracing_id,
BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
gpu_client->SetConnectionErrorHandler(
base::BindOnce(&ConnectionFilterImpl::OnGpuConnectionClosed,
@@ -115,7 +115,7 @@ class ConnectionFilterImpl : public ConnectionFilter {
}
void OnGpuConnectionClosed(const service_manager::Identity& service_identity,
- GpuClient* client) {
+ viz::GpuClient* client) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
gpu_clients_.erase(service_identity);
}
@@ -133,7 +133,7 @@ class ConnectionFilterImpl : public ConnectionFilter {
service_manager::BinderRegistryWithArgs<
const service_manager::BindSourceInfo&>
registry_;
- std::map<service_manager::Identity, std::unique_ptr<GpuClientImpl>>
+ std::map<service_manager::Identity, std::unique_ptr<viz::GpuClient>>
gpu_clients_;
DISALLOW_COPY_AND_ASSIGN(ConnectionFilterImpl);
diff --git a/chromium/content/browser/service_manager/service_manager_context.cc b/chromium/content/browser/service_manager/service_manager_context.cc
index 2daaf7231c0..f35734b66d0 100644
--- a/chromium/content/browser/service_manager/service_manager_context.cc
+++ b/chromium/content/browser/service_manager/service_manager_context.cc
@@ -23,7 +23,7 @@
#include "base/process/process_handle.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "build/build_config.h"
#include "content/app/strings/grit/content_strings.h"
#include "content/browser/browser_main_loop.h"
@@ -100,6 +100,13 @@
#include "components/services/font/public/interfaces/constants.mojom.h"
#endif
+#if defined(OS_CHROMEOS)
+#include "chromeos/assistant/buildflags.h" // nogncheck
+#if BUILDFLAG(ENABLE_CROS_LIBASSISTANT)
+#include "chromeos/services/assistant/public/mojom/constants.mojom.h" // nogncheck
+#endif // BUILDFLAG(ENABLE_CROS_LIBASSISTANT)
+#endif
+
namespace content {
namespace {
@@ -298,7 +305,7 @@ class ServiceBinaryLauncherFactory
bool ShouldEnableVizService() {
#if defined(USE_AURA)
// aura::Env can be null in tests.
- return aura::Env::GetInstanceDontCreate() &&
+ return aura::Env::HasInstance() &&
aura::Env::GetInstance()->mode() == aura::Env::Mode::MUS;
#else
return false;
@@ -508,7 +515,7 @@ ServiceManagerContext::ServiceManagerContext(
// affinity on the clients. We therefore require a single-thread runner.
scoped_refptr<base::SingleThreadTaskRunner> device_blocking_task_runner =
base::CreateSingleThreadTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BACKGROUND});
+ {base::MayBlock(), base::TaskPriority::BEST_EFFORT});
#if defined(OS_ANDROID)
JNIEnv* env = base::android::AttachCurrentThread();
@@ -567,7 +574,7 @@ ServiceManagerContext::ServiceManagerContext(
base::CreateSingleThreadTaskRunnerWithTraits(
#endif
base::TaskTraits({base::MayBlock(), base::WithBaseSyncPrimitives(),
- base::TaskPriority::BACKGROUND}),
+ base::TaskPriority::BEST_EFFORT}),
base::SingleThreadTaskRunnerThreadMode::DEDICATED);
packaged_services_connection_->AddEmbeddedService(
video_capture::mojom::kServiceName, video_capture_info);
@@ -666,6 +673,15 @@ ServiceManagerContext::ServiceManagerContext(
&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 (ShouldEnableVizService()) {
out_of_process_services[viz::mojom::kVizServiceName] =
base::BindRepeating(&base::ASCIIToUTF16, "Visuals Service");
@@ -721,7 +737,7 @@ bool ServiceManagerContext::HasValidProcessForProcessGroup(
auto iter = g_active_process_groups.Get().find(process_group_name);
if (iter == g_active_process_groups.Get().end() || !iter->second)
return false;
- return iter->second->GetData().handle != base::kNullProcessHandle;
+ return iter->second->GetData().IsHandleValid();
}
// static
diff --git a/chromium/content/browser/service_worker/README.md b/chromium/content/browser/service_worker/README.md
index 55d7fb79b43..c0550d31bc2 100644
--- a/chromium/content/browser/service_worker/README.md
+++ b/chromium/content/browser/service_worker/README.md
@@ -3,18 +3,28 @@
[content/renderer/service_worker]: /content/renderer/service_worker
[content/renderer/service_worker]: /content/renderer/service_worker
[content/common/service_worker]: /content/common/service_worker
+[disk_cache]: /net/disk_cache/README.md
+[embedded_worker.mojom]: https://codesearch.chromium.org/chromium/src/content/common/service_worker/embedded_worker.mojom
+[service_worker_container.mojom]: https://codesearch.chromium.org/chromium/src/content/common/service_worker/service_worker_container.mojom
+[service_worker_database.h]: https://codesearch.chromium.org/chromium/src/content/browser/service_worker/service_worker_database.h
[third_party/blink/common/service_worker]: /third_party/blink/common/service_worker
[third_party/blink/public/common/service_worker]: /third_party/blink/public/common/service_worker
[third_party/blink/public/mojom/service_worker]: /third_party/blink/public/mojom/service_worker
[third_party/blink/public/platform/modules/service_worker]: /third_party/blink/public/platform/modules/service_worker
[third_party/blink/public/web/modules/service_worker]: /third_party/blink/public/web/modules/service_worker
[third_party/blink/renderer/modules/service_worker]: /third_party/blink/renderer/modules/service_worker
-[Blink Public API]: /third_party/blink/public
+[Blink Public API]: /third_party/blink/public/README.md
+[Cache Storage API]: /content/browser/cache_storage/README.md
+[LevelDB]: /third_party/leveldatabase/README.chromium
[Onion Soup]: https://docs.google.com/document/d/1K1nO8G9dO9kNSmtVz2gJ2GG9gQOTgm65sJlV3Fga4jE/edit?usp=sharing
+[Quota Manager]: /storage/browser/quota
+[ServiceWorkerDatabase]: https://codesearch.chromium.org/chromium/src/content/browser/service_worker/service_worker_database.h
+[ServiceWorkerStorage]: https://codesearch.chromium.org/chromium/src/content/browser/service_worker/service_worker_storage.h
+[Service Worker specification]: https://w3c.github.io/ServiceWorker/
This is Chromium's implementation of [service
-workers](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API). See the
-[Service Worker specification](https://w3c.github.io/ServiceWorker/).
+workers](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API).
+See the [Service Worker specification].
## Directory structure
@@ -27,7 +37,7 @@ workers](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API). S
third_party/blink per [Onion Soup].
- [content/common/service_worker]: Common process code.
- [third_party/blink/common/service_worker]: Common process code. Contains the
- implementation of third_party/blink/public/common/service_worker.
+ implementation of [third_party/blink/public/common/service_worker].
- [third_party/blink/public/common/service_worker]: Header files for common
process code that can be used by both inside Blink and outside Blink.
- [third_party/blink/public/mojom/service_worker]: Mojom files for common
@@ -39,6 +49,73 @@ workers](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API). S
- [third_party/blink/renderer/modules/service_worker]: Renderer process code in
Blink. This is the closest code to the web-exposed Service Worker API.
+## Storage
+
+Service worker storage consists of the following.
+- **Service worker registration metadata** is stored in a [LevelDB] instance
+ located at ${DIR_USER_DATA}/Service Worker/Database.
+- **Service worker scripts** are stored in a [disk_cache] instance using the
+ "simple" implementation, located at ${DIR_USER_DATA}/Service
+ Worker/ScriptCache. Registration metadata points to these scripts.
+
+Code pointers include [ServiceWorkerDatabase] and [ServiceWorkerStorage].
+
+The related [Cache Storage API] uses a [disk_cache] instance using the "simple"
+implementation, located at ${DIR_USER_DATA}/Service Worker/CacheStorage. This
+location was chosen because the [Cache Storage API] is currently defined in the
+[Service Worker specification], but it can be used independently of service
+workers.
+
+For incognito windows, everything is in-memory.
+
+### Eviction
+
+Service workers storage lasts indefinitely, i.e, there is no periodic deletion
+of old but still installed service workers. Installed service workers are only
+evicted by the [Quota Manager] (or user action). The Quota Manager controls
+several web platform APIs, including sandboxed filesystem, WebSQL, appcache,
+IndexedDB, cache storage, service worker (registration and scripts), and
+background fetch.
+
+The Quota Manager starts eviction when one of the following conditions is true
+(as of August 2018):
+- **The global pool is full**: Chrome is using > 1/3 of the disk (>2/3 on CrOS).
+- **The system is critically low on space**: the disk has < min(1GB,1%) free
+ (regardless of how much Chrome is contributing!)
+
+When eviction starts, origins are purged on an LRU basis until the triggering
+condition no longer applies. Purging an origin deletes its storage completely.
+
+Note that Quota Manager eviction is independent of HTTP cache eviction. The
+HTTP cache is typically much smaller than the storage under the control of the
+Quota Manager, and it likely uses a simple non-origin-based LRU algorithm.
+
+## UseCounter integration
+
+Blink has a UseCounter mechanism intended to measure the percentage of page
+loads on the web that used a given feature. Service workers complicate this
+measurement because a feature use in a service worker potentially affects many
+page loads, including ones in the future.
+
+Therefore, service workers integrate with the UseCounter mechanism as follows:
+- **If a feature use occurs before the service worker finished installing**, it
+is recorded in storage along with the service worker. Any page thereafter that
+the service worker controls is counted as using the feature.
+- **If a feature use occurs after the service worker finished installing**, all
+currently controlled pages are counted as using the feature.
+
+For more details and rationale, see [Design of UseCounter for
+workers](https://docs.google.com/document/d/1VyYZnhjBdk-MzCRAcX37TM5-yjwTY40U_J9rWnEAo8c/edit?usp=sharing)
+and [crbug 376039](https://bugs.chromium.org/p/chromium/issues/detail?id=376039).
+
+Code pointers include:
+- (Browser -> Page) ServiceWorkerContainer.SetController and
+ServiceWorkerContainer.CountFeature in [service_worker_container.mojom].
+- (Service worker -> Browser) EmbeddedWorkerInstanceHost.CountFeature
+in [embedded_worker.mojom].
+- (Persistence) ServiceWorkerDatabase::RegistrationData::used_features
+in [service_worker_database.h].
+
## Other documentation
- [Service Worker Security FAQ](/docs/security/service-worker-security-faq.md)
diff --git a/chromium/content/browser/service_worker/embedded_worker_instance.cc b/chromium/content/browser/service_worker/embedded_worker_instance.cc
index 7e3365820e3..597aba71671 100644
--- a/chromium/content/browser/service_worker/embedded_worker_instance.cc
+++ b/chromium/content/browser/service_worker/embedded_worker_instance.cc
@@ -29,6 +29,7 @@
#include "content/public/common/child_process_host.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
+#include "content/public/common/renderer_preference_watcher.mojom.h"
#include "ipc/ipc_message.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "third_party/blink/public/common/features.h"
@@ -78,18 +79,60 @@ void NotifyWorkerVersionDoomedOnUI(int worker_process_id, int worker_route_id) {
worker_process_id, worker_route_id);
}
+std::unique_ptr<URLLoaderFactoryBundleInfo> CreateFactoryBundle(
+ RenderProcessHost* rph,
+ bool use_non_network_factories) {
+ auto factory_bundle = std::make_unique<URLLoaderFactoryBundleInfo>();
+ network::mojom::URLLoaderFactoryPtrInfo default_factory_info;
+ rph->CreateURLLoaderFactory(mojo::MakeRequest(&default_factory_info));
+ factory_bundle->default_factory_info() = std::move(default_factory_info);
+
+ if (use_non_network_factories) {
+ ContentBrowserClient::NonNetworkURLLoaderFactoryMap factories;
+ GetContentClient()
+ ->browser()
+ ->RegisterNonNetworkSubresourceURLLoaderFactories(
+ rph->GetID(), MSG_ROUTING_NONE, &factories);
+
+ for (auto& pair : factories) {
+ const std::string& scheme = pair.first;
+ std::unique_ptr<network::mojom::URLLoaderFactory> factory =
+ std::move(pair.second);
+
+ // To be safe, ignore schemes that aren't allowed to register service
+ // workers. We assume that importScripts should fail on such schemes.
+ if (!base::ContainsValue(GetServiceWorkerSchemes(), scheme))
+ continue;
+ network::mojom::URLLoaderFactoryPtr factory_ptr;
+ mojo::MakeStrongBinding(std::move(factory),
+ mojo::MakeRequest(&factory_ptr));
+ factory_bundle->factories_info().emplace(scheme,
+ factory_ptr.PassInterface());
+ }
+ }
+ return factory_bundle;
+}
+
using SetupProcessCallback = base::OnceCallback<void(
blink::ServiceWorkerStatusCode,
mojom::EmbeddedWorkerStartParamsPtr,
std::unique_ptr<ServiceWorkerProcessManager::AllocatedProcessInfo>,
std::unique_ptr<EmbeddedWorkerInstance::DevToolsProxy>,
- std::unique_ptr<URLLoaderFactoryBundleInfo>,
+ std::unique_ptr<
+ URLLoaderFactoryBundleInfo> /* factory_bundle_for_browser */,
+ std::unique_ptr<
+ URLLoaderFactoryBundleInfo> /* factory_bundle_for_renderer */,
blink::mojom::CacheStoragePtrInfo)>;
// Allocates a renderer process for starting a worker and does setup like
// registering with DevTools. Called on the UI thread. Calls |callback| on the
// IO thread. |context| and |weak_context| are only for passing to DevTools and
// must not be dereferenced here on the UI thread.
+// S13nServiceWorker:
+// This also sets up two URLLoaderFactoryBundles, one for
+// ServiceWorkerScriptLoaderFactory and the other is for passing to the
+// renderer. These bundles include factories for non-network URLs like
+// chrome-extension:// as needed.
void SetupOnUIThread(base::WeakPtr<ServiceWorkerProcessManager> process_manager,
bool can_use_existing_process,
mojom::EmbeddedWorkerStartParamsPtr params,
@@ -101,16 +144,18 @@ void SetupOnUIThread(base::WeakPtr<ServiceWorkerProcessManager> process_manager,
auto process_info =
std::make_unique<ServiceWorkerProcessManager::AllocatedProcessInfo>();
std::unique_ptr<EmbeddedWorkerInstance::DevToolsProxy> devtools_proxy;
- std::unique_ptr<URLLoaderFactoryBundleInfo> factory_bundle;
+ std::unique_ptr<URLLoaderFactoryBundleInfo> factory_bundle_for_browser;
+ std::unique_ptr<URLLoaderFactoryBundleInfo> factory_bundle_for_renderer;
if (!process_manager) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::BindOnce(std::move(callback),
- blink::ServiceWorkerStatusCode::kErrorAbort,
- std::move(params), std::move(process_info),
- std::move(devtools_proxy), std::move(factory_bundle),
- nullptr /* cache_storage */));
+ base::BindOnce(
+ std::move(callback), blink::ServiceWorkerStatusCode::kErrorAbort,
+ std::move(params), std::move(process_info),
+ std::move(devtools_proxy), std::move(factory_bundle_for_browser),
+ std::move(factory_bundle_for_renderer),
+ nullptr /* cache_storage */));
return;
}
@@ -124,7 +169,9 @@ void SetupOnUIThread(base::WeakPtr<ServiceWorkerProcessManager> process_manager,
BrowserThread::IO, FROM_HERE,
base::BindOnce(std::move(callback), status, std::move(params),
std::move(process_info), std::move(devtools_proxy),
- std::move(factory_bundle), nullptr /* cache_storage */));
+ std::move(factory_bundle_for_browser),
+ std::move(factory_bundle_for_renderer),
+ nullptr /* cache_storage */));
return;
}
const int process_id = process_info->process_id;
@@ -162,40 +209,16 @@ void SetupOnUIThread(base::WeakPtr<ServiceWorkerProcessManager> process_manager,
// since it's used for a single service worker startup until installation
// finishes (with the exception of https://crbug.com/719052).
if (blink::ServiceWorkerUtils::IsServicificationEnabled()) {
- network::mojom::URLLoaderFactoryPtrInfo default_factory_info;
- rph->CreateURLLoaderFactory(mojo::MakeRequest(&default_factory_info));
- factory_bundle = std::make_unique<URLLoaderFactoryBundleInfo>();
- factory_bundle->default_factory_info() = std::move(default_factory_info);
- }
-
- // S13nServiceWorker:
- // Create the loader factories for non-http(s) URLs, for example
- // chrome-extension:// URLs. For performance, only do this step when the main
- // script URL is non-http(s). We assume an http(s) service worker cannot
- // importScripts a non-http(s) URL.
- if (blink::ServiceWorkerUtils::IsServicificationEnabled() &&
- !params->script_url.SchemeIsHTTPOrHTTPS()) {
- ContentBrowserClient::NonNetworkURLLoaderFactoryMap factories;
- GetContentClient()
- ->browser()
- ->RegisterNonNetworkSubresourceURLLoaderFactories(
- rph->GetID(), MSG_ROUTING_NONE, &factories);
-
- for (auto& pair : factories) {
- const std::string& scheme = pair.first;
- std::unique_ptr<network::mojom::URLLoaderFactory> factory =
- std::move(pair.second);
-
- // To be safe, ignore schemes that aren't allowed to register service
- // workers. We assume that importScripts should fail on such schemes.
- if (!base::ContainsValue(GetServiceWorkerSchemes(), scheme))
- continue;
- network::mojom::URLLoaderFactoryPtr factory_ptr;
- mojo::MakeStrongBinding(std::move(factory),
- mojo::MakeRequest(&factory_ptr));
- factory_bundle->factories_info().emplace(scheme,
- factory_ptr.PassInterface());
- }
+ // For performance, we only create the loader factories for non-http(s)
+ // URLs (e.g. chrome-extension://) when the main script URL is
+ // non-http(s). We assume an http(s) service worker cannot
+ // importScripts a non-http(s) URL.
+ bool use_non_network_factories = !params->script_url.SchemeIsHTTPOrHTTPS();
+
+ factory_bundle_for_browser =
+ CreateFactoryBundle(rph, use_non_network_factories);
+ factory_bundle_for_renderer =
+ CreateFactoryBundle(rph, use_non_network_factories);
}
// Register to DevTools and update params accordingly.
@@ -218,12 +241,20 @@ void SetupOnUIThread(base::WeakPtr<ServiceWorkerProcessManager> process_manager,
GetContentClient()->browser()->UpdateRendererPreferencesForWorker(
process_manager->browser_context(), &params->renderer_preferences);
+ // Create a RendererPreferenceWatcher to observe updates in the preferences.
+ mojom::RendererPreferenceWatcherPtr watcher_ptr;
+ params->preference_watcher_request = mojo::MakeRequest(&watcher_ptr);
+ GetContentClient()->browser()->RegisterRendererPreferenceWatcherForWorkers(
+ process_manager->browser_context(), std::move(watcher_ptr));
+
// Continue to OnSetupCompleted on the IO thread.
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(std::move(callback), status, std::move(params),
std::move(process_info), std::move(devtools_proxy),
- std::move(factory_bundle), cache_storage.PassInterface()));
+ std::move(factory_bundle_for_browser),
+ std::move(factory_bundle_for_renderer),
+ cache_storage.PassInterface()));
}
bool HasSentStartWorker(EmbeddedWorkerInstance::StartingPhase phase) {
@@ -463,7 +494,8 @@ class EmbeddedWorkerInstance::StartTask {
std::unique_ptr<ServiceWorkerProcessManager::AllocatedProcessInfo>
process_info,
std::unique_ptr<EmbeddedWorkerInstance::DevToolsProxy> devtools_proxy,
- std::unique_ptr<URLLoaderFactoryBundleInfo> factory_bundle,
+ std::unique_ptr<URLLoaderFactoryBundleInfo> factory_bundle_for_browser,
+ std::unique_ptr<URLLoaderFactoryBundleInfo> factory_bundle_for_renderer,
blink::mojom::CacheStoragePtrInfo cache_storage) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -512,9 +544,15 @@ class EmbeddedWorkerInstance::StartTask {
// S13nServiceWorker: Build the URLLoaderFactory for loading new scripts.
scoped_refptr<network::SharedURLLoaderFactory> factory_for_new_scripts;
if (blink::ServiceWorkerUtils::IsServicificationEnabled()) {
- DCHECK(factory_bundle);
+ DCHECK(factory_bundle_for_browser);
factory_for_new_scripts = base::MakeRefCounted<URLLoaderFactoryBundle>(
- std::move(factory_bundle));
+ std::move(factory_bundle_for_browser));
+
+ // Send the factory bundle for subresource loading from the service worker
+ // (i.e. fetch()).
+ DCHECK(factory_bundle_for_renderer);
+ params->subresource_loader_factories =
+ std::move(factory_bundle_for_renderer);
}
instance_->SendStartWorker(std::move(params),
@@ -720,11 +758,13 @@ void EmbeddedWorkerInstance::SendStartWorker(
observer.OnStartWorkerMessageSent();
}
-void EmbeddedWorkerInstance::RequestTermination() {
+void EmbeddedWorkerInstance::RequestTermination(
+ RequestTerminationCallback callback) {
if (!blink::ServiceWorkerUtils::IsServicificationEnabled()) {
mojo::ReportBadMessage(
"Invalid termination request: RequestTermination() was called but "
"S13nServiceWorker is not enabled");
+ std::move(callback).Run(true /* will_be_terminated */);
return;
}
@@ -733,12 +773,19 @@ void EmbeddedWorkerInstance::RequestTermination() {
mojo::ReportBadMessage(
"Invalid termination request: Termination should be requested during "
"running or stopping");
+ std::move(callback).Run(true /* will_be_terminated */);
return;
}
- if (status() == EmbeddedWorkerStatus::STOPPING)
+ if (status() == EmbeddedWorkerStatus::STOPPING) {
+ std::move(callback).Run(true /* will_be_terminated */);
return;
+ }
owner_version_->StopWorkerIfIdle(true /* requested_from_renderer */);
+
+ // If DevTools is attached and the worker won't be stopped, the worker needs
+ // to continue to work.
+ std::move(callback).Run(status() != EmbeddedWorkerStatus::RUNNING);
}
void EmbeddedWorkerInstance::CountFeature(blink::mojom::WebFeature feature) {
@@ -913,7 +960,7 @@ void EmbeddedWorkerInstance::SetDevToolsAttached(bool attached) {
return;
if (inflight_start_task_)
inflight_start_task_->set_skip_recording_startup_time();
- registry_->OnDevToolsAttached(embedded_worker_id_);
+ registry_->AbortLifetimeTracking(embedded_worker_id_);
}
void EmbeddedWorkerInstance::OnNetworkAccessedForScriptLoad() {
diff --git a/chromium/content/browser/service_worker/embedded_worker_instance.h b/chromium/content/browser/service_worker/embedded_worker_instance.h
index 4f034cdf345..261425d2f41 100644
--- a/chromium/content/browser/service_worker/embedded_worker_instance.h
+++ b/chromium/content/browser/service_worker/embedded_worker_instance.h
@@ -210,7 +210,7 @@ class CONTENT_EXPORT EmbeddedWorkerInstance
base::WeakPtr<EmbeddedWorkerInstance> AsWeakPtr();
private:
- typedef base::ObserverList<Listener> ListenerList;
+ typedef base::ObserverList<Listener>::Unchecked ListenerList;
class StartTask;
class WorkerProcessHandle;
friend class EmbeddedWorkerRegistry;
@@ -253,7 +253,7 @@ class CONTENT_EXPORT EmbeddedWorkerInstance
// Implements mojom::EmbeddedWorkerInstanceHost.
// These functions all run on the IO thread.
- void RequestTermination() override;
+ void RequestTermination(RequestTerminationCallback callback) override;
void CountFeature(blink::mojom::WebFeature feature) override;
void OnReadyForInspection() override;
void OnScriptLoaded() override;
diff --git a/chromium/content/browser/service_worker/embedded_worker_registry.cc b/chromium/content/browser/service_worker/embedded_worker_registry.cc
index c63e6333f45..34287d99034 100644
--- a/chromium/content/browser/service_worker/embedded_worker_registry.cc
+++ b/chromium/content/browser/service_worker/embedded_worker_registry.cc
@@ -68,7 +68,7 @@ void EmbeddedWorkerRegistry::OnWorkerStopped(int process_id,
lifetime_tracker_.StopTiming(embedded_worker_id);
}
-void EmbeddedWorkerRegistry::OnDevToolsAttached(int embedded_worker_id) {
+void EmbeddedWorkerRegistry::AbortLifetimeTracking(int embedded_worker_id) {
lifetime_tracker_.AbortTiming(embedded_worker_id);
}
diff --git a/chromium/content/browser/service_worker/embedded_worker_registry.h b/chromium/content/browser/service_worker/embedded_worker_registry.h
index 20825f66eef..8aa9743703d 100644
--- a/chromium/content/browser/service_worker/embedded_worker_registry.h
+++ b/chromium/content/browser/service_worker/embedded_worker_registry.h
@@ -55,9 +55,8 @@ class CONTENT_EXPORT EmbeddedWorkerRegistry
bool OnWorkerStarted(int process_id, int embedded_worker_id);
void OnWorkerStopped(int process_id, int embedded_worker_id);
- // Called by EmbeddedWorkerInstance when it learns DevTools has attached to
- // it.
- void OnDevToolsAttached(int embedded_worker_id);
+ // Aborts the timer which tracks the lifetime of the worker for UMA logging.
+ void AbortLifetimeTracking(int embedded_worker_id);
// Returns an embedded worker instance for given |embedded_worker_id|.
EmbeddedWorkerInstance* GetWorker(int embedded_worker_id);
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 4942766b0e6..92fcf8b5fe8 100644
--- a/chromium/content/browser/service_worker/embedded_worker_test_helper.cc
+++ b/chromium/content/browser/service_worker/embedded_worker_test_helper.cc
@@ -24,8 +24,6 @@
#include "content/common/background_fetch/background_fetch_types.h"
#include "content/common/renderer.mojom.h"
#include "content/common/service_worker/service_worker.mojom.h"
-#include "content/common/service_worker/service_worker_messages.h"
-#include "content/public/common/push_event_payload.h"
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_browser_context.h"
#include "mojo/public/cpp/bindings/associated_binding_set.h"
@@ -36,6 +34,7 @@
#include "storage/common/blob_storage/blob_handle.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/service_worker/service_worker_utils.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_response.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom.h"
namespace content {
@@ -43,20 +42,13 @@ namespace content {
namespace {
void OnFetchEventCommon(
- mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
+ blink::mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
mojom::ServiceWorker::DispatchFetchEventCallback finish_callback) {
- response_callback->OnResponse(
- ServiceWorkerResponse(
- std::make_unique<std::vector<GURL>>(), 200, "OK",
- network::mojom::FetchResponseType::kDefault,
- std::make_unique<ServiceWorkerHeaderMap>(), std::string(), 0,
- nullptr /* blob */,
- blink::mojom::ServiceWorkerResponseError::kUnknown, base::Time(),
- false /* is_in_cache_storage */,
- std::string() /* cache_storage_cache_name */,
- std::make_unique<
- ServiceWorkerHeaderList>() /* cors_exposed_header_names */),
- base::Time::Now());
+ auto response = blink::mojom::FetchAPIResponse::New();
+ response->status_code = 200;
+ response->status_text = "OK";
+ response->response_type = network::mojom::FetchResponseType::kDefault;
+ response_callback->OnResponse(std::move(response), base::Time::Now());
std::move(finish_callback)
.Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
base::Time::Now());
@@ -220,46 +212,36 @@ class EmbeddedWorkerTestHelper::MockServiceWorker
}
void DispatchBackgroundFetchAbortEvent(
- const std::string& developer_id,
- const std::string& unique_id,
- const std::vector<BackgroundFetchSettledFetch>& fetches,
+ const BackgroundFetchRegistration& registration,
DispatchBackgroundFetchAbortEventCallback callback) override {
if (!helper_)
return;
- helper_->OnBackgroundFetchAbortEventStub(developer_id, unique_id, fetches,
- std::move(callback));
+ helper_->OnBackgroundFetchAbortEventStub(registration, std::move(callback));
}
void DispatchBackgroundFetchClickEvent(
- const std::string& developer_id,
- mojom::BackgroundFetchState state,
+ const BackgroundFetchRegistration& registration,
DispatchBackgroundFetchClickEventCallback callback) override {
if (!helper_)
return;
- helper_->OnBackgroundFetchClickEventStub(developer_id, state,
- std::move(callback));
+ helper_->OnBackgroundFetchClickEventStub(registration, std::move(callback));
}
void DispatchBackgroundFetchFailEvent(
- const std::string& developer_id,
- const std::string& unique_id,
- const std::vector<BackgroundFetchSettledFetch>& fetches,
+ const BackgroundFetchRegistration& registration,
DispatchBackgroundFetchFailEventCallback callback) override {
if (!helper_)
return;
- helper_->OnBackgroundFetchFailEventStub(developer_id, unique_id, fetches,
- std::move(callback));
+ helper_->OnBackgroundFetchFailEventStub(registration, std::move(callback));
}
- void DispatchBackgroundFetchedEvent(
- const std::string& developer_id,
- const std::string& unique_id,
- const std::vector<BackgroundFetchSettledFetch>& fetches,
- DispatchBackgroundFetchedEventCallback callback) override {
+ void DispatchBackgroundFetchSuccessEvent(
+ const BackgroundFetchRegistration& registration,
+ DispatchBackgroundFetchSuccessEventCallback callback) override {
if (!helper_)
return;
- helper_->OnBackgroundFetchedEventStub(developer_id, unique_id, fetches,
- std::move(callback));
+ helper_->OnBackgroundFetchSuccessEventStub(registration,
+ std::move(callback));
}
void DispatchCookieChangeEvent(
@@ -273,7 +255,7 @@ class EmbeddedWorkerTestHelper::MockServiceWorker
void DispatchFetchEvent(
blink::mojom::DispatchFetchEventParamsPtr params,
- mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
+ blink::mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
DispatchFetchEventCallback callback) override {
if (!helper_)
return;
@@ -305,7 +287,7 @@ class EmbeddedWorkerTestHelper::MockServiceWorker
std::move(callback));
}
- void DispatchPushEvent(const PushEventPayload& payload,
+ void DispatchPushEvent(const base::Optional<std::string>& payload,
DispatchPushEventCallback callback) override {
if (!helper_)
return;
@@ -359,9 +341,24 @@ class EmbeddedWorkerTestHelper::MockServiceWorker
std::move(callback));
}
+ void DispatchExtendableMessageEventWithCustomTimeout(
+ mojom::ExtendableMessageEventPtr event,
+ base::TimeDelta timeout,
+ DispatchExtendableMessageEventWithCustomTimeoutCallback callback)
+ override {
+ if (!helper_)
+ return;
+ helper_->OnExtendableMessageEventStub(std::move(event),
+ std::move(callback));
+ }
+
void Ping(PingCallback callback) override { std::move(callback).Run(); }
- void SetIdleTimerDelayToZero() override { NOTIMPLEMENTED(); }
+ void SetIdleTimerDelayToZero() override {
+ if (!helper_)
+ return;
+ helper_->OnSetIdleTimerDelayToZero(embedded_worker_id_);
+ }
private:
base::WeakPtr<EmbeddedWorkerTestHelper> helper_;
@@ -487,7 +484,11 @@ void EmbeddedWorkerTestHelper::SetNetworkFactory(
if (!factory)
factory = default_network_loader_factory_.get();
+ // Reset factory in URLLoaderFactoryGetter so that we don't hit DCHECK()
+ // there.
+ url_loader_factory_getter_->SetNetworkFactoryForTesting(nullptr);
url_loader_factory_getter_->SetNetworkFactoryForTesting(factory);
+
render_process_host_->OverrideURLLoaderFactory(factory);
new_render_process_host_->OverrideURLLoaderFactory(factory);
}
@@ -584,36 +585,30 @@ void EmbeddedWorkerTestHelper::OnActivateEvent(
}
void EmbeddedWorkerTestHelper::OnBackgroundFetchAbortEvent(
- const std::string& developer_id,
- const std::string& unique_id,
- const std::vector<BackgroundFetchSettledFetch>& fetches,
+ const BackgroundFetchRegistration& registration,
mojom::ServiceWorker::DispatchBackgroundFetchAbortEventCallback callback) {
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
base::Time::Now());
}
void EmbeddedWorkerTestHelper::OnBackgroundFetchClickEvent(
- const std::string& developer_id,
- mojom::BackgroundFetchState state,
+ const BackgroundFetchRegistration& registration,
mojom::ServiceWorker::DispatchBackgroundFetchClickEventCallback callback) {
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
base::Time::Now());
}
void EmbeddedWorkerTestHelper::OnBackgroundFetchFailEvent(
- const std::string& developer_id,
- const std::string& unique_id,
- const std::vector<BackgroundFetchSettledFetch>& fetches,
+ const BackgroundFetchRegistration& registration,
mojom::ServiceWorker::DispatchBackgroundFetchFailEventCallback callback) {
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
base::Time::Now());
}
-void EmbeddedWorkerTestHelper::OnBackgroundFetchedEvent(
- const std::string& developer_id,
- const std::string& unique_id,
- const std::vector<BackgroundFetchSettledFetch>& fetches,
- mojom::ServiceWorker::DispatchBackgroundFetchedEventCallback callback) {
+void EmbeddedWorkerTestHelper::OnBackgroundFetchSuccessEvent(
+ const BackgroundFetchRegistration& registration,
+ mojom::ServiceWorker::DispatchBackgroundFetchSuccessEventCallback
+ callback) {
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
base::Time::Now());
}
@@ -644,14 +639,14 @@ void EmbeddedWorkerTestHelper::OnFetchEvent(
int /* embedded_worker_id */,
const network::ResourceRequest& /* request */,
blink::mojom::FetchEventPreloadHandlePtr /* preload_handle */,
- mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
+ blink::mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
mojom::ServiceWorker::DispatchFetchEventCallback finish_callback) {
// TODO(falken): In-line common into here.
OnFetchEventCommon(std::move(response_callback), std::move(finish_callback));
}
void EmbeddedWorkerTestHelper::OnPushEvent(
- const PushEventPayload& payload,
+ base::Optional<std::string> payload,
mojom::ServiceWorker::DispatchPushEventCallback callback) {
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
base::Time::Now());
@@ -710,6 +705,11 @@ void EmbeddedWorkerTestHelper::OnPaymentRequestEvent(
base::Time::Now());
}
+void EmbeddedWorkerTestHelper::OnSetIdleTimerDelayToZero(
+ int embedded_worker_id) {
+ // Subclasses may implement this method.
+}
+
void EmbeddedWorkerTestHelper::SimulateWorkerReadyForInspection(
int embedded_worker_id) {
EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
@@ -856,49 +856,40 @@ void EmbeddedWorkerTestHelper::OnActivateEventStub(
}
void EmbeddedWorkerTestHelper::OnBackgroundFetchAbortEventStub(
- const std::string& developer_id,
- const std::string& unique_id,
- const std::vector<BackgroundFetchSettledFetch>& fetches,
+ const BackgroundFetchRegistration& registration,
mojom::ServiceWorker::DispatchBackgroundFetchAbortEventCallback callback) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(&EmbeddedWorkerTestHelper::OnBackgroundFetchAbortEvent,
- AsWeakPtr(), developer_id, unique_id, fetches,
- std::move(callback)));
+ AsWeakPtr(), registration, std::move(callback)));
}
void EmbeddedWorkerTestHelper::OnBackgroundFetchClickEventStub(
- const std::string& developer_id,
- mojom::BackgroundFetchState state,
+ const BackgroundFetchRegistration& registration,
mojom::ServiceWorker::DispatchBackgroundFetchClickEventCallback callback) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(&EmbeddedWorkerTestHelper::OnBackgroundFetchClickEvent,
- AsWeakPtr(), developer_id, state, std::move(callback)));
+ AsWeakPtr(), registration, std::move(callback)));
}
void EmbeddedWorkerTestHelper::OnBackgroundFetchFailEventStub(
- const std::string& developer_id,
- const std::string& unique_id,
- const std::vector<BackgroundFetchSettledFetch>& fetches,
+ const BackgroundFetchRegistration& registration,
mojom::ServiceWorker::DispatchBackgroundFetchFailEventCallback callback) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(&EmbeddedWorkerTestHelper::OnBackgroundFetchFailEvent,
- AsWeakPtr(), developer_id, unique_id, fetches,
- std::move(callback)));
+ AsWeakPtr(), registration, std::move(callback)));
}
-void EmbeddedWorkerTestHelper::OnBackgroundFetchedEventStub(
- const std::string& developer_id,
- const std::string& unique_id,
- const std::vector<BackgroundFetchSettledFetch>& fetches,
- mojom::ServiceWorker::DispatchBackgroundFetchedEventCallback callback) {
+void EmbeddedWorkerTestHelper::OnBackgroundFetchSuccessEventStub(
+ const BackgroundFetchRegistration& registration,
+ mojom::ServiceWorker::DispatchBackgroundFetchSuccessEventCallback
+ callback) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::BindOnce(&EmbeddedWorkerTestHelper::OnBackgroundFetchedEvent,
- AsWeakPtr(), developer_id, unique_id, fetches,
- std::move(callback)));
+ base::BindOnce(&EmbeddedWorkerTestHelper::OnBackgroundFetchSuccessEvent,
+ AsWeakPtr(), registration, std::move(callback)));
}
void EmbeddedWorkerTestHelper::OnCookieChangeEventStub(
@@ -931,7 +922,7 @@ void EmbeddedWorkerTestHelper::OnFetchEventStub(
int embedded_worker_id,
const network::ResourceRequest& request,
blink::mojom::FetchEventPreloadHandlePtr preload_handle,
- mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
+ blink::mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
mojom::ServiceWorker::DispatchFetchEventCallback finish_callback) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
@@ -965,11 +956,12 @@ void EmbeddedWorkerTestHelper::OnNotificationCloseEventStub(
}
void EmbeddedWorkerTestHelper::OnPushEventStub(
- const PushEventPayload& payload,
+ base::Optional<std::string> payload,
mojom::ServiceWorker::DispatchPushEventCallback callback) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(&EmbeddedWorkerTestHelper::OnPushEvent,
- AsWeakPtr(), payload, std::move(callback)));
+ FROM_HERE,
+ base::BindOnce(&EmbeddedWorkerTestHelper::OnPushEvent, AsWeakPtr(),
+ std::move(payload), std::move(callback)));
}
void EmbeddedWorkerTestHelper::OnAbortPaymentEventStub(
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 9204ee99207..04943106abf 100644
--- a/chromium/content/browser/service_worker/embedded_worker_test_helper.h
+++ b/chromium/content/browser/service_worker/embedded_worker_test_helper.h
@@ -35,7 +35,7 @@ class GURL;
namespace content {
-struct BackgroundFetchSettledFetch;
+struct BackgroundFetchRegistration;
class EmbeddedWorkerRegistry;
class EmbeddedWorkerTestHelper;
class MockRenderProcessHost;
@@ -43,7 +43,6 @@ class ServiceWorkerContextCore;
class ServiceWorkerContextWrapper;
class TestBrowserContext;
struct PlatformNotificationData;
-struct PushEventPayload;
// In-Process EmbeddedWorker test helper.
//
@@ -95,10 +94,6 @@ class EmbeddedWorkerTestHelper {
// If |user_data_directory| is empty, the context makes storage stuff in
// memory.
explicit EmbeddedWorkerTestHelper(const base::FilePath& user_data_directory);
- // S13nServiceWorker
- EmbeddedWorkerTestHelper(
- const base::FilePath& user_data_directory,
- scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter);
virtual ~EmbeddedWorkerTestHelper();
// Registers a Mojo endpoint object derived from
@@ -172,24 +167,18 @@ class EmbeddedWorkerTestHelper {
virtual void OnActivateEvent(
mojom::ServiceWorker::DispatchActivateEventCallback callback);
virtual void OnBackgroundFetchAbortEvent(
- const std::string& developer_id,
- const std::string& unique_id,
- const std::vector<BackgroundFetchSettledFetch>& fetches,
+ const BackgroundFetchRegistration& registration,
mojom::ServiceWorker::DispatchBackgroundFetchAbortEventCallback callback);
virtual void OnBackgroundFetchClickEvent(
- const std::string& developer_id,
- mojom::BackgroundFetchState state,
+ const BackgroundFetchRegistration& registration,
mojom::ServiceWorker::DispatchBackgroundFetchClickEventCallback callback);
virtual void OnBackgroundFetchFailEvent(
- const std::string& developer_id,
- const std::string& unique_id,
- const std::vector<BackgroundFetchSettledFetch>& fetches,
+ const BackgroundFetchRegistration& registration,
mojom::ServiceWorker::DispatchBackgroundFetchFailEventCallback callback);
- virtual void OnBackgroundFetchedEvent(
- const std::string& developer_id,
- const std::string& unique_id,
- const std::vector<BackgroundFetchSettledFetch>& fetches,
- mojom::ServiceWorker::DispatchBackgroundFetchedEventCallback callback);
+ virtual void OnBackgroundFetchSuccessEvent(
+ const BackgroundFetchRegistration& registration,
+ mojom::ServiceWorker::DispatchBackgroundFetchSuccessEventCallback
+ callback);
virtual void OnCookieChangeEvent(
const net::CanonicalCookie& cookie,
::network::mojom::CookieChangeCause cause,
@@ -203,7 +192,7 @@ class EmbeddedWorkerTestHelper {
int embedded_worker_id,
const network::ResourceRequest& request,
blink::mojom::FetchEventPreloadHandlePtr preload_handle,
- mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
+ blink::mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
mojom::ServiceWorker::DispatchFetchEventCallback finish_callback);
virtual void OnNotificationClickEvent(
const std::string& notification_id,
@@ -216,7 +205,7 @@ class EmbeddedWorkerTestHelper {
const PlatformNotificationData& notification_data,
mojom::ServiceWorker::DispatchNotificationCloseEventCallback callback);
virtual void OnPushEvent(
- const PushEventPayload& payload,
+ base::Optional<std::string> payload,
mojom::ServiceWorker::DispatchPushEventCallback callback);
virtual void OnAbortPaymentEvent(
payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
@@ -229,6 +218,7 @@ class EmbeddedWorkerTestHelper {
payments::mojom::PaymentRequestEventDataPtr data,
payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
mojom::ServiceWorker::DispatchPaymentRequestEventCallback callback);
+ virtual void OnSetIdleTimerDelayToZero(int embedded_worker_id);
// These functions simulate making Mojo calls to the browser.
void SimulateWorkerReadyForInspection(int embedded_worker_id);
@@ -248,6 +238,11 @@ class EmbeddedWorkerTestHelper {
return embedded_worker_id_host_map_[embedded_worker_id].get();
}
+ mojom::EmbeddedWorkerInstanceHostProxy* GetEmbeddedWorkerInstanceHost(
+ int embedded_worker_id) {
+ return embedded_worker_id_instance_host_ptr_map_[embedded_worker_id].get();
+ }
+
private:
class MockNetworkURLLoaderFactory;
class MockServiceWorker;
@@ -266,24 +261,18 @@ class EmbeddedWorkerTestHelper {
void OnActivateEventStub(
mojom::ServiceWorker::DispatchActivateEventCallback callback);
void OnBackgroundFetchAbortEventStub(
- const std::string& developer_id,
- const std::string& unique_id,
- const std::vector<BackgroundFetchSettledFetch>& fetches,
+ const BackgroundFetchRegistration& registration,
mojom::ServiceWorker::DispatchBackgroundFetchAbortEventCallback callback);
void OnBackgroundFetchClickEventStub(
- const std::string& developer_id,
- mojom::BackgroundFetchState state,
+ const BackgroundFetchRegistration& registration,
mojom::ServiceWorker::DispatchBackgroundFetchClickEventCallback callback);
void OnBackgroundFetchFailEventStub(
- const std::string& developer_id,
- const std::string& unique_id,
- const std::vector<BackgroundFetchSettledFetch>& fetches,
+ const BackgroundFetchRegistration& registration,
mojom::ServiceWorker::DispatchBackgroundFetchFailEventCallback callback);
- void OnBackgroundFetchedEventStub(
- const std::string& developer_id,
- const std::string& unique_id,
- const std::vector<BackgroundFetchSettledFetch>& fetches,
- mojom::ServiceWorker::DispatchBackgroundFetchedEventCallback callback);
+ void OnBackgroundFetchSuccessEventStub(
+ const BackgroundFetchRegistration& registration,
+ mojom::ServiceWorker::DispatchBackgroundFetchSuccessEventCallback
+ callback);
void OnCookieChangeEventStub(
const net::CanonicalCookie& cookie,
::network::mojom::CookieChangeCause cause,
@@ -297,7 +286,7 @@ class EmbeddedWorkerTestHelper {
int embedded_worker_id,
const network::ResourceRequest& request,
blink::mojom::FetchEventPreloadHandlePtr preload_handle,
- mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
+ blink::mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
mojom::ServiceWorker::DispatchFetchEventCallback finish_callback);
void OnNotificationClickEventStub(
const std::string& notification_id,
@@ -310,7 +299,7 @@ class EmbeddedWorkerTestHelper {
const PlatformNotificationData& notification_data,
mojom::ServiceWorker::DispatchNotificationCloseEventCallback callback);
void OnPushEventStub(
- const PushEventPayload& payload,
+ base::Optional<std::string> payload,
mojom::ServiceWorker::DispatchPushEventCallback callback);
void OnAbortPaymentEventStub(
payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
diff --git a/chromium/content/browser/service_worker/service_worker_browsertest.cc b/chromium/content/browser/service_worker/service_worker_browsertest.cc
index d8275ba30f8..7e129e81e95 100644
--- a/chromium/content/browser/service_worker/service_worker_browsertest.cc
+++ b/chromium/content/browser/service_worker/service_worker_browsertest.cc
@@ -22,8 +22,8 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/task_scheduler/post_task.h"
-#include "base/task_scheduler/task_traits.h"
+#include "base/task/post_task.h"
+#include "base/task/task_traits.h"
#include "base/test/bind_test_util.h"
#include "base/test/scoped_feature_list.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -45,7 +45,6 @@
#include "content/browser/service_worker/service_worker_test_utils.h"
#include "content/browser/service_worker/service_worker_version.h"
#include "content/browser/web_contents/web_contents_impl.h"
-#include "content/common/service_worker/service_worker_messages.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
@@ -63,6 +62,7 @@
#include "content/public/common/content_switches.h"
#include "content/public/common/referrer.h"
#include "content/public/common/resource_type.h"
+#include "content/public/common/url_loader_throttle.h"
#include "content/public/common/web_preferences.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
@@ -75,15 +75,19 @@
#include "net/dns/mock_host_resolver.h"
#include "net/http/http_response_info.h"
#include "net/log/net_log_with_source.h"
+#include "net/test/embedded_test_server/default_handlers.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"
#include "net/url_request/url_request_filter.h"
#include "net/url_request/url_request_test_job.h"
+#include "services/network/loader_util.h"
+#include "services/network/public/cpp/features.h"
#include "storage/browser/blob/blob_data_handle.h"
#include "storage/browser/blob/blob_data_snapshot.h"
#include "storage/browser/blob/blob_reader.h"
#include "storage/browser/blob/blob_storage_context.h"
+#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
#include "third_party/blink/public/common/service_worker/service_worker_type_converters.h"
#include "third_party/blink/public/common/service_worker/service_worker_utils.h"
@@ -105,7 +109,7 @@ const int kV8CacheTimeStampDataSize =
struct FetchResult {
blink::ServiceWorkerStatusCode status;
ServiceWorkerFetchDispatcher::FetchEventResult result;
- ServiceWorkerResponse response;
+ blink::mojom::FetchAPIResponsePtr response;
std::unique_ptr<storage::BlobDataHandle> blob_data_handle;
};
@@ -200,6 +204,7 @@ class WorkerActivatedObserver
}
// ServiceWorkerContextCoreObserver overrides.
void OnVersionStateChanged(int64_t version_id,
+ const GURL& scope,
ServiceWorkerVersion::Status) override {
ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
const ServiceWorkerVersion* version = context_->GetLiveVersion(version_id);
@@ -611,7 +616,7 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
void FetchOnRegisteredWorker(
ServiceWorkerFetchDispatcher::FetchEventResult* result,
- ServiceWorkerResponse* response,
+ blink::mojom::FetchAPIResponsePtr* response,
std::unique_ptr<storage::BlobDataHandle>* blob_data_handle) {
blob_context_ = ChromeBlobStorageContext::GetFor(
shell()->web_contents()->GetBrowserContext());
@@ -627,7 +632,7 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
fetch_run_loop.Run();
ASSERT_TRUE(prepare_result);
*result = fetch_result.result;
- *response = fetch_result.response;
+ *response = std::move(fetch_result.response);
*blob_data_handle = std::move(fetch_result.blob_data_handle);
ASSERT_EQ(blink::ServiceWorkerStatusCode::kOk, fetch_result.status);
}
@@ -671,8 +676,8 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
wrapper()->context()->AsWeakPtr(), &remote_endpoints_.back());
host->SetDocumentUrl(
embedded_test_server()->GetURL("/service_worker/host"));
- host->AssociateRegistration(registration_.get(),
- false /* notify_controllerchange */);
+ host->SetControllerRegistration(registration_,
+ false /* notify_controllerchange */);
wrapper()->context()->AddProviderHost(std::move(host));
}
@@ -962,20 +967,20 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
FetchResult* out_result,
blink::ServiceWorkerStatusCode actual_status,
ServiceWorkerFetchDispatcher::FetchEventResult actual_result,
- const ServiceWorkerResponse& actual_response,
+ blink::mojom::FetchAPIResponsePtr actual_response,
blink::mojom::ServiceWorkerStreamHandlePtr /* stream */,
- blink::mojom::BlobPtr /* blob */,
scoped_refptr<ServiceWorkerVersion> worker) {
ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
ASSERT_TRUE(fetch_dispatcher_);
fetch_dispatcher_.reset();
out_result->status = actual_status;
out_result->result = actual_result;
- out_result->response = actual_response;
- if (!actual_response.blob_uuid.empty()) {
+ out_result->response = std::move(actual_response);
+ if (out_result->response->blob) {
+ DCHECK(!out_result->response->blob->uuid.empty());
out_result->blob_data_handle =
blob_context->context()->GetBlobDataFromUUID(
- actual_response.blob_uuid);
+ out_result->response->blob->uuid);
}
if (!quit.is_null())
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, quit);
@@ -1346,7 +1351,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, TimeoutWorkerInEvent) {
IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, FetchEvent_Response) {
StartServerAndNavigateToSetup();
ServiceWorkerFetchDispatcher::FetchEventResult result;
- ServiceWorkerResponse response;
+ blink::mojom::FetchAPIResponsePtr response;
std::unique_ptr<storage::BlobDataHandle> blob_data_handle;
InstallTestHelper("/service_worker/fetch_event.js",
blink::ServiceWorkerStatusCode::kOk);
@@ -1356,12 +1361,12 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, FetchEvent_Response) {
FetchOnRegisteredWorker(&result, &response, &blob_data_handle);
ASSERT_EQ(ServiceWorkerFetchDispatcher::FetchEventResult::kGotResponse,
result);
- EXPECT_EQ(301, response.status_code);
- EXPECT_EQ("Moved Permanently", response.status_text);
- ServiceWorkerHeaderMap expected_headers;
+ EXPECT_EQ(301, response->status_code);
+ EXPECT_EQ("Moved Permanently", response->status_text);
+ base::flat_map<std::string, std::string> expected_headers;
expected_headers["content-language"] = "fi";
expected_headers["content-type"] = "text/html; charset=UTF-8";
- EXPECT_EQ(expected_headers, response.headers);
+ EXPECT_EQ(expected_headers, response->headers);
std::string body;
RunOnIOThread(base::BindOnce(&ReadResponseBody, &body,
@@ -1373,8 +1378,8 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
FetchEvent_ResponseViaCache) {
StartServerAndNavigateToSetup();
ServiceWorkerFetchDispatcher::FetchEventResult result;
- ServiceWorkerResponse response1;
- ServiceWorkerResponse response2;
+ blink::mojom::FetchAPIResponsePtr response1;
+ blink::mojom::FetchAPIResponsePtr response2;
std::unique_ptr<storage::BlobDataHandle> blob_data_handle;
const base::Time start_time(base::Time::Now());
InstallTestHelper("/service_worker/fetch_event_response_via_cache.js",
@@ -1385,27 +1390,29 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
FetchOnRegisteredWorker(&result, &response1, &blob_data_handle);
ASSERT_EQ(ServiceWorkerFetchDispatcher::FetchEventResult::kGotResponse,
result);
- EXPECT_EQ(200, response1.status_code);
- EXPECT_EQ("OK", response1.status_text);
- EXPECT_TRUE(response1.response_time >= start_time);
- EXPECT_FALSE(response1.is_in_cache_storage);
- EXPECT_EQ(std::string(), response2.cache_storage_cache_name);
+ EXPECT_EQ(200, response1->status_code);
+ EXPECT_EQ("OK", response1->status_text);
+ EXPECT_TRUE(response1->response_time >= start_time);
+ EXPECT_FALSE(response1->is_in_cache_storage);
+ ASSERT_TRUE(response1->cache_storage_cache_name);
+ EXPECT_EQ(std::string(), *response1->cache_storage_cache_name);
FetchOnRegisteredWorker(&result, &response2, &blob_data_handle);
ASSERT_EQ(ServiceWorkerFetchDispatcher::FetchEventResult::kGotResponse,
result);
- EXPECT_EQ(200, response2.status_code);
- EXPECT_EQ("OK", response2.status_text);
- EXPECT_EQ(response1.response_time, response2.response_time);
- EXPECT_TRUE(response2.is_in_cache_storage);
- EXPECT_EQ("cache_name", response2.cache_storage_cache_name);
+ EXPECT_EQ(200, response2->status_code);
+ EXPECT_EQ("OK", response2->status_text);
+ EXPECT_EQ(response1->response_time, response2->response_time);
+ EXPECT_TRUE(response2->is_in_cache_storage);
+ ASSERT_TRUE(response2->cache_storage_cache_name);
+ EXPECT_EQ("cache_name", *response2->cache_storage_cache_name);
}
IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
FetchEvent_respondWithRejection) {
StartServerAndNavigateToSetup();
ServiceWorkerFetchDispatcher::FetchEventResult result;
- ServiceWorkerResponse response;
+ blink::mojom::FetchAPIResponsePtr response;
std::unique_ptr<storage::BlobDataHandle> blob_data_handle;
InstallTestHelper("/service_worker/fetch_event_rejected.js",
blink::ServiceWorkerStatusCode::kOk);
@@ -1432,7 +1439,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
ASSERT_EQ(ServiceWorkerFetchDispatcher::FetchEventResult::kGotResponse,
result);
- EXPECT_EQ(0, response.status_code);
+ EXPECT_EQ(0, response->status_code);
ASSERT_FALSE(blob_data_handle);
}
@@ -1733,6 +1740,90 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest, Reload) {
run_loop.Run();
}
+// Test when the renderer requests termination because the service worker is
+// idle, and the browser ignores the request because DevTools is attached. The
+// 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) {
+ StartServerAndNavigateToSetup();
+
+ // This test is based on a new idle timer mechanism which is available only
+ // when S13nServiceWorker or NetworkService is enabled.
+ if (!blink::ServiceWorkerUtils::IsServicificationEnabled()) {
+ LOG(WARNING)
+ << "This test requires NetworkService or ServiceWorkerServicification.";
+ return;
+ }
+
+ // Register a service worker.
+ scoped_refptr<WorkerActivatedObserver> observer =
+ new WorkerActivatedObserver(wrapper());
+ observer->Init();
+ const GURL scope =
+ embedded_test_server()->GetURL("/service_worker/fetch_from_page.html");
+ const GURL worker_url = embedded_test_server()->GetURL(
+ "/service_worker/fetch_event_respond_with_fetch.js");
+
+ blink::mojom::ServiceWorkerRegistrationOptions options(
+ scope, blink::mojom::ServiceWorkerUpdateViaCache::kNone);
+ public_context()->RegisterServiceWorker(
+ worker_url, options,
+ base::BindOnce(&ExpectResultAndRun, true, base::DoNothing()));
+ observer->Wait();
+
+ // Navigate to a new page and request a sub resource. This should succeed
+ // normally.
+ {
+ const GURL url = embedded_test_server()->GetURL(
+ "/service_worker/fetch_from_page.html?url=/service_worker/empty.html");
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+ const base::string16 title = base::ASCIIToUTF16("DONE");
+ TitleWatcher watcher(shell()->web_contents(), title);
+ EXPECT_EQ(title, watcher.WaitAndGetTitle());
+ }
+
+ // Simulate to attach DevTools.
+ base::RunLoop loop;
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(
+ [](base::OnceClosure done, ServiceWorkerContextWrapper* wrapper,
+ int64_t version_id) {
+ ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ scoped_refptr<ServiceWorkerVersion> version =
+ wrapper->GetLiveVersion(version_id);
+ version->SetDevToolsAttached(true);
+
+ // Set the idle timer delay to zero for making the service worker
+ // idle immediately. This may cause infinite loop of IPCs when no
+ // event was queued in the renderer because a callback of
+ // RequestTermination() is called and it triggers another
+ // RequestTermination() immediately. However, this is unusual
+ // situation happening only in testing so it's acceptable.
+ // In production code, WakeUp() as the result of
+ // RequestTermination() doesn't happen when the idle timer delay is
+ // set to zero. Instead, activating a new worker will be triggered.
+ version->endpoint()->SetIdleTimerDelayToZero();
+ std::move(done).Run();
+ },
+ loop.QuitClosure(), base::Unretained(wrapper()),
+ observer->version_id()));
+ loop.Run();
+
+ // Trigger another sub resource request. The sub resource request will
+ // directly go to the worker thread and be queued because the worker is
+ // idle. However, the browser process notifies the renderer to let it continue
+ // to work because DevTools is attached, and it'll result in running all
+ // queued events.
+ EXPECT_EQ(200, EvalJs(shell(), R"(
+ (async () => {
+ let response = await fetch(params.get('url'));
+ return response.status;
+ })()
+ )"));
+}
+
class ServiceWorkerNavigationPreloadTest : public ServiceWorkerBrowserTest {
public:
using self = ServiceWorkerNavigationPreloadTest;
@@ -1991,21 +2082,32 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest, NetworkFallback) {
EXPECT_EQ("Hello world.",
LoadNavigationPreloadTestPage(page_url, worker_url, "PASS"));
- // The page request must be sent once or twice:
+ // The page request can be sent one, two, or three times.
// - A navigation preload request may be sent. But it is possible that the
// navigation preload request is canceled before reaching the server.
// - A fallback request must be sent since respondWith wasn't used.
+ // - A second fallback request can be sent because the HttpCache may get
+ // confused when there are two concurrent requests (navigation preload and
+ // fallback) and one of them is cancelled (navigation preload). It restarts
+ // the ongoing request, possibly triggering another network request (see
+ // https://crbug.com/876911).
const int request_count = GetRequestCount(kPageUrl);
- ASSERT_TRUE(request_count == 1 || request_count == 2);
+ ASSERT_TRUE(request_count == 1 || request_count == 2 || request_count == 3)
+ << request_count;
if (request_count == 1) {
// Fallback request.
EXPECT_FALSE(HasNavigationPreloadHeader(request_log_[kPageUrl][0]));
- } else if (request_count == 2) {
+ } else {
// Navigation preload request.
ASSERT_TRUE(HasNavigationPreloadHeader(request_log_[kPageUrl][0]));
EXPECT_EQ("true", GetNavigationPreloadHeader(request_log_[kPageUrl][0]));
// Fallback request.
EXPECT_FALSE(HasNavigationPreloadHeader(request_log_[kPageUrl][1]));
+
+ // Additional fallback request when the HttpCache reissues a network
+ // request.
+ if (request_count == 3)
+ EXPECT_FALSE(HasNavigationPreloadHeader(request_log_[kPageUrl][2]));
}
}
@@ -2997,12 +3099,14 @@ class CacheStorageSideDataSizeChecker
const base::Closure& continuation,
CacheStorageCacheHandle cache_handle,
CacheStorageError error,
- std::unique_ptr<ServiceWorkerResponse> response) {
+ blink::mojom::FetchAPIResponsePtr response) {
ASSERT_EQ(CacheStorageError::kSuccess, error);
ASSERT_TRUE(response->blob);
- auto blob = response->blob;
- response->blob->get()->ReadSideData(base::BindLambdaForTesting(
- [blob, result,
+ blink::mojom::BlobPtr blob_ptr(std::move(response->blob->blob));
+ auto blob_handle =
+ base::MakeRefCounted<storage::BlobHandle>(std::move(blob_ptr));
+ blob_handle->get()->ReadSideData(base::BindLambdaForTesting(
+ [blob_handle, result,
continuation](const base::Optional<std::vector<uint8_t>>& data) {
if (data)
*result = data->size();
@@ -3216,4 +3320,268 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerDisableWebSecurityTest, UpdateNoCrash) {
RunTestWithCrossOriginURL(kPageUrl, kScopeUrl);
}
+class HeaderInjectingThrottle : public URLLoaderThrottle {
+ public:
+ HeaderInjectingThrottle() = default;
+ ~HeaderInjectingThrottle() override = default;
+
+ void WillStartRequest(network::ResourceRequest* request,
+ bool* defer) override {
+ GURL url = request->url;
+ if (url.query().find("PlzRedirect") != std::string::npos) {
+ GURL::Replacements replacements;
+ replacements.SetQueryStr("DidRedirect");
+ request->url = url.ReplaceComponents(replacements);
+ return;
+ }
+
+ request->headers.SetHeader("x-injected", "injected value");
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(HeaderInjectingThrottle);
+};
+
+class ThrottlingContentBrowserClient : public TestContentBrowserClient {
+ public:
+ ThrottlingContentBrowserClient() : TestContentBrowserClient() {}
+ ~ThrottlingContentBrowserClient() override {}
+
+ // ContentBrowserClient overrides:
+ std::vector<std::unique_ptr<URLLoaderThrottle>> CreateURLLoaderThrottles(
+ const network::ResourceRequest& request,
+ ResourceContext* resource_context,
+ const base::RepeatingCallback<WebContents*()>& wc_getter,
+ NavigationUIData* navigation_ui_data,
+ int frame_tree_node_id) override {
+ std::vector<std::unique_ptr<URLLoaderThrottle>> throttles;
+ auto throttle = std::make_unique<HeaderInjectingThrottle>();
+ throttles.push_back(std::move(throttle));
+ return throttles;
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ThrottlingContentBrowserClient);
+};
+
+class ServiceWorkerURLLoaderThrottleTest : public ServiceWorkerBrowserTest {
+ public:
+ ~ServiceWorkerURLLoaderThrottleTest() override {}
+
+ void SetUpOnMainThread() override {
+ ServiceWorkerBrowserTest::SetUpOnMainThread();
+ net::test_server::RegisterDefaultHandlers(embedded_test_server());
+ embedded_test_server()->StartAcceptingConnections();
+ }
+
+ void TearDownOnMainThread() override {
+ ServiceWorkerBrowserTest::TearDownOnMainThread();
+ }
+
+ void NavigateAndWaitForDone(const GURL& url) {
+ const base::string16 title = base::ASCIIToUTF16("DONE");
+ TitleWatcher watcher(shell()->web_contents(), title);
+ watcher.AlsoWaitForTitle(base::ASCIIToUTF16("ERROR"));
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+ EXPECT_EQ(title, watcher.WaitAndGetTitle());
+ }
+
+ void RegisterServiceWorker(const std::string& worker_url) {
+ GURL url = embedded_test_server()->GetURL(
+ "/service_worker/create_service_worker.html?worker_url=" + worker_url);
+ NavigateAndWaitForDone(url);
+ }
+
+ void RegisterServiceWorkerWithScope(const std::string& worker_url,
+ const std::string& scope) {
+ GURL url = embedded_test_server()->GetURL(
+ "/service_worker/create_service_worker.html?worker_url=" + worker_url +
+ "&scope=" + scope);
+ NavigateAndWaitForDone(url);
+ }
+};
+
+// 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,
+ FetchEventForNavigationHasThrottledRequest) {
+ // This tests throttling behavior which only has an effect on service worker
+ // interception when servicification is on.
+ if (!blink::ServiceWorkerUtils::IsServicificationEnabled()) {
+ LOG(WARNING)
+ << "This test requires NetworkService or ServiceWorkerServicification.";
+ return;
+ }
+
+ // Add a throttle which injects a header.
+ ThrottlingContentBrowserClient content_browser_client;
+ auto* old_content_browser_client =
+ SetBrowserClientForTesting(&content_browser_client);
+
+ // Register the service worker.
+ RegisterServiceWorker("/service_worker/echo_request_headers.js");
+
+ // Perform a navigation. Add "?dump_headers" to tell the service worker to
+ // respond with the request headers.
+ GURL url =
+ embedded_test_server()->GetURL("/service_worker/empty.html?dump_headers");
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+
+ // Extract the headers.
+ EvalJsResult result = EvalJs(shell()->web_contents()->GetMainFrame(),
+ "document.body.textContent");
+ ASSERT_TRUE(result.error.empty());
+ std::unique_ptr<base::DictionaryValue> dict = base::DictionaryValue::From(
+ base::JSONReader::Read(result.ExtractString()));
+ ASSERT_TRUE(dict);
+
+ // Default headers are present.
+ EXPECT_TRUE(CheckHeader(*dict, "accept", network::kFrameAcceptHeader));
+ // Injected headers are present.
+ EXPECT_TRUE(CheckHeader(*dict, "x-injected", "injected value"));
+
+ SetBrowserClientForTesting(old_content_browser_client);
+}
+
+// Test that redirects by throttles occur before service worker interception.
+IN_PROC_BROWSER_TEST_F(ServiceWorkerURLLoaderThrottleTest,
+ RedirectOccursBeforeFetchEvent) {
+ // This tests throttling behavior which only has an effect on service worker
+ // interception when servicification is on.
+ if (!blink::ServiceWorkerUtils::IsServicificationEnabled()) {
+ LOG(WARNING)
+ << "This test requires NetworkService or ServiceWorkerServicification.";
+ return;
+ }
+
+ // Add a throttle which performs a redirect.
+ ThrottlingContentBrowserClient content_browser_client;
+ auto* old_content_browser_client =
+ SetBrowserClientForTesting(&content_browser_client);
+
+ // Register the service worker.
+ RegisterServiceWorker("/service_worker/fetch_event_pass_through.js");
+
+ // Perform a navigation. Add "?PlzRedirect" to tell the throttle to
+ // redirect to another URL.
+ GURL url =
+ embedded_test_server()->GetURL("/service_worker/empty.html?PlzRedirect");
+ GURL redirect_url =
+ embedded_test_server()->GetURL("/service_worker/empty.html?DidRedirect");
+ NavigateToURLBlockUntilNavigationsComplete(shell(), url, 1);
+ EXPECT_EQ(redirect_url, shell()->web_contents()->GetLastCommittedURL());
+
+ // This script asks the service worker what fetch events it saw.
+ const std::string script = R"(
+ (async () => {
+ const saw_message = new Promise(resolve => {
+ navigator.serviceWorker.onmessage = event => {
+ resolve(event.data);
+ };
+ });
+ const registration = await navigator.serviceWorker.ready;
+ registration.active.postMessage('');
+ return await saw_message;
+ })();
+ )";
+
+ // Ensure the service worker did not see a fetch event for the PlzRedirect
+ // URL, since throttles should have redirected before interception.
+ base::Value list(base::Value::Type::LIST);
+ list.GetList().emplace_back(redirect_url.spec());
+ EXPECT_EQ(list, EvalJs(shell()->web_contents()->GetMainFrame(), script));
+
+ SetBrowserClientForTesting(old_content_browser_client);
+}
+
+// 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(
+ ServiceWorkerURLLoaderThrottleTest,
+ NavigationHasThrottledRequestHeadersAfterNetworkFallback) {
+ // This tests throttling behavior which only has an effect on service worker
+ // interception when servicification is on.
+ if (!blink::ServiceWorkerUtils::IsServicificationEnabled()) {
+ LOG(WARNING)
+ << "This test requires NetworkService or ServiceWorkerServicification.";
+ return;
+ }
+
+ // Add a throttle which injects a header.
+ ThrottlingContentBrowserClient content_browser_client;
+ auto* old_content_browser_client =
+ SetBrowserClientForTesting(&content_browser_client);
+
+ // Register the service worker. Use "/" scope so the "/echoheader" default
+ // handler of EmbeddedTestServer is in-scope.
+ RegisterServiceWorkerWithScope("/service_worker/fetch_event_pass_through.js",
+ "/");
+
+ // Perform a navigation. Use "/echoheader" which echoes the given header.
+ GURL url = embedded_test_server()->GetURL("/echoheader?x-injected");
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+
+ // Check that there is a controller to check that the test is really testing
+ // service worker network fallback.
+ EXPECT_EQ(true, EvalJs(shell()->web_contents()->GetMainFrame(),
+ "!!navigator.serviceWorker.controller"));
+
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ // The injected header should be present.
+ EXPECT_EQ("injected value", EvalJs(shell()->web_contents()->GetMainFrame(),
+ "document.body.textContent"));
+ } else {
+ // S13nServiceWorker: the injected header is not present. Throttle-modified
+ // headers are not propagated to network requests through
+ // ResourceDispatcherHost, because the legacy network code has its own code
+ // path that applies the same throttling independent from the navigation's
+ // URLLoaderThrottles.
+ DCHECK(base::FeatureList::IsEnabled(
+ blink::features::kServiceWorkerServicification));
+ EXPECT_EQ("None", EvalJs(shell()->web_contents()->GetMainFrame(),
+ "document.body.textContent"));
+ }
+
+ SetBrowserClientForTesting(old_content_browser_client);
+}
+
+// Test that the headers injected by throttles during navigation are
+// present in the navigation preload request.
+IN_PROC_BROWSER_TEST_F(ServiceWorkerURLLoaderThrottleTest,
+ NavigationPreloadHasThrottledRequestHeaders) {
+ // This tests throttling behavior which only has an effect on service worker
+ // interception when servicification is on.
+ if (!blink::ServiceWorkerUtils::IsServicificationEnabled()) {
+ LOG(WARNING)
+ << "This test requires NetworkService or ServiceWorkerServicification.";
+ return;
+ }
+
+ // Add a throttle which injects a header.
+ ThrottlingContentBrowserClient content_browser_client;
+ auto* old_content_browser_client =
+ SetBrowserClientForTesting(&content_browser_client);
+
+ // Register the service worker. Use "/" scope so the "/echoheader" default
+ // handler of EmbeddedTestServer is in-scope.
+ RegisterServiceWorkerWithScope("/service_worker/navigation_preload_worker.js",
+ "/");
+
+ // Perform a navigation. Use "/echoheader" which echoes the given header. The
+ // server responds to the navigation preload request with this echoed
+ // response, and the service worker responds with the navigation preload
+ // response.
+ //
+ // Also test that "Service-Worker-Navigation-Preload" is present to verify
+ // we are testing the navigation preload request.
+ GURL url = embedded_test_server()->GetURL(
+ "/echoheader?Service-Worker-Navigation-Preload&x-injected");
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+ EXPECT_EQ("true\ninjected value",
+ EvalJs(shell()->web_contents()->GetMainFrame(),
+ "document.body.textContent"));
+
+ SetBrowserClientForTesting(old_content_browser_client);
+}
+
} // 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 b58e6db84b0..2d43b2ec095 100644
--- a/chromium/content/browser/service_worker/service_worker_cache_writer.cc
+++ b/chromium/content/browser/service_worker/service_worker_cache_writer.cc
@@ -298,9 +298,7 @@ int ServiceWorkerCacheWriter::DoReadDataForCompareDone(int result) {
return net::OK;
}
- // bytes_compared_ only gets incremented when a full block is compared, to
- // avoid having to use only parts of the buffered network data.
- bytes_compared_ += result;
+ bytes_compared_ += compare_offset_;
state_ = STATE_DONE;
return net::OK;
}
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 2f06d2c777c..e357240657f 100644
--- a/chromium/content/browser/service_worker/service_worker_cache_writer.h
+++ b/chromium/content/browser/service_worker/service_worker_cache_writer.h
@@ -202,14 +202,25 @@ class CONTENT_EXPORT ServiceWorkerCacheWriter {
size_t cached_length_;
+ // The amount of data from the network (|data_to_write_|) which has already
+ // been compared with data from storage (|data_to_read_|). This is
+ // initialized to 0 for every new arrival of network data.
+ size_t compare_offset_;
+
+ // Count of bytes which has been read from the network for comparison, and
+ // known as identical with the stored scripts. It is incremented only when a
+ // full block of network data is compared, to avoid having to use only
+ // fragments of the buffered network data.
size_t bytes_compared_;
+
+ // Count of bytes copied from |copy_reader_| to |writer_|.
size_t bytes_copied_;
+
+ // Count of bytes written back to |writer_|.
size_t bytes_written_;
bool did_replace_;
- size_t compare_offset_;
-
std::unique_ptr<ServiceWorkerResponseReader> compare_reader_;
std::unique_ptr<ServiceWorkerResponseReader> copy_reader_;
std::unique_ptr<ServiceWorkerResponseWriter> writer_;
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 c0a62ea2dcb..38d9f5c1f28 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
@@ -832,5 +832,66 @@ TEST_F(ServiceWorkerCacheWriterTest, CompareFailedCopyLong) {
EXPECT_TRUE(copy_reader->AllExpectedReadsDone());
}
+// Tests behavior when the compare reader does not complete in single try and
+// needs to issue another read.
+TEST_F(ServiceWorkerCacheWriterTest, MultipleComparisonInSingleWrite) {
+ // Data for |compare_reader|.
+ const std::vector<std::string> data_from_cache{"a", "b", "c"};
+
+ // Data for |writer|. The first 2 bytes are provided in a larger chunk than
+ // the |compare_reader| does.
+ const std::vector<std::string> data_from_net{"ab", "x"};
+
+ // Data for |copy_reader|. The comparison between cache and network data fails
+ // at the 3rd byte, so the cache writer will read only first 2 bytes from the
+ // |copy_reader|.
+ const std::vector<std::string> data_to_copy{"ab"};
+
+ // The written data is expected to be identical with |data_from_net|.
+ const std::vector<std::string> data_expected{"ab", "x"};
+
+ size_t bytes_cached = 0;
+ size_t bytes_from_net = 0;
+ size_t bytes_common = 0;
+
+ for (const auto& data : data_from_cache)
+ bytes_cached += data.size();
+
+ for (const auto& data : data_from_net)
+ bytes_from_net += data.size();
+
+ for (const auto& data : data_to_copy)
+ bytes_common += data.size();
+
+ MockServiceWorkerResponseWriter* writer = ExpectWriter();
+ MockServiceWorkerResponseReader* compare_reader = ExpectReader();
+ MockServiceWorkerResponseReader* copy_reader = ExpectReader();
+
+ compare_reader->ExpectReadInfoOk(bytes_cached, false);
+ for (const auto& data : data_from_cache)
+ compare_reader->ExpectReadDataOk(data, false);
+
+ copy_reader->ExpectReadInfoOk(bytes_common, false);
+ for (const auto& data : data_to_copy)
+ copy_reader->ExpectReadDataOk(data, false);
+
+ writer->ExpectWriteInfoOk(bytes_from_net, false);
+ for (const auto& data : data_expected)
+ writer->ExpectWriteDataOk(data.size(), false);
+
+ Initialize();
+
+ net::Error error = WriteHeaders(bytes_from_net);
+ EXPECT_EQ(net::OK, error);
+ for (const auto& data : data_from_net) {
+ error = WriteData(data);
+ EXPECT_EQ(net::OK, error);
+ }
+
+ EXPECT_TRUE(writer->AllExpectedWritesDone());
+ EXPECT_TRUE(compare_reader->AllExpectedReadsDone());
+ EXPECT_TRUE(copy_reader->AllExpectedReadsDone());
+}
+
} // namespace
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_consts.cc b/chromium/content/browser/service_worker/service_worker_consts.cc
index 0a6663fa0c5..b149396d1c3 100644
--- a/chromium/content/browser/service_worker/service_worker_consts.cc
+++ b/chromium/content/browser/service_worker/service_worker_consts.cc
@@ -46,6 +46,9 @@ const char ServiceWorkerConsts::kSetNavigationPreloadHeaderErrorPrefix[] =
const char ServiceWorkerConsts::kShutdownErrorMessage[] =
"The Service Worker system has shutdown.";
+const char ServiceWorkerConsts::kUpdateTimeoutErrorMesage[] =
+ "Service worker self-update limit exceeded.";
+
const char ServiceWorkerConsts::kUserDeniedPermissionMessage[] =
"The user denied permission to use Service Worker.";
diff --git a/chromium/content/browser/service_worker/service_worker_consts.h b/chromium/content/browser/service_worker/service_worker_consts.h
index d119a472c79..1eab9d5b933 100644
--- a/chromium/content/browser/service_worker/service_worker_consts.h
+++ b/chromium/content/browser/service_worker/service_worker_consts.h
@@ -21,6 +21,7 @@ struct ServiceWorkerConsts {
static const char kNoDocumentURLErrorMessage[];
static const char kSetNavigationPreloadHeaderErrorPrefix[];
static const char kShutdownErrorMessage[];
+ static const char kUpdateTimeoutErrorMesage[];
static const char kUserDeniedPermissionMessage[];
};
diff --git a/chromium/content/browser/service_worker/service_worker_content_settings_proxy_impl.cc b/chromium/content/browser/service_worker/service_worker_content_settings_proxy_impl.cc
index e4b82677f15..3ba2c39cc15 100644
--- a/chromium/content/browser/service_worker/service_worker_content_settings_proxy_impl.cc
+++ b/chromium/content/browser/service_worker/service_worker_content_settings_proxy_impl.cc
@@ -4,9 +4,13 @@
#include "content/browser/service_worker/service_worker_content_settings_proxy_impl.h"
+#include <utility>
+#include <vector>
+
#include "base/threading/thread.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/global_routing_id.h"
#include "content/public/common/content_client.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
@@ -40,7 +44,7 @@ void ServiceWorkerContentSettingsProxyImpl::AllowIndexedDB(
// content setting. However, service worker is not necessarily associated
// with frames or making the request on behalf of frames,
// so just pass an empty |render_frames|.
- std::vector<std::pair<int, int>> render_frames;
+ std::vector<GlobalFrameRoutingId> render_frames;
std::move(callback).Run(GetContentClient()->browser()->AllowWorkerIndexedDB(
origin_.GetURL(), name, context_->wrapper()->resource_context(),
render_frames));
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 8e6f44affb4..df3b6835062 100644
--- a/chromium/content/browser/service_worker/service_worker_context_core.cc
+++ b/chromium/content/browser/service_worker/service_worker_context_core.cc
@@ -21,6 +21,7 @@
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/service_worker/embedded_worker_registry.h"
#include "content/browser/service_worker/embedded_worker_status.h"
+#include "content/browser/service_worker/service_worker_consts.h"
#include "content/browser/service_worker/service_worker_context_core_observer.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_info.h"
@@ -197,6 +198,7 @@ class RegistrationDeletionListener
scoped_refptr<ServiceWorkerRegistration> registration_;
base::OnceClosure callback_;
};
+
} // namespace
const base::FilePath::CharType
@@ -442,6 +444,13 @@ void ServiceWorkerContextCore::RegisterServiceWorker(
const blink::mojom::ServiceWorkerRegistrationOptions& options,
RegistrationCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ std::string error_message;
+ if (!IsValidRegisterRequest(script_url, options.scope, &error_message)) {
+ std::move(callback).Run(
+ blink::ServiceWorkerStatusCode::kErrorInvalidArguments, error_message,
+ blink::mojom::kInvalidServiceWorkerRegistrationId);
+ return;
+ }
was_service_worker_registered_ = true;
job_coordinator_->Register(
script_url, options,
@@ -573,6 +582,26 @@ void ServiceWorkerContextCore::UnregistrationComplete(
}
}
+bool ServiceWorkerContextCore::IsValidRegisterRequest(
+ const GURL& script_url,
+ const GURL& scope_url,
+ std::string* out_error) const {
+ if (!scope_url.is_valid() || !script_url.is_valid()) {
+ *out_error = ServiceWorkerConsts::kBadMessageInvalidURL;
+ return false;
+ }
+ if (ServiceWorkerUtils::ContainsDisallowedCharacter(scope_url, script_url,
+ out_error)) {
+ return false;
+ }
+ std::vector<GURL> urls = {scope_url, script_url};
+ if (!ServiceWorkerUtils::AllOriginsMatchAndCanAccessServiceWorkers(urls)) {
+ *out_error = ServiceWorkerConsts::kBadMessageImproperOrigins;
+ return false;
+ }
+ return true;
+}
+
ServiceWorkerRegistration* ServiceWorkerContextCore::GetLiveRegistration(
int64_t id) {
RegistrationsMap::iterator it = live_registrations_.find(id);
@@ -749,7 +778,7 @@ void ServiceWorkerContextCore::OnVersionStateChanged(
ServiceWorkerVersion* version) {
observer_list_->Notify(
FROM_HERE, &ServiceWorkerContextCoreObserver::OnVersionStateChanged,
- version->version_id(), version->status());
+ version->version_id(), version->scope(), version->status());
}
void ServiceWorkerContextCore::OnDevToolsRoutingIdChanged(
@@ -807,9 +836,9 @@ void ServiceWorkerContextCore::OnControlleeAdded(
ServiceWorkerVersion* version,
const std::string& client_uuid,
const ServiceWorkerClientInfo& client_info) {
- observer_list_->Notify(FROM_HERE,
- &ServiceWorkerContextCoreObserver::OnControlleeAdded,
- version->version_id(), client_uuid, client_info);
+ observer_list_->Notify(
+ FROM_HERE, &ServiceWorkerContextCoreObserver::OnControlleeAdded,
+ version->version_id(), version->scope(), client_uuid, client_info);
}
void ServiceWorkerContextCore::OnControlleeRemoved(
@@ -817,7 +846,13 @@ void ServiceWorkerContextCore::OnControlleeRemoved(
const std::string& client_uuid) {
observer_list_->Notify(FROM_HERE,
&ServiceWorkerContextCoreObserver::OnControlleeRemoved,
- version->version_id(), client_uuid);
+ version->version_id(), version->scope(), client_uuid);
+}
+
+void ServiceWorkerContextCore::OnNoControllees(ServiceWorkerVersion* version) {
+ observer_list_->Notify(FROM_HERE,
+ &ServiceWorkerContextCoreObserver::OnNoControllees,
+ version->version_id(), version->scope());
}
ServiceWorkerProcessManager* ServiceWorkerContextCore::process_manager() {
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 9a299aa9eb2..e75d5b6fd82 100644
--- a/chromium/content/browser/service_worker/service_worker_context_core.h
+++ b/chromium/content/browser/service_worker/service_worker_context_core.h
@@ -152,6 +152,7 @@ class CONTENT_EXPORT ServiceWorkerContextCore
const ServiceWorkerClientInfo& client_info) override;
void OnControlleeRemoved(ServiceWorkerVersion* version,
const std::string& client_uuid) override;
+ void OnNoControllees(ServiceWorkerVersion* version) override;
ServiceWorkerContextWrapper* wrapper() const { return wrapper_; }
ServiceWorkerStorage* storage() { return storage_.get(); }
@@ -318,6 +319,10 @@ class CONTENT_EXPORT ServiceWorkerContextCore
int64_t registration_id,
blink::ServiceWorkerStatusCode status);
+ bool IsValidRegisterRequest(const GURL& script_url,
+ const GURL& scope_url,
+ std::string* out_error) const;
+
void DidGetRegistrationsForDeleteForOrigin(
base::OnceCallback<void(blink::ServiceWorkerStatusCode)> callback,
blink::ServiceWorkerStatusCode status,
diff --git a/chromium/content/browser/service_worker/service_worker_context_core_observer.h b/chromium/content/browser/service_worker/service_worker_context_core_observer.h
index 0787d0ed5c3..cc4a5d6d6b2 100644
--- a/chromium/content/browser/service_worker/service_worker_context_core_observer.h
+++ b/chromium/content/browser/service_worker/service_worker_context_core_observer.h
@@ -64,6 +64,7 @@ class ServiceWorkerContextCoreObserver {
virtual void OnRunningStateChanged(int64_t version_id,
EmbeddedWorkerStatus running_status) {}
virtual void OnVersionStateChanged(int64_t version_id,
+ const GURL& scope,
ServiceWorkerVersion::Status status) {}
virtual void OnVersionDevToolsRoutingIdChanged(int64_t version_id,
int process_id,
@@ -76,10 +77,13 @@ class ServiceWorkerContextCoreObserver {
virtual void OnReportConsoleMessage(int64_t version_id,
const ConsoleMessage& message) {}
virtual void OnControlleeAdded(int64_t version_id,
+ const GURL& scope,
const std::string& uuid,
const ServiceWorkerClientInfo& info) {}
virtual void OnControlleeRemoved(int64_t version_id,
+ const GURL& scope,
const std::string& uuid) {}
+ virtual void OnNoControllees(int64_t version_id, const GURL& scope) {}
// Called when the ServiceWorkerContainer.register() promise is resolved.
//
// This is called before the service worker registration is persisted to
diff --git a/chromium/content/browser/service_worker/service_worker_context_request_handler.cc b/chromium/content/browser/service_worker/service_worker_context_request_handler.cc
index 1fcb4c80b49..1570948c6ef 100644
--- a/chromium/content/browser/service_worker/service_worker_context_request_handler.cc
+++ b/chromium/content/browser/service_worker/service_worker_context_request_handler.cc
@@ -67,8 +67,6 @@ std::string ServiceWorkerContextRequestHandler::CreateJobStatusToString(
return "ERROR_UNINSTALLED_SCRIPT_IMPORT";
case CreateJobStatus::ERROR_OUT_OF_RESOURCE_IDS:
return "ERROR_OUT_OF_RESOURCE_IDS";
- case CreateJobStatus::NUM_TYPES:
- NOTREACHED();
}
NOTREACHED() << static_cast<int>(status);
return "UNKNOWN";
diff --git a/chromium/content/browser/service_worker/service_worker_context_request_handler.h b/chromium/content/browser/service_worker/service_worker_context_request_handler.h
index 26bf3869d41..4c9fa5c784a 100644
--- a/chromium/content/browser/service_worker/service_worker_context_request_handler.h
+++ b/chromium/content/browser/service_worker/service_worker_context_request_handler.h
@@ -51,7 +51,7 @@ class CONTENT_EXPORT ServiceWorkerContextRequestHandler
ERROR_OUT_OF_RESOURCE_IDS,
// Add new types here.
- NUM_TYPES
+ kMaxValue = ERROR_OUT_OF_RESOURCE_IDS,
};
ServiceWorkerContextRequestHandler(
diff --git a/chromium/content/browser/service_worker/service_worker_context_request_handler_unittest.cc b/chromium/content/browser/service_worker/service_worker_context_request_handler_unittest.cc
index cdf3aa4bb4c..692d21dc1f8 100644
--- a/chromium/content/browser/service_worker/service_worker_context_request_handler_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_context_request_handler_unittest.cc
@@ -31,6 +31,7 @@
#include "services/network/public/mojom/request_context_frame_type.mojom.h"
#include "storage/browser/blob/blob_storage_context.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
namespace content {
@@ -60,6 +61,11 @@ class ServiceWorkerContextRequestHandlerTest : public testing::Test {
: browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}
void SetUp() override {
+ // ServiceWorkerContextRequestHandler is a non-S13nServiceWorker specific
+ // class and we don't use it when S13nServiceWorker is enabled.
+ scoped_feature_list_.InitAndDisableFeature(
+ blink::features::kServiceWorkerServicification);
+
helper_.reset(new EmbeddedWorkerTestHelper(base::FilePath()));
context()->storage()->LazyInitializeForTest(base::DoNothing());
base::RunLoop().RunUntilIdle();
@@ -156,6 +162,9 @@ class ServiceWorkerContextRequestHandlerTest : public testing::Test {
}
protected:
+ // |scoped_feature_list_| must be before |thread_bundle_|.
+ // See comments in ServiceWorkerProviderHostTest.
+ base::test::ScopedFeatureList scoped_feature_list_;
TestBrowserThreadBundle browser_thread_bundle_;
std::unique_ptr<EmbeddedWorkerTestHelper> helper_;
scoped_refptr<ServiceWorkerRegistration> registration_;
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 f7c92935136..7ca85191c7b 100644
--- a/chromium/content/browser/service_worker/service_worker_context_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_context_unittest.cc
@@ -20,7 +20,7 @@
#include "content/browser/service_worker/service_worker_storage.h"
#include "content/browser/service_worker/service_worker_test_utils.h"
#include "content/browser/service_worker/service_worker_version.h"
-#include "content/common/service_worker/service_worker_messages.h"
+#include "content/public/browser/service_worker_context_observer.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -169,6 +169,9 @@ class ServiceWorkerContextTest : public ServiceWorkerContextCoreObserver,
}
ServiceWorkerContextCore* context() { return helper_->context(); }
+ ServiceWorkerContextWrapper* context_wrapper() {
+ return helper_->context_wrapper();
+ }
protected:
TestBrowserThreadBundle browser_thread_bundle_;
@@ -205,6 +208,182 @@ class RecordableEmbeddedWorkerInstanceClient
DISALLOW_COPY_AND_ASSIGN(RecordableEmbeddedWorkerInstanceClient);
};
+class TestServiceWorkerContextObserver : public ServiceWorkerContextObserver {
+ public:
+ enum class EventType {
+ RegistrationCompleted,
+ VersionActivated,
+ VersionRedundant,
+ NoControllees
+ };
+ struct EventLog {
+ EventType type;
+ base::Optional<GURL> url;
+ base::Optional<int64_t> version_id;
+ };
+
+ explicit TestServiceWorkerContextObserver(ServiceWorkerContext* context)
+ : context_(context) {
+ context_->AddObserver(this);
+ };
+
+ ~TestServiceWorkerContextObserver() override {
+ context_->RemoveObserver(this);
+ }
+
+ void OnRegistrationCompleted(const GURL& scope) override {
+ EventLog log;
+ log.type = EventType::RegistrationCompleted;
+ log.url = scope;
+ events_.push_back(log);
+ }
+
+ void OnVersionActivated(int64_t version_id, const GURL& scope) override {
+ EventLog log;
+ log.type = EventType::VersionActivated;
+ log.version_id = version_id;
+ log.url = scope;
+ events_.push_back(log);
+ }
+
+ void OnVersionRedundant(int64_t version_id, const GURL& scope) override {
+ EventLog log;
+ log.type = EventType::VersionRedundant;
+ log.version_id = version_id;
+ log.url = scope;
+ events_.push_back(log);
+ }
+
+ void OnNoControllees(int64_t version_id, const GURL& scope) override {
+ EventLog log;
+ log.type = EventType::NoControllees;
+ log.version_id = version_id;
+ log.url = scope;
+ events_.push_back(log);
+ }
+
+ const std::vector<EventLog>& events() { return events_; }
+
+ private:
+ ServiceWorkerContext* context_;
+ std::vector<EventLog> events_;
+ DISALLOW_COPY_AND_ASSIGN(TestServiceWorkerContextObserver);
+};
+
+// Make sure OnRegistrationCompleted is called on observer.
+TEST_F(ServiceWorkerContextTest, RegistrationCompletedObserver) {
+ GURL pattern("https://www.example.com/");
+ GURL script_url("https://www.example.com/service_worker.js");
+ blink::mojom::ServiceWorkerRegistrationOptions options;
+ options.scope = pattern;
+
+ TestServiceWorkerContextObserver observer(context_wrapper());
+
+ int64_t registration_id = blink::mojom::kInvalidServiceWorkerRegistrationId;
+ bool called = false;
+ context()->RegisterServiceWorker(
+ script_url, options, MakeRegisteredCallback(&called, &registration_id));
+ base::RunLoop().RunUntilIdle();
+
+ ASSERT_TRUE(called);
+ EXPECT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, registration_id);
+ ASSERT_EQ(2u, observer.events().size());
+ EXPECT_EQ(TestServiceWorkerContextObserver::EventType::RegistrationCompleted,
+ observer.events()[0].type);
+ EXPECT_EQ(pattern, observer.events()[0].url);
+ EXPECT_EQ(TestServiceWorkerContextObserver::EventType::VersionActivated,
+ observer.events()[1].type);
+ EXPECT_EQ(pattern, observer.events()[1].url);
+}
+
+// Make sure OnNoControllees is called on observer.
+TEST_F(ServiceWorkerContextTest, NoControlleesObserver) {
+ GURL pattern("https://www.example.com/");
+ GURL script_url("https://www.example.com/service_worker.js");
+ blink::mojom::ServiceWorkerRegistrationOptions options;
+ options.scope = pattern;
+
+ auto registration = base::MakeRefCounted<ServiceWorkerRegistration>(
+ options, 1l /* dummy registration id */, context()->AsWeakPtr());
+
+ auto version = base::MakeRefCounted<ServiceWorkerVersion>(
+ registration.get(), script_url, 2l /* dummy version id */,
+ context()->AsWeakPtr());
+
+ ServiceWorkerRemoteProviderEndpoint endpoint;
+ std::unique_ptr<ServiceWorkerProviderHost> host =
+ CreateProviderHostForWindow(helper_->mock_render_process_id(), 1, true,
+ context()->AsWeakPtr(), &endpoint);
+
+ version->AddControllee(host.get());
+ base::RunLoop().RunUntilIdle();
+
+ TestServiceWorkerContextObserver observer(context_wrapper());
+
+ version->RemoveControllee(host->client_uuid());
+ base::RunLoop().RunUntilIdle();
+
+ ASSERT_EQ(1u, observer.events().size());
+ EXPECT_EQ(TestServiceWorkerContextObserver::EventType::NoControllees,
+ observer.events()[0].type);
+ EXPECT_EQ(pattern, observer.events()[0].url);
+ EXPECT_EQ(2l, observer.events()[0].version_id);
+}
+
+// Make sure OnVersionActivated is called on observer.
+TEST_F(ServiceWorkerContextTest, VersionActivatedObserver) {
+ GURL pattern("https://www.example.com/");
+ GURL script_url("https://www.example.com/service_worker.js");
+ blink::mojom::ServiceWorkerRegistrationOptions options;
+ options.scope = pattern;
+
+ auto registration = base::MakeRefCounted<ServiceWorkerRegistration>(
+ options, 1l /* dummy registration id */, context()->AsWeakPtr());
+
+ auto version = base::MakeRefCounted<ServiceWorkerVersion>(
+ registration.get(), script_url, 2l /* dummy version id */,
+ context()->AsWeakPtr());
+
+ TestServiceWorkerContextObserver observer(context_wrapper());
+
+ version->set_fetch_handler_existence(
+ ServiceWorkerVersion::FetchHandlerExistence::DOES_NOT_EXIST);
+ version->SetStatus(ServiceWorkerVersion::Status::ACTIVATED);
+ base::RunLoop().RunUntilIdle();
+
+ ASSERT_EQ(1u, observer.events().size());
+ EXPECT_EQ(TestServiceWorkerContextObserver::EventType::VersionActivated,
+ observer.events()[0].type);
+ EXPECT_EQ(2l, observer.events()[0].version_id);
+}
+
+// Make sure OnVersionRedundant is called on observer.
+TEST_F(ServiceWorkerContextTest, VersionRedundantObserver) {
+ GURL pattern("https://www.example.com/");
+ GURL script_url("https://www.example.com/service_worker.js");
+ blink::mojom::ServiceWorkerRegistrationOptions options;
+ options.scope = pattern;
+
+ auto registration = base::MakeRefCounted<ServiceWorkerRegistration>(
+ options, 1l /* dummy registration id */, context()->AsWeakPtr());
+
+ auto version = base::MakeRefCounted<ServiceWorkerVersion>(
+ registration.get(), script_url, 2l /* dummy version id */,
+ context()->AsWeakPtr());
+
+ TestServiceWorkerContextObserver observer(context_wrapper());
+
+ version->set_fetch_handler_existence(
+ ServiceWorkerVersion::FetchHandlerExistence::DOES_NOT_EXIST);
+ version->SetStatus(ServiceWorkerVersion::Status::REDUNDANT);
+ base::RunLoop().RunUntilIdle();
+
+ ASSERT_EQ(1u, observer.events().size());
+ EXPECT_EQ(TestServiceWorkerContextObserver::EventType::VersionRedundant,
+ observer.events()[0].type);
+ EXPECT_EQ(2l, observer.events()[0].version_id);
+}
+
// Make sure basic registration is working.
TEST_F(ServiceWorkerContextTest, Register) {
GURL pattern("https://www.example.com/");
diff --git a/chromium/content/browser/service_worker/service_worker_context_watcher.cc b/chromium/content/browser/service_worker/service_worker_context_watcher.cc
index 5bb4c8f5527..93255031e6d 100644
--- a/chromium/content/browser/service_worker/service_worker_context_watcher.cc
+++ b/chromium/content/browser/service_worker/service_worker_context_watcher.cc
@@ -248,6 +248,7 @@ void ServiceWorkerContextWatcher::OnRunningStateChanged(
void ServiceWorkerContextWatcher::OnVersionStateChanged(
int64_t version_id,
+ const GURL& scope,
content::ServiceWorkerVersion::Status status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
auto it = version_info_map_.find(version_id);
@@ -332,6 +333,7 @@ void ServiceWorkerContextWatcher::OnReportConsoleMessage(
void ServiceWorkerContextWatcher::OnControlleeAdded(
int64_t version_id,
+ const GURL& scope,
const std::string& uuid,
const ServiceWorkerClientInfo& info) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -344,6 +346,7 @@ void ServiceWorkerContextWatcher::OnControlleeAdded(
}
void ServiceWorkerContextWatcher::OnControlleeRemoved(int64_t version_id,
+ const GURL& scope,
const std::string& uuid) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
auto it = version_info_map_.find(version_id);
diff --git a/chromium/content/browser/service_worker/service_worker_context_watcher.h b/chromium/content/browser/service_worker/service_worker_context_watcher.h
index 1eb56b76459..3d3e20c248d 100644
--- a/chromium/content/browser/service_worker/service_worker_context_watcher.h
+++ b/chromium/content/browser/service_worker/service_worker_context_watcher.h
@@ -89,6 +89,7 @@ class CONTENT_EXPORT ServiceWorkerContextWatcher
content::EmbeddedWorkerStatus running_status) override;
void OnVersionStateChanged(
int64_t version_id,
+ const GURL& scope,
content::ServiceWorkerVersion::Status status) override;
void OnVersionDevToolsRoutingIdChanged(int64_t version_id,
int process_id,
@@ -102,9 +103,11 @@ class CONTENT_EXPORT ServiceWorkerContextWatcher
void OnReportConsoleMessage(int64_t version_id,
const ConsoleMessage& message) override;
void OnControlleeAdded(int64_t version_id,
+ const GURL& scope,
const std::string& uuid,
const ServiceWorkerClientInfo& info) override;
void OnControlleeRemoved(int64_t version_id,
+ const GURL& scope,
const std::string& uuid) override;
void OnRegistrationCompleted(int64_t registration_id,
const GURL& pattern) override;
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 9927359ee1b..4203d20bd22 100644
--- a/chromium/content/browser/service_worker/service_worker_context_wrapper.cc
+++ b/chromium/content/browser/service_worker/service_worker_context_wrapper.cc
@@ -12,12 +12,14 @@
#include "base/barrier_closure.h"
#include "base/bind.h"
+#include "base/feature_list.h"
#include "base/files/file_path.h"
+#include "base/guid.h"
#include "base/lazy_instance.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/single_thread_task_runner.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/service_worker/embedded_worker_status.h"
#include "content/browser/service_worker/service_worker_process_manager.h"
@@ -28,19 +30,21 @@
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/service_worker_context_observer.h"
+#include "content/public/common/content_features.h"
#include "net/base/url_util.h"
#include "storage/browser/quota/quota_manager_proxy.h"
#include "storage/browser/quota/special_storage_policy.h"
#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
+#include "url/gurl.h"
namespace content {
namespace {
-typedef std::set<std::string> HeaderNameSet;
-base::LazyInstance<HeaderNameSet>::DestructorAtExit g_excluded_header_name_set =
- LAZY_INSTANCE_INITIALIZER;
+// Value used to set the timeout when starting a long running ServiceWorker. See
+// ServiceWorkerContextWrapper::StartServiceWorkerAndDispatchLongRunningMessage.
+const int kActiveWorkerTimeoutDays = 999;
void WorkerStarted(ServiceWorkerContextWrapper::StatusCallback callback,
blink::ServiceWorkerStatusCode status) {
@@ -90,7 +94,9 @@ void DidStartWorker(scoped_refptr<ServiceWorkerVersion> version,
return;
}
EmbeddedWorkerInstance* instance = version->embedded_worker();
- std::move(info_callback).Run(instance->process_id(), instance->thread_id());
+ std::move(info_callback)
+ .Run(version->version_id(), instance->process_id(),
+ instance->thread_id());
}
void FoundRegistrationForStartWorker(
@@ -152,29 +158,37 @@ void FinishUnregistrationOnIO(ServiceWorkerContext::ResultCallback callback,
status == blink::ServiceWorkerStatusCode::kOk));
}
-} // namespace
-
-// static
-void ServiceWorkerContext::AddExcludedHeadersForFetchEvent(
- const std::set<std::string>& header_names) {
+void MessageFinishedSending(ServiceWorkerContext::ResultCallback callback,
+ blink::ServiceWorkerStatusCode status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- g_excluded_header_name_set.Get().insert(header_names.begin(),
- header_names.end());
+ std::move(callback).Run(status == blink::ServiceWorkerStatusCode::kOk);
}
-// static
-bool ServiceWorkerContext::IsExcludedHeaderNameForFetchEvent(
- const std::string& header_name) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- return g_excluded_header_name_set.Get().find(header_name) !=
- g_excluded_header_name_set.Get().end();
+void RunOnceClosure(scoped_refptr<ServiceWorkerContextWrapper> ref_holder,
+ base::OnceClosure task) {
+ std::move(task).Run();
}
+} // namespace
+
// static
bool ServiceWorkerContext::ScopeMatches(const GURL& scope, const GURL& url) {
return ServiceWorkerUtils::ScopeMatches(scope, url);
}
+// static
+void ServiceWorkerContext::RunTask(
+ scoped_refptr<base::SequencedTaskRunner> task_runner,
+ const base::Location& from_here,
+ ServiceWorkerContext* service_worker_context,
+ base::OnceClosure task) {
+ auto ref = base::WrapRefCounted(
+ static_cast<ServiceWorkerContextWrapper*>(service_worker_context));
+ task_runner->PostTask(
+ from_here,
+ base::BindOnce(&RunOnceClosure, std::move(ref), std::move(task)));
+}
+
ServiceWorkerContextWrapper::ServiceWorkerContextWrapper(
BrowserContext* browser_context)
: core_observer_list_(
@@ -262,6 +276,25 @@ void ServiceWorkerContextWrapper::OnRegistrationCompleted(
observer.OnRegistrationCompleted(pattern);
}
+void ServiceWorkerContextWrapper::OnNoControllees(int64_t version_id,
+ const GURL& scope) {
+ for (auto& observer : observer_list_)
+ observer.OnNoControllees(version_id, scope);
+}
+
+void ServiceWorkerContextWrapper::OnVersionStateChanged(
+ int64_t version_id,
+ const GURL& scope,
+ ServiceWorkerVersion::Status status) {
+ if (status == ServiceWorkerVersion::Status::ACTIVATED) {
+ for (auto& observer : observer_list_)
+ observer.OnVersionActivated(version_id, scope);
+ } else if (status == ServiceWorkerVersion::Status::REDUNDANT) {
+ for (auto& observer : observer_list_)
+ observer.OnVersionRedundant(version_id, scope);
+ }
+}
+
void ServiceWorkerContextWrapper::AddObserver(
ServiceWorkerContextObserver* observer) {
observer_list_.AddObserver(observer);
@@ -434,6 +467,84 @@ void ServiceWorkerContextWrapper::StartWorkerForPattern(
std::move(failure_callback)));
}
+void ServiceWorkerContextWrapper::
+ StartServiceWorkerAndDispatchLongRunningMessage(
+ const GURL& pattern,
+ blink::TransferableMessage message,
+ ResultCallback result_callback) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ if (!base::FeatureList::IsEnabled(
+ features::kServiceWorkerLongRunningMessage)) {
+ std::move(result_callback).Run(false);
+ return;
+ }
+
+ if (!context_core_) {
+ std::move(result_callback).Run(false);
+ return;
+ }
+
+ context_core_->storage()->FindRegistrationForPattern(
+ net::SimplifyUrlForRequest(pattern),
+ base::BindOnce(&ServiceWorkerContextWrapper::
+ DidFindRegistrationForLongRunningMessage,
+ this, std::move(message), pattern,
+ std::move(result_callback)));
+}
+
+void ServiceWorkerContextWrapper::DidFindRegistrationForLongRunningMessage(
+ blink::TransferableMessage message,
+ const GURL& source_origin,
+ ResultCallback result_callback,
+ blink::ServiceWorkerStatusCode service_worker_status,
+ scoped_refptr<ServiceWorkerRegistration> registration) {
+ if (service_worker_status != blink::ServiceWorkerStatusCode::kOk) {
+ LOG(WARNING) << "No registration available, status: "
+ << static_cast<int>(service_worker_status);
+ std::move(result_callback).Run(false);
+ return;
+ }
+ registration->active_version()->StartWorker(
+ ServiceWorkerMetrics::EventType::LONG_RUNNING_MESSAGE,
+ base::BindOnce(&ServiceWorkerContextWrapper::
+ DidStartServiceWorkerForLongRunningMessage,
+ this, std::move(message), source_origin, registration,
+ std::move(result_callback)));
+}
+
+void ServiceWorkerContextWrapper::DidStartServiceWorkerForLongRunningMessage(
+ blink::TransferableMessage message,
+ const GURL& source_origin,
+ scoped_refptr<ServiceWorkerRegistration> registration,
+ ResultCallback result_callback,
+ blink::ServiceWorkerStatusCode status) {
+ if (status != blink::ServiceWorkerStatusCode::kOk) {
+ std::move(result_callback).Run(false);
+ return;
+ }
+
+ scoped_refptr<ServiceWorkerVersion> version = registration->active_version();
+
+ int request_id = version->StartRequestWithCustomTimeout(
+ ServiceWorkerMetrics::EventType::LONG_RUNNING_MESSAGE,
+ base::BindOnce(&MessageFinishedSending, std::move(result_callback)),
+ base::TimeDelta::FromDays(kActiveWorkerTimeoutDays),
+ ServiceWorkerVersion::CONTINUE_ON_TIMEOUT);
+
+ mojom::ExtendableMessageEventPtr event = mojom::ExtendableMessageEvent::New();
+ event->message = std::move(message);
+ event->source_origin = url::Origin::Create(source_origin);
+ event->source_info_for_service_worker =
+ version->provider_host()
+ ->GetOrCreateServiceWorkerObjectHost(version)
+ ->CreateCompleteObjectInfoToSend();
+
+ version->endpoint()->DispatchExtendableMessageEventWithCustomTimeout(
+ std::move(event), base::TimeDelta::FromDays(kActiveWorkerTimeoutDays),
+ version->CreateSimpleEventCallback(request_id));
+}
+
void ServiceWorkerContextWrapper::StartServiceWorkerForNavigationHint(
const GURL& document_url,
StartServiceWorkerForNavigationHintCallback callback) {
@@ -530,20 +641,20 @@ void ServiceWorkerContextWrapper::HasMainFrameProviderHost(
context_core_->HasMainFrameProviderHost(origin, std::move(callback));
}
-std::unique_ptr<std::vector<std::pair<int, int>>>
+std::unique_ptr<std::vector<GlobalFrameRoutingId>>
ServiceWorkerContextWrapper::GetProviderHostIds(const GURL& origin) const {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- std::unique_ptr<std::vector<std::pair<int, int>>> provider_host_ids(
- new std::vector<std::pair<int, int>>());
+ std::unique_ptr<std::vector<GlobalFrameRoutingId>> provider_host_ids(
+ new std::vector<GlobalFrameRoutingId>());
for (std::unique_ptr<ServiceWorkerContextCore::ProviderHostIterator> it =
context_core_->GetClientProviderHostIterator(
origin, false /* include_reserved_clients */);
!it->IsAtEnd(); it->Advance()) {
ServiceWorkerProviderHost* provider_host = it->GetProviderHost();
- provider_host_ids->push_back(
- std::make_pair(provider_host->process_id(), provider_host->frame_id()));
+ provider_host_ids->push_back(GlobalFrameRoutingId(
+ provider_host->process_id(), provider_host->frame_id()));
}
return provider_host_ids;
diff --git a/chromium/content/browser/service_worker/service_worker_context_wrapper.h b/chromium/content/browser/service_worker/service_worker_context_wrapper.h
index f1b9b94c5cc..7766bd2311a 100644
--- a/chromium/content/browser/service_worker/service_worker_context_wrapper.h
+++ b/chromium/content/browser/service_worker/service_worker_context_wrapper.h
@@ -19,6 +19,7 @@
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_context_core_observer.h"
#include "content/common/content_export.h"
+#include "content/public/browser/global_routing_id.h"
#include "content/public/browser/service_worker_context.h"
namespace base {
@@ -101,6 +102,10 @@ class CONTENT_EXPORT ServiceWorkerContextWrapper
// ServiceWorkerContextCoreObserver implementation:
void OnRegistrationCompleted(int64_t registration_id,
const GURL& pattern) override;
+ void OnNoControllees(int64_t version_id, const GURL& scope) override;
+ void OnVersionStateChanged(int64_t version_id,
+ const GURL& scope,
+ ServiceWorkerVersion::Status status) override;
// ServiceWorkerContext implementation:
void AddObserver(ServiceWorkerContextObserver* observer) override;
@@ -127,6 +132,10 @@ class CONTENT_EXPORT ServiceWorkerContextWrapper
void StartWorkerForPattern(const GURL& pattern,
StartWorkerCallback info_callback,
base::OnceClosure failure_callback) override;
+ void StartServiceWorkerAndDispatchLongRunningMessage(
+ const GURL& pattern,
+ blink::TransferableMessage message,
+ ResultCallback result_callback) override;
void StartServiceWorkerForNavigationHint(
const GURL& document_url,
StartServiceWorkerForNavigationHintCallback callback) override;
@@ -143,10 +152,9 @@ class CONTENT_EXPORT ServiceWorkerContextWrapper
void HasMainFrameProviderHost(const GURL& origin,
BoolCallback callback) const;
- // Returns all render process ids and frame ids for the given |origin|.
- std::unique_ptr<
- std::vector<std::pair<int /* render process id */, int /* frame id */>>>
- GetProviderHostIds(const GURL& origin) const;
+ // Returns all frame ids for the given |origin|.
+ std::unique_ptr<std::vector<GlobalFrameRoutingId>> GetProviderHostIds(
+ const GURL& origin) const;
// Returns the registration whose scope longest matches |document_url|. It is
// guaranteed that the returned registration has the activated worker.
@@ -354,6 +362,27 @@ class CONTENT_EXPORT ServiceWorkerContextWrapper
base::OnceClosure callback,
scoped_refptr<base::SingleThreadTaskRunner> task_runner_for_callback);
+ void DidFindRegistrationForLongRunningMessage(
+ blink::TransferableMessage message,
+ const GURL& source_origin,
+ ResultCallback result_callback,
+ blink::ServiceWorkerStatusCode service_worker_status,
+ scoped_refptr<ServiceWorkerRegistration> registration);
+
+ void DidStartServiceWorkerForLongRunningMessage(
+ blink::TransferableMessage message,
+ const GURL& source_origin,
+ scoped_refptr<ServiceWorkerRegistration> registration,
+ ServiceWorkerContext::ResultCallback result_callback,
+ blink::ServiceWorkerStatusCode service_worker_status);
+
+ void SendActiveWorkerMessage(
+ blink::TransferableMessage message,
+ const GURL& source_origin,
+ ServiceWorkerContext::ResultCallback result_callback,
+ blink::ServiceWorkerStatusCode status,
+ scoped_refptr<ServiceWorkerRegistration> registration);
+
// The core context is only for use on the IO thread.
// Can be null before/during init, during/after shutdown, and after
// DeleteAndStartOver fails.
@@ -367,7 +396,7 @@ class CONTENT_EXPORT ServiceWorkerContextWrapper
// Observers which live outside content's implementation boundary. Observer
// methods will always be dispatched on the UI thread.
- base::ObserverList<ServiceWorkerContextObserver> observer_list_;
+ base::ObserverList<ServiceWorkerContextObserver>::Unchecked observer_list_;
const std::unique_ptr<ServiceWorkerProcessManager> process_manager_;
// Cleared in ShutdownOnIO():
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 dc214676e02..8c7859bfbe6 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
@@ -4,9 +4,8 @@
#include "content/browser/service_worker/service_worker_controllee_request_handler.h"
-#include <memory>
#include <set>
-#include <string>
+#include <utility>
#include "base/trace_event/trace_event.h"
#include "components/offline_pages/buildflags/buildflags.h"
@@ -72,13 +71,73 @@ bool ShouldFallbackToLoadOfflinePage(
return false;
}
offline_pages::OfflinePageHeader offline_header(offline_header_value);
- return offline_header.reason ==
- offline_pages::OfflinePageHeader::Reason::DOWNLOAD;
+ return offline_header.reason !=
+ offline_pages::OfflinePageHeader::Reason::NONE &&
+ offline_header.reason !=
+ offline_pages::OfflinePageHeader::Reason::RELOAD;
}
#endif // BUILDFLAG(ENABLE_OFFLINE_PAGES)
} // namespace
+// RAII class that disallows calling SetControllerRegistration() on a provider
+// host.
+class ServiceWorkerControlleeRequestHandler::
+ ScopedDisallowSetControllerRegistration {
+ public:
+ explicit ScopedDisallowSetControllerRegistration(
+ base::WeakPtr<ServiceWorkerProviderHost> provider_host)
+ : provider_host_(std::move(provider_host)) {
+ DCHECK(provider_host_->IsSetControllerRegistrationAllowed())
+ << "The host already disallows using a registration; nested disallow "
+ "is not supported.";
+ provider_host_->AllowSetControllerRegistration(false);
+ }
+
+ ~ScopedDisallowSetControllerRegistration() {
+ if (!provider_host_)
+ return;
+ DCHECK(!provider_host_->IsSetControllerRegistrationAllowed())
+ << "Failed to disallow using a registration.";
+ provider_host_->AllowSetControllerRegistration(true);
+ }
+
+ private:
+ base::WeakPtr<ServiceWorkerProviderHost> provider_host_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedDisallowSetControllerRegistration);
+};
+
+class ServiceWorkerControlleeRequestHandler::MainResourceRequestTracker {
+ public:
+ MainResourceRequestTracker() = default;
+
+ ~MainResourceRequestTracker() {
+ if (recorded_destination_)
+ return;
+ RecordDestination(
+ will_dispatch_fetch_
+ ? ServiceWorkerMetrics::MainResourceRequestDestination::
+ kAbortedWhileDispatchingFetchEvent
+ : ServiceWorkerMetrics::MainResourceRequestDestination::
+ kAbortedWithoutDispatchingFetchEvent);
+ }
+
+ void RecordDestination(
+ ServiceWorkerMetrics::MainResourceRequestDestination destination) {
+ CHECK(!recorded_destination_);
+ recorded_destination_ = true;
+ ServiceWorkerMetrics::RecordMainResourceRequestDestination(destination);
+ }
+
+ void WillDispatchFetchEvent() { will_dispatch_fetch_ = true; }
+
+ private:
+ bool recorded_destination_ = false;
+ bool will_dispatch_fetch_ = false;
+ DISALLOW_COPY_AND_ASSIGN(MainResourceRequestTracker);
+};
+
ServiceWorkerControlleeRequestHandler::ServiceWorkerControlleeRequestHandler(
base::WeakPtr<ServiceWorkerContextCore> context,
base::WeakPtr<ServiceWorkerProviderHost> provider_host,
@@ -92,14 +151,13 @@ ServiceWorkerControlleeRequestHandler::ServiceWorkerControlleeRequestHandler(
RequestContextType request_context_type,
network::mojom::RequestContextFrameType frame_type,
scoped_refptr<network::ResourceRequestBody> body)
- : ServiceWorkerRequestHandler(context,
- provider_host,
- blob_storage_context,
+ : ServiceWorkerRequestHandler(std::move(context),
+ std::move(provider_host),
+ std::move(blob_storage_context),
resource_type),
resource_type_(resource_type),
is_main_resource_load_(
ServiceWorkerUtils::IsMainResourceType(resource_type)),
- is_main_frame_load_(resource_type == RESOURCE_TYPE_MAIN_FRAME),
request_mode_(request_mode),
credentials_mode_(credentials_mode),
redirect_mode_(redirect_mode),
@@ -107,7 +165,7 @@ ServiceWorkerControlleeRequestHandler::ServiceWorkerControlleeRequestHandler(
keepalive_(keepalive),
request_context_type_(request_context_type),
frame_type_(frame_type),
- body_(body),
+ body_(std::move(body)),
force_update_started_(false),
use_network_(false),
weak_factory_(this) {}
@@ -115,13 +173,10 @@ ServiceWorkerControlleeRequestHandler::ServiceWorkerControlleeRequestHandler(
ServiceWorkerControlleeRequestHandler::
~ServiceWorkerControlleeRequestHandler() {
MaybeScheduleUpdate();
-
- if (is_main_resource_load_ && provider_host_)
- provider_host_->SetAllowAssociation(true);
}
void ServiceWorkerControlleeRequestHandler::MaybeScheduleUpdate() {
- if (!provider_host_ || !provider_host_->active_version())
+ if (!provider_host_ || !provider_host_->controller())
return;
if (blink::ServiceWorkerUtils::IsServicificationEnabled()) {
@@ -145,9 +200,9 @@ void ServiceWorkerControlleeRequestHandler::MaybeScheduleUpdate() {
return;
if (is_main_resource_load_)
- provider_host_->active_version()->ScheduleUpdate();
+ provider_host_->controller()->ScheduleUpdate();
else
- provider_host_->active_version()->DeferScheduledUpdate();
+ provider_host_->controller()->DeferScheduledUpdate();
}
net::URLRequestJob* ServiceWorkerControlleeRequestHandler::MaybeCreateJob(
@@ -187,12 +242,11 @@ net::URLRequestJob* ServiceWorkerControlleeRequestHandler::MaybeCreateJob(
#endif // BUILDFLAG(ENABLE_OFFLINE_PAGES)
// It's for original request (A) or redirect case (B-a or B-b).
- std::unique_ptr<ServiceWorkerURLRequestJob> job(
- new ServiceWorkerURLRequestJob(
- request, network_delegate, provider_host_->client_uuid(),
- blob_storage_context_, resource_context, request_mode_,
- credentials_mode_, redirect_mode_, integrity_, keepalive_,
- resource_type_, request_context_type_, frame_type_, body_, this));
+ auto job = std::make_unique<ServiceWorkerURLRequestJob>(
+ request, network_delegate, provider_host_->client_uuid(),
+ blob_storage_context_, resource_context, request_mode_, credentials_mode_,
+ redirect_mode_, integrity_, keepalive_, resource_type_,
+ request_context_type_, frame_type_, body_, this);
url_job_ = std::make_unique<ServiceWorkerURLJobWrapper>(job->GetWeakPtr());
resource_context_ = resource_context;
@@ -220,9 +274,10 @@ net::URLRequestJob* ServiceWorkerControlleeRequestHandler::MaybeCreateJob(
}
void ServiceWorkerControlleeRequestHandler::MaybeCreateLoader(
- const network::ResourceRequest& resource_request,
+ const network::ResourceRequest& tentative_resource_request,
ResourceContext* resource_context,
- LoaderCallback callback) {
+ LoaderCallback callback,
+ FallbackCallback fallback_callback) {
DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled());
DCHECK(is_main_resource_load_);
ClearJob();
@@ -240,7 +295,13 @@ void ServiceWorkerControlleeRequestHandler::MaybeCreateLoader(
#if BUILDFLAG(ENABLE_OFFLINE_PAGES)
// Fall back for the subsequent offline page interceptor to load the offline
// snapshot of the page if required.
- if (ShouldFallbackToLoadOfflinePage(resource_request.headers)) {
+ //
+ // TODO(crbug.com/876527): Figure out how offline page interception should
+ // interact with URLLoaderThrottles. It might be incorrect to use
+ // |tentative_resource_request.headers| here, since throttles can rewrite
+ // headers between now and when the request handler passed to
+ // |loader_callback_| is invoked.
+ if (ShouldFallbackToLoadOfflinePage(tentative_resource_request.headers)) {
std::move(callback).Run({});
return;
}
@@ -248,13 +309,14 @@ void ServiceWorkerControlleeRequestHandler::MaybeCreateLoader(
url_job_ = std::make_unique<ServiceWorkerURLJobWrapper>(
std::make_unique<ServiceWorkerNavigationLoader>(
- std::move(callback), this, resource_request,
+ std::move(callback), std::move(fallback_callback), this,
+ tentative_resource_request,
base::WrapRefCounted(context_->loader_factory_getter())));
resource_context_ = resource_context;
- PrepareForMainResource(resource_request.url,
- resource_request.site_for_cookies);
+ PrepareForMainResource(tentative_resource_request.url,
+ tentative_resource_request.site_for_cookies);
if (url_job_->ShouldFallbackToNetwork()) {
// We're falling back to the next NavigationLoaderInterceptor, forward
@@ -277,7 +339,7 @@ ServiceWorkerControlleeRequestHandler::MaybeCreateSubresourceLoaderParams() {
// DidLookupRegistrationForMainResource() for the request didn't find
// a matching service worker for this request, and
- // ServiceWorkerProviderHost::AssociateRegistration() was not called.
+ // ServiceWorkerProviderHost::SetControllerRegistration() was not called.
if (!provider_host_ || !provider_host_->controller())
return base::nullopt;
@@ -311,40 +373,46 @@ void ServiceWorkerControlleeRequestHandler::PrepareForMainResource(
DCHECK(!JobWasCanceled());
DCHECK(context_);
DCHECK(provider_host_);
+ tracker_ = std::make_unique<MainResourceRequestTracker>();
+
TRACE_EVENT_ASYNC_BEGIN1(
"ServiceWorker",
"ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
url_job_.get(), "URL", url.spec());
- // The corresponding provider_host may already have associated a registration
- // in redirect case, unassociate it now.
- provider_host_->DisassociateRegistration();
+ // The provider host may already have set a controller in redirect case,
+ // unset it now.
+ provider_host_->SetControllerRegistration(
+ nullptr, false /* notify_controllerchange */);
- // Also prevent a register job from establishing an association to a new
- // registration while we're finding an existing registration.
- provider_host_->SetAllowAssociation(false);
+ // Also prevent a registration from claiming this host while it's not
+ // yet execution ready.
+ auto disallow_controller =
+ std::make_unique<ScopedDisallowSetControllerRegistration>(provider_host_);
stripped_url_ = net::SimplifyUrlForRequest(url);
provider_host_->SetDocumentUrl(stripped_url_);
provider_host_->SetTopmostFrameUrl(site_for_cookies);
context_->storage()->FindRegistrationForDocument(
- stripped_url_, base::BindOnce(&self::DidLookupRegistrationForMainResource,
- weak_factory_.GetWeakPtr()));
+ stripped_url_, base::BindOnce(&ServiceWorkerControlleeRequestHandler::
+ DidLookupRegistrationForMainResource,
+ weak_factory_.GetWeakPtr(),
+ std::move(disallow_controller)));
}
void ServiceWorkerControlleeRequestHandler::
DidLookupRegistrationForMainResource(
+ std::unique_ptr<ScopedDisallowSetControllerRegistration>
+ disallow_controller,
blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration) {
// The job may have been canceled before this was invoked.
if (JobWasCanceled())
return;
- const bool need_to_update = !force_update_started_ && registration &&
- context_->force_update_on_page_load();
-
- if (provider_host_ && !need_to_update)
- provider_host_->SetAllowAssociation(true);
if (status != blink::ServiceWorkerStatusCode::kOk) {
+ tracker_->RecordDestination(
+ ServiceWorkerMetrics::MainResourceRequestDestination::
+ kNetworkBecauseNoRegistration);
url_job_->FallbackToNetwork();
TRACE_EVENT_ASYNC_END1(
"ServiceWorker",
@@ -352,9 +420,12 @@ void ServiceWorkerControlleeRequestHandler::
url_job_.get(), "Status", blink::ServiceWorkerStatusToString(status));
return;
}
- DCHECK(registration.get());
+ DCHECK(registration);
if (!provider_host_) {
+ tracker_->RecordDestination(
+ ServiceWorkerMetrics::MainResourceRequestDestination::
+ kNetworkBecauseNoProvider);
url_job_->FallbackToNetwork();
TRACE_EVENT_ASYNC_END1(
"ServiceWorker",
@@ -362,8 +433,12 @@ void ServiceWorkerControlleeRequestHandler::
url_job_.get(), "Info", "No Provider");
return;
}
+ provider_host_->AddMatchingRegistration(registration.get());
if (!context_) {
+ tracker_->RecordDestination(
+ ServiceWorkerMetrics::MainResourceRequestDestination::
+ kNetworkBecauseNoContext);
url_job_->FallbackToNetwork();
TRACE_EVENT_ASYNC_END1(
"ServiceWorker",
@@ -375,18 +450,23 @@ void ServiceWorkerControlleeRequestHandler::
if (!GetContentClient()->browser()->AllowServiceWorker(
registration->pattern(), provider_host_->topmost_frame_url(),
resource_context_, provider_host_->web_contents_getter())) {
+ tracker_->RecordDestination(
+ ServiceWorkerMetrics::MainResourceRequestDestination::
+ kNetworkBecauseNotAllowed);
url_job_->FallbackToNetwork();
- TRACE_EVENT_ASYNC_END2(
+ TRACE_EVENT_ASYNC_END1(
"ServiceWorker",
"ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
- url_job_.get(), "Status", blink::ServiceWorkerStatusToString(status),
- "Info", "ServiceWorker is blocked");
+ url_job_.get(), "Info", "ServiceWorker is blocked");
return;
}
if (!provider_host_->IsContextSecureForServiceWorker()) {
// TODO(falken): Figure out a way to surface in the page's DevTools
// console that the service worker was blocked for security.
+ tracker_->RecordDestination(
+ ServiceWorkerMetrics::MainResourceRequestDestination::
+ kNetworkBecauseNotSecure);
url_job_->FallbackToNetwork();
TRACE_EVENT_ASYNC_END1(
"ServiceWorker",
@@ -395,13 +475,17 @@ void ServiceWorkerControlleeRequestHandler::
return;
}
+ const bool need_to_update =
+ !force_update_started_ && context_->force_update_on_page_load();
if (need_to_update) {
force_update_started_ = true;
context_->UpdateServiceWorker(
registration.get(), true /* force_bypass_cache */,
true /* skip_script_comparison */,
- base::BindOnce(&self::DidUpdateRegistration, weak_factory_.GetWeakPtr(),
- registration));
+ base::BindOnce(
+ &ServiceWorkerControlleeRequestHandler::DidUpdateRegistration,
+ weak_factory_.GetWeakPtr(), registration,
+ std::move(disallow_controller)));
return;
}
@@ -413,47 +497,117 @@ void ServiceWorkerControlleeRequestHandler::
scoped_refptr<ServiceWorkerVersion> active_version =
registration->active_version();
+ if (!active_version) {
+ tracker_->RecordDestination(
+ ServiceWorkerMetrics::MainResourceRequestDestination::
+ kNetworkBecauseNoActiveVersion);
+ url_job_->FallbackToNetwork();
+ TRACE_EVENT_ASYNC_END1(
+ "ServiceWorker",
+ "ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
+ url_job_.get(), "Info",
+ "No active version, so falling back to network");
+ return;
+ }
+ DCHECK(active_version->status() == ServiceWorkerVersion::ACTIVATING ||
+ active_version->status() == ServiceWorkerVersion::ACTIVATED)
+ << ServiceWorkerVersion::VersionStatusToString(active_version->status());
// Wait until it's activated before firing fetch events.
- if (active_version.get() &&
- active_version->status() == ServiceWorkerVersion::ACTIVATING) {
- provider_host_->SetAllowAssociation(false);
- active_version->RegisterStatusChangeCallback(base::BindOnce(
- &self::OnVersionStatusChanged, weak_factory_.GetWeakPtr(), registration,
- active_version));
- TRACE_EVENT_ASYNC_END2(
+ if (active_version->status() == ServiceWorkerVersion::ACTIVATING) {
+ registration->active_version()->RegisterStatusChangeCallback(
+ base::BindOnce(&ServiceWorkerControlleeRequestHandler::
+ ContinueWithInScopeMainResourceRequest,
+ weak_factory_.GetWeakPtr(), registration, active_version,
+ std::move(disallow_controller)));
+ TRACE_EVENT_ASYNC_END1(
"ServiceWorker",
"ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
- url_job_.get(), "Status", blink::ServiceWorkerStatusToString(status),
- "Info", "Wait until finished SW activation");
+ url_job_.get(), "Info", "Wait until finished SW activation");
return;
}
- // TODO(falken): Factor out the rest of this function and
- // OnVersionStatusChanged into the same function.
+ ContinueWithInScopeMainResourceRequest(std::move(registration),
+ std::move(active_version),
+ std::move(disallow_controller));
+}
- // A registration exists, so associate it. Note that the controller is only
- // set if there's an active version. If there's no active version, we should
- // still associate so the provider host can use .ready.
- provider_host_->AssociateRegistration(registration.get(),
- false /* notify_controllerchange */);
+void ServiceWorkerControlleeRequestHandler::
+ ContinueWithInScopeMainResourceRequest(
+ scoped_refptr<ServiceWorkerRegistration> registration,
+ scoped_refptr<ServiceWorkerVersion> active_version,
+ std::unique_ptr<ScopedDisallowSetControllerRegistration>
+ disallow_controller) {
+ // The job may have been canceled before this was invoked. In that
+ // case, |url_job_| can't be used, so return.
+ if (JobWasCanceled()) {
+ tracker_->RecordDestination(
+ ServiceWorkerMetrics::MainResourceRequestDestination::kJobWasCancelled);
+ TRACE_EVENT_ASYNC_END1(
+ "ServiceWorker",
+ "ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
+ url_job_.get(), "Info", "The job was canceled");
+ return;
+ }
- if (!active_version.get() ||
- active_version->status() != ServiceWorkerVersion::ACTIVATED) {
+ if (!provider_host_) {
+ tracker_->RecordDestination(
+ ServiceWorkerMetrics::MainResourceRequestDestination::
+ kNetworkBecauseNoProviderAfterContinuing);
+ url_job_->FallbackToNetwork();
+ TRACE_EVENT_ASYNC_END1(
+ "ServiceWorker",
+ "ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
+ url_job_.get(), "Info",
+ "The provider host is gone, so falling back to network");
+ return;
+ }
+
+ if (active_version->status() != ServiceWorkerVersion::ACTIVATED) {
+ // TODO(falken): Clean this up and clarify in what cases we come here. I
+ // guess it's:
+ // - strange system error cases where promoting from ACTIVATING to ACTIVATED
+ // failed (shouldn't happen)
+ // - something calling Doom(), etc, making the active_version REDUNDANT
+ // - a version called skipWaiting() during activation so the expected
+ // version is no longer the active one (shouldn't happen: skipWaiting()
+ // waits for the active version to finish activating).
+ // In most cases, it sounds like falling back to network would not be right,
+ // since it's still in-scope. We probably should do:
+ // 1) If the provider host has an active version that is ACTIVATED, just
+ // use that, even if it wasn't the expected one.
+ // 2) If the provider host has an active version that is not ACTIVATED,
+ // just fail the load. The correct thing is probably to re-try
+ // activating that version, but there's a risk of an infinite loop of
+ // retries.
+ // 3) If the provider host does not have an active version, just fail the
+ // load.
+ tracker_->RecordDestination(
+ ServiceWorkerMetrics::MainResourceRequestDestination::
+ kNetworkBecauseNoActiveVersionAfterContinuing);
url_job_->FallbackToNetwork();
TRACE_EVENT_ASYNC_END2(
"ServiceWorker",
"ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
- url_job_.get(), "Status", blink::ServiceWorkerStatusToString(status),
- "Info",
- "ServiceWorkerVersion is not available, so falling back to network");
+ url_job_.get(), "Info",
+ "The expected active version is not ACTIVATED, so falling back to "
+ "network",
+ "Status",
+ ServiceWorkerVersion::VersionStatusToString(active_version->status()));
return;
}
+ disallow_controller.reset();
+ provider_host_->SetControllerRegistration(
+ registration, false /* notify_controllerchange */);
+
+ DCHECK_EQ(active_version, registration->active_version());
+ DCHECK_EQ(active_version, provider_host_->controller());
DCHECK_NE(active_version->fetch_handler_existence(),
ServiceWorkerVersion::FetchHandlerExistence::UNKNOWN);
ServiceWorkerMetrics::CountControlledPageLoad(
- active_version->site_for_uma(), stripped_url_, is_main_frame_load_);
+ active_version->site_for_uma(), stripped_url_,
+ resource_type_ == RESOURCE_TYPE_MAIN_FRAME);
if (blink::ServiceWorkerUtils::IsServicificationEnabled() &&
IsResourceTypeFrame(resource_type_)) {
@@ -461,49 +615,23 @@ void ServiceWorkerControlleeRequestHandler::
}
bool is_forwarded =
MaybeForwardToServiceWorker(url_job_.get(), active_version.get());
-
- TRACE_EVENT_ASYNC_END2(
+ if (!is_forwarded) {
+ tracker_->RecordDestination(
+ ServiceWorkerMetrics::MainResourceRequestDestination::
+ kNetworkBecauseNoFetchEventHandler);
+ }
+ TRACE_EVENT_ASYNC_END1(
"ServiceWorker",
"ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
- url_job_.get(), "Status", blink::ServiceWorkerStatusToString(status),
- "Info",
+ url_job_.get(), "Info",
(is_forwarded) ? "Forwarded to the ServiceWorker"
: "Skipped the ServiceWorker which has no fetch handler");
}
-void ServiceWorkerControlleeRequestHandler::OnVersionStatusChanged(
- scoped_refptr<ServiceWorkerRegistration> registration,
- scoped_refptr<ServiceWorkerVersion> version) {
- // The job may have been canceled before this was invoked.
- if (JobWasCanceled())
- return;
-
- if (provider_host_)
- provider_host_->SetAllowAssociation(true);
- if (version != registration->active_version() ||
- version->status() != ServiceWorkerVersion::ACTIVATED ||
- !provider_host_) {
- url_job_->FallbackToNetwork();
- return;
- }
-
- DCHECK_NE(version->fetch_handler_existence(),
- ServiceWorkerVersion::FetchHandlerExistence::UNKNOWN);
- ServiceWorkerMetrics::CountControlledPageLoad(
- version->site_for_uma(), stripped_url_, is_main_frame_load_);
-
- provider_host_->AssociateRegistration(registration.get(),
- false /* notify_controllerchange */);
-
- if (blink::ServiceWorkerUtils::IsServicificationEnabled() &&
- IsResourceTypeFrame(resource_type_)) {
- provider_host_->AddServiceWorkerToUpdate(version);
- }
- MaybeForwardToServiceWorker(url_job_.get(), version.get());
-}
-
void ServiceWorkerControlleeRequestHandler::DidUpdateRegistration(
- const scoped_refptr<ServiceWorkerRegistration>& original_registration,
+ scoped_refptr<ServiceWorkerRegistration> original_registration,
+ std::unique_ptr<ScopedDisallowSetControllerRegistration>
+ disallow_controller,
blink::ServiceWorkerStatusCode status,
const std::string& status_message,
int64_t registration_id) {
@@ -522,24 +650,28 @@ void ServiceWorkerControlleeRequestHandler::DidUpdateRegistration(
// Update failed. Look up the registration again since the original
// registration was possibly unregistered in the meantime.
context_->storage()->FindRegistrationForDocument(
- stripped_url_,
- base::BindOnce(&self::DidLookupRegistrationForMainResource,
- weak_factory_.GetWeakPtr()));
+ stripped_url_, base::BindOnce(&ServiceWorkerControlleeRequestHandler::
+ DidLookupRegistrationForMainResource,
+ weak_factory_.GetWeakPtr(),
+ std::move(disallow_controller)));
return;
}
DCHECK_EQ(original_registration->id(), registration_id);
- scoped_refptr<ServiceWorkerVersion> new_version =
+ ServiceWorkerVersion* new_version =
original_registration->installing_version();
new_version->ReportForceUpdateToDevTools();
new_version->set_skip_waiting(true);
new_version->RegisterStatusChangeCallback(base::BindOnce(
- &self::OnUpdatedVersionStatusChanged, weak_factory_.GetWeakPtr(),
- original_registration, new_version));
+ &ServiceWorkerControlleeRequestHandler::OnUpdatedVersionStatusChanged,
+ weak_factory_.GetWeakPtr(), std::move(original_registration),
+ base::WrapRefCounted(new_version), std::move(disallow_controller)));
}
void ServiceWorkerControlleeRequestHandler::OnUpdatedVersionStatusChanged(
- const scoped_refptr<ServiceWorkerRegistration>& registration,
- const scoped_refptr<ServiceWorkerVersion>& version) {
+ scoped_refptr<ServiceWorkerRegistration> registration,
+ scoped_refptr<ServiceWorkerVersion> version,
+ std::unique_ptr<ScopedDisallowSetControllerRegistration>
+ disallow_controller) {
// The job may have been canceled before this was invoked.
if (JobWasCanceled())
return;
@@ -554,14 +686,16 @@ void ServiceWorkerControlleeRequestHandler::OnUpdatedVersionStatusChanged(
// continue with the incumbent version.
// In case unregister job may have run, look up the registration again.
context_->storage()->FindRegistrationForDocument(
- stripped_url_,
- base::BindOnce(&self::DidLookupRegistrationForMainResource,
- weak_factory_.GetWeakPtr()));
+ stripped_url_, base::BindOnce(&ServiceWorkerControlleeRequestHandler::
+ DidLookupRegistrationForMainResource,
+ weak_factory_.GetWeakPtr(),
+ std::move(disallow_controller)));
return;
}
- version->RegisterStatusChangeCallback(
- base::BindOnce(&self::OnUpdatedVersionStatusChanged,
- weak_factory_.GetWeakPtr(), registration, version));
+ version->RegisterStatusChangeCallback(base::BindOnce(
+ &ServiceWorkerControlleeRequestHandler::OnUpdatedVersionStatusChanged,
+ weak_factory_.GetWeakPtr(), std::move(registration), version,
+ std::move(disallow_controller)));
}
void ServiceWorkerControlleeRequestHandler::PrepareForSubResource() {
@@ -575,14 +709,13 @@ void ServiceWorkerControlleeRequestHandler::PrepareForSubResource() {
// because a permanent failure occurred when trying to start it.
//
// As this is an exceptional case, just error out.
- // TODO(falken): Figure out if |active_version| can change to |controller| and
- // do it or document the findings.
- if (!provider_host_->active_version()) {
+ ServiceWorkerVersion* controller = provider_host_->controller();
+ if (!controller) {
url_job_->FailDueToLostController();
return;
}
- MaybeForwardToServiceWorker(url_job_.get(), provider_host_->active_version());
+ MaybeForwardToServiceWorker(url_job_.get(), controller);
}
void ServiceWorkerControlleeRequestHandler::OnPrepareToRestart() {
@@ -597,11 +730,11 @@ ServiceWorkerControlleeRequestHandler::GetServiceWorkerVersion(
*result = ServiceWorkerMetrics::REQUEST_JOB_ERROR_NO_PROVIDER_HOST;
return nullptr;
}
- if (!provider_host_->active_version()) {
+ if (!provider_host_->controller()) {
*result = ServiceWorkerMetrics::REQUEST_JOB_ERROR_NO_ACTIVE_VERSION;
return nullptr;
}
- return provider_host_->active_version();
+ return provider_host_->controller();
}
bool ServiceWorkerControlleeRequestHandler::RequestStillValid(
@@ -621,7 +754,25 @@ void ServiceWorkerControlleeRequestHandler::MainResourceLoadFailed() {
provider_host_->NotifyControllerLost();
}
+void ServiceWorkerControlleeRequestHandler::ReportDestination(
+ ServiceWorkerMetrics::MainResourceRequestDestination destination) {
+ DCHECK(is_main_resource_load_);
+ tracker_->RecordDestination(destination);
+}
+
+void ServiceWorkerControlleeRequestHandler::
+ WillDispatchFetchEventForMainResource() {
+ DCHECK(is_main_resource_load_);
+ tracker_->WillDispatchFetchEvent();
+}
+
void ServiceWorkerControlleeRequestHandler::ClearJob() {
+ // Invalidate weak pointers to cancel RegisterStatusChangeCallback().
+ // Otherwise we may end up calling ForwardToServiceWorer()
+ // or FallbackToNetwork() twice on the same |url_job_|.
+ // TODO(bashi): Consider not to reuse this handler when restarting the
+ // request after S13nServiceWorker is shipped.
+ weak_factory_.InvalidateWeakPtrs();
url_job_.reset();
}
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 ed148bea249..0ad6eed9b4b 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
@@ -6,6 +6,8 @@
#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CONTROLLEE_REQUEST_HANDLER_H_
#include <stdint.h>
+#include <memory>
+#include <string>
#include "base/gtest_prod_util.h"
#include "base/macros.h"
@@ -37,8 +39,9 @@ namespace content {
class ServiceWorkerRegistration;
class ServiceWorkerVersion;
-// A request handler derivative used to handle requests from
-// controlled documents.
+// A request handler derivative used to handle requests for,
+// and requests from, controlled documents and shared workers.
+//
// Note that in IsServicificationEnabled cases this is used only for
// main resource fetch during navigation or shared worker creation.
class CONTENT_EXPORT ServiceWorkerControlleeRequestHandler
@@ -77,52 +80,65 @@ class CONTENT_EXPORT ServiceWorkerControlleeRequestHandler
// cases. (In fallback-to-network cases we basically forward the request
// to the request to the next request handler)
// NavigationLoaderInterceptor overrides:
- void MaybeCreateLoader(const network::ResourceRequest& request,
+ void MaybeCreateLoader(const network::ResourceRequest& tentative_request,
ResourceContext* resource_context,
- LoaderCallback callback) override;
+ LoaderCallback callback,
+ FallbackCallback fallback_callback) override;
// Returns params with the ControllerServiceWorkerPtr if we have found
// a matching controller service worker for the |request| that is given
// to MaybeCreateLoader(). Otherwise this returns base::nullopt.
base::Optional<SubresourceLoaderParams> MaybeCreateSubresourceLoaderParams()
override;
+ // Exposed for testing.
+ ServiceWorkerURLJobWrapper* url_job() const { return url_job_.get(); }
+
private:
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerControlleeRequestHandlerTest,
ActivateWaitingVersion);
- typedef ServiceWorkerControlleeRequestHandler self;
+ class ScopedDisallowSetControllerRegistration;
+ class MainResourceRequestTracker;
// For main resource case.
void PrepareForMainResource(const GURL& url, const GURL& site_for_cookies);
void DidLookupRegistrationForMainResource(
+ std::unique_ptr<ScopedDisallowSetControllerRegistration>
+ disallow_controller,
blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration);
- void OnVersionStatusChanged(
+ void ContinueWithInScopeMainResourceRequest(
scoped_refptr<ServiceWorkerRegistration> registration,
- scoped_refptr<ServiceWorkerVersion> version);
+ scoped_refptr<ServiceWorkerVersion> version,
+ std::unique_ptr<ScopedDisallowSetControllerRegistration>
+ disallow_controller);
+ // For forced update.
void DidUpdateRegistration(
- const scoped_refptr<ServiceWorkerRegistration>& original_registration,
+ scoped_refptr<ServiceWorkerRegistration> original_registration,
+ std::unique_ptr<ScopedDisallowSetControllerRegistration>
+ disallow_controller,
blink::ServiceWorkerStatusCode status,
const std::string& status_message,
int64_t registration_id);
void OnUpdatedVersionStatusChanged(
- const scoped_refptr<ServiceWorkerRegistration>& registration,
- const scoped_refptr<ServiceWorkerVersion>& version);
+ scoped_refptr<ServiceWorkerRegistration> registration,
+ scoped_refptr<ServiceWorkerVersion> version,
+ std::unique_ptr<ScopedDisallowSetControllerRegistration>
+ disallow_controller);
// For sub resource case.
void PrepareForSubResource();
// ServiceWorkerURLJobWrapper::Delegate implementation:
-
- // Called just before the request is restarted. Makes sure the next request
- // goes over the network.
void OnPrepareToRestart() override;
-
ServiceWorkerVersion* GetServiceWorkerVersion(
ServiceWorkerMetrics::URLRequestJobResult* result) override;
bool RequestStillValid(
ServiceWorkerMetrics::URLRequestJobResult* result) override;
void MainResourceLoadFailed() override;
+ void ReportDestination(ServiceWorkerMetrics::MainResourceRequestDestination
+ destination) override;
+ void WillDispatchFetchEventForMainResource() override;
// Sets |job_| to nullptr, and clears all extra response info associated with
// that job, except for timing information.
@@ -136,7 +152,6 @@ class CONTENT_EXPORT ServiceWorkerControlleeRequestHandler
const ResourceType resource_type_;
const bool is_main_resource_load_;
- const bool is_main_frame_load_;
std::unique_ptr<ServiceWorkerURLJobWrapper> url_job_;
network::mojom::FetchRequestMode request_mode_;
network::mojom::FetchCredentialsMode credentials_mode_;
@@ -155,6 +170,8 @@ class CONTENT_EXPORT ServiceWorkerControlleeRequestHandler
// next intercept opportunity, for main frame requests.
bool use_network_;
+ std::unique_ptr<MainResourceRequestTracker> tracker_;
+
base::WeakPtrFactory<ServiceWorkerControlleeRequestHandler> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerControlleeRequestHandler);
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 5974fee450c..930165c99aa 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
@@ -11,6 +11,7 @@
#include "base/files/scoped_temp_dir.h"
#include "base/logging.h"
#include "base/run_loop.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"
#include "content/browser/service_worker/service_worker_context_core.h"
@@ -33,6 +34,7 @@
#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/features.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
namespace content {
@@ -40,7 +42,8 @@ namespace service_worker_controllee_request_handler_unittest {
int kMockProviderId = 1;
-class ServiceWorkerControlleeRequestHandlerTest : public testing::Test {
+class ServiceWorkerControlleeRequestHandlerTest
+ : public testing::TestWithParam<bool> {
public:
class ServiceWorkerRequestTestResources {
public:
@@ -51,6 +54,7 @@ class ServiceWorkerControlleeRequestHandlerTest : public testing::Test {
network::mojom::FetchRequestMode fetch_type =
network::mojom::FetchRequestMode::kNoCORS)
: test_(test),
+ resource_type_(type),
request_(test->url_request_context_.CreateRequest(
url,
net::DEFAULT_PRIORITY,
@@ -77,21 +81,57 @@ class ServiceWorkerControlleeRequestHandlerTest : public testing::Test {
return static_cast<ServiceWorkerURLRequestJob*>(job_.get());
}
+ void MaybeCreateLoader() {
+ network::ResourceRequest resource_request;
+ resource_request.url = request_->url();
+ resource_request.resource_type = resource_type_;
+ resource_request.headers = request()->extra_request_headers();
+ handler_->MaybeCreateLoader(resource_request,
+ &test_->mock_resource_context_,
+ base::DoNothing(), base::DoNothing());
+ }
+
+ ServiceWorkerURLJobWrapper* MaybeCreateJobWrapper() {
+ if (test_->IsServiceWorkerServicificationEnabled()) {
+ MaybeCreateLoader();
+ return handler_->url_job();
+ } else {
+ ServiceWorkerURLRequestJob* job = MaybeCreateJob();
+ if (job) {
+ job_wrapper_ =
+ std::make_unique<ServiceWorkerURLJobWrapper>(job->GetWeakPtr());
+ }
+ return job_wrapper_.get();
+ }
+ }
+
void ResetHandler() { handler_.reset(nullptr); }
net::URLRequest* request() const { return request_.get(); }
private:
ServiceWorkerControlleeRequestHandlerTest* test_;
+ const ResourceType resource_type_;
std::unique_ptr<net::URLRequest> request_;
std::unique_ptr<ServiceWorkerControlleeRequestHandler> handler_;
+ // |job_| and |job_wrapper_| are only for non-S13nServiceWorker cases.
+ // When S13nServiceWorker is enabled we use a job wrapper which is owned by
+ // |handler_|.
std::unique_ptr<net::URLRequestJob> job_;
+ std::unique_ptr<ServiceWorkerURLJobWrapper> job_wrapper_;
};
ServiceWorkerControlleeRequestHandlerTest()
: browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}
void SetUp() override {
+ if (IsServiceWorkerServicificationEnabled()) {
+ scoped_feature_list_.InitAndEnableFeature(
+ blink::features::kServiceWorkerServicification);
+ } else {
+ scoped_feature_list_.InitAndDisableFeature(
+ blink::features::kServiceWorkerServicification);
+ }
SetUpWithHelper(new EmbeddedWorkerTestHelper(base::FilePath()));
}
@@ -139,7 +179,19 @@ class ServiceWorkerControlleeRequestHandlerTest : public testing::Test {
ServiceWorkerContextCore* context() const { return helper_->context(); }
+ void SetProviderHostIsSecure(ServiceWorkerProviderHost* host,
+ bool is_secure) {
+ host->info_->is_parent_frame_secure = is_secure;
+ }
+
+ bool IsServiceWorkerServicificationEnabled() { return GetParam(); }
+
protected:
+ // |scoped_feature_list_| must be before |thread_bundle_|, since
+ // the thread bundle's destruction causes service worker-related
+ // objects to destruct, whose destructors need to know whether servicification
+ // is enabled.
+ base::test::ScopedFeatureList scoped_feature_list_;
TestBrowserThreadBundle browser_thread_bundle_;
std::unique_ptr<EmbeddedWorkerTestHelper> helper_;
scoped_refptr<ServiceWorkerRegistration> registration_;
@@ -165,7 +217,7 @@ class ServiceWorkerTestContentBrowserClient : public TestContentBrowserClient {
}
};
-TEST_F(ServiceWorkerControlleeRequestHandlerTest, DisallowServiceWorker) {
+TEST_P(ServiceWorkerControlleeRequestHandlerTest, DisallowServiceWorker) {
ServiceWorkerTestContentBrowserClient test_browser_client;
ContentBrowserClient* old_browser_client =
SetBrowserClientForTesting(&test_browser_client);
@@ -182,7 +234,8 @@ TEST_F(ServiceWorkerControlleeRequestHandlerTest, DisallowServiceWorker) {
// Conduct a main resource load.
ServiceWorkerRequestTestResources test_resources(
this, GURL("https://host/scope/doc"), RESOURCE_TYPE_MAIN_FRAME);
- ServiceWorkerURLRequestJob* sw_job = test_resources.MaybeCreateJob();
+ ServiceWorkerURLJobWrapper* sw_job = test_resources.MaybeCreateJobWrapper();
+ ASSERT_TRUE(sw_job);
EXPECT_FALSE(sw_job->ShouldFallbackToNetwork());
EXPECT_FALSE(sw_job->ShouldForwardToServiceWorker());
@@ -197,7 +250,36 @@ TEST_F(ServiceWorkerControlleeRequestHandlerTest, DisallowServiceWorker) {
SetBrowserClientForTesting(old_browser_client);
}
-TEST_F(ServiceWorkerControlleeRequestHandlerTest, ActivateWaitingVersion) {
+TEST_P(ServiceWorkerControlleeRequestHandlerTest, InsecureContext) {
+ // Store an activated worker.
+ version_->set_fetch_handler_existence(
+ ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
+ version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
+ registration_->SetActiveVersion(version_);
+ context()->storage()->StoreRegistration(registration_.get(), version_.get(),
+ base::DoNothing());
+ base::RunLoop().RunUntilIdle();
+
+ SetProviderHostIsSecure(provider_host_.get(), false);
+
+ // Conduct a main resource load.
+ ServiceWorkerRequestTestResources test_resources(
+ this, GURL("https://host/scope/doc"), RESOURCE_TYPE_MAIN_FRAME);
+ ServiceWorkerURLJobWrapper* sw_job = test_resources.MaybeCreateJobWrapper();
+ ASSERT_TRUE(sw_job);
+
+ EXPECT_FALSE(sw_job->ShouldFallbackToNetwork());
+ EXPECT_FALSE(sw_job->ShouldForwardToServiceWorker());
+ EXPECT_FALSE(version_->HasControllee());
+ base::RunLoop().RunUntilIdle();
+
+ // Verify we did not use the worker.
+ EXPECT_TRUE(sw_job->ShouldFallbackToNetwork());
+ EXPECT_FALSE(sw_job->ShouldForwardToServiceWorker());
+ EXPECT_FALSE(version_->HasControllee());
+}
+
+TEST_P(ServiceWorkerControlleeRequestHandlerTest, ActivateWaitingVersion) {
// Store a registration that is installed but not activated yet.
version_->set_fetch_handler_existence(
ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
@@ -210,7 +292,8 @@ TEST_F(ServiceWorkerControlleeRequestHandlerTest, ActivateWaitingVersion) {
// Conduct a main resource load.
ServiceWorkerRequestTestResources test_resources(
this, GURL("https://host/scope/doc"), RESOURCE_TYPE_MAIN_FRAME);
- ServiceWorkerURLRequestJob* sw_job = test_resources.MaybeCreateJob();
+ ServiceWorkerURLJobWrapper* sw_job = test_resources.MaybeCreateJobWrapper();
+ ASSERT_TRUE(sw_job);
EXPECT_FALSE(sw_job->ShouldFallbackToNetwork());
EXPECT_FALSE(sw_job->ShouldForwardToServiceWorker());
@@ -218,19 +301,22 @@ TEST_F(ServiceWorkerControlleeRequestHandlerTest, ActivateWaitingVersion) {
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(ServiceWorkerVersion::ACTIVATED,
- version_->status());
+ EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, version_->status());
EXPECT_FALSE(sw_job->ShouldFallbackToNetwork());
EXPECT_TRUE(sw_job->ShouldForwardToServiceWorker());
EXPECT_TRUE(version_->HasControllee());
- // Navigations should trigger an update too.
test_resources.ResetHandler();
- EXPECT_TRUE(version_->update_timer_.IsRunning());
+ // Navigations should trigger an update too when S13nServiceWorker is
+ // disabled. Note that when S13nServiceWorker is enabled we defer scheduling
+ // update. See the comment on
+ // ServiceWorkerProviderHost::AddServiceWorkerToUpdate() for details.
+ if (!IsServiceWorkerServicificationEnabled())
+ EXPECT_TRUE(version_->update_timer_.IsRunning());
}
// Test that an installing registration is associated with a provider host.
-TEST_F(ServiceWorkerControlleeRequestHandlerTest, InstallingRegistration) {
+TEST_P(ServiceWorkerControlleeRequestHandlerTest, InstallingRegistration) {
// Create an installing registration.
version_->SetStatus(ServiceWorkerVersion::INSTALLING);
version_->set_fetch_handler_existence(
@@ -241,22 +327,22 @@ TEST_F(ServiceWorkerControlleeRequestHandlerTest, InstallingRegistration) {
// Conduct a main resource load.
ServiceWorkerRequestTestResources test_resources(
this, GURL("https://host/scope/doc"), RESOURCE_TYPE_MAIN_FRAME);
- ServiceWorkerURLRequestJob* job = test_resources.MaybeCreateJob();
+ ServiceWorkerURLJobWrapper* job = test_resources.MaybeCreateJobWrapper();
base::RunLoop().RunUntilIdle();
// The handler should have fallen back to network and destroyed the job. The
- // registration should be associated with the provider host, although it is
- // not controlled since there is no active version.
+ // provider host should not be controlled. However it should add the
+ // registration as a matching registration so it can be used for .ready and
+ // claim().
EXPECT_FALSE(job);
- EXPECT_EQ(registration_.get(), provider_host_->associated_registration());
- EXPECT_EQ(version_.get(), provider_host_->installing_version());
EXPECT_FALSE(version_->HasControllee());
EXPECT_FALSE(provider_host_->controller());
+ EXPECT_EQ(registration_.get(), provider_host_->MatchRegistration());
}
// Test to not regress crbug/414118.
-TEST_F(ServiceWorkerControlleeRequestHandlerTest, DeletedProviderHost) {
+TEST_P(ServiceWorkerControlleeRequestHandlerTest, DeletedProviderHost) {
// Store a registration so the call to FindRegistrationForDocument will read
// from the database.
version_->set_fetch_handler_existence(
@@ -272,7 +358,8 @@ TEST_F(ServiceWorkerControlleeRequestHandlerTest, DeletedProviderHost) {
// Conduct a main resource load.
ServiceWorkerRequestTestResources test_resources(
this, GURL("https://host/scope/doc"), RESOURCE_TYPE_MAIN_FRAME);
- ServiceWorkerURLRequestJob* sw_job = test_resources.MaybeCreateJob();
+ ServiceWorkerURLJobWrapper* sw_job = test_resources.MaybeCreateJobWrapper();
+ ASSERT_TRUE(sw_job);
EXPECT_FALSE(sw_job->ShouldFallbackToNetwork());
EXPECT_FALSE(sw_job->ShouldForwardToServiceWorker());
@@ -290,7 +377,14 @@ TEST_F(ServiceWorkerControlleeRequestHandlerTest, DeletedProviderHost) {
// Tests the scenario where a controllee request handler was created
// for a subresource request, but before MaybeCreateJob() is run, the
// controller/active version becomes null.
-TEST_F(ServiceWorkerControlleeRequestHandlerTest, LostActiveVersion) {
+TEST_P(ServiceWorkerControlleeRequestHandlerTest, LostActiveVersion) {
+ // Skip this test when S13nServiceWorker is enabled because we don't use
+ // ServiceWorkerControlleeRequestHandler for subresource loading.
+ // TODO(bashi): Add a test in ServiceWorkerProviderHost to cover this
+ // scenario when S13nServiceWorker is enabled.
+ if (IsServiceWorkerServicificationEnabled())
+ return;
+
// Store an activated worker.
version_->set_fetch_handler_existence(
ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
@@ -307,14 +401,12 @@ TEST_F(ServiceWorkerControlleeRequestHandlerTest, LostActiveVersion) {
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(version_->HasControllee());
EXPECT_EQ(version_, provider_host_->controller());
- EXPECT_EQ(version_, provider_host_->active_version());
// Unset the active version.
provider_host_->NotifyControllerLost();
registration_->SetActiveVersion(nullptr);
EXPECT_FALSE(version_->HasControllee());
EXPECT_FALSE(provider_host_->controller());
- EXPECT_FALSE(provider_host_->active_version());
// Conduct a subresource load.
ServiceWorkerRequestTestResources sub_test_resources(
@@ -327,7 +419,14 @@ TEST_F(ServiceWorkerControlleeRequestHandlerTest, LostActiveVersion) {
sub_job->response_type_);
}
-TEST_F(ServiceWorkerControlleeRequestHandlerTest, FallbackWithNoFetchHandler) {
+TEST_P(ServiceWorkerControlleeRequestHandlerTest, FallbackWithNoFetchHandler) {
+ // Skip this test when S13nServiceWorker is enabled because we don't use
+ // ServiceWorkerControlleeRequestHandler for subresource loading.
+ // TODO(bashi): Add a test in ServiceWorkerProviderHost to cover this
+ // scenario when S13nServiceWorker is enabled.
+ if (IsServiceWorkerServicificationEnabled())
+ return;
+
version_->set_fetch_handler_existence(
ServiceWorkerVersion::FetchHandlerExistence::DOES_NOT_EXIST);
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
@@ -377,7 +476,7 @@ TEST_F(ServiceWorkerControlleeRequestHandlerTest, FallbackWithNoFetchHandler) {
}
#if BUILDFLAG(ENABLE_OFFLINE_PAGES)
-TEST_F(ServiceWorkerControlleeRequestHandlerTest, FallbackWithOfflineHeader) {
+TEST_P(ServiceWorkerControlleeRequestHandlerTest, FallbackWithOfflineHeader) {
version_->set_fetch_handler_existence(
ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
@@ -393,12 +492,12 @@ TEST_F(ServiceWorkerControlleeRequestHandlerTest, FallbackWithOfflineHeader) {
// Sets an offline header to indicate force loading offline page.
test_resources.request()->SetExtraRequestHeaderByName(
"X-Chrome-offline", "reason=download", true);
- ServiceWorkerURLRequestJob* sw_job = test_resources.MaybeCreateJob();
+ ServiceWorkerURLJobWrapper* sw_job = test_resources.MaybeCreateJobWrapper();
EXPECT_FALSE(sw_job);
}
-TEST_F(ServiceWorkerControlleeRequestHandlerTest, FallbackWithNoOfflineHeader) {
+TEST_P(ServiceWorkerControlleeRequestHandlerTest, FallbackWithNoOfflineHeader) {
version_->set_fetch_handler_existence(
ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
@@ -414,11 +513,15 @@ TEST_F(ServiceWorkerControlleeRequestHandlerTest, FallbackWithNoOfflineHeader) {
// Empty offline header value should not cause fallback.
test_resources.request()->SetExtraRequestHeaderByName("X-Chrome-offline", "",
true);
- ServiceWorkerURLRequestJob* sw_job = test_resources.MaybeCreateJob();
+ ServiceWorkerURLJobWrapper* sw_job = test_resources.MaybeCreateJobWrapper();
EXPECT_TRUE(sw_job);
}
-#endif // BUILDFLAG(ENABLE_OFFLINE_PAGE
+#endif // BUILDFLAG(ENABLE_OFFLINE_PAGE)
+
+INSTANTIATE_TEST_CASE_P(IsServiceWorkerServicificationEnabled,
+ ServiceWorkerControlleeRequestHandlerTest,
+ ::testing::Bool(););
} // namespace service_worker_controllee_request_handler_unittest
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_disk_cache.cc b/chromium/content/browser/service_worker/service_worker_disk_cache.cc
index 1369b37841e..27989a034f7 100644
--- a/chromium/content/browser/service_worker/service_worker_disk_cache.cc
+++ b/chromium/content/browser/service_worker/service_worker_disk_cache.cc
@@ -4,6 +4,8 @@
#include "content/browser/service_worker/service_worker_disk_cache.h"
+#include <utility>
+
namespace content {
ServiceWorkerDiskCache::ServiceWorkerDiskCache()
@@ -13,17 +15,17 @@ ServiceWorkerDiskCache::ServiceWorkerDiskCache()
ServiceWorkerResponseReader::ServiceWorkerResponseReader(
int64_t resource_id,
- const base::WeakPtr<AppCacheDiskCacheInterface>& disk_cache)
- : AppCacheResponseReader(resource_id, disk_cache) {}
+ base::WeakPtr<AppCacheDiskCacheInterface> disk_cache)
+ : AppCacheResponseReader(resource_id, std::move(disk_cache)) {}
ServiceWorkerResponseWriter::ServiceWorkerResponseWriter(
int64_t resource_id,
- const base::WeakPtr<AppCacheDiskCacheInterface>& disk_cache)
- : AppCacheResponseWriter(resource_id, disk_cache) {}
+ base::WeakPtr<AppCacheDiskCacheInterface> disk_cache)
+ : AppCacheResponseWriter(resource_id, std::move(disk_cache)) {}
ServiceWorkerResponseMetadataWriter::ServiceWorkerResponseMetadataWriter(
int64_t resource_id,
- const base::WeakPtr<AppCacheDiskCacheInterface>& disk_cache)
- : AppCacheResponseMetadataWriter(resource_id, disk_cache) {}
+ base::WeakPtr<AppCacheDiskCacheInterface> disk_cache)
+ : AppCacheResponseMetadataWriter(resource_id, std::move(disk_cache)) {}
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_disk_cache.h b/chromium/content/browser/service_worker/service_worker_disk_cache.h
index b5ce04cddc5..bfadf688bf3 100644
--- a/chromium/content/browser/service_worker/service_worker_disk_cache.h
+++ b/chromium/content/browser/service_worker/service_worker_disk_cache.h
@@ -18,8 +18,7 @@ namespace content {
// TODO(michaeln): If this reuse sticks, refactor/move the
// resused classes to a more common location.
-class CONTENT_EXPORT ServiceWorkerDiskCache
- : public AppCacheDiskCache {
+class CONTENT_EXPORT ServiceWorkerDiskCache : public AppCacheDiskCache {
public:
ServiceWorkerDiskCache();
};
@@ -32,7 +31,7 @@ class CONTENT_EXPORT ServiceWorkerResponseReader
ServiceWorkerResponseReader(
int64_t resource_id,
- const base::WeakPtr<AppCacheDiskCacheInterface>& disk_cache);
+ base::WeakPtr<AppCacheDiskCacheInterface> disk_cache);
};
class CONTENT_EXPORT ServiceWorkerResponseWriter
@@ -43,7 +42,7 @@ class CONTENT_EXPORT ServiceWorkerResponseWriter
ServiceWorkerResponseWriter(
int64_t resource_id,
- const base::WeakPtr<AppCacheDiskCacheInterface>& disk_cache);
+ base::WeakPtr<AppCacheDiskCacheInterface> disk_cache);
};
class CONTENT_EXPORT ServiceWorkerResponseMetadataWriter
@@ -54,7 +53,7 @@ class CONTENT_EXPORT ServiceWorkerResponseMetadataWriter
ServiceWorkerResponseMetadataWriter(
int64_t resource_id,
- const base::WeakPtr<AppCacheDiskCacheInterface>& disk_cache);
+ base::WeakPtr<AppCacheDiskCacheInterface> disk_cache);
};
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc b/chromium/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc
index fae15052435..7bdd0811226 100644
--- a/chromium/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc
@@ -21,7 +21,6 @@
#include "content/browser/service_worker/service_worker_navigation_handle_core.h"
#include "content/browser/service_worker/service_worker_object_host.h"
#include "content/browser/service_worker/service_worker_test_utils.h"
-#include "content/common/service_worker/service_worker_messages.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/browser/child_process_termination_info.h"
#include "content/public/common/browser_side_navigation_policy.h"
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 dcc36e82bc0..21e9f3cb7df 100644
--- a/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.cc
+++ b/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.cc
@@ -25,7 +25,6 @@
#include "content/browser/service_worker/service_worker_version.h"
#include "content/browser/url_loader_factory_getter.h"
#include "content/common/service_worker/service_worker.mojom.h"
-#include "content/common/service_worker/service_worker_messages.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/browser_side_navigation_policy.h"
@@ -46,61 +45,6 @@ namespace content {
namespace {
-// This class wraps a mojo::AssociatedInterfacePtr<URLLoader>. It also is a
-// URLLoader implementation and delegates URLLoader calls to the wrapped loader.
-class DelegatingURLLoader final : public network::mojom::URLLoader {
- public:
- explicit DelegatingURLLoader(network::mojom::URLLoaderPtr loader)
- : binding_(this), loader_(std::move(loader)) {}
- ~DelegatingURLLoader() override {}
-
- void FollowRedirect(const base::Optional<std::vector<std::string>>&
- to_be_removed_request_headers,
- const base::Optional<net::HttpRequestHeaders>&
- modified_request_headers) override {
- DCHECK(!modified_request_headers.has_value())
- << "Redirect with modified headers was not supported yet. "
- "crbug.com/845683";
- loader_->FollowRedirect(base::nullopt, base::nullopt);
- }
- void ProceedWithResponse() override { NOTREACHED(); }
-
- void SetPriority(net::RequestPriority priority,
- int intra_priority_value) override {
- loader_->SetPriority(priority, intra_priority_value);
- }
-
- void PauseReadingBodyFromNet() override {
- loader_->PauseReadingBodyFromNet();
- }
- void ResumeReadingBodyFromNet() override {
- loader_->ResumeReadingBodyFromNet();
- }
-
- network::mojom::URLLoaderPtr CreateInterfacePtrAndBind() {
- network::mojom::URLLoaderPtr loader;
- binding_.Bind(mojo::MakeRequest(&loader));
- // This unretained pointer is safe, because |binding_| is owned by |this|
- // and the callback will never be called after |this| is destroyed.
- binding_.set_connection_error_handler(
- base::BindOnce(&DelegatingURLLoader::Cancel, base::Unretained(this)));
- return loader;
- }
-
- private:
- // Called when the network::mojom::URLLoaderPtr in the service worker is
- // deleted.
- void Cancel() {
- // Cancel loading as stated in url_loader.mojom.
- loader_ = nullptr;
- }
-
- mojo::Binding<network::mojom::URLLoader> binding_;
- network::mojom::URLLoaderPtr loader_;
-
- DISALLOW_COPY_AND_ASSIGN(DelegatingURLLoader);
-};
-
void NotifyNavigationPreloadRequestSentOnUI(
const network::ResourceRequest& request,
const std::pair<int, int>& worker_id,
@@ -361,11 +305,12 @@ const net::NetworkTrafficAnnotationTag kNavigationPreloadTrafficAnnotation =
// ServiceWorkerVersion::StartRequest*(), and held in pending_requests_
// until FinishRequest() is called.
class ServiceWorkerFetchDispatcher::ResponseCallback
- : public mojom::ServiceWorkerFetchResponseCallback {
+ : public blink::mojom::ServiceWorkerFetchResponseCallback {
public:
- ResponseCallback(mojom::ServiceWorkerFetchResponseCallbackRequest request,
- base::WeakPtr<ServiceWorkerFetchDispatcher> fetch_dispatcher,
- ServiceWorkerVersion* version)
+ ResponseCallback(
+ blink::mojom::ServiceWorkerFetchResponseCallbackRequest request,
+ base::WeakPtr<ServiceWorkerFetchDispatcher> fetch_dispatcher,
+ ServiceWorkerVersion* version)
: binding_(this, std::move(request)),
fetch_dispatcher_(fetch_dispatcher),
version_(version) {}
@@ -377,32 +322,25 @@ class ServiceWorkerFetchDispatcher::ResponseCallback
fetch_event_id_ = id;
}
- // Implements mojom::ServiceWorkerFetchResponseCallback.
- void OnResponse(const ServiceWorkerResponse& response,
+ // Implements blink::mojom::ServiceWorkerFetchResponseCallback.
+ void OnResponse(blink::mojom::FetchAPIResponsePtr response,
base::Time dispatch_event_time) override {
- HandleResponse(fetch_dispatcher_, version_, fetch_event_id_, response,
- nullptr /* body_as_stream */, nullptr /* body_as_blob */,
- FetchEventResult::kGotResponse, dispatch_event_time);
- }
- void OnResponseBlob(const ServiceWorkerResponse& response,
- blink::mojom::BlobPtr body_as_blob,
- base::Time dispatch_event_time) override {
- HandleResponse(fetch_dispatcher_, version_, fetch_event_id_, response,
- nullptr /* body_as_stream */, std::move(body_as_blob),
+ HandleResponse(fetch_dispatcher_, version_, fetch_event_id_,
+ std::move(response), nullptr /* body_as_stream */,
FetchEventResult::kGotResponse, dispatch_event_time);
}
void OnResponseStream(
- const ServiceWorkerResponse& response,
+ blink::mojom::FetchAPIResponsePtr response,
blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
base::Time dispatch_event_time) override {
- HandleResponse(fetch_dispatcher_, version_, fetch_event_id_, response,
- std::move(body_as_stream), nullptr /* body_as_blob */,
+ HandleResponse(fetch_dispatcher_, version_, fetch_event_id_,
+ std::move(response), std::move(body_as_stream),
FetchEventResult::kGotResponse, dispatch_event_time);
}
void OnFallback(base::Time dispatch_event_time) override {
HandleResponse(fetch_dispatcher_, version_, fetch_event_id_,
- ServiceWorkerResponse(), nullptr /* body_as_stream */,
- nullptr /* body_as_blob */,
+ blink::mojom::FetchAPIResponse::New(),
+ nullptr /* body_as_stream */,
FetchEventResult::kShouldFallback, dispatch_event_time);
}
@@ -413,9 +351,8 @@ class ServiceWorkerFetchDispatcher::ResponseCallback
base::WeakPtr<ServiceWorkerFetchDispatcher> fetch_dispatcher,
ServiceWorkerVersion* version,
base::Optional<int> fetch_event_id,
- const ServiceWorkerResponse& response,
+ blink::mojom::FetchAPIResponsePtr response,
blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
- blink::mojom::BlobPtr body_as_blob,
FetchEventResult fetch_result,
base::Time dispatch_event_time) {
if (!version->FinishRequest(fetch_event_id.value(),
@@ -425,12 +362,11 @@ class ServiceWorkerFetchDispatcher::ResponseCallback
// |fetch_dispatcher| is null if the URLRequest was killed.
if (!fetch_dispatcher)
return;
- fetch_dispatcher->DidFinish(fetch_event_id.value(), fetch_result, response,
- std::move(body_as_stream),
- std::move(body_as_blob));
+ fetch_dispatcher->DidFinish(fetch_event_id.value(), fetch_result,
+ std::move(response), std::move(body_as_stream));
}
- mojo::Binding<mojom::ServiceWorkerFetchResponseCallback> binding_;
+ mojo::Binding<blink::mojom::ServiceWorkerFetchResponseCallback> binding_;
base::WeakPtr<ServiceWorkerFetchDispatcher> fetch_dispatcher_;
// Owns |this| via pending_requests_.
ServiceWorkerVersion* version_;
@@ -449,10 +385,8 @@ class ServiceWorkerFetchDispatcher::URLLoaderAssets
public:
URLLoaderAssets(
std::unique_ptr<network::mojom::URLLoaderFactory> url_loader_factory,
- std::unique_ptr<network::mojom::URLLoader> url_loader,
std::unique_ptr<DelegatingURLLoaderClient> url_loader_client)
: url_loader_factory_(std::move(url_loader_factory)),
- url_loader_(std::move(url_loader)),
url_loader_client_(std::move(url_loader_client)) {}
void MaybeReportToDevTools(std::pair<int, int> worker_id,
@@ -465,7 +399,6 @@ class ServiceWorkerFetchDispatcher::URLLoaderAssets
virtual ~URLLoaderAssets() {}
std::unique_ptr<network::mojom::URLLoaderFactory> url_loader_factory_;
- std::unique_ptr<network::mojom::URLLoader> url_loader_;
std::unique_ptr<DelegatingURLLoaderClient> url_loader_client_;
DISALLOW_COPY_AND_ASSIGN(URLLoaderAssets);
@@ -575,7 +508,7 @@ void ServiceWorkerFetchDispatcher::DispatchFetchEvent() {
net_log_.BeginEvent(net::NetLogEventType::SERVICE_WORKER_FETCH_EVENT);
// Set up for receiving the response.
- mojom::ServiceWorkerFetchResponseCallbackPtr response_callback_ptr;
+ blink::mojom::ServiceWorkerFetchResponseCallbackPtr response_callback_ptr;
auto response_callback = std::make_unique<ResponseCallback>(
mojo::MakeRequest(&response_callback_ptr), weak_factory_.GetWeakPtr(),
version_.get());
@@ -629,27 +562,25 @@ void ServiceWorkerFetchDispatcher::DidFailToDispatch(
void ServiceWorkerFetchDispatcher::DidFail(
blink::ServiceWorkerStatusCode status) {
DCHECK_NE(blink::ServiceWorkerStatusCode::kOk, status);
- Complete(status, FetchEventResult::kShouldFallback, ServiceWorkerResponse(),
- nullptr /* body_as_stream */, nullptr /* body_as_blob */);
+ Complete(status, FetchEventResult::kShouldFallback,
+ blink::mojom::FetchAPIResponse::New(), nullptr /* body_as_stream */);
}
void ServiceWorkerFetchDispatcher::DidFinish(
int request_id,
FetchEventResult fetch_result,
- const ServiceWorkerResponse& response,
- blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
- blink::mojom::BlobPtr body_as_blob) {
+ blink::mojom::FetchAPIResponsePtr response,
+ blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream) {
net_log_.EndEvent(net::NetLogEventType::SERVICE_WORKER_FETCH_EVENT);
- Complete(blink::ServiceWorkerStatusCode::kOk, fetch_result, response,
- std::move(body_as_stream), std::move(body_as_blob));
+ Complete(blink::ServiceWorkerStatusCode::kOk, fetch_result,
+ std::move(response), std::move(body_as_stream));
}
void ServiceWorkerFetchDispatcher::Complete(
blink::ServiceWorkerStatusCode status,
FetchEventResult fetch_result,
- const ServiceWorkerResponse& response,
- blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
- blink::mojom::BlobPtr body_as_blob) {
+ blink::mojom::FetchAPIResponsePtr response,
+ blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream) {
DCHECK(fetch_callback_);
did_complete_ = true;
@@ -658,8 +589,8 @@ void ServiceWorkerFetchDispatcher::Complete(
base::Bind(&NetLogFetchEventCallback, status, fetch_result));
std::move(fetch_callback_)
- .Run(status, fetch_result, response, std::move(body_as_stream),
- std::move(body_as_blob), version_);
+ .Run(status, fetch_result, std::move(response), std::move(body_as_stream),
+ version_);
}
// Non-S13nServiceWorker
@@ -679,16 +610,7 @@ bool ServiceWorkerFetchDispatcher::MaybeStartNavigationPreload(
ResourceRequestInfoImpl* original_info =
ResourceRequestInfoImpl::ForRequest(original_request);
ResourceRequesterInfo* requester_info = original_info->requester_info();
- if (IsBrowserSideNavigationEnabled()) {
- DCHECK(requester_info->IsBrowserSideNavigation());
- } else {
- DCHECK(requester_info->IsRenderer());
- if (!requester_info->filter())
- return false;
- }
-
- DCHECK(!url_loader_assets_);
-
+ DCHECK(requester_info->IsBrowserSideNavigation());
auto url_loader_factory = std::make_unique<URLLoaderFactoryImpl>(
ResourceRequesterInfo::CreateForNavigationPreload(requester_info));
@@ -731,30 +653,27 @@ bool ServiceWorkerFetchDispatcher::MaybeStartNavigationPreload(
DCHECK_LT(request_id, -1);
preload_handle_ = blink::mojom::FetchEventPreloadHandle::New();
- network::mojom::URLLoaderClientPtr url_loader_client_ptr;
+ network::mojom::URLLoaderClientPtr inner_url_loader_client;
preload_handle_->url_loader_client_request =
- mojo::MakeRequest(&url_loader_client_ptr);
+ mojo::MakeRequest(&inner_url_loader_client);
auto url_loader_client = std::make_unique<DelegatingURLLoaderClient>(
- std::move(url_loader_client_ptr), std::move(on_response), request);
- network::mojom::URLLoaderClientPtr url_loader_client_ptr_to_pass;
- url_loader_client->Bind(&url_loader_client_ptr_to_pass);
- network::mojom::URLLoaderPtr url_loader_associated_ptr;
+ std::move(inner_url_loader_client), std::move(on_response), request);
+ network::mojom::URLLoaderClientPtr url_loader_client_to_pass;
+ url_loader_client->Bind(&url_loader_client_to_pass);
+ network::mojom::URLLoaderPtr url_loader;
url_loader_factory->CreateLoaderAndStart(
- mojo::MakeRequest(&url_loader_associated_ptr),
- original_info->GetRouteID(), request_id,
+ mojo::MakeRequest(&url_loader), original_info->GetRouteID(), request_id,
network::mojom::kURLLoadOptionNone, request,
- std::move(url_loader_client_ptr_to_pass),
+ std::move(url_loader_client_to_pass),
net::MutableNetworkTrafficAnnotationTag(
original_request->traffic_annotation()));
- auto url_loader = std::make_unique<DelegatingURLLoader>(
- std::move(url_loader_associated_ptr));
- preload_handle_->url_loader =
- url_loader->CreateInterfacePtrAndBind().PassInterface();
+ preload_handle_->url_loader = url_loader.PassInterface();
+
+ DCHECK(!url_loader_assets_);
url_loader_assets_ = base::MakeRefCounted<URLLoaderAssets>(
- std::move(url_loader_factory), std::move(url_loader),
- std::move(url_loader_client));
+ std::move(url_loader_factory), std::move(url_loader_client));
return true;
}
@@ -779,13 +698,11 @@ bool ServiceWorkerFetchDispatcher::MaybeStartNavigationPreloadWithURLLoader(
resource_request.resource_type = RESOURCE_TYPE_SUB_RESOURCE;
resource_request.skip_service_worker = true;
resource_request.do_not_prompt_for_login = true;
+
DCHECK(net::HttpUtil::IsValidHeaderValue(
version_->navigation_preload_state().header));
- // TODO(crbug/762357): Record header size UMA, but not until *all* the
- // navigation preload metrics are recorded on the S13N path; otherwise the
- // metrics will get unbalanced.
- // ServiceWorkerMetrics::RecordNavigationPreloadRequestHeaderSize(
- // version_->navigation_preload_state().header.length());
+ ServiceWorkerMetrics::RecordNavigationPreloadRequestHeaderSize(
+ version_->navigation_preload_state().header.length());
resource_request.headers.SetHeader(
"Service-Worker-Navigation-Preload",
version_->navigation_preload_state().header);
@@ -794,40 +711,33 @@ bool ServiceWorkerFetchDispatcher::MaybeStartNavigationPreloadWithURLLoader(
// Create the DelegatingURLLoaderClient, which becomes the
// URLLoaderClient for the navigation preload network request.
- network::mojom::URLLoaderClientPtr url_loader_client_ptr;
+ network::mojom::URLLoaderClientPtr inner_url_loader_client;
preload_handle_->url_loader_client_request =
- mojo::MakeRequest(&url_loader_client_ptr);
+ mojo::MakeRequest(&inner_url_loader_client);
auto url_loader_client = std::make_unique<DelegatingURLLoaderClient>(
- std::move(url_loader_client_ptr), std::move(on_response),
+ std::move(inner_url_loader_client), std::move(on_response),
resource_request);
// Start the network request for the URL using the network loader.
// TODO(falken): What to do about routing_id, request_id?
- network::mojom::URLLoaderClientPtr url_loader_client_ptr_to_pass;
- url_loader_client->Bind(&url_loader_client_ptr_to_pass);
- network::mojom::URLLoaderPtr url_loader_associated_ptr;
+ network::mojom::URLLoaderClientPtr url_loader_client_to_pass;
+ url_loader_client->Bind(&url_loader_client_to_pass);
+ network::mojom::URLLoaderPtr url_loader;
url_loader_factory_getter->GetNetworkFactory()->CreateLoaderAndStart(
- mojo::MakeRequest(&url_loader_associated_ptr), -1 /* routing_id? */,
+ mojo::MakeRequest(&url_loader), -1 /* routing_id? */,
-1 /* request_id? */, network::mojom::kURLLoadOptionNone,
- resource_request, std::move(url_loader_client_ptr_to_pass),
+ resource_request, std::move(url_loader_client_to_pass),
net::MutableNetworkTrafficAnnotationTag(
kNavigationPreloadTrafficAnnotation));
- // Hook the load up to DelegatingURLLoader, which will call our
- // DelegatingURLLoaderClient.
- auto url_loader = std::make_unique<DelegatingURLLoader>(
- std::move(url_loader_associated_ptr));
- preload_handle_->url_loader =
- url_loader->CreateInterfacePtrAndBind().PassInterface();
+ preload_handle_->url_loader = url_loader.PassInterface();
DCHECK(!url_loader_assets_);
// Unlike the non-S13N code path, we don't own the URLLoaderFactory being used
// (it's the generic network factory), so we don't need to pass it to
// URLLoaderAssets to keep it alive.
- std::unique_ptr<network::mojom::URLLoaderFactory> null_factory;
url_loader_assets_ = base::MakeRefCounted<URLLoaderAssets>(
- std::move(null_factory), std::move(url_loader),
- std::move(url_loader_client));
+ nullptr /* url_loader_factory */, std::move(url_loader_client));
return true;
}
diff --git a/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.h b/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.h
index 29c19dca1fe..c8024ab6147 100644
--- a/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.h
+++ b/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.h
@@ -16,7 +16,6 @@
#include "content/browser/service_worker/service_worker_metrics.h"
#include "content/common/content_export.h"
#include "content/common/service_worker/service_worker.mojom.h"
-#include "content/common/service_worker/service_worker_types.h"
#include "content/public/common/resource_type.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "net/log/net_log_with_source.h"
@@ -24,6 +23,7 @@
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
#include "third_party/blink/public/mojom/blob/blob.mojom.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_response.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom.h"
namespace net {
@@ -49,9 +49,8 @@ class CONTENT_EXPORT ServiceWorkerFetchDispatcher {
using FetchCallback =
base::OnceCallback<void(blink::ServiceWorkerStatusCode,
FetchEventResult,
- const ServiceWorkerResponse&,
+ blink::mojom::FetchAPIResponsePtr,
blink::mojom::ServiceWorkerStreamHandlePtr,
- blink::mojom::BlobPtr,
scoped_refptr<ServiceWorkerVersion>)>;
// |request_body_*| and |client_id| are used in non-S13nServiceWorker only.
@@ -98,14 +97,12 @@ class CONTENT_EXPORT ServiceWorkerFetchDispatcher {
void DidFail(blink::ServiceWorkerStatusCode status);
void DidFinish(int request_id,
FetchEventResult fetch_result,
- const ServiceWorkerResponse& response,
- blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
- blink::mojom::BlobPtr body_as_blob);
+ blink::mojom::FetchAPIResponsePtr response,
+ blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream);
void Complete(blink::ServiceWorkerStatusCode status,
FetchEventResult fetch_result,
- const ServiceWorkerResponse& response,
- blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
- blink::mojom::BlobPtr body_as_blob);
+ blink::mojom::FetchAPIResponsePtr response,
+ blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream);
// The fetch event stays open until all respondWith() and waitUntil() promises
// are settled. This function is called once the renderer signals that
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 3b93dc19aa0..3af388b83b0 100644
--- a/chromium/content/browser/service_worker/service_worker_internals_ui.cc
+++ b/chromium/content/browser/service_worker/service_worker_internals_ui.cc
@@ -261,6 +261,7 @@ class ServiceWorkerInternalsUI::PartitionObserver
Value(base::Int64ToString(version_id)));
}
void OnVersionStateChanged(int64_t version_id,
+ const GURL& scope,
ServiceWorkerVersion::Status) override {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
web_ui_->CallJavascriptFunctionUnsafe(
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 724ffb5a524..9de6ec76b1f 100644
--- a/chromium/content/browser/service_worker/service_worker_job_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_job_unittest.cc
@@ -24,7 +24,6 @@
#include "content/browser/service_worker/service_worker_registration_object_host.h"
#include "content/browser/service_worker/service_worker_registration_status.h"
#include "content/browser/service_worker/service_worker_test_utils.h"
-#include "content/common/service_worker/service_worker_messages.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
@@ -862,13 +861,14 @@ void WriteResponse(ServiceWorkerStorage* storage,
std::unique_ptr<ServiceWorkerResponseWriter> writer =
storage->CreateResponseWriter(id);
- std::unique_ptr<net::HttpResponseInfo> info(new net::HttpResponseInfo);
+ std::unique_ptr<net::HttpResponseInfo> info =
+ std::make_unique<net::HttpResponseInfo>();
info->request_time = base::Time::Now();
info->response_time = base::Time::Now();
info->was_cached = false;
info->headers = new net::HttpResponseHeaders(headers);
scoped_refptr<HttpResponseInfoIOBuffer> info_buffer =
- new HttpResponseInfoIOBuffer(info.release());
+ base::MakeRefCounted<HttpResponseInfoIOBuffer>(std::move(info));
int rv = -1234;
writer->WriteInfo(info_buffer.get(), base::BindOnce(&OnIOComplete, &rv));
diff --git a/chromium/content/browser/service_worker/service_worker_metrics.cc b/chromium/content/browser/service_worker/service_worker_metrics.cc
index 40bd68cfec9..19d807e0725 100644
--- a/chromium/content/browser/service_worker/service_worker_metrics.cc
+++ b/chromium/content/browser/service_worker/service_worker_metrics.cc
@@ -9,6 +9,7 @@
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
+#include "base/strings/strcat.h"
#include "base/strings/string_util.h"
#include "base/time/time.h"
#include "content/browser/service_worker/embedded_worker_status.h"
@@ -22,7 +23,7 @@ namespace content {
namespace {
-std::string StartSituationToSuffix(
+const char* StartSituationToSuffix(
ServiceWorkerMetrics::StartSituation situation) {
// Don't change these returned strings. They are written (in hashed form) into
// logs.
@@ -44,18 +45,28 @@ std::string StartSituationToSuffix(
}
// TODO(falken): Remove this when the associated UMA are removed.
-std::string StartSituationToDeprecatedSuffix(
+const char* StartSituationToDeprecatedSuffix(
ServiceWorkerMetrics::StartSituation situation) {
// Don't change this returned string. It is written (in hashed form) into
// logs.
- std::string suffix = StartSituationToSuffix(situation);
- // Replace '.' separator with '_'.
- DCHECK(suffix.length() > 1 && suffix[0] == '.');
- suffix[0] = '_';
- return suffix;
+ switch (situation) {
+ case ServiceWorkerMetrics::StartSituation::UNKNOWN:
+ NOTREACHED();
+ return "_Unknown";
+ case ServiceWorkerMetrics::StartSituation::DURING_STARTUP:
+ return "_DuringStartup";
+ case ServiceWorkerMetrics::StartSituation::NEW_PROCESS:
+ return "_NewProcess";
+ case ServiceWorkerMetrics::StartSituation::EXISTING_UNREADY_PROCESS:
+ return "_ExistingUnreadyProcess";
+ case ServiceWorkerMetrics::StartSituation::EXISTING_READY_PROCESS:
+ return "_ExistingReadyProcess";
+ }
+ NOTREACHED() << static_cast<int>(situation);
+ return "_Unknown";
}
-std::string EventTypeToSuffix(ServiceWorkerMetrics::EventType event_type) {
+const char* EventTypeToSuffix(ServiceWorkerMetrics::EventType event_type) {
// Don't change these returned strings. They are written (in hashed form) into
// logs.
switch (event_type) {
@@ -99,8 +110,6 @@ std::string EventTypeToSuffix(ServiceWorkerMetrics::EventType event_type) {
return "_BACKGROUND_FETCH_CLICK";
case ServiceWorkerMetrics::EventType::BACKGROUND_FETCH_FAIL:
return "_BACKGROUND_FETCH_FAIL";
- case ServiceWorkerMetrics::EventType::BACKGROUND_FETCHED:
- return "_BACKGROUND_FETCHED";
case ServiceWorkerMetrics::EventType::NAVIGATION_HINT:
return "_NAVIGATION_HINT";
case ServiceWorkerMetrics::EventType::CAN_MAKE_PAYMENT:
@@ -109,8 +118,10 @@ std::string EventTypeToSuffix(ServiceWorkerMetrics::EventType event_type) {
return "_ABORT_PAYMENT";
case ServiceWorkerMetrics::EventType::COOKIE_CHANGE:
return "_COOKIE_CHANGE";
- case ServiceWorkerMetrics::EventType::NUM_TYPES:
- NOTREACHED() << static_cast<int>(event_type);
+ case ServiceWorkerMetrics::EventType::LONG_RUNNING_MESSAGE:
+ return "_LONG_RUNNING_MESSAGE";
+ case ServiceWorkerMetrics::EventType::BACKGROUND_FETCH_SUCCESS:
+ return "_BACKGROUND_FETCH_SUCCESS";
}
return "_UNKNOWN";
}
@@ -147,12 +158,11 @@ ServiceWorkerMetrics::WorkerPreparationType GetWorkerPreparationType(
return Preparation::UNKNOWN;
}
-std::string GetWorkerPreparationSuffix(
+const char* GetWorkerPreparationSuffix(
ServiceWorkerMetrics::WorkerPreparationType status) {
using Preparation = ServiceWorkerMetrics::WorkerPreparationType;
switch (status) {
case Preparation::UNKNOWN:
- case Preparation::NUM_TYPES:
break;
case Preparation::START_DURING_STARTUP:
return "_StartWorkerDuringStartup";
@@ -173,44 +183,6 @@ std::string GetWorkerPreparationSuffix(
return "_UNKNOWN";
}
-// Use this for histograms with dynamically generated names, which
-// otherwise can't use the UMA_HISTOGRAM macro without code duplication.
-void RecordSuffixedTimeHistogram(const std::string& name,
- const std::string& suffix,
- base::TimeDelta sample) {
- const std::string name_with_suffix = name + suffix;
- // This unrolls UMA_HISTOGRAM_TIMES.
- base::HistogramBase* histogram_pointer = base::Histogram::FactoryTimeGet(
- name_with_suffix, base::TimeDelta::FromMilliseconds(1),
- base::TimeDelta::FromSeconds(10), 50,
- base::HistogramBase::kUmaTargetedHistogramFlag);
- histogram_pointer->AddTime(sample);
-}
-
-// Use this for histograms with dynamically generated names, which
-// otherwise can't use the UMA_MEDIUM_HISTOGRAM macro without code duplication.
-void RecordSuffixedMediumTimeHistogram(const std::string& name,
- const std::string& suffix,
- base::TimeDelta sample) {
- const std::string name_with_suffix = name + suffix;
- // This unrolls UMA_HISTOGRAM_MEDIUM_TIMES.
- base::HistogramBase* histogram_pointer = base::Histogram::FactoryTimeGet(
- name_with_suffix, base::TimeDelta::FromMilliseconds(10),
- base::TimeDelta::FromMinutes(3), 50,
- base::HistogramBase::kUmaTargetedHistogramFlag);
- histogram_pointer->AddTime(sample);
-}
-
-// Use this for histograms with dynamically generated names, which
-// otherwise can't use the UMA_HISTOGRAM macro without code duplication.
-void RecordHistogramEnum(const std::string& name, int value, int max_value) {
- // This unrolls UMA_HISTOGRAM_ENUMERATION.
- base::HistogramBase* histogram_pointer = base::LinearHistogram::FactoryGet(
- name, 1, max_value, max_value + 1,
- base::HistogramBase::kUmaTargetedHistogramFlag);
- histogram_pointer->Add(value);
-}
-
void RecordURLMetricOnUI(const std::string& metric_name, const GURL& url) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
GetContentClient()->browser()->RecordURLMetric(metric_name, url);
@@ -277,8 +249,6 @@ const char* ServiceWorkerMetrics::EventTypeToString(EventType event_type) {
return "Background Fetch Click";
case EventType::BACKGROUND_FETCH_FAIL:
return "Background Fetch Fail";
- case EventType::BACKGROUND_FETCHED:
- return "Background Fetched";
case EventType::NAVIGATION_HINT:
return "Navigation Hint";
case EventType::CAN_MAKE_PAYMENT:
@@ -287,8 +257,10 @@ const char* ServiceWorkerMetrics::EventTypeToString(EventType event_type) {
return "Abort Payment";
case EventType::COOKIE_CHANGE:
return "Cookie Change";
- case EventType::NUM_TYPES:
- break;
+ case EventType::LONG_RUNNING_MESSAGE:
+ return "Long Running Message";
+ case EventType::BACKGROUND_FETCH_SUCCESS:
+ return "Background Fetch Success";
}
NOTREACHED() << "Got unexpected event type: " << static_cast<int>(event_type);
return "error";
@@ -329,7 +301,7 @@ ServiceWorkerMetrics::Site ServiceWorkerMetrics::SiteFromURL(const GURL& url) {
return ServiceWorkerMetrics::Site::NEW_TAB_PAGE;
}
- const std::string host = url.host();
+ const base::StringPiece host = url.host_piece();
if (host == "plus.google.com")
return ServiceWorkerMetrics::Site::PLUS;
if (host == "inbox.google.com")
@@ -403,12 +375,9 @@ void ServiceWorkerMetrics::CountControlledPageLoad(Site site,
const GURL& url,
bool is_main_frame_load) {
DCHECK_NE(site, Site::OTHER);
- UMA_HISTOGRAM_ENUMERATION("ServiceWorker.PageLoad", static_cast<int>(site),
- static_cast<int>(Site::NUM_TYPES));
+ UMA_HISTOGRAM_ENUMERATION("ServiceWorker.PageLoad", site);
if (is_main_frame_load) {
- UMA_HISTOGRAM_ENUMERATION("ServiceWorker.MainFramePageLoad",
- static_cast<int>(site),
- static_cast<int>(Site::NUM_TYPES));
+ UMA_HISTOGRAM_ENUMERATION("ServiceWorker.MainFramePageLoad", site);
}
if (ShouldExcludeSiteFromHistogram(site))
return;
@@ -429,16 +398,14 @@ void ServiceWorkerMetrics::RecordStartWorkerStatus(
}
UMA_HISTOGRAM_ENUMERATION("ServiceWorker.StartWorker.Status", status);
- RecordHistogramEnum(
- std::string("ServiceWorker.StartWorker.StatusByPurpose") +
- EventTypeToSuffix(purpose),
- static_cast<uint32_t>(status),
- static_cast<uint32_t>(blink::ServiceWorkerStatusCode::kMaxValue));
- UMA_HISTOGRAM_ENUMERATION("ServiceWorker.StartWorker.Purpose", purpose,
- EventType::NUM_TYPES);
+ base::UmaHistogramEnumeration(
+ base::StrCat({"ServiceWorker.StartWorker.StatusByPurpose",
+ EventTypeToSuffix(purpose)}),
+ status);
+ UMA_HISTOGRAM_ENUMERATION("ServiceWorker.StartWorker.Purpose", purpose);
if (status == blink::ServiceWorkerStatusCode::kErrorTimeout) {
UMA_HISTOGRAM_ENUMERATION("ServiceWorker.StartWorker.Timeout.StartPurpose",
- purpose, EventType::NUM_TYPES);
+ purpose);
}
}
@@ -455,13 +422,14 @@ void ServiceWorkerMetrics::RecordStartWorkerTime(base::TimeDelta time,
EventType purpose) {
if (is_installed) {
UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.StartWorker.Time", time);
- RecordSuffixedMediumTimeHistogram(
- "ServiceWorker.StartWorker.Time",
- StartSituationToDeprecatedSuffix(start_situation), time);
- RecordSuffixedMediumTimeHistogram(
- "ServiceWorker.StartWorker.Time",
- StartSituationToDeprecatedSuffix(start_situation) +
- EventTypeToSuffix(purpose),
+ base::UmaHistogramMediumTimes(
+ base::StrCat({"ServiceWorker.StartWorker.Time",
+ StartSituationToDeprecatedSuffix(start_situation)}),
+ time);
+ base::UmaHistogramMediumTimes(
+ base::StrCat({"ServiceWorker.StartWorker.Time",
+ StartSituationToDeprecatedSuffix(start_situation),
+ EventTypeToSuffix(purpose)}),
time);
} else {
UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.StartNewWorker.Time", time);
@@ -478,18 +446,15 @@ void ServiceWorkerMetrics::RecordActivatedWorkerPreparationForMainFrame(
WorkerPreparationType preparation =
GetWorkerPreparationType(initial_worker_status, start_situation);
UMA_HISTOGRAM_ENUMERATION(
- "ServiceWorker.ActivatedWorkerPreparationForMainFrame.Type",
- static_cast<int>(preparation),
- static_cast<int>(WorkerPreparationType::NUM_TYPES));
+ "ServiceWorker.ActivatedWorkerPreparationForMainFrame.Type", preparation);
std::string suffix =
GetContentClient()->browser()->GetMetricSuffixForURL(url);
if (!suffix.empty()) {
- RecordHistogramEnum(
- std::string(
- "ServiceWorker.ActivatedWorkerPreparationForMainFrame.Type.") +
- suffix,
- static_cast<int>(preparation),
- static_cast<int>(WorkerPreparationType::NUM_TYPES) - 1);
+ base::UmaHistogramEnumeration(
+ base::StrCat(
+ {"ServiceWorker.ActivatedWorkerPreparationForMainFrame.Type.",
+ suffix}),
+ preparation);
}
if (did_navigation_preload) {
@@ -501,8 +466,7 @@ void ServiceWorkerMetrics::RecordActivatedWorkerPreparationForMainFrame(
UMA_HISTOGRAM_ENUMERATION(
"ServiceWorker.ActivatedWorkerPreparationForMainFrame.Type_"
"NavigationPreloadEnabled",
- static_cast<int>(preparation),
- static_cast<int>(WorkerPreparationType::NUM_TYPES));
+ preparation);
}
// Don't record .Time if S13nServiceWorker is enabled.
@@ -515,9 +479,10 @@ void ServiceWorkerMetrics::RecordActivatedWorkerPreparationForMainFrame(
"ServiceWorker.ActivatedWorkerPreparationForMainFrame.Time", time);
// Record the preparation time using the worker preparation suffix.
- RecordSuffixedMediumTimeHistogram(
- "ServiceWorker.ActivatedWorkerPreparationForMainFrame.Time",
- GetWorkerPreparationSuffix(preparation), time);
+ base::UmaHistogramMediumTimes(
+ base::StrCat({"ServiceWorker.ActivatedWorkerPreparationForMainFrame.Time",
+ GetWorkerPreparationSuffix(preparation)}),
+ time);
// Record the preparation time using the navigation preload suffix.
if (did_navigation_preload) {
@@ -536,9 +501,7 @@ void ServiceWorkerMetrics::RecordActivatedWorkerPreparationForMainFrame(
}
void ServiceWorkerMetrics::RecordWorkerStopped(StopStatus status) {
- UMA_HISTOGRAM_ENUMERATION("ServiceWorker.WorkerStopped",
- static_cast<int>(status),
- static_cast<int>(StopStatus::NUM_TYPES));
+ UMA_HISTOGRAM_ENUMERATION("ServiceWorker.WorkerStopped", status);
}
void ServiceWorkerMetrics::RecordStopWorkerTime(base::TimeDelta time) {
@@ -565,15 +528,14 @@ void ServiceWorkerMetrics::RecordInstallEventStatus(
void ServiceWorkerMetrics::RecordEventDispatchingDelay(EventType event_type,
base::TimeDelta time) {
- const std::string name = "ServiceWorker.EventDispatchingDelay";
- UMA_HISTOGRAM_TIMES(name, time);
- RecordSuffixedTimeHistogram(name, EventTypeToSuffix(event_type), time);
+ static constexpr char kName[] = "ServiceWorker.EventDispatchingDelay";
+ UMA_HISTOGRAM_TIMES(kName, time);
+ base::UmaHistogramTimes(base::StrCat({kName, EventTypeToSuffix(event_type)}),
+ time);
}
void ServiceWorkerMetrics::RecordEventTimeout(EventType event) {
- UMA_HISTOGRAM_ENUMERATION("ServiceWorker.RequestTimeouts.Count",
- static_cast<int>(event),
- static_cast<int>(EventType::NUM_TYPES));
+ UMA_HISTOGRAM_ENUMERATION("ServiceWorker.RequestTimeouts.Count", event);
}
void ServiceWorkerMetrics::RecordEventDuration(EventType event,
@@ -653,9 +615,9 @@ void ServiceWorkerMetrics::RecordEventDuration(EventType event,
UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.BackgroundFetchFailEvent.Time",
time);
break;
- case EventType::BACKGROUND_FETCHED:
- UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.BackgroundFetchedEvent.Time",
- time);
+ case EventType::BACKGROUND_FETCH_SUCCESS:
+ UMA_HISTOGRAM_MEDIUM_TIMES(
+ "ServiceWorker.BackgroundFetchSuccessEvent.Time", time);
break;
case EventType::CAN_MAKE_PAYMENT:
UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.CanMakePaymentEvent.Time",
@@ -667,11 +629,14 @@ void ServiceWorkerMetrics::RecordEventDuration(EventType event,
case EventType::COOKIE_CHANGE:
UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.CookieChangeEvent.Time", time);
break;
+ case EventType::LONG_RUNNING_MESSAGE:
+ // Since this event is expected to last indefinitely we don't need to log
+ // how long they actually last.
+ break;
case EventType::NAVIGATION_HINT:
// The navigation hint should not be sent as an event.
case EventType::UNKNOWN:
- case EventType::NUM_TYPES:
NOTREACHED() << "Invalid event type";
break;
}
@@ -743,9 +708,10 @@ void ServiceWorkerMetrics::RecordStartWorkerTiming(const StartTimes& times,
// Total duration.
UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.StartTiming.Duration",
times.local_end - times.local_start);
- RecordSuffixedMediumTimeHistogram("ServiceWorker.StartTiming.Duration",
- StartSituationToSuffix(situation),
- times.local_end - times.local_start);
+ base::UmaHistogramMediumTimes(
+ base::StrCat({"ServiceWorker.StartTiming.Duration",
+ StartSituationToSuffix(situation)}),
+ times.local_end - times.local_start);
// SentStartWorker milestone.
UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.StartTiming.StartToSentStartWorker",
@@ -785,8 +751,7 @@ void ServiceWorkerMetrics::RecordStartWorkerTiming(const StartTimes& times,
void ServiceWorkerMetrics::RecordStartWorkerTimingClockConsistency(
CrossProcessTimeDelta type) {
- UMA_HISTOGRAM_ENUMERATION("ServiceWorker.StartTiming.ClockConsistency", type,
- CrossProcessTimeDelta::NUM_TYPES);
+ UMA_HISTOGRAM_ENUMERATION("ServiceWorker.StartTiming.ClockConsistency", type);
}
void ServiceWorkerMetrics::RecordStartStatusAfterFailure(
@@ -848,8 +813,7 @@ void ServiceWorkerMetrics::RecordNavigationPreloadResponse(
GetWorkerPreparationType(initial_worker_status, start_situation);
UMA_HISTOGRAM_ENUMERATION(
- "ServiceWorker.NavPreload.WorkerPreparationType_MainFrame", preparation,
- WorkerPreparationType::NUM_TYPES);
+ "ServiceWorker.NavPreload.WorkerPreparationType_MainFrame", preparation);
UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.NavPreload.ResponseTime_MainFrame",
response_start);
UMA_HISTOGRAM_BOOLEAN("ServiceWorker.NavPreload.FinishedFirst_MainFrame",
@@ -887,31 +851,28 @@ void ServiceWorkerMetrics::RecordContextRequestHandlerStatus(
ServiceWorkerContextRequestHandler::CreateJobStatus status,
bool is_installed,
bool is_main_script) {
- const int value = static_cast<int>(status);
- const int max = static_cast<int>(
- ServiceWorkerContextRequestHandler::CreateJobStatus::NUM_TYPES);
if (is_installed) {
if (is_main_script) {
UMA_HISTOGRAM_ENUMERATION(
"ServiceWorker.ContextRequestHandlerStatus.InstalledWorker."
"MainScript",
- value, max);
+ status);
} else {
UMA_HISTOGRAM_ENUMERATION(
"ServiceWorker.ContextRequestHandlerStatus.InstalledWorker."
"ImportedScript",
- value, max);
+ status);
}
} else {
if (is_main_script) {
UMA_HISTOGRAM_ENUMERATION(
"ServiceWorker.ContextRequestHandlerStatus.NewWorker.MainScript",
- value, max);
+ status);
} else {
UMA_HISTOGRAM_ENUMERATION(
"ServiceWorker.ContextRequestHandlerStatus.NewWorker."
"ImportedScript",
- value, max);
+ status);
}
}
}
@@ -942,13 +903,18 @@ void ServiceWorkerMetrics::RecordUninstalledScriptImport(const GURL& url) {
void ServiceWorkerMetrics::RecordStartServiceWorkerForNavigationHintResult(
StartServiceWorkerForNavigationHintResult result) {
- UMA_HISTOGRAM_ENUMERATION(
- "ServiceWorker.StartForNavigationHint.Result", result,
- StartServiceWorkerForNavigationHintResult::NUM_TYPES);
+ UMA_HISTOGRAM_ENUMERATION("ServiceWorker.StartForNavigationHint.Result",
+ result);
}
void ServiceWorkerMetrics::RecordRegisteredOriginCount(size_t origin_count) {
UMA_HISTOGRAM_COUNTS_1M("ServiceWorker.RegisteredOriginCount", origin_count);
}
+void ServiceWorkerMetrics::RecordMainResourceRequestDestination(
+ MainResourceRequestDestination destination) {
+ UMA_HISTOGRAM_ENUMERATION("ServiceWorker.MainResourceRequestDestination",
+ destination);
+}
+
} // 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 d4a4a6bea09..a0898955023 100644
--- a/chromium/content/browser/service_worker/service_worker_metrics.h
+++ b/chromium/content/browser/service_worker/service_worker_metrics.h
@@ -29,6 +29,46 @@ enum class EmbeddedWorkerStatus;
class ServiceWorkerMetrics {
public:
// Used for UMA. Append-only.
+ enum class MainResourceRequestDestination {
+ // The request was routed to the service worker. Fetch event dispatching
+ // possibly succeeded or failed.
+ // ServiceWorker.FetchEvent.MainResource.Status was logged with the result
+ // of the dispatch.
+ kServiceWorker = 0,
+
+ // The request was routed to network for the specified reason.
+ kNetworkBecauseNoActiveVersion = 1,
+ kNetworkBecauseNoActiveVersionAfterContinuing = 2,
+ kNetworkBecauseNoContext = 3,
+ kNetworkBecauseNoFetchEventHandler = 4,
+ kNetworkBecauseNoProvider = 5,
+ kNetworkBecauseNoProviderAfterContinuing = 6,
+ kNetworkBecauseNoRegistration = 7,
+ kNetworkBecauseNotAllowed = 8,
+ kNetworkBecauseNotSecure = 9,
+
+ // The loader couldn't dispatch the fetch event because there was no active
+ // worker.
+ kErrorNoActiveWorkerFromDelegate = 10,
+ // The loader couldn't dispatch the fetch event because the request body
+ // failed.
+ kErrorRequestBodyFailed = 11,
+
+ // The request was being routed to the service worker, but the handler was
+ // destroyed before the result of the fetch event dispatch was received.
+ kAbortedWhileDispatchingFetchEvent = 12,
+ // The handler was destroyed without dispatching a fetch event to the
+ // service
+ // worker.
+ kAbortedWithoutDispatchingFetchEvent = 13,
+
+ // The request was not routed because it was cancelled.
+ kJobWasCancelled = 14,
+
+ kMaxValue = 14,
+ };
+
+ // Used for UMA. Append-only.
enum ReadResponseResult {
READ_OK,
READ_HEADERS_ERROR,
@@ -128,7 +168,7 @@ class ServiceWorkerMetrics {
DETACH_BY_REGISTRY,
TIMEOUT,
// Add new types here.
- NUM_TYPES
+ kMaxValue = TIMEOUT,
};
// Used for UMA. Append-only.
@@ -168,13 +208,15 @@ class ServiceWorkerMetrics {
BACKGROUND_FETCH_ABORT = 23,
BACKGROUND_FETCH_CLICK = 24,
BACKGROUND_FETCH_FAIL = 25,
- BACKGROUND_FETCHED = 26,
+ // BACKGROUND_FETCHED = 26, // Obsolete
NAVIGATION_HINT = 27,
CAN_MAKE_PAYMENT = 28,
ABORT_PAYMENT = 29,
COOKIE_CHANGE = 30,
+ LONG_RUNNING_MESSAGE = 31,
+ BACKGROUND_FETCH_SUCCESS = 32,
// Add new events to record here.
- NUM_TYPES
+ kMaxValue = BACKGROUND_FETCH_SUCCESS,
};
// Used for UMA. Append only.
@@ -187,7 +229,7 @@ class ServiceWorkerMetrics {
PLUS,
INBOX,
DOCS,
- NUM_TYPES
+ kMaxValue = DOCS,
};
// Not used for UMA.
@@ -234,7 +276,7 @@ class ServiceWorkerMetrics {
// existing ready process.
START_IN_EXISTING_READY_PROCESS = 8,
// Add new types here.
- NUM_TYPES
+ kMaxValue = START_IN_EXISTING_READY_PROCESS,
};
// Used for UMA. Append only.
@@ -244,7 +286,7 @@ class ServiceWorkerMetrics {
NEGATIVE,
INACCURATE_CLOCK,
// Add new types here.
- NUM_TYPES
+ kMaxValue = INACCURATE_CLOCK,
};
// These are prefixed with "local" or "remote" to indicate whether the browser
@@ -443,6 +485,9 @@ class ServiceWorkerMetrics {
// Records the number of origins with a registered service worker.
static void RecordRegisteredOriginCount(size_t origin_count);
+ static void RecordMainResourceRequestDestination(
+ MainResourceRequestDestination destination);
+
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(ServiceWorkerMetrics);
};
diff --git a/chromium/content/browser/service_worker/service_worker_navigation_loader.cc b/chromium/content/browser/service_worker/service_worker_navigation_loader.cc
index 24fa5a697bc..79f9270e1c1 100644
--- a/chromium/content/browser/service_worker/service_worker_navigation_loader.cc
+++ b/chromium/content/browser/service_worker/service_worker_navigation_loader.cc
@@ -25,7 +25,7 @@ namespace {
std::string ComposeFetchEventResultString(
ServiceWorkerFetchDispatcher::FetchEventResult result,
- const ServiceWorkerResponse& response) {
+ const blink::mojom::FetchAPIResponse& response) {
if (result == ServiceWorkerFetchDispatcher::FetchEventResult::kShouldFallback)
return "Fallback to network";
std::stringstream stream;
@@ -85,25 +85,31 @@ class ServiceWorkerNavigationLoader::StreamWaiter
ServiceWorkerNavigationLoader::ServiceWorkerNavigationLoader(
NavigationLoaderInterceptor::LoaderCallback callback,
+ NavigationLoaderInterceptor::FallbackCallback fallback_callback,
Delegate* delegate,
- const network::ResourceRequest& resource_request,
+ const network::ResourceRequest& tentative_resource_request,
scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter)
: loader_callback_(std::move(callback)),
+ fallback_callback_(std::move(fallback_callback)),
delegate_(delegate),
- resource_request_(resource_request),
url_loader_factory_getter_(std::move(url_loader_factory_getter)),
binding_(this),
weak_factory_(this) {
TRACE_EVENT_WITH_FLOW1(
"ServiceWorker",
"ServiceWorkerNavigationLoader::ServiceWorkerNavigationloader", this,
- TRACE_EVENT_FLAG_FLOW_OUT, "url", resource_request_.url.spec());
+ TRACE_EVENT_FLAG_FLOW_OUT, "url", tentative_resource_request.url.spec());
+ DCHECK(delegate_);
DCHECK(ServiceWorkerUtils::IsMainResourceType(
- static_cast<ResourceType>(resource_request.resource_type)));
+ static_cast<ResourceType>(tentative_resource_request.resource_type)));
response_head_.load_timing.request_start = base::TimeTicks::Now();
response_head_.load_timing.request_start_time = base::Time::Now();
+
+ // Beware that the final resource request may change due to throttles, so
+ // don't save |tentative_resource_request| here. We'll get the real one in
+ // StartRequest.
}
ServiceWorkerNavigationLoader::~ServiceWorkerNavigationLoader() {
@@ -134,19 +140,26 @@ void ServiceWorkerNavigationLoader::ForwardToServiceWorker() {
"ServiceWorker", "ServiceWorkerNavigationLoader::ForwardToServiceWorker",
this, TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
response_type_ = ResponseType::FORWARD_TO_SERVICE_WORKER;
- StartRequest();
+
+ std::move(loader_callback_)
+ .Run(base::BindOnce(&ServiceWorkerNavigationLoader::StartRequest,
+ weak_factory_.GetWeakPtr()));
}
bool ServiceWorkerNavigationLoader::ShouldFallbackToNetwork() {
return response_type_ == ResponseType::FALLBACK_TO_NETWORK;
}
+bool ServiceWorkerNavigationLoader::ShouldForwardToServiceWorker() {
+ return response_type_ == ResponseType::FORWARD_TO_SERVICE_WORKER;
+}
+
bool ServiceWorkerNavigationLoader::WasCanceled() const {
return status_ == Status::kCancelled;
}
void ServiceWorkerNavigationLoader::DetachedFromRequest() {
- detached_from_request_ = true;
+ delegate_ = nullptr;
DeleteIfNeeded();
}
@@ -155,7 +168,21 @@ ServiceWorkerNavigationLoader::AsWeakPtr() {
return weak_factory_.GetWeakPtr();
}
-void ServiceWorkerNavigationLoader::StartRequest() {
+void ServiceWorkerNavigationLoader::StartRequest(
+ const network::ResourceRequest& resource_request,
+ network::mojom::URLLoaderRequest request,
+ network::mojom::URLLoaderClientPtr client) {
+ resource_request_ = resource_request;
+
+ DCHECK(delegate_);
+ DCHECK(!binding_.is_bound());
+ DCHECK(!url_loader_client_.is_bound());
+ binding_.Bind(std::move(request));
+ binding_.set_connection_error_handler(
+ base::BindOnce(&ServiceWorkerNavigationLoader::OnConnectionClosed,
+ base::Unretained(this)));
+ url_loader_client_ = std::move(client);
+
DCHECK_EQ(ResponseType::FORWARD_TO_SERVICE_WORKER, response_type_);
DCHECK_EQ(Status::kNotStarted, status_);
status_ = Status::kStarted;
@@ -169,14 +196,18 @@ void ServiceWorkerNavigationLoader::StartRequest() {
ServiceWorkerVersion* active_worker =
delegate_->GetServiceWorkerVersion(&result);
if (!active_worker) {
- ReturnNetworkError();
+ delegate_->ReportDestination(
+ ServiceWorkerMetrics::MainResourceRequestDestination::
+ kErrorNoActiveWorkerFromDelegate);
+ CommitCompleted(net::ERR_FAILED);
return;
}
// ServiceWorkerFetchDispatcher requires a std::unique_ptr<ResourceRequest>
// so make one here.
// TODO(crbug.com/803125): Try to eliminate unnecessary copying?
- auto request = std::make_unique<network::ResourceRequest>(resource_request_);
+ auto resource_request_to_pass =
+ std::make_unique<network::ResourceRequest>(resource_request_);
// Passing the request body over Mojo moves out the DataPipeGetter elements,
// which would mean we should clone the body like
@@ -184,13 +215,15 @@ void ServiceWorkerNavigationLoader::StartRequest() {
// here yet: they are only created by the renderer when converting from a
// Blob, which doesn't happen for navigations. In interest of speed, just
// don't clone until proven necessary.
- DCHECK(BodyHasNoDataPipeGetters(request->request_body.get()))
+ DCHECK(BodyHasNoDataPipeGetters(resource_request_to_pass->request_body.get()))
<< "We assumed there would be no data pipe getter elements here, but "
"there are. Add code here to clone the body before proceeding.";
// Dispatch the fetch event.
+ delegate_->WillDispatchFetchEventForMainResource();
fetch_dispatcher_ = std::make_unique<ServiceWorkerFetchDispatcher>(
- std::move(request), std::string() /* request_body_blob_uuid */,
+ std::move(resource_request_to_pass),
+ std::string() /* request_body_blob_uuid */,
0 /* request_body_blob_size */, nullptr /* request_body_blob */,
std::string() /* client_id */, active_worker,
net::NetLogWithSource() /* TODO(scottmg): net log? */,
@@ -239,19 +272,6 @@ void ServiceWorkerNavigationLoader::CommitCompleted(int error_code) {
network::URLLoaderCompletionStatus(error_code));
}
-void ServiceWorkerNavigationLoader::ReturnNetworkError() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- TRACE_EVENT_WITH_FLOW0(
- "ServiceWorker", "ServiceWorkerNavigationLoader::ReturnNetworkError",
- this, TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
-
- DCHECK(!url_loader_client_.is_bound());
- DCHECK(loader_callback_);
- std::move(loader_callback_)
- .Run(base::BindOnce(&ServiceWorkerNavigationLoader::StartErrorResponse,
- weak_factory_.GetWeakPtr()));
-}
-
void ServiceWorkerNavigationLoader::DidPrepareFetchEvent(
scoped_refptr<ServiceWorkerVersion> version,
EmbeddedWorkerStatus initial_worker_status) {
@@ -277,9 +297,8 @@ void ServiceWorkerNavigationLoader::DidPrepareFetchEvent(
void ServiceWorkerNavigationLoader::DidDispatchFetchEvent(
blink::ServiceWorkerStatusCode status,
ServiceWorkerFetchDispatcher::FetchEventResult fetch_result,
- const ServiceWorkerResponse& response,
+ blink::mojom::FetchAPIResponsePtr response,
blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
- blink::mojom::BlobPtr body_as_blob,
scoped_refptr<ServiceWorkerVersion> version) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -287,26 +306,41 @@ void ServiceWorkerNavigationLoader::DidDispatchFetchEvent(
"ServiceWorker", "ServiceWorkerNavigationLoader::DidDispatchFetchEvent",
this, TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "status",
blink::ServiceWorkerStatusToString(status), "result",
- ComposeFetchEventResultString(fetch_result, response));
+ ComposeFetchEventResultString(fetch_result, *response));
+
ServiceWorkerMetrics::RecordFetchEventStatus(true /* is_main_resource */,
status);
+ if (delegate_) {
+ delegate_->ReportDestination(
+ ServiceWorkerMetrics::MainResourceRequestDestination::kServiceWorker);
+ }
ServiceWorkerMetrics::URLRequestJobResult result =
ServiceWorkerMetrics::REQUEST_JOB_ERROR_BAD_DELEGATE;
- if (!delegate_->RequestStillValid(&result)) {
- ReturnNetworkError();
+ if (!delegate_ || !delegate_->RequestStillValid(&result)) {
+ // The navigation or shared worker startup is cancelled. Just abort.
+ CommitCompleted(net::ERR_ABORTED);
return;
}
if (status != blink::ServiceWorkerStatusCode::kOk) {
+ // Dispatching the event to the service worker failed. Do a last resort
+ // attempt to load the page via network as if there was no service worker.
+ // It'd be more correct and simpler to remove this path and show an error
+ // page, but the risk is that the user will be stuck if there's a persistent
+ // failure.
delegate_->MainResourceLoadFailed();
- FallbackToNetwork();
+ std::move(fallback_callback_)
+ .Run(true /* reset_subresource_loader_params */);
return;
}
if (fetch_result ==
ServiceWorkerFetchDispatcher::FetchEventResult::kShouldFallback) {
- FallbackToNetwork();
+ // TODO(falken): Propagate the timing info to the renderer somehow, or else
+ // Navigation Timing etc APIs won't know about service worker.
+ std::move(fallback_callback_)
+ .Run(false /* reset_subresource_loader_params */);
return;
}
@@ -315,35 +349,22 @@ void ServiceWorkerNavigationLoader::DidDispatchFetchEvent(
// A response with status code 0 is Blink telling us to respond with
// network error.
- if (response.status_code == 0) {
- ReturnNetworkError();
+ if (response->status_code == 0) {
+ CommitCompleted(net::ERR_FAILED);
return;
}
- std::move(loader_callback_)
- .Run(base::BindOnce(&ServiceWorkerNavigationLoader::StartResponse,
- weak_factory_.GetWeakPtr(), response, version,
- std::move(body_as_stream), std::move(body_as_blob)));
+ StartResponse(std::move(response), std::move(version),
+ std::move(body_as_stream));
}
void ServiceWorkerNavigationLoader::StartResponse(
- const ServiceWorkerResponse& response,
+ blink::mojom::FetchAPIResponsePtr response,
scoped_refptr<ServiceWorkerVersion> version,
- blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
- blink::mojom::BlobPtr body_as_blob,
- network::mojom::URLLoaderRequest request,
- network::mojom::URLLoaderClientPtr client) {
- DCHECK(!binding_.is_bound());
- DCHECK(!url_loader_client_.is_bound());
- binding_.Bind(std::move(request));
- binding_.set_connection_error_handler(
- base::BindOnce(&ServiceWorkerNavigationLoader::OnConnectionClosed,
- base::Unretained(this)));
- url_loader_client_ = std::move(client);
-
- ServiceWorkerLoaderHelpers::SaveResponseInfo(response, &response_head_);
+ blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream) {
+ ServiceWorkerLoaderHelpers::SaveResponseInfo(*response, &response_head_);
ServiceWorkerLoaderHelpers::SaveResponseHeaders(
- response.status_code, response.status_text, response.headers,
+ response->status_code, response->status_text, response->headers,
&response_head_);
response_head_.did_service_worker_navigation_preload =
@@ -395,8 +416,9 @@ void ServiceWorkerNavigationLoader::StartResponse(
}
// Handle a blob response body.
- if (body_as_blob) {
- body_as_blob_ = std::move(body_as_blob);
+ if (response->blob) {
+ DCHECK(response->blob->blob.is_valid());
+ body_as_blob_.Bind(std::move(response->blob->blob));
mojo::ScopedDataPipeConsumerHandle data_pipe;
int error = ServiceWorkerLoaderHelpers::ReadBlobResponseBody(
&body_as_blob_, resource_request_.headers,
@@ -426,15 +448,6 @@ void ServiceWorkerNavigationLoader::StartResponse(
CommitCompleted(net::OK);
}
-void ServiceWorkerNavigationLoader::StartErrorResponse(
- network::mojom::URLLoaderRequest request,
- network::mojom::URLLoaderClientPtr client) {
- DCHECK_EQ(Status::kStarted, status_);
- DCHECK(!url_loader_client_.is_bound());
- url_loader_client_ = std::move(client);
- CommitCompleted(net::ERR_FAILED);
-}
-
// URLLoader implementation----------------------------------------
void ServiceWorkerNavigationLoader::FollowRedirect(
@@ -482,7 +495,7 @@ void ServiceWorkerNavigationLoader::OnConnectionClosed() {
}
void ServiceWorkerNavigationLoader::DeleteIfNeeded() {
- if (!binding_.is_bound() && detached_from_request_)
+ if (!binding_.is_bound() && !delegate_)
delete this;
}
diff --git a/chromium/content/browser/service_worker/service_worker_navigation_loader.h b/chromium/content/browser/service_worker/service_worker_navigation_loader.h
index b39480174a3..f31dc270ae8 100644
--- a/chromium/content/browser/service_worker/service_worker_navigation_loader.h
+++ b/chromium/content/browser/service_worker/service_worker_navigation_loader.h
@@ -17,17 +17,16 @@
#include "content/browser/service_worker/service_worker_response_type.h"
#include "content/browser/service_worker/service_worker_url_job_wrapper.h"
#include "content/browser/url_loader_factory_getter.h"
-#include "content/common/service_worker/service_worker_types.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "services/network/public/mojom/url_loader.mojom.h"
#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
#include "third_party/blink/public/mojom/blob/blob.mojom.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_response.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_stream_handle.mojom.h"
namespace content {
-struct ServiceWorkerResponse;
class ServiceWorkerVersion;
// S13nServiceWorker:
@@ -60,25 +59,27 @@ class CONTENT_EXPORT ServiceWorkerNavigationLoader
// to the network this will call |loader_callback| with a null
// RequestHandler, which will be then handled by NavigationURLLoaderImpl.
// 2. If it is decided that the request should be sent to the SW,
- // this job dispatches a FetchEvent in StartRequest.
- // 3. In DidDispatchFetchEvent() this job determines the request's
- // final destination, and may still call |loader_callback| with null
- // RequestHandler if it turns out that we need to fallback to the network.
- // 4. Otherwise if the SW returned a stream or blob as a response
- // this job calls |loader_callback| with a RequestHandler bound from
- // StartResponse().
- // 5. Then StartResponse() will be called with a
- // network::mojom::URLLoaderClientPtr that is connected to
- // NavigationURLLoaderImpl (for resource loading for navigation).
- // This forwards the blob/stream data pipe to the NavigationURLLoader if
- // the response body was sent as a blob/stream.
+ // this job calls |loader_callback|, passing StartRequest as the
+ // RequestHandler.
+ // 3. At this point, the NavigationURLLoaderImpl can throttle the request,
+ // and invoke the RequestHandler later with a possibly modified request.
+ // 4. StartRequest is invoked. This dispatches a FetchEvent.
+ // 5. DidDispatchFetchEvent() determines the request's final destination. If
+ // it turns out we need to fallback to network, it calls
+ // |fallback_callback|.
+ // 6. Otherwise if the SW returned a stream or blob as a response
+ // this job passes the response to the network::mojom::URLLoaderClientPtr
+ // connected to NavigationURLLoaderImpl (for resource loading for
+ // navigation), that was given to StartRequest. This forwards the
+ // blob/stream data pipe to the NavigationURLLoader.
//
// Loads for shared workers work similarly, except SharedWorkerScriptLoader
// is used instead of NavigationURLLoaderImpl.
ServiceWorkerNavigationLoader(
NavigationLoaderInterceptor::LoaderCallback loader_callback,
+ NavigationLoaderInterceptor::FallbackCallback fallback_callback,
Delegate* delegate,
- const network::ResourceRequest& resource_request,
+ const network::ResourceRequest& tentative_resource_request,
scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter);
~ServiceWorkerNavigationLoader() override;
@@ -87,6 +88,7 @@ class CONTENT_EXPORT ServiceWorkerNavigationLoader
void FallbackToNetwork();
void ForwardToServiceWorker();
bool ShouldFallbackToNetwork();
+ bool ShouldForwardToServiceWorker();
bool WasCanceled() const;
// The navigation request that was holding this job is
@@ -102,43 +104,27 @@ class CONTENT_EXPORT ServiceWorkerNavigationLoader
class StreamWaiter;
// For FORWARD_TO_SERVICE_WORKER case.
- void StartRequest();
+ void StartRequest(const network::ResourceRequest& resource_request,
+ network::mojom::URLLoaderRequest request,
+ network::mojom::URLLoaderClientPtr client);
void DidPrepareFetchEvent(scoped_refptr<ServiceWorkerVersion> version,
EmbeddedWorkerStatus initial_worker_status);
void DidDispatchFetchEvent(
blink::ServiceWorkerStatusCode status,
ServiceWorkerFetchDispatcher::FetchEventResult fetch_result,
- const ServiceWorkerResponse& response,
+ blink::mojom::FetchAPIResponsePtr response,
blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
- blink::mojom::BlobPtr body_as_blob,
scoped_refptr<ServiceWorkerVersion> version);
- // Used as the RequestHandler passed to |loader_callback_| when the service
- // worker chooses to handle a resource request. Returns the response to
- // |client|. |body_as_blob| is kept around until BlobDataHandle is created
- // from blob_uuid just to make sure the blob is kept alive.
- void StartResponse(const ServiceWorkerResponse& response,
+ void StartResponse(blink::mojom::FetchAPIResponsePtr response,
scoped_refptr<ServiceWorkerVersion> version,
- blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
- blink::mojom::BlobPtr body_as_blob,
- network::mojom::URLLoaderRequest request,
- network::mojom::URLLoaderClientPtr client);
+ blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream);
- // Used as the RequestHandler passed to |loader_callback_| on error. Returns a
- // network error to |client|.
- void StartErrorResponse(network::mojom::URLLoaderRequest request,
- network::mojom::URLLoaderClientPtr client);
-
- // Calls url_loader_client_->OnReceiveResopnse() with |response_head_|.
+ // Calls url_loader_client_->OnReceiveResponse() with |response_head_|.
void CommitResponseHeaders();
- // Calls url_loader_client_->OnComplete(). Expected to be called after
- // CommitResponseHeaders (i.e. status_ == kSentHeader).
+ // Calls url_loader_client_->OnComplete().
void CommitCompleted(int error_code);
- // Calls |loader_callback_| with StartErrorResponse callback. Must not be
- // called once either StartResponse or StartErrorResponse is called.
- void ReturnNetworkError();
-
// network::mojom::URLLoader:
void FollowRedirect(const base::Optional<std::vector<std::string>>&
to_be_removed_request_headers,
@@ -155,10 +141,22 @@ class CONTENT_EXPORT ServiceWorkerNavigationLoader
void OnConnectionClosed();
void DeleteIfNeeded();
+ void ReportDestination(
+ ServiceWorkerMetrics::MainResourceRequestDestination destination);
+
ResponseType response_type_ = ResponseType::NOT_DETERMINED;
NavigationLoaderInterceptor::LoaderCallback loader_callback_;
+ NavigationLoaderInterceptor::FallbackCallback fallback_callback_;
+
+ // |delegate_| is non-null and owns |this| until DetachedFromRequest() is
+ // called. Once that is called, |delegate_| is reset to null and |this| owns
+ // itself, self-destructing when a connection error on |binding_| occurs.
+ //
+ // Note: A WeakPtr wouldn't be super safe here because the delegate can
+ // conceivably still be alive and used for another loader, after calling
+ // DetachedFromRequest() for this loader.
+ Delegate* delegate_ = nullptr;
- Delegate* delegate_;
network::ResourceRequest resource_request_;
scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter_;
std::unique_ptr<ServiceWorkerFetchDispatcher> fetch_dispatcher_;
@@ -182,8 +180,6 @@ class CONTENT_EXPORT ServiceWorkerNavigationLoader
};
Status status_ = Status::kNotStarted;
- bool detached_from_request_ = false;
-
base::WeakPtrFactory<ServiceWorkerNavigationLoader> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerNavigationLoader);
diff --git a/chromium/content/browser/service_worker/service_worker_navigation_loader_unittest.cc b/chromium/content/browser/service_worker/service_worker_navigation_loader_unittest.cc
index 3b22bc42d71..02010ab2c3e 100644
--- a/chromium/content/browser/service_worker/service_worker_navigation_loader_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_navigation_loader_unittest.cc
@@ -44,6 +44,34 @@ void ReceiveRequestHandler(
*out_handler = std::move(handler);
}
+blink::mojom::FetchAPIResponsePtr OkResponse(
+ blink::mojom::SerializedBlobPtr blob_body) {
+ auto response = blink::mojom::FetchAPIResponse::New();
+ response->status_code = 200;
+ response->status_text = "OK";
+ response->response_type = network::mojom::FetchResponseType::kDefault;
+ response->blob = std::move(blob_body);
+ return response;
+}
+
+blink::mojom::FetchAPIResponsePtr ErrorResponse() {
+ auto response = blink::mojom::FetchAPIResponse::New();
+ response->status_code = 0;
+ response->response_type = network::mojom::FetchResponseType::kDefault;
+ response->error = blink::mojom::ServiceWorkerResponseError::kPromiseRejected;
+ return response;
+}
+
+blink::mojom::FetchAPIResponsePtr RedirectResponse(
+ const std::string& redirect_location_header) {
+ auto response = blink::mojom::FetchAPIResponse::New();
+ response->status_code = 301;
+ response->status_text = "Moved Permanently";
+ response->response_type = network::mojom::FetchResponseType::kDefault;
+ response->headers["Location"] = redirect_location_header;
+ return response;
+}
+
// NavigationPreloadLoaderClient mocks the renderer-side URLLoaderClient for the
// navigation preload network request performed by the browser. In production
// code, this is ServiceWorkerContextClient::NavigationPreloadRequest,
@@ -71,7 +99,7 @@ class NavigationPreloadLoaderClient final
public:
NavigationPreloadLoaderClient(
blink::mojom::FetchEventPreloadHandlePtr preload_handle,
- mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
+ blink::mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
mojom::ServiceWorker::DispatchFetchEventCallback finish_callback)
: url_loader_(std::move(preload_handle->url_loader)),
binding_(this, std::move(preload_handle->url_loader_client_request)),
@@ -102,21 +130,14 @@ class NavigationPreloadLoaderClient final
// Simulate passing the navigation preload response to
// FetchEvent#respondWith.
+ auto response = blink::mojom::FetchAPIResponse::New();
+ response->url_list =
+ std::vector<GURL>(response_head_.url_list_via_service_worker);
+ response->status_code = response_head_.headers->response_code();
+ response->status_text = response_head_.headers->GetStatusText();
+ response->response_type = response_head_.response_type;
response_callback_->OnResponseStream(
- ServiceWorkerResponse(
- std::make_unique<std::vector<GURL>>(
- response_head_.url_list_via_service_worker),
- response_head_.headers->response_code(),
- response_head_.headers->GetStatusText(),
- response_head_.response_type_via_service_worker,
- std::make_unique<ServiceWorkerHeaderMap>(), "" /* blob_uuid */,
- 0 /* blob_size */, nullptr /* blob */,
- blink::mojom::ServiceWorkerResponseError::kUnknown, base::Time(),
- false /* response_is_in_cache_storage */,
- std::string() /* response_cache_storage_cache_name */,
- std::make_unique<
- ServiceWorkerHeaderList>() /* cors_exposed_header_names */),
- std::move(stream_handle), base::Time::Now());
+ std::move(response), std::move(stream_handle), base::Time::Now());
std::move(finish_callback_)
.Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
base::Time::Now());
@@ -142,7 +163,7 @@ class NavigationPreloadLoaderClient final
mojo::ScopedDataPipeConsumerHandle body_;
// Callbacks that complete Helper::OnFetchEvent().
- mojom::ServiceWorkerFetchResponseCallbackPtr response_callback_;
+ blink::mojom::ServiceWorkerFetchResponseCallbackPtr response_callback_;
mojom::ServiceWorker::DispatchFetchEventCallback finish_callback_;
DISALLOW_COPY_AND_ASSIGN(NavigationPreloadLoaderClient);
@@ -156,7 +177,7 @@ class Helper : public EmbeddedWorkerTestHelper {
~Helper() override = default;
// Tells this helper to respond to fetch events with the specified blob.
- void RespondWithBlob(blink::mojom::BlobPtr blob) {
+ void RespondWithBlob(blink::mojom::SerializedBlobPtr blob) {
response_mode_ = ResponseMode::kBlob;
blob_body_ = std::move(blob);
}
@@ -230,7 +251,7 @@ class Helper : public EmbeddedWorkerTestHelper {
int embedded_worker_id,
const network::ResourceRequest& request,
blink::mojom::FetchEventPreloadHandlePtr preload_handle,
- mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
+ blink::mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
mojom::ServiceWorker::DispatchFetchEventCallback finish_callback)
override {
// Basic checks on DispatchFetchEvent parameters.
@@ -246,35 +267,16 @@ class Helper : public EmbeddedWorkerTestHelper {
std::move(response_callback), std::move(finish_callback));
return;
case ResponseMode::kBlob:
- response_callback->OnResponseBlob(
- ServiceWorkerResponse(
- std::make_unique<std::vector<GURL>>(), 200, "OK",
- network::mojom::FetchResponseType::kDefault,
- std::make_unique<ServiceWorkerHeaderMap>(), "" /* blob_uuid */,
- 0 /* blob_size */, nullptr /* blob */,
- blink::mojom::ServiceWorkerResponseError::kUnknown,
- base::Time(), false /* response_is_in_cache_storage */,
- std::string() /* response_cache_storage_cache_name */,
- std::make_unique<
- ServiceWorkerHeaderList>() /* cors_exposed_header_names */),
- std::move(blob_body_), base::Time::Now());
+ response_callback->OnResponse(OkResponse(std::move(blob_body_)),
+ base::Time::Now());
std::move(finish_callback)
.Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
base::Time::Now());
return;
case ResponseMode::kStream:
- response_callback->OnResponseStream(
- ServiceWorkerResponse(
- std::make_unique<std::vector<GURL>>(), 200, "OK",
- network::mojom::FetchResponseType::kDefault,
- std::make_unique<ServiceWorkerHeaderMap>(), "" /* blob_uuid */,
- 0 /* blob_size */, nullptr /* blob */,
- blink::mojom::ServiceWorkerResponseError::kUnknown,
- base::Time(), false /* response_is_in_cache_storage */,
- std::string() /* response_cache_storage_cache_name */,
- std::make_unique<
- ServiceWorkerHeaderList>() /* cors_exposed_header_names */),
- std::move(stream_handle_), base::Time::Now());
+ response_callback->OnResponseStream(OkResponse(nullptr /* blob_body */),
+ std::move(stream_handle_),
+ base::Time::Now());
std::move(finish_callback)
.Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
base::Time::Now());
@@ -286,19 +288,7 @@ class Helper : public EmbeddedWorkerTestHelper {
base::Time::Now());
return;
case ResponseMode::kErrorResponse:
- response_callback->OnResponse(
- ServiceWorkerResponse(
- std::make_unique<std::vector<GURL>>(), 0 /* status_code */,
- "" /* status_text */,
- network::mojom::FetchResponseType::kDefault,
- std::make_unique<ServiceWorkerHeaderMap>(), "" /* blob_uuid */,
- 0 /* blob_size */, nullptr /* blob */,
- blink::mojom::ServiceWorkerResponseError::kPromiseRejected,
- base::Time(), false /* response_is_in_cache_storage */,
- std::string() /* response_cache_storage_cache_name */,
- std::make_unique<
- ServiceWorkerHeaderList>() /* cors_exposed_header_names */),
- base::Time::Now());
+ response_callback->OnResponse(ErrorResponse(), base::Time::Now());
std::move(finish_callback)
.Run(blink::mojom::ServiceWorkerEventStatus::REJECTED,
base::Time::Now());
@@ -327,34 +317,13 @@ class Helper : public EmbeddedWorkerTestHelper {
return;
case ResponseMode::kEarlyResponse:
finish_callback_ = std::move(finish_callback);
- response_callback->OnResponse(
- ServiceWorkerResponse(
- std::make_unique<std::vector<GURL>>(), 200, "OK",
- network::mojom::FetchResponseType::kDefault,
- std::make_unique<ServiceWorkerHeaderMap>(), "" /* blob_uuid */,
- 0 /* blob_size */, nullptr /* blob */,
- blink::mojom::ServiceWorkerResponseError::kUnknown,
- base::Time(), false /* response_is_in_cache_storage */,
- std::string() /* response_cache_storage_cache_name */,
- std::make_unique<
- ServiceWorkerHeaderList>() /* cors_exposed_header_names */),
- base::Time::Now());
+ response_callback->OnResponse(OkResponse(nullptr /* blob_body */),
+ base::Time::Now());
// Now the caller must call FinishWaitUntil() to finish the event.
return;
case ResponseMode::kRedirect:
- auto headers = std::make_unique<ServiceWorkerHeaderMap>();
- (*headers)["location"] = redirected_url_.spec();
- response_callback->OnResponse(
- ServiceWorkerResponse(
- std::make_unique<std::vector<GURL>>(), 301, "Moved Permanently",
- network::mojom::FetchResponseType::kDefault, std::move(headers),
- "" /* blob_uuid */, 0 /* blob_size */, nullptr /* blob */,
- blink::mojom::ServiceWorkerResponseError::kUnknown,
- base::Time(), false /* response_is_in_cache_storage */,
- std::string() /* response_cache_storage_cache_name */,
- std::make_unique<
- ServiceWorkerHeaderList>() /* cors_exposed_header_names */),
- base::Time::Now());
+ response_callback->OnResponse(RedirectResponse(redirected_url_.spec()),
+ base::Time::Now());
std::move(finish_callback)
.Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
base::Time::Now());
@@ -380,7 +349,7 @@ class Helper : public EmbeddedWorkerTestHelper {
scoped_refptr<network::ResourceRequestBody> request_body_;
// For ResponseMode::kBlob.
- blink::mojom::BlobPtr blob_body_;
+ blink::mojom::SerializedBlobPtr blob_body_;
// For ResponseMode::kStream.
blink::mojom::ServiceWorkerStreamHandlePtr stream_handle_;
@@ -403,8 +372,7 @@ CreateResponseInfoFromServiceWorker() {
head->was_fetched_via_service_worker = true;
head->was_fallback_required_by_service_worker = false;
head->url_list_via_service_worker = std::vector<GURL>();
- head->response_type_via_service_worker =
- network::mojom::FetchResponseType::kDefault;
+ head->response_type = network::mojom::FetchResponseType::kDefault;
head->is_in_cache_storage = false;
head->cache_storage_cache_name = std::string();
head->did_service_worker_navigation_preload = false;
@@ -476,15 +444,19 @@ class ServiceWorkerNavigationLoaderTest
kDidNotHandleRequest,
};
- // Returns whether ServiceWorkerNavigationLoader handled the request. If
- // kHandledRequest was returned, the request is ongoing and the caller can use
- // functions like client_.RunUntilComplete() to wait for completion.
+ // Starts a request. Returns whether ServiceWorkerNavigationLoader handled the
+ // request. If kHandledRequest was returned, the request is ongoing and the
+ // caller can use functions like client_.RunUntilComplete() to wait for
+ // completion.
LoaderResult StartRequest(std::unique_ptr<network::ResourceRequest> request) {
// Start a ServiceWorkerNavigationLoader. It should return a
// RequestHandler.
SingleRequestURLLoaderFactory::RequestHandler handler;
loader_ = std::make_unique<ServiceWorkerNavigationLoader>(
- base::BindOnce(&ReceiveRequestHandler, &handler), this, *request,
+ base::BindOnce(&ReceiveRequestHandler, &handler),
+ base::BindOnce(&ServiceWorkerNavigationLoaderTest::Fallback,
+ base::Unretained(this)),
+ this, *request,
base::WrapRefCounted<URLLoaderFactoryGetter>(
helper_->context()->loader_factory_getter()));
loader_->ForwardToServiceWorker();
@@ -493,12 +465,32 @@ class ServiceWorkerNavigationLoaderTest
return LoaderResult::kDidNotHandleRequest;
// Run the handler. It will load |request.url|.
- std::move(handler).Run(mojo::MakeRequest(&loader_ptr_),
+ std::move(handler).Run(*request, mojo::MakeRequest(&loader_ptr_),
client_.CreateInterfacePtr());
return LoaderResult::kHandledRequest;
}
+ // The |fallback_callback| passed to the ServiceWorkerNavigationLoader in
+ // StartRequest().
+ void Fallback(bool reset_subresource_loader_params) {
+ did_call_fallback_callback_ = true;
+ reset_subresource_loader_params_ = reset_subresource_loader_params;
+ if (quit_closure_for_fallback_callback_)
+ std::move(quit_closure_for_fallback_callback_).Run();
+ }
+
+ // Runs until the ServiceWorkerNavigationLoader created in StartRequest()
+ // calls the |fallback_callback| given to it. The argument passed to
+ // |fallback_callback| is saved in |reset_subresurce_loader_params_|.
+ void RunUntilFallbackCallback() {
+ if (did_call_fallback_callback_)
+ return;
+ base::RunLoop run_loop;
+ quit_closure_for_fallback_callback_ = run_loop.QuitClosure();
+ run_loop.Run();
+ }
+
void ExpectResponseInfo(const network::ResourceResponseHead& info,
const network::ResourceResponseHead& expected_info) {
EXPECT_EQ(expected_info.was_fetched_via_service_worker,
@@ -507,8 +499,7 @@ class ServiceWorkerNavigationLoaderTest
info.was_fallback_required_by_service_worker);
EXPECT_EQ(expected_info.url_list_via_service_worker,
info.url_list_via_service_worker);
- EXPECT_EQ(expected_info.response_type_via_service_worker,
- info.response_type_via_service_worker);
+ EXPECT_EQ(expected_info.response_type, info.response_type);
EXPECT_FALSE(info.service_worker_start_time.is_null());
EXPECT_FALSE(info.service_worker_ready_time.is_null());
EXPECT_LT(info.service_worker_start_time, info.service_worker_ready_time);
@@ -559,6 +550,11 @@ class ServiceWorkerNavigationLoaderTest
bool was_main_resource_load_failed_called_ = false;
std::unique_ptr<ServiceWorkerNavigationLoader> loader_;
network::mojom::URLLoaderPtr loader_ptr_;
+
+ bool did_call_fallback_callback_ = false;
+ bool reset_subresource_loader_params_ = false;
+ base::OnceClosure quit_closure_for_fallback_callback_;
+
base::test::ScopedFeatureList feature_list_;
};
@@ -608,10 +604,9 @@ TEST_F(ServiceWorkerNavigationLoaderTest, RequestBody) {
request->request_body = request_body;
// This test doesn't use the response to the fetch event, so just have the
- // service worker do simple network fallback.
- helper_->RespondWithFallback();
- LoaderResult result = StartRequest(std::move(request));
- EXPECT_EQ(LoaderResult::kDidNotHandleRequest, result);
+ // service worker do the default simple response.
+ StartRequest(std::move(request));
+ client_.RunUntilComplete();
// Verify that the request body was passed to the fetch event.
std::string body;
@@ -626,10 +621,13 @@ TEST_F(ServiceWorkerNavigationLoaderTest, BlobResponse) {
blob_data->AppendData(kResponseBody);
std::unique_ptr<storage::BlobDataHandle> blob_handle =
blob_context_.AddFinishedBlob(std::move(blob_data));
- blink::mojom::BlobPtr blob_ptr;
- blink::mojom::BlobRequest request = mojo::MakeRequest(&blob_ptr);
+
+ auto blob = blink::mojom::SerializedBlob::New();
+ blob->uuid = blob_handle->uuid();
+ blob->size = blob_handle->size();
+ blink::mojom::BlobRequest request = mojo::MakeRequest(&blob->blob);
storage::BlobImpl::Create(std::move(blob_handle), std::move(request));
- helper_->RespondWithBlob(std::move(blob_ptr));
+ helper_->RespondWithBlob(std::move(blob));
// Perform the request.
LoaderResult result = StartRequest(CreateRequest());
@@ -657,10 +655,11 @@ TEST_F(ServiceWorkerNavigationLoaderTest, BrokenBlobResponse) {
std::unique_ptr<storage::BlobDataHandle> blob_handle =
blob_context_.AddBrokenBlob(kBrokenUUID, "", "",
storage::BlobStatus::ERR_OUT_OF_MEMORY);
- blink::mojom::BlobPtr blob_ptr;
- blink::mojom::BlobRequest request = mojo::MakeRequest(&blob_ptr);
+ auto blob = blink::mojom::SerializedBlob::New();
+ blob->uuid = kBrokenUUID;
+ blink::mojom::BlobRequest request = mojo::MakeRequest(&blob->blob);
storage::BlobImpl::Create(std::move(blob_handle), std::move(request));
- helper_->RespondWithBlob(std::move(blob_ptr));
+ helper_->RespondWithBlob(std::move(blob));
// Perform the request.
LoaderResult result = StartRequest(CreateRequest());
@@ -809,7 +808,12 @@ TEST_F(ServiceWorkerNavigationLoaderTest, FallbackResponse) {
// Perform the request.
LoaderResult result = StartRequest(CreateRequest());
- EXPECT_EQ(LoaderResult::kDidNotHandleRequest, result);
+ EXPECT_EQ(LoaderResult::kHandledRequest, result);
+
+ // The fallback callback should be called.
+ RunUntilFallbackCallback();
+ EXPECT_FALSE(reset_subresource_loader_params_);
+ EXPECT_FALSE(was_main_resource_load_failed_called_);
// The request should not be handled by the loader, but it shouldn't be a
// failure.
@@ -842,8 +846,13 @@ TEST_F(ServiceWorkerNavigationLoaderTest, FailFetchDispatch) {
// Perform the request.
LoaderResult result = StartRequest(CreateRequest());
- EXPECT_EQ(LoaderResult::kDidNotHandleRequest, result);
+ EXPECT_EQ(LoaderResult::kHandledRequest, result);
+
+ // The fallback callback should be called.
+ RunUntilFallbackCallback();
+ EXPECT_TRUE(reset_subresource_loader_params_);
EXPECT_TRUE(was_main_resource_load_failed_called_);
+
histogram_tester.ExpectUniqueSample(
kHistogramMainResourceFetchEvent,
blink::ServiceWorkerStatusCode::kErrorFailed, 1);
@@ -886,7 +895,10 @@ TEST_F(ServiceWorkerNavigationLoaderTest, FallbackToNetwork) {
SingleRequestURLLoaderFactory::RequestHandler handler;
auto loader = std::make_unique<ServiceWorkerNavigationLoader>(
- base::BindOnce(&ReceiveRequestHandler, &handler), this, request,
+ base::BindOnce(&ReceiveRequestHandler, &handler),
+ base::BindOnce(&ServiceWorkerNavigationLoaderTest::Fallback,
+ base::Unretained(this)),
+ this, request,
base::WrapRefCounted<URLLoaderFactoryGetter>(
helper_->context()->loader_factory_getter()));
// Ask the loader to fallback to network. In production code,
@@ -983,7 +995,10 @@ TEST_F(ServiceWorkerNavigationLoaderTest, LifetimeAfterFallbackToNetwork) {
SingleRequestURLLoaderFactory::RequestHandler handler;
auto loader = std::make_unique<ServiceWorkerNavigationLoader>(
- base::BindOnce(&ReceiveRequestHandler, &handler), this, request,
+ base::BindOnce(&ReceiveRequestHandler, &handler),
+ base::BindOnce(&ServiceWorkerNavigationLoaderTest::Fallback,
+ base::Unretained(this)),
+ this, request,
base::WrapRefCounted<URLLoaderFactoryGetter>(
helper_->context()->loader_factory_getter()));
base::WeakPtr<ServiceWorkerNavigationLoader> loader_weakptr =
@@ -1000,5 +1015,16 @@ TEST_F(ServiceWorkerNavigationLoaderTest, LifetimeAfterFallbackToNetwork) {
EXPECT_FALSE(loader_weakptr);
}
+TEST_F(ServiceWorkerNavigationLoaderTest, DetachedDuringFetchEvent) {
+ LoaderResult result = StartRequest(CreateRequest());
+ EXPECT_EQ(LoaderResult::kHandledRequest, result);
+
+ // Detach the loader immediately after it started. This results in
+ // DidDispatchFetchEvent() being invoked later with null |delegate_|.
+ loader_.release()->DetachedFromRequest();
+ client_.RunUntilComplete();
+ EXPECT_EQ(net::ERR_ABORTED, client_.completion_status().error_code);
+}
+
} // namespace service_worker_navigation_loader_unittest
} // namespace content
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 369f7356f0d..fc38698dff6 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
@@ -248,7 +248,7 @@ void ServiceWorkerNewScriptLoader::OnReceiveResponse(
}
WriteHeaders(
- base::MakeRefCounted<HttpResponseInfoIOBuffer>(response_info.release()));
+ base::MakeRefCounted<HttpResponseInfoIOBuffer>(std::move(response_info)));
// Don't pass SSLInfo to the client when the original request doesn't ask
// to send it.
@@ -316,8 +316,6 @@ void ServiceWorkerNewScriptLoader::OnStartLoadingResponseBody(
void ServiceWorkerNewScriptLoader::OnComplete(
const network::URLLoaderCompletionStatus& status) {
- DCHECK(network_loader_state_ == NetworkLoaderState::kWaitingForBody ||
- network_loader_state_ == NetworkLoaderState::kLoadingBody);
NetworkLoaderState previous_state = network_loader_state_;
network_loader_state_ = NetworkLoaderState::kCompleted;
if (status.error_code != net::OK) {
@@ -325,6 +323,9 @@ void ServiceWorkerNewScriptLoader::OnComplete(
return;
}
+ DCHECK(previous_state == NetworkLoaderState::kWaitingForBody ||
+ previous_state == NetworkLoaderState::kLoadingBody);
+
// Response body is empty.
if (previous_state == NetworkLoaderState::kWaitingForBody) {
DCHECK_EQ(WriterState::kNotStarted, body_writer_state_);
diff --git a/chromium/content/browser/service_worker/service_worker_object_host.cc b/chromium/content/browser/service_worker/service_worker_object_host.cc
index 49b037866c3..cd4f6ea5728 100644
--- a/chromium/content/browser/service_worker/service_worker_object_host.cc
+++ b/chromium/content/browser/service_worker/service_worker_object_host.cc
@@ -19,7 +19,7 @@ namespace content {
namespace {
using StatusCallback = base::OnceCallback<void(blink::ServiceWorkerStatusCode)>;
-using SetExtendableMessageEventSourceCallback =
+using PrepareExtendableMessageEventCallback =
base::OnceCallback<bool(mojom::ExtendableMessageEventPtr*)>;
void DispatchExtendableMessageEventAfterStartWorker(
@@ -28,7 +28,7 @@ void DispatchExtendableMessageEventAfterStartWorker(
const url::Origin& source_origin,
const base::Optional<base::TimeDelta>& timeout,
StatusCallback callback,
- SetExtendableMessageEventSourceCallback set_source_callback,
+ PrepareExtendableMessageEventCallback prepare_callback,
blink::ServiceWorkerStatusCode start_worker_status) {
if (start_worker_status != blink::ServiceWorkerStatusCode::kOk) {
std::move(callback).Run(start_worker_status);
@@ -38,7 +38,7 @@ void DispatchExtendableMessageEventAfterStartWorker(
mojom::ExtendableMessageEventPtr event = mojom::ExtendableMessageEvent::New();
event->message = std::move(message);
event->source_origin = source_origin;
- if (!std::move(set_source_callback).Run(&event)) {
+ if (!std::move(prepare_callback).Run(&event)) {
std::move(callback).Run(blink::ServiceWorkerStatusCode::kErrorFailed);
return;
}
@@ -62,7 +62,7 @@ void StartWorkerToDispatchExtendableMessageEvent(
const url::Origin& source_origin,
const base::Optional<base::TimeDelta>& timeout,
StatusCallback callback,
- SetExtendableMessageEventSourceCallback set_source_callback) {
+ PrepareExtendableMessageEventCallback prepare_callback) {
// If not enough time is left to actually process the event don't even
// bother starting the worker and sending the event.
if (timeout && *timeout < base::TimeDelta::FromMilliseconds(100)) {
@@ -74,27 +74,42 @@ void StartWorkerToDispatchExtendableMessageEvent(
ServiceWorkerMetrics::EventType::MESSAGE,
base::BindOnce(&DispatchExtendableMessageEventAfterStartWorker, worker,
std::move(message), source_origin, timeout,
- std::move(callback), std::move(set_source_callback)));
+ std::move(callback), std::move(prepare_callback)));
}
-bool SetSourceClientInfo(
+bool PrepareExtendableMessageEventFromClient(
+ base::WeakPtr<ServiceWorkerContextCore> context,
+ int64_t registration_id,
blink::mojom::ServiceWorkerClientInfoPtr source_client_info,
mojom::ExtendableMessageEventPtr* event) {
+ if (!context) {
+ return false;
+ }
DCHECK(source_client_info && !source_client_info->client_uuid.empty());
(*event)->source_info_for_client = std::move(source_client_info);
// Hide the client url if the client has a unique origin.
if ((*event)->source_origin.unique())
(*event)->source_info_for_client->url = GURL();
+
+ // Reset |registration->self_update_delay| iff postMessage is coming from a
+ // client, to prevent workers from postMessage to another version to reset
+ // the delay (https://crbug.com/805496).
+ ServiceWorkerRegistration* registration =
+ context->GetLiveRegistration(registration_id);
+ DCHECK(registration) << "running workers should have a live registration";
+ registration->set_self_update_delay(base::TimeDelta());
+
return true;
}
// The output |event| must be sent over Mojo immediately after this function
// returns. See ServiceWorkerObjectHost::CreateCompleteObjectInfoToSend() for
// details.
-bool SetSourceServiceWorkerInfo(scoped_refptr<ServiceWorkerVersion> worker,
- base::WeakPtr<ServiceWorkerProviderHost>
- source_service_worker_provider_host,
- mojom::ExtendableMessageEventPtr* event) {
+bool PrepareExtendableMessageEventFromServiceWorker(
+ scoped_refptr<ServiceWorkerVersion> worker,
+ base::WeakPtr<ServiceWorkerProviderHost>
+ source_service_worker_provider_host,
+ mojom::ExtendableMessageEventPtr* event) {
// The service worker execution context may have been destroyed by the time we
// get here.
if (!source_service_worker_provider_host)
@@ -121,11 +136,16 @@ bool SetSourceServiceWorkerInfo(scoped_refptr<ServiceWorkerVersion> worker,
}
void DispatchExtendableMessageEventFromClient(
+ base::WeakPtr<ServiceWorkerContextCore> context,
scoped_refptr<ServiceWorkerVersion> worker,
blink::TransferableMessage message,
const url::Origin& source_origin,
StatusCallback callback,
blink::mojom::ServiceWorkerClientInfoPtr source_client_info) {
+ if (!context) {
+ std::move(callback).Run(blink::ServiceWorkerStatusCode::kErrorAbort);
+ return;
+ }
// |source_client_info| may be null if a client sent the message but its
// info could not be retrieved.
if (!source_client_info) {
@@ -136,7 +156,8 @@ void DispatchExtendableMessageEventFromClient(
StartWorkerToDispatchExtendableMessageEvent(
worker, std::move(message), source_origin, base::nullopt /* timeout */,
std::move(callback),
- base::BindOnce(&SetSourceClientInfo, std::move(source_client_info)));
+ base::BindOnce(&PrepareExtendableMessageEventFromClient, context,
+ worker->registration_id(), std::move(source_client_info)));
}
void DispatchExtendableMessageEventFromServiceWorker(
@@ -156,7 +177,7 @@ void DispatchExtendableMessageEventFromServiceWorker(
source_service_worker_provider_host->provider_type());
StartWorkerToDispatchExtendableMessageEvent(
worker, std::move(message), source_origin, timeout, std::move(callback),
- base::BindOnce(&SetSourceServiceWorkerInfo, worker,
+ base::BindOnce(&PrepareExtendableMessageEventFromServiceWorker, worker,
source_service_worker_provider_host));
}
@@ -261,8 +282,8 @@ void ServiceWorkerObjectHost::DispatchExtendableMessageEvent(
case blink::mojom::ServiceWorkerProviderType::kForWindow:
service_worker_client_utils::GetClient(
provider_host_,
- base::BindOnce(&DispatchExtendableMessageEventFromClient, version_,
- std::move(message), provider_origin_,
+ base::BindOnce(&DispatchExtendableMessageEventFromClient, context_,
+ version_, std::move(message), provider_origin_,
std::move(callback)));
return;
case blink::mojom::ServiceWorkerProviderType::kForServiceWorker: {
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 f3f335bde5e..1f25d3eb9be 100644
--- a/chromium/content/browser/service_worker/service_worker_provider_host.cc
+++ b/chromium/content/browser/service_worker/service_worker_provider_host.cc
@@ -37,6 +37,7 @@
#include "content/public/common/child_process_host.h"
#include "content/public/common/content_client.h"
#include "content/public/common/origin_util.h"
+#include "mojo/public/cpp/bindings/message.h"
#include "mojo/public/cpp/bindings/strong_associated_binding.h"
#include "net/base/url_util.h"
#include "services/network/public/cpp/resource_request_body.h"
@@ -89,15 +90,19 @@ class ServiceWorkerURLTrackingRequestHandler
return nullptr;
}
- void MaybeCreateLoader(const network::ResourceRequest& resource_request,
- ResourceContext*,
- LoaderCallback callback) override {
+ void MaybeCreateLoader(
+ const network::ResourceRequest& tentative_resource_request,
+ ResourceContext*,
+ LoaderCallback callback,
+ FallbackCallback fallback_callback) override {
// |provider_host_| may have been deleted when the request is resumed.
if (!provider_host_)
return;
- const GURL stripped_url = net::SimplifyUrlForRequest(resource_request.url);
+ const GURL stripped_url =
+ net::SimplifyUrlForRequest(tentative_resource_request.url);
provider_host_->SetDocumentUrl(stripped_url);
- provider_host_->SetTopmostFrameUrl(resource_request.site_for_cookies);
+ provider_host_->SetTopmostFrameUrl(
+ tentative_resource_request.site_for_cookies);
// Fall back to network.
std::move(callback).Run({});
}
@@ -282,7 +287,6 @@ ServiceWorkerProviderHost::ServiceWorkerProviderHost(
render_thread_id_(kDocumentMainThreadId),
info_(std::move(info)),
context_(context),
- allow_association_(true),
binding_(this),
interface_provider_binding_(this) {
DCHECK_NE(blink::mojom::ServiceWorkerProviderType::kUnknown, info_->type);
@@ -322,6 +326,8 @@ ServiceWorkerProviderHost::~ServiceWorkerProviderHost() {
// Remove |this| as an observer of ServiceWorkerRegistrations.
// TODO(falken): Use ScopedObserver instead of this explicit call.
+ controller_.reset();
+ controller_registration_.reset();
RemoveAllMatchingRegistrations();
// Explicitly destroy the ServiceWorkerObjectHosts and
@@ -402,8 +408,6 @@ void ServiceWorkerProviderHost::OnVersionAttributesChanged(
void ServiceWorkerProviderHost::OnRegistrationFailed(
ServiceWorkerRegistration* registration) {
- if (associated_registration_ == registration)
- DisassociateRegistration();
RemoveMatchingRegistration(registration);
}
@@ -414,18 +418,15 @@ void ServiceWorkerProviderHost::OnRegistrationFinishedUninstalling(
void ServiceWorkerProviderHost::OnSkippedWaiting(
ServiceWorkerRegistration* registration) {
- if (associated_registration_ != registration)
+ if (controller_registration_ != registration)
return;
- // A client is "using" a registration if it is controlled by the active
- // worker of the registration. skipWaiting doesn't cause a client to start
- // using the registration.
- if (!controller_)
- return;
- ServiceWorkerVersion* active_version = registration->active_version();
- DCHECK(active_version);
- DCHECK_EQ(active_version->status(), ServiceWorkerVersion::ACTIVATING);
- SetControllerVersionAttribute(active_version,
- true /* notify_controllerchange */);
+
+ DCHECK(controller());
+ ServiceWorkerVersion* active = controller_registration_->active_version();
+ DCHECK(active);
+ DCHECK_NE(active, controller());
+ DCHECK_EQ(active->status(), ServiceWorkerVersion::ACTIVATING);
+ UpdateController(true /* notify_controllerchange */);
}
mojom::ControllerServiceWorkerPtr
@@ -443,6 +444,7 @@ ServiceWorkerProviderHost::GetControllerServiceWorkerPtr() {
void ServiceWorkerProviderHost::SetDocumentUrl(const GURL& url) {
DCHECK(!url.has_ref());
+ DCHECK(!controller());
document_url_ = url;
if (IsProviderForClient())
SyncMatchingRegistrations();
@@ -458,9 +460,10 @@ const GURL& ServiceWorkerProviderHost::topmost_frame_url() const {
return topmost_frame_url_;
}
-void ServiceWorkerProviderHost::SetControllerVersionAttribute(
- ServiceWorkerVersion* version,
- bool notify_controllerchange) {
+void ServiceWorkerProviderHost::UpdateController(bool notify_controllerchange) {
+ ServiceWorkerVersion* version =
+ controller_registration_ ? controller_registration_->active_version()
+ : nullptr;
CHECK(!version || IsContextSecureForServiceWorker());
if (version == controller_.get())
return;
@@ -470,8 +473,7 @@ void ServiceWorkerProviderHost::SetControllerVersionAttribute(
if (version)
version->AddControllee(this);
-
- if (previous_version.get())
+ if (previous_version)
previous_version->RemoveControllee(client_uuid_);
// SetController message should be sent only for clients.
@@ -521,24 +523,21 @@ blink::mojom::ServiceWorkerClientType ServiceWorkerProviderHost::client_type()
return blink::mojom::ServiceWorkerClientType::kWindow;
}
-void ServiceWorkerProviderHost::AssociateRegistration(
- ServiceWorkerRegistration* registration,
+void ServiceWorkerProviderHost::SetControllerRegistration(
+ scoped_refptr<ServiceWorkerRegistration> controller_registration,
bool notify_controllerchange) {
- CHECK(IsContextSecureForServiceWorker());
DCHECK(IsProviderForClient());
- DCHECK(CanAssociateRegistration(registration));
- associated_registration_ = registration;
- AddMatchingRegistration(registration);
- SetControllerVersionAttribute(registration->active_version(),
- notify_controllerchange);
-}
-void ServiceWorkerProviderHost::DisassociateRegistration() {
- DCHECK(IsProviderForClient());
- if (!associated_registration_.get())
- return;
- associated_registration_ = nullptr;
- SetControllerVersionAttribute(nullptr, false /* notify_controllerchange */);
+ if (controller_registration) {
+ CHECK(IsContextSecureForServiceWorker());
+ DCHECK(controller_registration->active_version());
+#if DCHECK_IS_ON()
+ DCHECK(IsMatchingRegistration(controller_registration.get()));
+#endif // DCHECK_IS_ON()
+ }
+
+ controller_registration_ = controller_registration;
+ UpdateController(notify_controllerchange);
}
void ServiceWorkerProviderHost::AddMatchingRegistration(
@@ -557,9 +556,13 @@ void ServiceWorkerProviderHost::AddMatchingRegistration(
void ServiceWorkerProviderHost::RemoveMatchingRegistration(
ServiceWorkerRegistration* registration) {
- size_t key = registration->pattern().spec().size();
- DCHECK(base::ContainsKey(matching_registrations_, key));
+ DCHECK_NE(controller_registration_, registration);
+#if DCHECK_IS_ON()
+ DCHECK(IsMatchingRegistration(registration));
+#endif // DCHECK_IS_ON()
+
registration->RemoveListener(this);
+ size_t key = registration->pattern().spec().size();
matching_registrations_.erase(key);
}
@@ -600,7 +603,7 @@ bool ServiceWorkerProviderHost::AllowServiceWorker(const GURL& scope) {
}
void ServiceWorkerProviderHost::NotifyControllerLost() {
- SetControllerVersionAttribute(nullptr, true /* notify_controllerchange */);
+ SetControllerRegistration(nullptr, true /* notify_controllerchange */);
}
void ServiceWorkerProviderHost::AddServiceWorkerToUpdate(
@@ -675,17 +678,6 @@ ServiceWorkerProviderHost::GetOrCreateServiceWorkerObjectHost(
return service_worker_object_hosts_[version_id]->AsWeakPtr();
}
-bool ServiceWorkerProviderHost::CanAssociateRegistration(
- ServiceWorkerRegistration* registration) {
- if (!context_)
- return false;
- if (running_hosted_version_.get())
- return false;
- if (!registration || associated_registration_.get() || !allow_association_)
- return false;
- return true;
-}
-
void ServiceWorkerProviderHost::PostMessageToClient(
ServiceWorkerVersion* version,
blink::TransferableMessage message) {
@@ -715,15 +707,20 @@ void ServiceWorkerProviderHost::CountFeature(blink::mojom::WebFeature feature) {
}
void ServiceWorkerProviderHost::ClaimedByRegistration(
- ServiceWorkerRegistration* registration) {
+ scoped_refptr<ServiceWorkerRegistration> registration) {
DCHECK(registration->active_version());
- if (registration == associated_registration_) {
- SetControllerVersionAttribute(registration->active_version(),
- true /* notify_controllerchange */);
- } else if (allow_association_) {
- DisassociateRegistration();
- AssociateRegistration(registration, true /* notify_controllerchange */);
+ // TODO(falken): This should just early return, or DCHECK. claim() should have
+ // no effect on a page that's already using the registration.
+ if (registration == controller_registration_) {
+ UpdateController(true /* notify_controllerchange */);
+ return;
}
+
+ // TODO(crbug.com/866353): It shouldn't be necesary to check
+ // |allow_set_controller_registration_|. See the comment for
+ // AllowSetControllerRegistration().
+ if (allow_set_controller_registration_)
+ SetControllerRegistration(registration, true /* notify_controllerchange */);
}
void ServiceWorkerProviderHost::CompleteNavigationInitialized(
@@ -802,6 +799,8 @@ void ServiceWorkerProviderHost::CompleteSharedWorkerPreparation() {
void ServiceWorkerProviderHost::SyncMatchingRegistrations() {
DCHECK(context_);
+ DCHECK(!controller_registration());
+
RemoveAllMatchingRegistrations();
const auto& registrations = context_->GetLiveRegistrations();
for (const auto& key_registration : registrations) {
@@ -813,7 +812,23 @@ void ServiceWorkerProviderHost::SyncMatchingRegistrations() {
}
}
+#if DCHECK_IS_ON()
+bool ServiceWorkerProviderHost::IsMatchingRegistration(
+ ServiceWorkerRegistration* registration) const {
+ std::string spec = registration->pattern().spec();
+ size_t key = spec.size();
+
+ auto iter = matching_registrations_.find(key);
+ if (iter == matching_registrations_.end())
+ return false;
+ if (iter->second.get() != registration)
+ return false;
+ return true;
+}
+#endif // DCHECK_IS_ON()
+
void ServiceWorkerProviderHost::RemoveAllMatchingRegistrations() {
+ DCHECK(!controller_registration());
for (const auto& it : matching_registrations_) {
ServiceWorkerRegistration* registration = it.second.get();
registration->RemoveListener(this);
@@ -858,8 +873,8 @@ void ServiceWorkerProviderHost::SendSetControllerServiceWorker(
return;
}
- DCHECK(associated_registration_);
- DCHECK_EQ(associated_registration_->active_version(), controller_.get());
+ DCHECK(controller_registration());
+ DCHECK_EQ(controller_registration_->active_version(), controller_.get());
controller_info->mode = GetControllerMode();
@@ -885,6 +900,18 @@ void ServiceWorkerProviderHost::SendSetControllerServiceWorker(
notify_controllerchange);
}
+#if DCHECK_IS_ON()
+void ServiceWorkerProviderHost::CheckControllerConsistency() const {
+ if (!controller_) {
+ DCHECK(!controller_registration_);
+ return;
+ }
+ DCHECK(IsProviderForClient());
+ DCHECK(controller_registration_);
+ DCHECK_EQ(controller_->registration_id(), controller_registration_->id());
+}
+#endif
+
void ServiceWorkerProviderHost::Register(
const GURL& script_url,
blink::mojom::ServiceWorkerRegistrationOptionsPtr options,
@@ -894,31 +921,36 @@ void ServiceWorkerProviderHost::Register(
nullptr)) {
return;
}
-
- std::string error_message;
- if (!IsValidRegisterMessage(script_url, *options, &error_message)) {
- mojo::ReportBadMessage(error_message);
+ if (client_type() != blink::mojom::ServiceWorkerClientType::kWindow) {
+ mojo::ReportBadMessage(ServiceWorkerConsts::kBadMessageFromNonWindow);
+ std::move(callback).Run(blink::mojom::ServiceWorkerErrorType::kUnknown,
+ std::string(), nullptr);
+ return;
+ }
+ std::vector<GURL> urls = {document_url(), options->scope, script_url};
+ if (!ServiceWorkerUtils::AllOriginsMatchAndCanAccessServiceWorkers(urls)) {
+ mojo::ReportBadMessage(ServiceWorkerConsts::kBadMessageImproperOrigins);
// ReportBadMessage() will kill the renderer process, but Mojo complains if
// the callback is not run. Just run it with nonsense arguments.
std::move(callback).Run(blink::mojom::ServiceWorkerErrorType::kUnknown,
std::string(), nullptr);
return;
}
-
int64_t trace_id = base::TimeTicks::Now().since_origin().InMicroseconds();
TRACE_EVENT_ASYNC_BEGIN2(
"ServiceWorker", "ServiceWorkerProviderHost::Register", trace_id, "Scope",
options->scope.spec(), "Script URL", script_url.spec());
context_->RegisterServiceWorker(
script_url, *options,
- base::AdaptCallbackForRepeating(
- base::BindOnce(&ServiceWorkerProviderHost::RegistrationComplete,
- AsWeakPtr(), std::move(callback), trace_id)));
+ base::BindOnce(&ServiceWorkerProviderHost::RegistrationComplete,
+ AsWeakPtr(), std::move(callback), trace_id,
+ mojo::GetBadMessageCallback()));
}
void ServiceWorkerProviderHost::RegistrationComplete(
RegisterCallback callback,
int64_t trace_id,
+ mojo::ReportBadMessageCallback bad_message_callback,
blink::ServiceWorkerStatusCode status,
const std::string& status_message,
int64_t registration_id) {
@@ -926,6 +958,16 @@ void ServiceWorkerProviderHost::RegistrationComplete(
trace_id, "Status",
blink::ServiceWorkerStatusToString(status),
"Registration ID", registration_id);
+ // kErrorInvalidArguments means the renderer gave unexpectedly bad arguments,
+ // so terminate it.
+ if (status == blink::ServiceWorkerStatusCode::kErrorInvalidArguments) {
+ std::move(bad_message_callback).Run(status_message);
+ // |bad_message_callback| will kill the renderer process, but Mojo complains
+ // if the callback is not run. Just run it with nonsense arguments.
+ std::move(callback).Run(blink::mojom::ServiceWorkerErrorType::kUnknown,
+ std::string(), nullptr);
+ return;
+ }
if (!IsContextAlive()) {
std::move(callback).Run(
blink::mojom::ServiceWorkerErrorType::kAbort,
@@ -1163,31 +1205,6 @@ void ServiceWorkerProviderHost::HintToUpdateServiceWorker() {
versions_to_update_.clear();
}
-bool ServiceWorkerProviderHost::IsValidRegisterMessage(
- const GURL& script_url,
- const blink::mojom::ServiceWorkerRegistrationOptions& options,
- std::string* out_error) const {
- if (client_type() != blink::mojom::ServiceWorkerClientType::kWindow) {
- *out_error = ServiceWorkerConsts::kBadMessageFromNonWindow;
- return false;
- }
- if (!options.scope.is_valid() || !script_url.is_valid()) {
- *out_error = ServiceWorkerConsts::kBadMessageInvalidURL;
- return false;
- }
- if (ServiceWorkerUtils::ContainsDisallowedCharacter(options.scope, script_url,
- out_error)) {
- return false;
- }
- std::vector<GURL> urls = {document_url(), options.scope, script_url};
- if (!ServiceWorkerUtils::AllOriginsMatchAndCanAccessServiceWorkers(urls)) {
- *out_error = ServiceWorkerConsts::kBadMessageImproperOrigins;
- return false;
- }
-
- return true;
-}
-
bool ServiceWorkerProviderHost::IsValidGetRegistrationMessage(
const GURL& client_url,
std::string* out_error) const {
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 ded291f894a..2fe3e1ef2b8 100644
--- a/chromium/content/browser/service_worker/service_worker_provider_host.h
+++ b/chromium/content/browser/service_worker/service_worker_provider_host.h
@@ -203,47 +203,21 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
// and if it has a fetch event handler.
blink::mojom::ControllerServiceWorkerMode GetControllerMode() const;
- // Returns this provider's controller. The controller is typically the same as
- // active_version() but can differ in the following cases:
- // (1) The client was created before the registration existed or had an active
- // version (in spec language, it is not "using" the registration).
- // (2) The client had a controller but NotifyControllerLost() was called due
- // to an exceptional circumstance (here also it is not "using" the
- // registration).
- // (3) During algorithms such as the update, skipWaiting(), and claim() steps,
- // the active version and controller may temporarily differ. For example, to
- // perform skipWaiting(), the registration's active version is updated first
- // and then the provider host's controlling version is updated to match it.
+ // For service worker clients. Returns this client's controller.
ServiceWorkerVersion* controller() const {
- // Only clients can have controllers.
- DCHECK(!controller_ || IsProviderForClient());
- return controller_.get();
- }
-
- ServiceWorkerVersion* active_version() const {
- return associated_registration_.get()
- ? associated_registration_->active_version()
- : nullptr;
- }
+#if DCHECK_IS_ON()
+ CheckControllerConsistency();
+#endif // DCHECK_IS_ON()
- ServiceWorkerVersion* waiting_version() const {
- return associated_registration_.get()
- ? associated_registration_->waiting_version()
- : nullptr;
+ return controller_.get();
}
- ServiceWorkerVersion* installing_version() const {
- return associated_registration_.get()
- ? associated_registration_->installing_version()
- : nullptr;
- }
+ ServiceWorkerRegistration* controller_registration() const {
+#if DCHECK_IS_ON()
+ CheckControllerConsistency();
+#endif // DCHECK_IS_ON()
- // Returns the associated registration. The provider host listens to this
- // registration to resolve the .ready promise and set its controller.
- ServiceWorkerRegistration* associated_registration() const {
- // Only clients can have an associated registration.
- DCHECK(!associated_registration_ || IsProviderForClient());
- return associated_registration_.get();
+ return controller_registration_.get();
}
// For service worker execution contexts. The version of the service worker.
@@ -267,10 +241,9 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
//
// - During navigation, right after a request handler for the main resource
// has found the matching registration and has started the worker.
- // - When a controller is updated by SetControllerVersionAttribute() (e.g.
- // by OnSkippedWaiting, {Dis,}AssociateRegistration, NotifyControllerLost
- // or ClaimedByRegistration). In some cases the controller worker may not
- // be started yet.
+ // - When a controller is updated by UpdateController() (e.g.
+ // by OnSkippedWaiting() or SetControllerRegistration()).
+ // In some cases the controller worker may not be started yet.
//
// This may return nullptr if the controller service worker does not have a
// fetch handler, i.e. when the renderer does not need the controller ptr.
@@ -320,15 +293,29 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
// Can only be called when IsProviderForClient() is true.
blink::mojom::ServiceWorkerClientType client_type() const;
- // For service worker clients. Associates to |registration| to listen for its
- // version change events and sets the controller. If |notify_controllerchange|
- // is true, instructs the renderer to dispatch a 'controllerchange' event.
- void AssociateRegistration(ServiceWorkerRegistration* registration,
- bool notify_controllerchange);
+ // For service worker clients. Makes this client be controlled by
+ // |registration|'s active worker, or makes this client be not
+ // controlled if |registration| is null. If |notify_controllerchange| is true,
+ // instructs the renderer to dispatch a 'controllerchange' event.
+ void SetControllerRegistration(
+ scoped_refptr<ServiceWorkerRegistration> controller_registration,
+ bool notify_controllerchange);
- // For service worker clients. Clears the associated registration and stops
- // listening to it.
- void DisassociateRegistration();
+ // For use by the ServiceWorkerControlleeRequestHandler to disallow a
+ // registration claiming this host while its main resource request is
+ // occurring.
+ //
+ // TODO(crbug.com/866353): This should be unneccessary: registration code
+ // already avoids claiming clients that are not execution ready. However
+ // there may be edge cases with shared workers (pre-NetS13nServiceWorker) and
+ // about:blank iframes, since |is_execution_ready_| is initialized true for
+ // them. Try to remove this after S13nServiceWorker.
+ void AllowSetControllerRegistration(bool allow) {
+ allow_set_controller_registration_ = allow;
+ }
+ bool IsSetControllerRegistrationAllowed() {
+ return allow_set_controller_registration_;
+ }
// Returns a handler for a request. May return nullptr if the request doesn't
// require special handling.
@@ -366,14 +353,6 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
base::WeakPtr<ServiceWorkerObjectHost> GetOrCreateServiceWorkerObjectHost(
scoped_refptr<ServiceWorkerVersion> version);
- // Returns true if |registration| can be associated with this provider.
- bool CanAssociateRegistration(ServiceWorkerRegistration* registration);
-
- // For use by the ServiceWorkerControlleeRequestHandler to disallow
- // new registration association while a navigation is occurring and
- // an existing registration is being looked for.
- void SetAllowAssociation(bool allow) { allow_association_ = allow; }
-
// Returns true if the context referred to by this host (i.e. |context_|) is
// still alive.
bool IsContextAlive();
@@ -387,7 +366,8 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
void CountFeature(blink::mojom::WebFeature feature);
// |registration| claims the document to be controlled.
- void ClaimedByRegistration(ServiceWorkerRegistration* registration);
+ void ClaimedByRegistration(
+ scoped_refptr<ServiceWorkerRegistration> registration);
// For service worker clients. Completes initialization of
// provider hosts used for navigation requests.
@@ -419,6 +399,16 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
// After this is called, is_execution_ready() returns true.
void CompleteSharedWorkerPreparation();
+ // For service worker clients. The host keeps track of all the prospective
+ // longest-matching registrations, in order to resolve .ready or respond to
+ // claim() attempts.
+ //
+ // This is subtle: it doesn't keep all registrations (e.g., from storage) in
+ // memory, but just the ones that are possibly the longest-matching one. The
+ // best match from storage is added at load time. That match can't uninstall
+ // while this host is a controllee, so all the other stored registrations can
+ // be ignored. Only a newly installed registration can claim it, and new
+ // installing registrations are added as matches.
void AddMatchingRegistration(ServiceWorkerRegistration* registration);
void RemoveMatchingRegistration(ServiceWorkerRegistration* registration);
@@ -471,6 +461,8 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
friend class ServiceWorkerProviderHostTest;
friend class ServiceWorkerWriteToCacheJobTest;
friend class ServiceWorkerContextRequestHandlerTest;
+ friend class service_worker_controllee_request_handler_unittest::
+ ServiceWorkerControlleeRequestHandlerTest;
friend class service_worker_object_host_unittest::ServiceWorkerObjectHostTest;
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerWriteToCacheJobTest, Update_SameScript);
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerWriteToCacheJobTest,
@@ -509,17 +501,20 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
ServiceWorkerRegistration* registration) override;
void OnSkippedWaiting(ServiceWorkerRegistration* registration) override;
- // Sets the controller field to |version| or if |version| is nullptr, clears
- // the field. If |notify_controllerchange| is true, instructs the renderer to
- // dispatch a 'controller' change event.
- void SetControllerVersionAttribute(ServiceWorkerVersion* version,
- bool notify_controllerchange);
-
- void SendAssociateRegistrationMessage();
+ // Sets the controller to |controller_registration_->active_version()| or null
+ // if there is no associated registration.
+ //
+ // If |notify_controllerchange| is true, instructs the renderer to dispatch a
+ // 'controller' change event.
+ void UpdateController(bool notify_controllerchange);
// Syncs matching registrations with live registrations.
void SyncMatchingRegistrations();
+#if DCHECK_IS_ON()
+ bool IsMatchingRegistration(ServiceWorkerRegistration* registration) const;
+#endif // DCHECK_IS_ON()
+
// Discards all references to matching registrations.
void RemoveAllMatchingRegistrations();
@@ -530,6 +525,10 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
// instructs the renderer to dispatch a 'controllerchange' event.
void SendSetControllerServiceWorker(bool notify_controllerchange);
+#if DCHECK_IS_ON()
+ void CheckControllerConsistency() const;
+#endif // DCHECK_IS_ON()
+
// Implements mojom::ServiceWorkerContainerHost.
void Register(const GURL& script_url,
blink::mojom::ServiceWorkerRegistrationOptionsPtr options,
@@ -550,6 +549,7 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
// Callback for ServiceWorkerContextCore::RegisterServiceWorker().
void RegistrationComplete(RegisterCallback callback,
int64_t trace_id,
+ mojo::ReportBadMessageCallback bad_message_callback,
blink::ServiceWorkerStatusCode status,
const std::string& status_message,
int64_t registration_id);
@@ -572,10 +572,6 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
mojom::ControllerServiceWorkerRequest controller_request,
blink::ServiceWorkerStatusCode status);
- bool IsValidRegisterMessage(
- const GURL& script_url,
- const blink::mojom::ServiceWorkerRegistrationOptions& options,
- std::string* out_error) const;
bool IsValidGetRegistrationMessage(const GURL& client_url,
std::string* out_error) const;
bool IsValidGetRegistrationsMessage(std::string* out_error) const;
@@ -616,14 +612,13 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
GURL document_url_;
GURL topmost_frame_url_;
- scoped_refptr<ServiceWorkerRegistration> associated_registration_;
-
// Keyed by registration scope URL length.
using ServiceWorkerRegistrationMap =
std::map<size_t, scoped_refptr<ServiceWorkerRegistration>>;
// Contains all living registrations whose pattern this document's URL
- // starts with. It is empty if IsContextSecureForServiceWorker() is
- // false.
+ // starts with, used for .ready and claim(). It is empty if
+ // IsContextSecureForServiceWorker() is false. See also
+ // AddMatchingRegistration().
ServiceWorkerRegistrationMap matching_registrations_;
// Contains all ServiceWorkerRegistrationObjectHost instances corresponding to
@@ -651,16 +646,22 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
std::unique_ptr<GetRegistrationForReadyCallback> get_ready_callback_;
// For service worker clients. The controller service worker (i.e.,
- // ServiceWorkerContainer#controller).
+ // ServiceWorkerContainer#controller) and its registration. The controller is
+ // typically the same as the registration's active version, but during
+ // algorithms such as the update, skipWaiting(), and claim() steps, the active
+ // version and controller may temporarily differ. For example, to perform
+ // skipWaiting(), the registration's active version is updated first and then
+ // the provider host's controller is updated to match it.
scoped_refptr<ServiceWorkerVersion> controller_;
+ scoped_refptr<ServiceWorkerRegistration> controller_registration_;
+ bool allow_set_controller_registration_ = true;
+
// For service worker execution contexts. The ServiceWorkerVersion of the
// service worker this is a provider for.
scoped_refptr<ServiceWorkerVersion> running_hosted_version_;
base::WeakPtr<ServiceWorkerContextCore> context_;
- bool allow_association_;
-
// |container_| is the Mojo endpoint to the renderer-side
// ServiceWorkerContainer that |this| is a ServiceWorkerContainerHost for.
mojom::ServiceWorkerContainerAssociatedPtr container_;
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 7cc8b71f605..926cb6bedf1 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
@@ -19,7 +19,6 @@
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/service_worker/service_worker_test_utils.h"
#include "content/browser/service_worker/service_worker_version.h"
-#include "content/common/service_worker/service_worker_messages.h"
#include "content/common/url_schemes.h"
#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/child_process_host.h"
@@ -468,18 +467,18 @@ TEST_P(ServiceWorkerProviderHostTest, Controller) {
// Finish the navigation.
FinishNavigation(host.get(), std::move(info));
- host->AssociateRegistration(registration1_.get(),
- false /* notify_controllerchange */);
+ host->SetControllerRegistration(registration1_,
+ false /* notify_controllerchange */);
base::RunLoop().RunUntilIdle();
// The page should be controlled since there was an active version at the
// time navigation started. The SetController IPC should have been sent.
- EXPECT_TRUE(host->active_version());
- EXPECT_EQ(host->active_version(), host->controller());
+ EXPECT_TRUE(host->controller());
EXPECT_TRUE(container->was_set_controller_called());
+ EXPECT_EQ(registration1_.get(), host->MatchRegistration());
}
-TEST_P(ServiceWorkerProviderHostTest, ActiveIsNotController) {
+TEST_P(ServiceWorkerProviderHostTest, UncontrolledWithMatchingRegistration) {
// Create a host.
base::WeakPtr<ServiceWorkerProviderHost> host =
ServiceWorkerProviderHost::PreCreateNavigationHost(
@@ -498,11 +497,8 @@ TEST_P(ServiceWorkerProviderHostTest, ActiveIsNotController) {
1 /* version_id */, helper_->context()->AsWeakPtr());
registration1_->SetInstallingVersion(version);
-
// Finish the navigation.
FinishNavigation(host.get(), std::move(info));
- host->AssociateRegistration(registration1_.get(),
- false /* notify_controllerchange */);
// Promote the worker to active while navigation is still happening.
registration1_->SetActiveVersion(version);
base::RunLoop().RunUntilIdle();
@@ -510,9 +506,11 @@ TEST_P(ServiceWorkerProviderHostTest, ActiveIsNotController) {
// The page should not be controlled since there was no active version at the
// time navigation started. Furthermore, no SetController IPC should have been
// sent.
- EXPECT_TRUE(host->active_version());
EXPECT_FALSE(host->controller());
EXPECT_FALSE(container->was_set_controller_called());
+ // However, the host should know the registration is its best match, for
+ // .ready and claim().
+ EXPECT_EQ(registration1_.get(), host->MatchRegistration());
}
TEST_P(ServiceWorkerProviderHostTest,
@@ -919,7 +917,7 @@ TEST_P(ServiceWorkerProviderHostTest, DontSetControllerInDestructor) {
// Make the active worker the controller and give it an ongoing request. This
// way when a waiting worker calls SkipWaiting(), activation won't trigger
// until we're ready.
- provider_host1->AssociateRegistration(registration1_.get(), false);
+ provider_host1->SetControllerRegistration(registration1_, false);
EXPECT_EQ(version1.get(), provider_host1->controller());
// The worker must be running to have a request.
version1->StartWorker(ServiceWorkerMetrics::EventType::PUSH,
diff --git a/chromium/content/browser/service_worker/service_worker_read_from_cache_job_unittest.cc b/chromium/content/browser/service_worker/service_worker_read_from_cache_job_unittest.cc
index 4fdb26ad89c..150c6466381 100644
--- a/chromium/content/browser/service_worker/service_worker_read_from_cache_job_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_read_from_cache_job_unittest.cc
@@ -118,13 +118,14 @@ class ServiceWorkerReadFromCacheJobTest : public testing::Test {
std::unique_ptr<ServiceWorkerResponseWriter> writer =
context()->storage()->CreateResponseWriter(resource_id);
- std::unique_ptr<net::HttpResponseInfo> info(new net::HttpResponseInfo);
+ std::unique_ptr<net::HttpResponseInfo> info =
+ std::make_unique<net::HttpResponseInfo>();
info->request_time = base::Time::Now();
info->response_time = base::Time::Now();
info->was_cached = false;
info->headers = new net::HttpResponseHeaders(headers);
scoped_refptr<HttpResponseInfoIOBuffer> info_buffer =
- new HttpResponseInfoIOBuffer(info.release());
+ base::MakeRefCounted<HttpResponseInfoIOBuffer>(std::move(info));
{
net::TestCompletionCallback cb;
writer->WriteInfo(info_buffer.get(), cb.callback());
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 81b62c81e86..f832ed1c409 100644
--- a/chromium/content/browser/service_worker/service_worker_register_job.cc
+++ b/chromium/content/browser/service_worker/service_worker_register_job.cc
@@ -20,7 +20,6 @@
#include "content/browser/service_worker/service_worker_version.h"
#include "content/browser/service_worker/service_worker_write_to_cache_job.h"
#include "content/common/service_worker/service_worker.mojom.h"
-#include "content/common/service_worker/service_worker_messages.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/browser/browser_thread.h"
diff --git a/chromium/content/browser/service_worker/service_worker_registration.cc b/chromium/content/browser/service_worker/service_worker_registration.cc
index dec34316469..f215fd804ed 100644
--- a/chromium/content/browser/service_worker/service_worker_registration.cc
+++ b/chromium/content/browser/service_worker/service_worker_registration.cc
@@ -13,7 +13,6 @@
#include "content/browser/service_worker/service_worker_info.h"
#include "content/browser/service_worker/service_worker_metrics.h"
#include "content/browser/service_worker/service_worker_register_job.h"
-#include "content/common/service_worker/service_worker_messages.h"
#include "content/public/browser/browser_thread.h"
#include "third_party/blink/public/common/service_worker/service_worker_utils.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
diff --git a/chromium/content/browser/service_worker/service_worker_registration.h b/chromium/content/browser/service_worker/service_worker_registration.h
index e579f31c727..e41fa4a0af3 100644
--- a/chromium/content/browser/service_worker/service_worker_registration.h
+++ b/chromium/content/browser/service_worker/service_worker_registration.h
@@ -15,6 +15,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/single_thread_task_runner.h"
+#include "base/time/time.h"
#include "content/browser/service_worker/service_worker_version.h"
#include "content/common/content_export.h"
#include "content/common/service_worker/service_worker_types.h"
@@ -162,6 +163,13 @@ class CONTENT_EXPORT ServiceWorkerRegistration
base::Time last_update_check() const { return last_update_check_; }
void set_last_update_check(base::Time last) { last_update_check_ = last; }
+ // The delay for self-updating service workers, to prevent them from running
+ // forever (see https://crbug.com/805496).
+ base::TimeDelta self_update_delay() const { return self_update_delay_; }
+ void set_self_update_delay(const base::TimeDelta& delay) {
+ 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);
@@ -227,6 +235,7 @@ class CONTENT_EXPORT ServiceWorkerRegistration
bool should_activate_when_ready_;
blink::mojom::NavigationPreloadState navigation_preload_state_;
base::Time last_update_check_;
+ base::TimeDelta self_update_delay_;
int64_t resources_total_size_bytes_;
// This registration is the primary owner of these versions.
@@ -234,7 +243,7 @@ class CONTENT_EXPORT ServiceWorkerRegistration
scoped_refptr<ServiceWorkerVersion> waiting_version_;
scoped_refptr<ServiceWorkerVersion> installing_version_;
- base::ObserverList<Listener> listeners_;
+ base::ObserverList<Listener>::Unchecked listeners_;
std::vector<base::Closure> registration_finished_callbacks_;
base::WeakPtr<ServiceWorkerContextCore> context_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
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 4e758bf31af..5466cd6ef11 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
@@ -4,11 +4,13 @@
#include "content/browser/service_worker/service_worker_registration_object_host.h"
+#include "base/time/time.h"
#include "content/browser/service_worker/service_worker_consts.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_object_host.h"
#include "content/browser/service_worker/service_worker_provider_host.h"
#include "content/common/service_worker/service_worker_utils.h"
+#include "content/public/browser/browser_thread.h"
#include "net/http/http_util.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
@@ -16,6 +18,9 @@ namespace content {
namespace {
+constexpr base::TimeDelta kSelfUpdateDelay = base::TimeDelta::FromSeconds(30);
+constexpr base::TimeDelta kMaxSelfUpdateDelay = base::TimeDelta::FromMinutes(3);
+
// Returns an object info to send over Mojo. The info must be sent immediately.
// See ServiceWorkerObjectHost::CreateCompleteObjectInfoToSend() for details.
blink::mojom::ServiceWorkerObjectInfoPtr CreateCompleteObjectInfoToSend(
@@ -28,6 +33,45 @@ blink::mojom::ServiceWorkerObjectInfoPtr CreateCompleteObjectInfoToSend(
return service_worker_object_host->CreateCompleteObjectInfoToSend();
}
+void ExecuteUpdate(base::WeakPtr<ServiceWorkerContextCore> context,
+ int64_t registration_id,
+ bool force_bypass_cache,
+ bool skip_script_comparison,
+ ServiceWorkerContextCore::UpdateCallback callback,
+ blink::ServiceWorkerStatusCode status) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (status != blink::ServiceWorkerStatusCode::kOk) {
+ // The delay was already very long and update() is rejected immediately.
+ DCHECK_EQ(blink::ServiceWorkerStatusCode::kErrorTimeout, status);
+ std::move(callback).Run(blink::ServiceWorkerStatusCode::kErrorTimeout,
+ ServiceWorkerConsts::kUpdateTimeoutErrorMesage,
+ registration_id);
+ return;
+ }
+
+ if (!context) {
+ std::move(callback).Run(blink::ServiceWorkerStatusCode::kErrorAbort,
+ ServiceWorkerConsts::kShutdownErrorMessage,
+ registration_id);
+ return;
+ }
+
+ ServiceWorkerRegistration* registration =
+ context->GetLiveRegistration(registration_id);
+ if (!registration) {
+ // The service worker is no longer running, so update() won't be rejected.
+ // We still run the callback so the caller knows.
+ std::move(callback).Run(blink::ServiceWorkerStatusCode::kErrorTimeout,
+ ServiceWorkerConsts::kUpdateTimeoutErrorMesage,
+ registration_id);
+ return;
+ }
+
+ context->UpdateServiceWorker(registration, force_bypass_cache,
+ skip_script_comparison, std::move(callback));
+}
+
} // anonymous namespace
ServiceWorkerRegistrationObjectHost::ServiceWorkerRegistrationObjectHost(
@@ -116,14 +160,58 @@ void ServiceWorkerRegistrationObjectHost::Update(UpdateCallback callback) {
return;
}
- context_->UpdateServiceWorker(
- registration_.get(), false /* force_bypass_cache */,
- false /* skip_script_comparison */,
- base::AdaptCallbackForRepeating(
+ DelayUpdate(
+ provider_host_->provider_type(), registration_.get(),
+ provider_host_->running_hosted_version(),
+ base::BindOnce(
+ &ExecuteUpdate, context_, registration_->id(),
+ false /* force_bypass_cache */, false /* skip_script_comparison */,
base::BindOnce(&ServiceWorkerRegistrationObjectHost::UpdateComplete,
weak_ptr_factory_.GetWeakPtr(), std::move(callback))));
}
+void ServiceWorkerRegistrationObjectHost::DelayUpdate(
+ blink::mojom::ServiceWorkerProviderType provider_type,
+ ServiceWorkerRegistration* registration,
+ ServiceWorkerVersion* version,
+ StatusCallback update_function) {
+ DCHECK(registration);
+
+ if (provider_type !=
+ blink::mojom::ServiceWorkerProviderType::kForServiceWorker ||
+ (version && version->HasControllee())) {
+ // Don't delay update() if called by non-workers or by workers with
+ // controllees.
+ std::move(update_function).Run(blink::ServiceWorkerStatusCode::kOk);
+ return;
+ }
+
+ base::TimeDelta delay = registration->self_update_delay();
+ if (delay > kMaxSelfUpdateDelay) {
+ std::move(update_function)
+ .Run(blink::ServiceWorkerStatusCode::kErrorTimeout);
+ return;
+ }
+
+ if (delay < kSelfUpdateDelay) {
+ registration->set_self_update_delay(kSelfUpdateDelay);
+ } else {
+ registration->set_self_update_delay(delay * 2);
+ }
+
+ if (delay < base::TimeDelta::Min()) {
+ // Only enforce the delay of update() iff |delay| exists.
+ std::move(update_function).Run(blink::ServiceWorkerStatusCode::kOk);
+ return;
+ }
+
+ BrowserThread::PostDelayedTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(std::move(update_function),
+ blink::ServiceWorkerStatusCode::kOk),
+ delay);
+}
+
void ServiceWorkerRegistrationObjectHost::Unregister(
UnregisterCallback callback) {
if (!CanServeRegistrationObjectHostMethods(
@@ -302,6 +390,7 @@ void ServiceWorkerRegistrationObjectHost::SetVersionAttributes(
waiting = CreateCompleteObjectInfoToSend(provider_host_, waiting_version);
if (changed_mask.active_changed())
active = CreateCompleteObjectInfoToSend(provider_host_, active_version);
+
DCHECK(remote_registration_);
remote_registration_->SetVersionAttributes(
changed_mask.changed(), std::move(installing), std::move(waiting),
diff --git a/chromium/content/browser/service_worker/service_worker_registration_object_host.h b/chromium/content/browser/service_worker/service_worker_registration_object_host.h
index b96daf0cda7..cfca9b43e02 100644
--- a/chromium/content/browser/service_worker/service_worker_registration_object_host.h
+++ b/chromium/content/browser/service_worker/service_worker_registration_object_host.h
@@ -17,6 +17,9 @@
#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
namespace content {
+namespace service_worker_registration_unittest {
+class ServiceWorkerRegistrationObjectHostTest;
+} // namespace service_worker_registration_unittest
class ServiceWorkerContextCore;
class ServiceWorkerVersion;
@@ -46,6 +49,12 @@ class CONTENT_EXPORT ServiceWorkerRegistrationObjectHost
ServiceWorkerRegistration* registration() { return registration_.get(); }
private:
+ friend class service_worker_registration_unittest::
+ ServiceWorkerRegistrationObjectHostTest;
+
+ using StatusCallback =
+ base::OnceCallback<void(blink::ServiceWorkerStatusCode status)>;
+
// ServiceWorkerRegistration::Listener overrides.
void OnVersionAttributesChanged(
ServiceWorkerRegistration* registration,
@@ -68,6 +77,20 @@ class CONTENT_EXPORT ServiceWorkerRegistrationObjectHost
const std::string& value,
SetNavigationPreloadHeaderCallback callback) override;
+ // Delays an update if it is called by a worker without controllee, to prevent
+ // workers from running forever (see https://crbug.com/805496).
+ // Calls |update_function| with blink::ServiceWorkerStatusCode::kOk if the
+ // update should procceed, and blink::ServiceWorkerStatusCode::kTimeout
+ // otherwise.
+ // If there is no delay, or if the delay is very long, |update_function| is
+ // executed synchronously (before this method returns).
+ //
+ // TODO(falken): See if tests can call |Update| directly, then this separate
+ // function isn't needed.
+ static void DelayUpdate(blink::mojom::ServiceWorkerProviderType provider_type,
+ ServiceWorkerRegistration* registration,
+ ServiceWorkerVersion* version,
+ StatusCallback update_function);
// Called back from ServiceWorkerContextCore when an update is complete.
void UpdateComplete(UpdateCallback callback,
blink::ServiceWorkerStatusCode status,
diff --git a/chromium/content/browser/service_worker/service_worker_registration_status.cc b/chromium/content/browser/service_worker/service_worker_registration_status.cc
index c331293b639..6d154ff4c48 100644
--- a/chromium/content/browser/service_worker/service_worker_registration_status.cc
+++ b/chromium/content/browser/service_worker/service_worker_registration_status.cc
@@ -68,6 +68,7 @@ void GetServiceWorkerErrorTypeForRegistration(
case blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected:
case blink::ServiceWorkerStatusCode::kErrorState:
case blink::ServiceWorkerStatusCode::kErrorDiskCache:
+ case blink::ServiceWorkerStatusCode::kErrorInvalidArguments:
// Unexpected, or should have bailed out before calling this, or we don't
// have a corresponding blink error code yet.
break; // Fall through to NOTREACHED().
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 35671bbced4..62bf488958e 100644
--- a/chromium/content/browser/service_worker/service_worker_registration_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_registration_unittest.cc
@@ -128,13 +128,27 @@ class MockServiceWorkerRegistrationObject
binding_;
};
+// We need this for NoInflightRequest test. The test expects that a worker
+// will be terminated when SetIdleTimerDelayToZero() is called.
+class RegistrationTestHelper : public EmbeddedWorkerTestHelper {
+ public:
+ RegistrationTestHelper() : EmbeddedWorkerTestHelper(base::FilePath()) {}
+ ~RegistrationTestHelper() override = default;
+
+ protected:
+ void OnSetIdleTimerDelayToZero(int embedded_worker_id) override {
+ GetEmbeddedWorkerInstanceHost(embedded_worker_id)
+ ->RequestTermination(base::DoNothing());
+ }
+};
+
class ServiceWorkerRegistrationTest : public testing::Test {
public:
ServiceWorkerRegistrationTest()
: thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}
void SetUp() override {
- helper_.reset(new EmbeddedWorkerTestHelper(base::FilePath()));
+ helper_ = std::make_unique<RegistrationTestHelper>();
context()->storage()->LazyInitializeForTest(base::DoNothing());
base::RunLoop().RunUntilIdle();
@@ -685,6 +699,27 @@ class ServiceWorkerRegistrationObjectHostTest
return error;
}
+ blink::ServiceWorkerStatusCode CallDelayUpdate(
+ blink::mojom::ServiceWorkerProviderType provider_type,
+ ServiceWorkerRegistration* registration,
+ ServiceWorkerVersion* version) {
+ base::Optional<blink::ServiceWorkerStatusCode> status;
+ base::RunLoop run_loop;
+ ServiceWorkerRegistrationObjectHost::DelayUpdate(
+ blink::mojom::ServiceWorkerProviderType::kForServiceWorker,
+ registration, version,
+ base::BindOnce(
+ [](base::Optional<blink::ServiceWorkerStatusCode>* out_status,
+ base::OnceClosure callback,
+ blink::ServiceWorkerStatusCode status) {
+ *out_status = status;
+ std::move(callback).Run();
+ },
+ &status, run_loop.QuitClosure()));
+ run_loop.Run();
+ return status.value();
+ }
+
blink::mojom::ServiceWorkerErrorType CallUnregister(
blink::mojom::ServiceWorkerRegistrationObjectHost* registration_host) {
blink::mojom::ServiceWorkerErrorType error =
@@ -717,21 +752,21 @@ class ServiceWorkerRegistrationObjectHostTest
return status.value();
}
- int64_t SetUpRegistration(const GURL& scope, const GURL& script_url) {
- storage()->LazyInitializeForTest(base::DoNothing());
- base::RunLoop().RunUntilIdle();
-
- // Prepare ServiceWorkerRegistration.
+ scoped_refptr<ServiceWorkerRegistration> CreateRegistration(
+ const GURL& scope) {
blink::mojom::ServiceWorkerRegistrationOptions options;
options.scope = scope;
- scoped_refptr<ServiceWorkerRegistration> registration =
- base::MakeRefCounted<ServiceWorkerRegistration>(
- options, storage()->NewRegistrationId(), context()->AsWeakPtr());
- // Prepare ServiceWorkerVersion.
+ return base::MakeRefCounted<ServiceWorkerRegistration>(
+ options, storage()->NewRegistrationId(), context()->AsWeakPtr());
+ }
+
+ scoped_refptr<ServiceWorkerVersion> CreateVersion(
+ ServiceWorkerRegistration* registration,
+ const GURL& script_url) {
scoped_refptr<ServiceWorkerVersion> version =
- base::MakeRefCounted<ServiceWorkerVersion>(
- registration.get(), script_url, storage()->NewVersionId(),
- context()->AsWeakPtr());
+ base::MakeRefCounted<ServiceWorkerVersion>(registration, script_url,
+ storage()->NewVersionId(),
+ context()->AsWeakPtr());
std::vector<ServiceWorkerDatabase::ResourceRecord> records;
records.push_back(WriteToDiskCacheSync(
storage(), version->script_url(), storage()->NewResourceId(),
@@ -742,13 +777,26 @@ class ServiceWorkerRegistrationObjectHostTest
version->set_fetch_handler_existence(
ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
version->SetStatus(ServiceWorkerVersion::INSTALLING);
+ return version;
+ }
+
+ int64_t SetUpRegistration(const GURL& scope, const GURL& script_url) {
+ storage()->LazyInitializeForTest(base::DoNothing());
+ base::RunLoop().RunUntilIdle();
+
+ // Prepare ServiceWorkerRegistration and ServiceWorkerVersion.
+ scoped_refptr<ServiceWorkerRegistration> registration =
+ CreateRegistration(scope);
+ scoped_refptr<ServiceWorkerVersion> version =
+ CreateVersion(registration.get(), script_url);
+
// Make the registration findable via storage functions.
bool called = false;
blink::ServiceWorkerStatusCode status =
blink::ServiceWorkerStatusCode::kErrorFailed;
- storage()->StoreRegistration(registration.get(), version.get(),
- base::AdaptCallbackForRepeating(base::BindOnce(
- &SaveStatusCallback, &called, &status)));
+ storage()->StoreRegistration(
+ registration.get(), version.get(),
+ base::BindOnce(&SaveStatusCallback, &called, &status));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status);
@@ -880,6 +928,102 @@ TEST_F(ServiceWorkerRegistrationObjectHostTest,
SetBrowserClientForTesting(old_browser_client);
}
+TEST_F(ServiceWorkerRegistrationObjectHostTest, Update_NoDelayFromControllee) {
+ const GURL kScope("https://www.example.com/");
+ const GURL kScriptUrl("https://www.example.com/sw.js");
+ int64_t registration_id = SetUpRegistration(kScope, kScriptUrl);
+ const int64_t kProviderId = 99; // Dummy value
+ ServiceWorkerRemoteProviderEndpoint remote_endpoint =
+ PrepareProviderHost(kProviderId, kScope);
+ blink::mojom::ServiceWorkerRegistrationObjectHostAssociatedPtr
+ registration_host_ptr;
+
+ blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info =
+ GetRegistrationFromRemote(remote_endpoint.host_ptr()->get(), kScope);
+ registration_host_ptr.Bind(std::move(info->host_ptr_info));
+ // Ignore the messages to the registration object, otherwise the callbacks
+ // issued from |registration_host_ptr| may wait for receiving the messages to
+ // |info->request|.
+ info->request = nullptr;
+
+ // Get registration and set |self_update_delay| to zero.
+ ServiceWorkerRegistration* registration =
+ context()->GetLiveRegistration(registration_id);
+ ASSERT_TRUE(registration);
+ registration->set_self_update_delay(base::TimeDelta());
+ EXPECT_EQ(base::TimeDelta(), registration->self_update_delay());
+
+ EXPECT_EQ(blink::mojom::ServiceWorkerErrorType::kNone,
+ CallUpdate(registration_host_ptr.get()));
+ EXPECT_EQ(base::TimeDelta(), registration->self_update_delay());
+}
+
+TEST_F(ServiceWorkerRegistrationObjectHostTest,
+ Update_DelayFromWorkerWithoutControllee) {
+ const GURL kScope("https://www.example.com/");
+ const GURL kScriptUrl("https://www.example.com/sw.js");
+ scoped_refptr<ServiceWorkerRegistration> registration =
+ CreateRegistration(kScope);
+ scoped_refptr<ServiceWorkerVersion> version =
+ CreateVersion(registration.get(), kScriptUrl);
+
+ // Initially set |self_update_delay| to zero.
+ registration->set_self_update_delay(base::TimeDelta());
+ EXPECT_EQ(base::TimeDelta(), registration->self_update_delay());
+
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
+ CallDelayUpdate(
+ blink::mojom::ServiceWorkerProviderType::kForServiceWorker,
+ registration.get(), version.get()));
+ EXPECT_LT(base::TimeDelta(), registration->self_update_delay());
+
+ // TODO(falken): Add a test verifying that a delayed update will be executed
+ // eventually.
+
+ // Set |self_update_delay| to a time so that update() will reject immediately.
+ registration->set_self_update_delay(base::TimeDelta::FromMinutes(5));
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorTimeout,
+ CallDelayUpdate(
+ blink::mojom::ServiceWorkerProviderType::kForServiceWorker,
+ registration.get(), version.get()));
+ EXPECT_LE(base::TimeDelta::FromMinutes(5), registration->self_update_delay());
+}
+
+TEST_F(ServiceWorkerRegistrationObjectHostTest,
+ Update_NoDelayFromWorkerWithControllee) {
+ const GURL kScope("https://www.example.com/");
+ const GURL kScriptUrl("https://www.example.com/sw.js");
+ const int64_t kProviderId = 99; // Dummy value
+ scoped_refptr<ServiceWorkerRegistration> registration =
+ CreateRegistration(kScope);
+ scoped_refptr<ServiceWorkerVersion> version =
+ CreateVersion(registration.get(), kScriptUrl);
+ ServiceWorkerRemoteProviderEndpoint remote_endpoint;
+ std::unique_ptr<ServiceWorkerProviderHost> host = CreateProviderHostForWindow(
+ helper_->mock_render_process_id(), kProviderId,
+ true /* is_parent_frame_secure */, context()->AsWeakPtr(),
+ &remote_endpoint);
+ host->SetDocumentUrl(kScope);
+ version->AddControllee(host.get());
+
+ // Initially set |self_update_delay| to zero.
+ registration->set_self_update_delay(base::TimeDelta());
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
+ CallDelayUpdate(
+ blink::mojom::ServiceWorkerProviderType::kForServiceWorker,
+ registration.get(), version.get()));
+ EXPECT_EQ(base::TimeDelta(), registration->self_update_delay());
+
+ // Set |self_update_delay| to a time so that update() will reject immediately
+ // if the worker doesn't have at least one controlee.
+ registration->set_self_update_delay(base::TimeDelta::FromMinutes(5));
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
+ CallDelayUpdate(
+ blink::mojom::ServiceWorkerProviderType::kForServiceWorker,
+ registration.get(), version.get()));
+ EXPECT_EQ(base::TimeDelta::FromMinutes(5), registration->self_update_delay());
+}
+
TEST_F(ServiceWorkerRegistrationObjectHostTest, Unregister_Success) {
const GURL kScope("https://www.example.com/");
const GURL kScriptUrl("https://www.example.com/sw.js");
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 15033201505..e72645e490f 100644
--- a/chromium/content/browser/service_worker/service_worker_request_handler.cc
+++ b/chromium/content/browser/service_worker/service_worker_request_handler.cc
@@ -136,7 +136,7 @@ void ServiceWorkerRequestHandler::InitializeForNavigation(
// static
std::unique_ptr<NavigationLoaderInterceptor>
ServiceWorkerRequestHandler::InitializeForNavigationNetworkService(
- const network::ResourceRequest& resource_request,
+ const GURL& url,
ResourceContext* resource_context,
ServiceWorkerNavigationHandleCore* navigation_handle_core,
storage::BlobStorageContext* blob_storage_context,
@@ -152,8 +152,7 @@ ServiceWorkerRequestHandler::InitializeForNavigationNetworkService(
// Create the handler even for insecure HTTP since it's used in the
// case of redirect to HTTPS.
- if (!resource_request.url.SchemeIsHTTPOrHTTPS() &&
- !OriginCanAccessServiceWorkers(resource_request.url)) {
+ if (!url.SchemeIsHTTPOrHTTPS() && !OriginCanAccessServiceWorkers(url)) {
return nullptr;
}
@@ -284,7 +283,7 @@ bool ServiceWorkerRequestHandler::IsControlledByServiceWorker(
ServiceWorkerRequestHandler* handler = GetHandler(request);
if (!handler || !handler->provider_host_)
return false;
- return handler->provider_host_->associated_registration() ||
+ return handler->provider_host_->controller() ||
handler->provider_host_->running_hosted_version();
}
@@ -296,9 +295,10 @@ ServiceWorkerProviderHost* ServiceWorkerRequestHandler::GetProviderHost(
}
void ServiceWorkerRequestHandler::MaybeCreateLoader(
- const network::ResourceRequest& request,
+ const network::ResourceRequest& tentative_request,
ResourceContext* resource_context,
- LoaderCallback callback) {
+ LoaderCallback callback,
+ FallbackCallback fallback_callback) {
NOTREACHED();
std::move(callback).Run({});
}
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 5ab4546ffb3..41132905487 100644
--- a/chromium/content/browser/service_worker/service_worker_request_handler.h
+++ b/chromium/content/browser/service_worker/service_worker_request_handler.h
@@ -71,7 +71,7 @@ class CONTENT_EXPORT ServiceWorkerRequestHandler
// just creates a NavigationLoaderInterceptor and returns it.
static std::unique_ptr<NavigationLoaderInterceptor>
InitializeForNavigationNetworkService(
- const network::ResourceRequest& resource_request,
+ const GURL& url,
ResourceContext* resource_context,
ServiceWorkerNavigationHandleCore* navigation_handle_core,
storage::BlobStorageContext* blob_storage_context,
@@ -139,9 +139,10 @@ class CONTENT_EXPORT ServiceWorkerRequestHandler
ResourceContext* context) = 0;
// NavigationLoaderInterceptor overrides.
- void MaybeCreateLoader(const network::ResourceRequest& request,
+ void MaybeCreateLoader(const network::ResourceRequest& tentative_request,
ResourceContext* resource_context,
- LoaderCallback callback) override;
+ LoaderCallback callback,
+ FallbackCallback fallback_callback) override;
protected:
ServiceWorkerRequestHandler(
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 1806fc576cd..2aaa2c7e9ee 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
@@ -135,6 +135,20 @@ class ServiceWorkerRequestHandlerTest : public testing::Test {
void InitializeHandlerForNavigationSimpleTest(const std::string& url,
bool expected_handler_created) {
+ bool handler_created = false;
+ if (blink::ServiceWorkerUtils::IsServicificationEnabled()) {
+ handler_created = InitializeHandlerForNavigationNetworkService(
+ url, expected_handler_created);
+ } else {
+ handler_created = InitializeHandlerForNavigationNonNetworkService(
+ url, expected_handler_created);
+ }
+ EXPECT_EQ(expected_handler_created, handler_created);
+ }
+
+ bool InitializeHandlerForNavigationNonNetworkService(
+ const std::string& url,
+ bool expected_handler_created) {
std::unique_ptr<ServiceWorkerNavigationHandleCore> navigation_handle_core =
CreateNavigationHandleCore(helper_->context_wrapper());
std::unique_ptr<net::URLRequest> request = CreateRequest(url, "GET");
@@ -142,9 +156,27 @@ class ServiceWorkerRequestHandlerTest : public testing::Test {
request.get(), navigation_handle_core.get(), &blob_storage_context_,
false /* skip_service_worker */, RESOURCE_TYPE_MAIN_FRAME,
REQUEST_CONTEXT_TYPE_HYPERLINK,
- network::mojom::RequestContextFrameType::kTopLevel, true,
- nullptr /* body */, base::RepeatingCallback<WebContents*(void)>());
- EXPECT_EQ(expected_handler_created, !!GetHandler(request.get()));
+ network::mojom::RequestContextFrameType::kTopLevel,
+ true /* is_parent_frame_secure */, nullptr /* body */,
+ base::RepeatingCallback<WebContents*(void)>());
+ return !!GetHandler(request.get());
+ }
+
+ bool InitializeHandlerForNavigationNetworkService(
+ const std::string& url,
+ bool expected_handler_created) {
+ std::unique_ptr<ServiceWorkerNavigationHandleCore> navigation_handle_core =
+ CreateNavigationHandleCore(helper_->context_wrapper());
+ std::unique_ptr<NavigationLoaderInterceptor> interceptor =
+ ServiceWorkerRequestHandler::InitializeForNavigationNetworkService(
+ GURL(url), nullptr /* resource_context */,
+ navigation_handle_core.get(), &blob_storage_context_,
+ false /* skip_service_worker */, RESOURCE_TYPE_MAIN_FRAME,
+ REQUEST_CONTEXT_TYPE_HYPERLINK,
+ network::mojom::RequestContextFrameType::kTopLevel,
+ true /* is_parent_frame_secure */, nullptr /* body */,
+ base::RepeatingCallback<WebContents*(void)>());
+ return !!interceptor.get();
}
TestBrowserThreadBundle browser_thread_bundle_;
diff --git a/chromium/content/browser/service_worker/service_worker_response_info.cc b/chromium/content/browser/service_worker/service_worker_response_info.cc
index 83efc85f19d..e837a8d854a 100644
--- a/chromium/content/browser/service_worker/service_worker_response_info.cc
+++ b/chromium/content/browser/service_worker/service_worker_response_info.cc
@@ -42,8 +42,7 @@ void ServiceWorkerResponseInfo::GetExtraResponseInfo(
response_info->was_fallback_required_by_service_worker =
was_fallback_required_;
response_info->url_list_via_service_worker = url_list_via_service_worker_;
- response_info->response_type_via_service_worker =
- response_type_via_service_worker_;
+ response_info->response_type = response_type_via_service_worker_;
response_info->service_worker_start_time = service_worker_start_time_;
response_info->service_worker_ready_time = service_worker_ready_time_;
response_info->is_in_cache_storage = response_is_in_cache_storage_;
diff --git a/chromium/content/browser/service_worker/service_worker_script_cache_map.cc b/chromium/content/browser/service_worker/service_worker_script_cache_map.cc
index c843ab379f0..09f44ad00a1 100644
--- a/chromium/content/browser/service_worker/service_worker_script_cache_map.cc
+++ b/chromium/content/browser/service_worker/service_worker_script_cache_map.cc
@@ -92,12 +92,18 @@ void ServiceWorkerScriptCacheMap::WriteMetadata(
const GURL& url,
const std::vector<uint8_t>& data,
const net::CompletionCallback& callback) {
+ if (!context_) {
+ callback.Run(net::ERR_ABORTED);
+ return;
+ }
+
ResourceMap::iterator found = resource_map_.find(url);
if (found == resource_map_.end() ||
found->second.resource_id == kInvalidServiceWorkerResourceId) {
callback.Run(net::ERR_FILE_NOT_FOUND);
return;
}
+
scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(data.size()));
if (data.size())
memmove(buffer->data(), &data[0], data.size());
diff --git a/chromium/content/browser/service_worker/service_worker_script_loader_factory.h b/chromium/content/browser/service_worker/service_worker_script_loader_factory.h
index efc08ff62e5..2eb05ea0815 100644
--- a/chromium/content/browser/service_worker/service_worker_script_loader_factory.h
+++ b/chromium/content/browser/service_worker/service_worker_script_loader_factory.h
@@ -6,6 +6,7 @@
#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_SCRIPT_LOADER_FACTORY_H_
#include "base/macros.h"
+#include "content/common/content_export.h"
#include "mojo/public/cpp/bindings/binding_set.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
@@ -30,7 +31,7 @@ class ServiceWorkerProviderHost;
//
// This factory creates either a ServiceWorkerNewScriptLoader or a
// ServiceWorkerInstalledScriptLoader to load a script.
-class ServiceWorkerScriptLoaderFactory
+class CONTENT_EXPORT ServiceWorkerScriptLoaderFactory
: public network::mojom::URLLoaderFactory {
public:
// |loader_factory| is used to load scripts. Typically
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
new file mode 100644
index 00000000000..c53cae17369
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_script_loader_factory_unittest.cc
@@ -0,0 +1,176 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/service_worker/service_worker_script_loader_factory.h"
+
+#include "base/run_loop.h"
+#include "base/test/scoped_feature_list.h"
+#include "content/browser/service_worker/embedded_worker_test_helper.h"
+#include "content/browser/service_worker/service_worker_context_core.h"
+#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 "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()
+ : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}
+ ~ServiceWorkerScriptLoaderFactoryTest() override = default;
+
+ void SetUp() override {
+ scoped_feature_list_.InitAndEnableFeature(
+ blink::features::kServiceWorkerServicification);
+
+ helper_ = std::make_unique<EmbeddedWorkerTestHelper>(base::FilePath());
+ ServiceWorkerContextCore* context = helper_->context();
+ context->storage()->LazyInitializeForTest(base::DoNothing());
+ base::RunLoop().RunUntilIdle();
+
+ scope_ = GURL("https://host/scope");
+
+ 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"),
+ 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>();
+ helper_->SetNetworkFactory(network_loader_factory_.get());
+
+ factory_ = std::make_unique<ServiceWorkerScriptLoaderFactory>(
+ helper_->context()->AsWeakPtr(), provider_host_,
+ helper_->url_loader_factory_getter()->GetNetworkFactory());
+ }
+
+ protected:
+ network::mojom::URLLoaderPtr CreateTestLoaderAndStart(
+ network::TestURLLoaderClient* client) {
+ network::mojom::URLLoaderPtr loader;
+ network::ResourceRequest resource_request;
+ resource_request.url = scope_;
+ resource_request.resource_type = RESOURCE_TYPE_SERVICE_WORKER;
+ factory_->CreateLoaderAndStart(
+ mojo::MakeRequest(&loader), 0 /* routing_id */, 0 /* request_id */,
+ network::mojom::kURLLoadOptionNone, resource_request,
+ client->CreateInterfacePtr(),
+ net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
+ return loader;
+ }
+
+ base::test::ScopedFeatureList scoped_feature_list_;
+ TestBrowserThreadBundle browser_thread_bundle_;
+ std::unique_ptr<EmbeddedWorkerTestHelper> helper_;
+ GURL scope_;
+ 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<ServiceWorkerScriptLoaderFactory> factory_;
+};
+
+TEST_F(ServiceWorkerScriptLoaderFactoryTest, Success) {
+ network::TestURLLoaderClient client;
+ network::mojom::URLLoaderPtr loader = CreateTestLoaderAndStart(&client);
+ client.RunUntilComplete();
+ EXPECT_EQ(net::OK, client.completion_status().error_code);
+}
+
+TEST_F(ServiceWorkerScriptLoaderFactoryTest, Redundant) {
+ version_->SetStatus(ServiceWorkerVersion::REDUNDANT);
+
+ network::TestURLLoaderClient client;
+ network::mojom::URLLoaderPtr loader = CreateTestLoaderAndStart(&client);
+ client.RunUntilComplete();
+ EXPECT_EQ(net::ERR_ABORTED, client.completion_status().error_code);
+}
+
+TEST_F(ServiceWorkerScriptLoaderFactoryTest, NoProviderHost) {
+ helper_->context()->RemoveProviderHost(helper_->mock_render_process_id(),
+ provider_host_->provider_id());
+
+ network::TestURLLoaderClient client;
+ network::mojom::URLLoaderPtr loader = CreateTestLoaderAndStart(&client);
+ client.RunUntilComplete();
+ EXPECT_EQ(net::ERR_ABORTED, client.completion_status().error_code);
+}
+
+TEST_F(ServiceWorkerScriptLoaderFactoryTest, ContextDestroyed) {
+ helper_->ShutdownContext();
+ base::RunLoop().RunUntilIdle();
+
+ network::TestURLLoaderClient client;
+ network::mojom::URLLoaderPtr loader = CreateTestLoaderAndStart(&client);
+ client.RunUntilComplete();
+ EXPECT_EQ(net::ERR_ABORTED, client.completion_status().error_code);
+}
+
+} // 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 93a71912a4c..92b13a6c60e 100644
--- a/chromium/content/browser/service_worker/service_worker_storage.cc
+++ b/chromium/content/browser/service_worker/service_worker_storage.cc
@@ -12,8 +12,8 @@
#include "base/files/file_util.h"
#include "base/memory/ptr_util.h"
#include "base/sequenced_task_runner.h"
+#include "base/task/post_task.h"
#include "base/task_runner_util.h"
-#include "base/task_scheduler/post_task.h"
#include "base/trace_event/trace_event.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_disk_cache.h"
diff --git a/chromium/content/browser/service_worker/service_worker_storage_unittest.cc b/chromium/content/browser/service_worker/service_worker_storage_unittest.cc
index babac6c2096..9d1aab24ec6 100644
--- a/chromium/content/browser/service_worker/service_worker_storage_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_storage_unittest.cc
@@ -172,13 +172,14 @@ int WriteResponse(ServiceWorkerStorage* storage,
std::unique_ptr<ServiceWorkerResponseWriter> writer =
storage->CreateResponseWriter(id);
- std::unique_ptr<net::HttpResponseInfo> info(new net::HttpResponseInfo);
+ std::unique_ptr<net::HttpResponseInfo> info =
+ std::make_unique<net::HttpResponseInfo>();
info->request_time = base::Time::Now();
info->response_time = base::Time::Now();
info->was_cached = false;
info->headers = new net::HttpResponseHeaders(headers);
scoped_refptr<HttpResponseInfoIOBuffer> info_buffer =
- new HttpResponseInfoIOBuffer(info.release());
+ base::MakeRefCounted<HttpResponseInfoIOBuffer>(std::move(info));
int rv = 0;
{
TestCompletionCallback cb;
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 384440dc50c..05e9cb72dea 100644
--- a/chromium/content/browser/service_worker/service_worker_test_utils.cc
+++ b/chromium/content/browser/service_worker/service_worker_test_utils.cc
@@ -105,7 +105,7 @@ void WriteBodyToDiskCache(std::unique_ptr<ServiceWorkerResponseWriter> writer,
const std::string& body,
base::OnceClosure callback) {
scoped_refptr<HttpResponseInfoIOBuffer> info_buffer =
- base::MakeRefCounted<HttpResponseInfoIOBuffer>(info.release());
+ base::MakeRefCounted<HttpResponseInfoIOBuffer>(std::move(info));
info_buffer->response_data_size = body.size();
ServiceWorkerResponseWriter* writer_rawptr = writer.get();
writer_rawptr->WriteInfo(
diff --git a/chromium/content/browser/service_worker/service_worker_url_job_wrapper.cc b/chromium/content/browser/service_worker/service_worker_url_job_wrapper.cc
index 52fc1fc8fe3..eaf770dc02d 100644
--- a/chromium/content/browser/service_worker/service_worker_url_job_wrapper.cc
+++ b/chromium/content/browser/service_worker/service_worker_url_job_wrapper.cc
@@ -64,6 +64,14 @@ bool ServiceWorkerURLJobWrapper::ShouldFallbackToNetwork() {
}
}
+bool ServiceWorkerURLJobWrapper::ShouldForwardToServiceWorker() {
+ if (url_loader_job_) {
+ return url_loader_job_->ShouldForwardToServiceWorker();
+ } else {
+ return url_request_job_->ShouldForwardToServiceWorker();
+ }
+}
+
void ServiceWorkerURLJobWrapper::FailDueToLostController() {
// This function is only called for subresource requests, so it can't
// be called for |url_loader_job_|, which is for navigations.
diff --git a/chromium/content/browser/service_worker/service_worker_url_job_wrapper.h b/chromium/content/browser/service_worker/service_worker_url_job_wrapper.h
index acaf609c685..c2cc39872ce 100644
--- a/chromium/content/browser/service_worker/service_worker_url_job_wrapper.h
+++ b/chromium/content/browser/service_worker/service_worker_url_job_wrapper.h
@@ -22,7 +22,7 @@ class ServiceWorkerVersion;
// non-S13nServiceWorker). It wraps either a
// ServiceWorkerURLRequestJob or a callback for URLLoader and forwards to the
// underlying implementation.
-class ServiceWorkerURLJobWrapper {
+class CONTENT_EXPORT ServiceWorkerURLJobWrapper {
public:
// A helper used by the ServiceWorkerNavigationLoader or
// ServiceWorkerURLRequestJob.
@@ -51,6 +51,11 @@ class ServiceWorkerURLJobWrapper {
// Called to signal that loading failed, and that the resource being loaded
// was a main resource.
virtual void MainResourceLoadFailed() {}
+
+ virtual void ReportDestination(
+ ServiceWorkerMetrics::MainResourceRequestDestination destination) {}
+
+ virtual void WillDispatchFetchEventForMainResource() {}
};
// Non-S13nServiceWorker.
@@ -72,6 +77,9 @@ class ServiceWorkerURLJobWrapper {
// instead should fallback to the network.
bool ShouldFallbackToNetwork();
+ // Returns true if this job should be forwarded to a service worker.
+ bool ShouldForwardToServiceWorker();
+
// Tells the job to abort with a start error. Currently this is only called
// because the controller was lost. This function could be made more generic
// if needed later.
diff --git a/chromium/content/browser/service_worker/service_worker_url_request_job.cc b/chromium/content/browser/service_worker/service_worker_url_request_job.cc
index c40adc1c9bb..033f55cb8cd 100644
--- a/chromium/content/browser/service_worker/service_worker_url_request_job.cc
+++ b/chromium/content/browser/service_worker/service_worker_url_request_job.cc
@@ -20,7 +20,7 @@
#include "base/location.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/stringprintf.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "content/browser/resource_context_impl.h"
@@ -353,6 +353,7 @@ ServiceWorkerURLRequestJob::~ServiceWorkerURLRequestJob() {
if (!ShouldRecordResult())
return;
+
ServiceWorkerMetrics::URLRequestJobResult result =
ServiceWorkerMetrics::REQUEST_JOB_ERROR_KILLED;
if (response_body_type_ == STREAM)
@@ -558,8 +559,7 @@ ServiceWorkerURLRequestJob::CreateResourceRequest() {
for (net::HttpRequestHeaders::Iterator it(request_->extra_request_headers());
it.GetNext();) {
- if (!ServiceWorkerContext::IsExcludedHeaderNameForFetchEvent(it.name()))
- request->headers.SetHeader(it.name(), it.value());
+ request->headers.SetHeader(it.name(), it.value());
}
request->referrer = GURL(request_->referrer());
@@ -658,9 +658,8 @@ void ServiceWorkerURLRequestJob::DidPrepareFetchEvent(
void ServiceWorkerURLRequestJob::DidDispatchFetchEvent(
blink::ServiceWorkerStatusCode status,
ServiceWorkerFetchDispatcher::FetchEventResult fetch_result,
- const ServiceWorkerResponse& response,
+ blink::mojom::FetchAPIResponsePtr response,
blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
- blink::mojom::BlobPtr body_as_blob,
scoped_refptr<ServiceWorkerVersion> version) {
// Do not clear |fetch_dispatcher_| if it has dispatched a navigation preload
// request to keep the network::mojom::URLLoader related objects in it,
@@ -669,6 +668,10 @@ void ServiceWorkerURLRequestJob::DidDispatchFetchEvent(
if (!did_navigation_preload_) {
fetch_dispatcher_.reset();
}
+ if (IsMainResourceLoad()) {
+ ReportDestination(
+ ServiceWorkerMetrics::MainResourceRequestDestination::kServiceWorker);
+ }
ServiceWorkerMetrics::RecordFetchEventStatus(IsMainResourceLoad(), status);
ServiceWorkerMetrics::URLRequestJobResult result =
@@ -708,9 +711,9 @@ void ServiceWorkerURLRequestJob::DidDispatchFetchEvent(
// A response with status code 0 is Blink telling us to respond with network
// error.
- if (response.status_code == 0) {
- RecordStatusZeroResponseError(response.error);
- NotifyStartError(ServiceWorkerResponseErrorToNetStatus(response.error));
+ if (response->status_code == 0) {
+ RecordStatusZeroResponseError(response->error);
+ NotifyStartError(ServiceWorkerResponseErrorToNetStatus(response->error));
return;
}
@@ -730,7 +733,7 @@ void ServiceWorkerURLRequestJob::DidDispatchFetchEvent(
// Process stream using Mojo's data pipe.
if (!body_as_stream.is_null()) {
SetResponseBodyType(STREAM);
- SetResponse(response);
+ SetResponse(std::move(response));
data_pipe_reader_.reset(new ServiceWorkerDataPipeReader(
this, version, std::move(body_as_stream)));
data_pipe_reader_->Start();
@@ -738,14 +741,14 @@ void ServiceWorkerURLRequestJob::DidDispatchFetchEvent(
}
// Set up a request for reading the blob.
- // |body_as_blob| must be kept around until we call this to ensure that
- // it's alive.
- // TODO(falken): Can we just read |body_as_blob| directly like in
+ // TODO(falken): Can we just read |response->blob->blob| directly like in
// ServiceWorkerNavigationLoader?
- if (!response.blob_uuid.empty() && blob_storage_context_) {
+ if (response->blob && blob_storage_context_) {
+ DCHECK(!response->blob->uuid.empty());
+ DCHECK(response->blob->blob.is_valid());
SetResponseBodyType(BLOB);
std::unique_ptr<storage::BlobDataHandle> blob_data_handle =
- blob_storage_context_->GetBlobDataFromUUID(response.blob_uuid);
+ blob_storage_context_->GetBlobDataFromUUID(response->blob->uuid);
if (!blob_data_handle) {
// The renderer gave us a bad blob UUID.
RecordResult(ServiceWorkerMetrics::REQUEST_JOB_ERROR_BAD_BLOB);
@@ -756,7 +759,7 @@ void ServiceWorkerURLRequestJob::DidDispatchFetchEvent(
blob_reader_->Start(std::move(blob_data_handle), request()->context());
}
- SetResponse(response);
+ SetResponse(std::move(response));
if (!blob_reader_) {
RecordResult(ServiceWorkerMetrics::REQUEST_JOB_HEADERS_ONLY_RESPONSE);
CommitResponseHeader();
@@ -764,31 +767,36 @@ void ServiceWorkerURLRequestJob::DidDispatchFetchEvent(
}
void ServiceWorkerURLRequestJob::SetResponse(
- const ServiceWorkerResponse& response) {
- response_url_list_ = response.url_list;
- fetch_response_type_ = response.response_type;
- cors_exposed_header_names_ = response.cors_exposed_header_names;
- response_time_ = response.response_time;
- CreateResponseHeader(response.status_code, response.status_text,
- response.headers);
+ blink::mojom::FetchAPIResponsePtr response) {
+ response_url_list_ = std::move(response->url_list);
+ fetch_response_type_ = response->response_type;
+ cors_exposed_header_names_ = std::move(response->cors_exposed_header_names);
+ response_time_ = response->response_time;
+ CreateResponseHeader(response->status_code, response->status_text,
+ std::move(response->headers));
load_timing_info_.receive_headers_end = base::TimeTicks::Now();
- response_is_in_cache_storage_ = response.is_in_cache_storage;
- response_cache_storage_cache_name_ = response.cache_storage_cache_name;
+ response_is_in_cache_storage_ = response->is_in_cache_storage;
+ if (response->cache_storage_cache_name) {
+ response_cache_storage_cache_name_ =
+ std::move(*(response->cache_storage_cache_name));
+ } else {
+ response_cache_storage_cache_name_.clear();
+ }
}
void ServiceWorkerURLRequestJob::CreateResponseHeader(
int status_code,
const std::string& status_text,
- const ServiceWorkerHeaderMap& headers) {
+ ResponseHeaderMap headers) {
// Build a string instead of using HttpResponseHeaders::AddHeader on
// each header, since AddHeader has O(n^2) performance.
std::string buf(base::StringPrintf("HTTP/1.1 %d %s\r\n", status_code,
status_text.c_str()));
- for (const auto& item : headers) {
- buf.append(item.first);
+ for (auto& item : headers) {
+ buf.append(std::move(item.first));
buf.append(": ");
- buf.append(item.second);
+ buf.append(std::move(item.second));
buf.append("\r\n");
}
buf.append("\r\n");
@@ -809,8 +817,8 @@ void ServiceWorkerURLRequestJob::CommitResponseHeader() {
void ServiceWorkerURLRequestJob::DeliverErrorResponse() {
// TODO(falken): Print an error to the console of the ServiceWorker and of
// the requesting page.
- CreateResponseHeader(
- 500, "Service Worker Response Error", ServiceWorkerHeaderMap());
+ CreateResponseHeader(500, "Service Worker Response Error",
+ ResponseHeaderMap());
CommitResponseHeader();
}
@@ -831,7 +839,7 @@ void ServiceWorkerURLRequestJob::FinalizeFallbackToRenderer() {
if (ShouldRecordResult())
RecordResult(ServiceWorkerMetrics::REQUEST_JOB_FALLBACK_FOR_CORS);
CreateResponseHeader(400, "Service Worker Fallback Required",
- ServiceWorkerHeaderMap());
+ ResponseHeaderMap());
response_type_ = ResponseType::FALLBACK_TO_RENDERER;
CommitResponseHeader();
}
@@ -946,6 +954,11 @@ void ServiceWorkerURLRequestJob::RequestBodyFileSizesResolved(bool success) {
if (!success) {
RecordResult(
ServiceWorkerMetrics::REQUEST_JOB_ERROR_REQUEST_BODY_BLOB_FAILED);
+ if (IsMainResourceLoad()) {
+ ReportDestination(ServiceWorkerMetrics::MainResourceRequestDestination::
+ kErrorRequestBodyFailed);
+ }
+
// TODO(falken): This and below should probably be NotifyStartError, not
// DeliverErrorResponse. But changing it causes
// ServiceWorkerURLRequestJobTest.DeletedProviderHostBeforeFetchEvent to
@@ -960,6 +973,10 @@ void ServiceWorkerURLRequestJob::RequestBodyFileSizesResolved(bool success) {
delegate_->GetServiceWorkerVersion(&result);
if (!active_worker) {
RecordResult(result);
+ if (IsMainResourceLoad()) {
+ ReportDestination(ServiceWorkerMetrics::MainResourceRequestDestination::
+ kErrorNoActiveWorkerFromDelegate);
+ }
DeliverErrorResponse();
return;
}
@@ -981,6 +998,8 @@ void ServiceWorkerURLRequestJob::RequestBodyFileSizesResolved(bool success) {
}
DCHECK(!fetch_dispatcher_);
+ if (IsMainResourceLoad())
+ delegate_->WillDispatchFetchEventForMainResource();
fetch_dispatcher_ = std::make_unique<ServiceWorkerFetchDispatcher>(
std::move(resource_request), blob_uuid, blob_size, std::move(blob),
client_id_, base::WrapRefCounted(active_worker), request()->net_log(),
@@ -1006,4 +1025,10 @@ void ServiceWorkerURLRequestJob::OnNavigationPreloadResponse() {
nav_preload_metrics_->ReportNavigationPreloadFinished();
}
+void ServiceWorkerURLRequestJob::ReportDestination(
+ ServiceWorkerMetrics::MainResourceRequestDestination destination) {
+ DCHECK(IsMainResourceLoad());
+ delegate_->ReportDestination(destination);
+}
+
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_url_request_job.h b/chromium/content/browser/service_worker/service_worker_url_request_job.h
index 5c8f00e1ee7..ea2182bae3d 100644
--- a/chromium/content/browser/service_worker/service_worker_url_request_job.h
+++ b/chromium/content/browser/service_worker/service_worker_url_request_job.h
@@ -24,7 +24,6 @@
#include "content/browser/service_worker/service_worker_url_job_wrapper.h"
#include "content/common/content_export.h"
#include "content/common/service_worker/service_worker.mojom.h"
-#include "content/common/service_worker/service_worker_types.h"
#include "content/public/common/request_context_type.h"
#include "content/public/common/resource_type.h"
#include "mojo/public/cpp/system/data_pipe.h"
@@ -37,6 +36,7 @@
#include "services/network/public/mojom/request_context_frame_type.mojom.h"
#include "storage/common/blob_storage/blob_storage_constants.h"
#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_response.mojom.h"
#include "url/gurl.h"
namespace net {
@@ -148,6 +148,8 @@ class CONTENT_EXPORT ServiceWorkerURLRequestJob : public net::URLRequestJob {
base::WeakPtr<ServiceWorkerURLRequestJob> GetWeakPtr();
private:
+ using ResponseHeaderMap = base::flat_map<std::string, std::string>;
+
class FileSizeResolver;
class NavigationPreloadMetrics;
friend class service_worker_url_request_job_unittest::DelayHelper;
@@ -190,16 +192,15 @@ class CONTENT_EXPORT ServiceWorkerURLRequestJob : public net::URLRequestJob {
void DidDispatchFetchEvent(
blink::ServiceWorkerStatusCode status,
ServiceWorkerFetchDispatcher::FetchEventResult fetch_result,
- const ServiceWorkerResponse& response,
+ blink::mojom::FetchAPIResponsePtr response,
blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
- blink::mojom::BlobPtr body_as_blob,
scoped_refptr<ServiceWorkerVersion> version);
- void SetResponse(const ServiceWorkerResponse& response);
+ void SetResponse(blink::mojom::FetchAPIResponsePtr response);
// Populates |http_response_headers_|.
void CreateResponseHeader(int status_code,
const std::string& status_text,
- const ServiceWorkerHeaderMap& headers);
+ ResponseHeaderMap headers);
// Creates |http_response_info_| using |http_response_headers_| and calls
// NotifyHeadersComplete.
@@ -251,6 +252,9 @@ class CONTENT_EXPORT ServiceWorkerURLRequestJob : public net::URLRequestJob {
void MaybeReportNavigationPreloadMetrics();
+ void ReportDestination(
+ ServiceWorkerMetrics::MainResourceRequestDestination destination);
+
// Not owned.
Delegate* delegate_;
@@ -336,6 +340,9 @@ class CONTENT_EXPORT ServiceWorkerURLRequestJob : public net::URLRequestJob {
std::unique_ptr<FileSizeResolver> file_size_resolver_;
+ bool started_fetch_dispatch_ = false;
+ bool reported_destination_ = false;
+
base::WeakPtrFactory<ServiceWorkerURLRequestJob> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerURLRequestJob);
diff --git a/chromium/content/browser/service_worker/service_worker_url_request_job_unittest.cc b/chromium/content/browser/service_worker/service_worker_url_request_job_unittest.cc
index ce237a44d28..fef3544e4ba 100644
--- a/chromium/content/browser/service_worker/service_worker_url_request_job_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_url_request_job_unittest.cc
@@ -15,6 +15,7 @@
#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"
@@ -30,7 +31,6 @@
#include "content/browser/service_worker/service_worker_response_info.h"
#include "content/browser/service_worker/service_worker_test_utils.h"
#include "content/browser/service_worker/service_worker_version.h"
-#include "content/common/service_worker/service_worker_messages.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/browser/blob_handle.h"
@@ -60,6 +60,7 @@
#include "storage/browser/blob/blob_url_request_job_factory.h"
#include "storage/common/blob_storage/blob_handle.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
#include "third_party/blink/public/mojom/service_worker/service_worker.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom.h"
@@ -148,14 +149,22 @@ std::unique_ptr<storage::BlobProtocolHandler> CreateMockBlobProtocolHandler(
return std::make_unique<storage::BlobProtocolHandler>(blob_storage_context);
}
-std::unique_ptr<ServiceWorkerHeaderMap> MakeHeaders() {
- auto headers = std::make_unique<ServiceWorkerHeaderMap>();
- (*headers)["Pineapple"] = "Pen";
- (*headers)["Foo"] = "Bar";
- (*headers)["Set-Cookie"] = "CookieCookieCookie";
+base::flat_map<std::string, std::string> MakeHeaders() {
+ base::flat_map<std::string, std::string> headers;
+ headers["Pineapple"] = "Pen";
+ headers["Foo"] = "Bar";
+ headers["Set-Cookie"] = "CookieCookieCookie";
return headers;
}
+blink::mojom::FetchAPIResponsePtr MakeOkResponse() {
+ auto response = blink::mojom::FetchAPIResponse::New();
+ response->status_code = 200;
+ response->status_text = "OK";
+ response->response_type = network::mojom::FetchResponseType::kDefault;
+ return response;
+}
+
void SaveStatusCallback(blink::ServiceWorkerStatusCode* out_status,
blink::ServiceWorkerStatusCode status) {
*out_status = status;
@@ -195,6 +204,10 @@ class ServiceWorkerURLRequestJobTest
~ServiceWorkerURLRequestJobTest() override {}
void SetUp() override {
+ // ServiceWorkerURLRequestJob is a non-S13nServiceWorker specific class
+ // and we don't use it when S13nServiceWorker is enabled.
+ scoped_feature_list_.InitAndDisableFeature(
+ blink::features::kServiceWorkerServicification);
browser_context_.reset(new TestBrowserContext);
InitializeResourceContext(browser_context_.get());
}
@@ -248,8 +261,8 @@ class ServiceWorkerURLRequestJobTest
provider_host_ = provider_host->AsWeakPtr();
provider_host->SetDocumentUrl(GURL("https://example.com/"));
registration_->SetActiveVersion(version_);
- provider_host->AssociateRegistration(registration_.get(),
- false /* notify_controllerchange */);
+ provider_host->SetControllerRegistration(
+ registration_, false /* notify_controllerchange */);
// Set up scaffolding for handling URL requests.
ChromeBlobStorageContext* chrome_blob_storage_context =
@@ -383,11 +396,11 @@ class ServiceWorkerURLRequestJobTest
*result = ServiceWorkerMetrics::REQUEST_JOB_ERROR_NO_PROVIDER_HOST;
return nullptr;
}
- if (!provider_host_->active_version()) {
+ if (!provider_host_->controller()) {
*result = ServiceWorkerMetrics::REQUEST_JOB_ERROR_NO_ACTIVE_VERSION;
return nullptr;
}
- return provider_host_->active_version();
+ return provider_host_->controller();
}
bool RequestStillValid(
@@ -406,6 +419,10 @@ class ServiceWorkerURLRequestJobTest
}
// ---------------------------------------------------------------------------
+ // |scoped_feature_list_| must be before |thread_bundle_|.
+ // See comments in ServiceWorkerProviderHostTest.
+ base::test::ScopedFeatureList scoped_feature_list_;
+
TestBrowserThreadBundle thread_bundle_;
base::SimpleTestTickClock tick_clock_;
@@ -473,18 +490,7 @@ class DelayHelper : public EmbeddedWorkerTestHelper {
}
void Respond() {
- response_callback_->OnResponse(
- ServiceWorkerResponse(
- std::make_unique<std::vector<GURL>>(), 200, "OK",
- network::mojom::FetchResponseType::kDefault,
- std::make_unique<ServiceWorkerHeaderMap>(), std::string(), 0,
- nullptr /* blob */,
- blink::mojom::ServiceWorkerResponseError::kUnknown, base::Time(),
- false /* response_is_in_cache_storage */,
- std::string() /* response_cache_storage_cache_name */,
- std::make_unique<
- ServiceWorkerHeaderList>() /* cors_exposed_header_names */),
- base::Time::Now());
+ response_callback_->OnResponse(MakeOkResponse(), base::Time::Now());
std::move(finish_callback_)
.Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
base::Time::Now());
@@ -519,7 +525,7 @@ class DelayHelper : public EmbeddedWorkerTestHelper {
int embedded_worker_id,
const network::ResourceRequest& /* request */,
blink::mojom::FetchEventPreloadHandlePtr preload_handle,
- mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
+ blink::mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
mojom::ServiceWorker::DispatchFetchEventCallback finish_callback)
override {
embedded_worker_id_ = embedded_worker_id;
@@ -540,7 +546,7 @@ class DelayHelper : public EmbeddedWorkerTestHelper {
mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info_;
blink::mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info_;
int embedded_worker_id_ = 0;
- mojom::ServiceWorkerFetchResponseCallbackPtr response_callback_;
+ blink::mojom::ServiceWorkerFetchResponseCallbackPtr response_callback_;
blink::mojom::FetchEventPreloadHandlePtr preload_handle_;
mojom::ServiceWorker::DispatchFetchEventCallback finish_callback_;
ServiceWorkerURLRequestJobTest* test_;
@@ -697,22 +703,11 @@ class ProviderDeleteHelper : public EmbeddedWorkerTestHelper {
int /* embedded_worker_id */,
const network::ResourceRequest& /* request */,
blink::mojom::FetchEventPreloadHandlePtr /* preload_handle */,
- mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
+ blink::mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
mojom::ServiceWorker::DispatchFetchEventCallback finish_callback)
override {
context()->RemoveProviderHost(mock_render_process_id(), kProviderID);
- response_callback->OnResponse(
- ServiceWorkerResponse(
- std::make_unique<std::vector<GURL>>(), 200, "OK",
- network::mojom::FetchResponseType::kDefault,
- std::make_unique<ServiceWorkerHeaderMap>(), std::string(), 0,
- nullptr /* blob */,
- blink::mojom::ServiceWorkerResponseError::kUnknown, base::Time(),
- false /* response_is_in_cache_storage */,
- std::string() /* response_cache_storage_cache_name */,
- std::make_unique<
- ServiceWorkerHeaderList>() /* cors_exposed_header_names */),
- base::Time::Now());
+ response_callback->OnResponse(MakeOkResponse(), base::Time::Now());
std::move(finish_callback)
.Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
base::Time::Now());
@@ -787,20 +782,19 @@ class BlobResponder : public EmbeddedWorkerTestHelper {
int /* embedded_worker_id */,
const network::ResourceRequest& /* request */,
blink::mojom::FetchEventPreloadHandlePtr /* preload_handle */,
- mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
+ blink::mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
mojom::ServiceWorker::DispatchFetchEventCallback finish_callback)
override {
- response_callback->OnResponse(
- ServiceWorkerResponse(
- std::make_unique<std::vector<GURL>>(), 200, "OK",
- network::mojom::FetchResponseType::kDefault, MakeHeaders(),
- blob_uuid_, blob_size_, nullptr /* blob */,
- blink::mojom::ServiceWorkerResponseError::kUnknown, base::Time(),
- false /* response_is_in_cache_storage */,
- std::string() /* response_cache_storage_cache_name */,
- std::make_unique<
- ServiceWorkerHeaderList>() /* cors_exposed_header_names */),
- base::Time::Now());
+ blink::mojom::FetchAPIResponsePtr response = MakeOkResponse();
+ response->headers = MakeHeaders();
+ response->blob = blink::mojom::SerializedBlob::New();
+ response->blob->uuid = blob_uuid_;
+ response->blob->size = blob_size_;
+ // As |response->blob->blob| must have a non-null value to be passed via
+ // Mojo, we give it a dummy value.
+ auto dummy_request = mojo::MakeRequest(&response->blob->blob);
+
+ response_callback->OnResponse(std::move(response), base::Time::Now());
std::move(finish_callback)
.Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
base::Time::Now());
@@ -888,21 +882,14 @@ class StreamResponder : public EmbeddedWorkerTestHelper {
int /* embedded_worker_id */,
const network::ResourceRequest& /* request */,
blink::mojom::FetchEventPreloadHandlePtr /* preload_handle */,
- mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
+ blink::mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
mojom::ServiceWorker::DispatchFetchEventCallback finish_callback)
override {
ASSERT_FALSE(stream_handle_.is_null());
+ blink::mojom::FetchAPIResponsePtr response = MakeOkResponse();
+ response->headers = MakeHeaders();
response_callback->OnResponseStream(
- ServiceWorkerResponse(
- std::make_unique<std::vector<GURL>>(), 200, "OK",
- network::mojom::FetchResponseType::kDefault, MakeHeaders(), "", 0,
- nullptr /* blob */,
- blink::mojom::ServiceWorkerResponseError::kUnknown, base::Time(),
- false /* response_is_in_cache_storage */,
- std::string() /* response_cache_storage_cache_name */,
- std::make_unique<
- ServiceWorkerHeaderList>() /* cors_exposed_header_names */),
- std::move(stream_handle_), base::Time::Now());
+ std::move(response), std::move(stream_handle_), base::Time::Now());
std::move(finish_callback)
.Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
base::Time::Now());
@@ -1278,7 +1265,8 @@ class FailFetchHelper : public EmbeddedWorkerTestHelper {
int embedded_worker_id,
const network::ResourceRequest& /* request */,
blink::mojom::FetchEventPreloadHandlePtr /* preload_handle */,
- mojom::ServiceWorkerFetchResponseCallbackPtr /* response_callback */,
+ blink::mojom::
+ ServiceWorkerFetchResponseCallbackPtr /* response_callback */,
mojom::ServiceWorker::DispatchFetchEventCallback finish_callback)
override {
SimulateWorkerStopped(embedded_worker_id);
@@ -1371,22 +1359,11 @@ class EarlyResponseHelper : public EmbeddedWorkerTestHelper {
int /* embedded_worker_id */,
const network::ResourceRequest& /* request */,
blink::mojom::FetchEventPreloadHandlePtr /* preload_handle */,
- mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
+ blink::mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
mojom::ServiceWorker::DispatchFetchEventCallback finish_callback)
override {
finish_callback_ = std::move(finish_callback);
- response_callback->OnResponse(
- ServiceWorkerResponse(
- std::make_unique<std::vector<GURL>>(), 200, "OK",
- network::mojom::FetchResponseType::kDefault,
- std::make_unique<ServiceWorkerHeaderMap>(), std::string(), 0,
- nullptr /* blob */,
- blink::mojom::ServiceWorkerResponseError::kUnknown, base::Time(),
- false /* response_is_in_cache_storage */,
- std::string() /* response_cache_storage_cache_name */,
- std::make_unique<
- ServiceWorkerHeaderList>() /* cors_exposed_header_names */),
- base::Time::Now());
+ response_callback->OnResponse(MakeOkResponse(), base::Time::Now());
}
private:
diff --git a/chromium/content/browser/service_worker/service_worker_version.cc b/chromium/content/browser/service_worker/service_worker_version.cc
index 8d58920080e..5d8213494b9 100644
--- a/chromium/content/browser/service_worker/service_worker_version.cc
+++ b/chromium/content/browser/service_worker/service_worker_version.cc
@@ -31,7 +31,6 @@
#include "content/browser/service_worker/service_worker_installed_scripts_sender.h"
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/common/service_worker/embedded_worker.mojom.h"
-#include "content/common/service_worker/service_worker_messages.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
@@ -113,25 +112,6 @@ void ClearTick(base::TimeTicks* time) {
*time = base::TimeTicks();
}
-std::string VersionStatusToString(ServiceWorkerVersion::Status status) {
- switch (status) {
- case ServiceWorkerVersion::NEW:
- return "new";
- case ServiceWorkerVersion::INSTALLING:
- return "installing";
- case ServiceWorkerVersion::INSTALLED:
- return "installed";
- case ServiceWorkerVersion::ACTIVATING:
- return "activating";
- case ServiceWorkerVersion::ACTIVATED:
- return "activated";
- case ServiceWorkerVersion::REDUNDANT:
- return "redundant";
- }
- NOTREACHED() << status;
- return std::string();
-}
-
const int kInvalidTraceId = -1;
int NextTraceId() {
@@ -499,8 +479,8 @@ void ServiceWorkerVersion::ScheduleUpdate() {
// and soon no one might hold a reference to us.
context_->ProtectVersion(base::WrapRefCounted(this));
update_timer_.Start(FROM_HERE, kUpdateDelay,
- base::Bind(&ServiceWorkerVersion::StartUpdate,
- weak_factory_.GetWeakPtr()));
+ base::BindOnce(&ServiceWorkerVersion::StartUpdate,
+ weak_factory_.GetWeakPtr()));
}
void ServiceWorkerVersion::StartUpdate() {
@@ -535,10 +515,36 @@ int ServiceWorkerVersion::StartRequestWithCustomTimeout(
event_type == ServiceWorkerMetrics::EventType::ACTIVATE ||
event_type == ServiceWorkerMetrics::EventType::MESSAGE ||
event_type == ServiceWorkerMetrics::EventType::EXTERNAL_REQUEST ||
+ event_type == ServiceWorkerMetrics::EventType::LONG_RUNNING_MESSAGE ||
status() == ACTIVATED)
<< "Event of type " << static_cast<int>(event_type)
<< " can only be dispatched to an active worker: " << status();
+ // |context_| is needed for some bookkeeping. If there's no context, the
+ // request will be aborted soon, so don't bother aborting the request directly
+ // here, and just skip this bookkeeping.
+ if (context_) {
+ if (event_type == ServiceWorkerMetrics::EventType::LONG_RUNNING_MESSAGE) {
+ context_->embedded_worker_registry()->AbortLifetimeTracking(
+ embedded_worker_->embedded_worker_id());
+ }
+
+ if (event_type != ServiceWorkerMetrics::EventType::INSTALL &&
+ event_type != ServiceWorkerMetrics::EventType::ACTIVATE &&
+ event_type != ServiceWorkerMetrics::EventType::MESSAGE) {
+ // Reset the self-update delay iff this is not an event that can triggered
+ // by a service worker itself. Otherwise, service workers can use update()
+ // to keep running forever via install and activate events, or
+ // postMessage() between themselves to reset the delay via message event.
+ // postMessage() resets the delay in ServiceWorkerObjectHost, iff it
+ // didn't come from a service worker.
+ ServiceWorkerRegistration* registration =
+ context_->GetLiveRegistration(registration_id_);
+ DCHECK(registration) << "running workers should have a live registration";
+ registration->set_self_update_delay(base::TimeDelta());
+ }
+ }
+
auto request = std::make_unique<InflightRequest>(
std::move(error_callback), clock_->Now(), tick_clock_->NowTicks(),
event_type);
@@ -670,6 +676,12 @@ void ServiceWorkerVersion::AddControllee(
RestartTick(&idle_time_);
ClearTick(&no_controllees_time_);
+ ServiceWorkerRegistration* registration =
+ context_->GetLiveRegistration(registration_id_);
+ if (registration) {
+ registration->set_self_update_delay(base::TimeDelta());
+ }
+
// Notify observers asynchronously for consistency with RemoveControllee.
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
@@ -735,6 +747,10 @@ void ServiceWorkerVersion::SetStartWorkerStatusCode(
}
void ServiceWorkerVersion::Doom() {
+ // Protect |this| because NotifyControllerLost() and Stop() callees
+ // may drop references to |this|.
+ scoped_refptr<ServiceWorkerVersion> protect(this);
+
// Tell controllees that this version is dead. Each controllee will call
// ServiceWorkerVersion::RemoveControllee(), so be careful with iterators.
auto iter = controllee_map_.begin();
@@ -1211,7 +1227,7 @@ void ServiceWorkerVersion::NavigateClient(const std::string& client_uuid,
binding_.Close();
return;
}
- if (provider_host->active_version() != this) {
+ if (provider_host->controller() != this) {
std::move(callback).Run(
false /* success */, nullptr /* client */,
std::string(
@@ -1345,6 +1361,7 @@ void ServiceWorkerVersion::CountFeature(blink::mojom::WebFeature feature) {
provider_host_by_uuid.second->CountFeature(feature);
}
+// static
bool ServiceWorkerVersion::IsInstalled(ServiceWorkerVersion::Status status) {
switch (status) {
case ServiceWorkerVersion::NEW:
@@ -1360,6 +1377,27 @@ bool ServiceWorkerVersion::IsInstalled(ServiceWorkerVersion::Status status) {
return false;
}
+// static
+std::string ServiceWorkerVersion::VersionStatusToString(
+ ServiceWorkerVersion::Status status) {
+ switch (status) {
+ case ServiceWorkerVersion::NEW:
+ return "new";
+ case ServiceWorkerVersion::INSTALLING:
+ return "installing";
+ case ServiceWorkerVersion::INSTALLED:
+ return "installed";
+ case ServiceWorkerVersion::ACTIVATING:
+ return "activating";
+ case ServiceWorkerVersion::ACTIVATED:
+ return "activated";
+ case ServiceWorkerVersion::REDUNDANT:
+ return "redundant";
+ }
+ NOTREACHED() << status;
+ return std::string();
+}
+
void ServiceWorkerVersion::IncrementPendingUpdateHintCount() {
DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled());
pending_update_hint_count_++;
diff --git a/chromium/content/browser/service_worker/service_worker_version.h b/chromium/content/browser/service_worker/service_worker_version.h
index 8549a667e3c..166f9093530 100644
--- a/chromium/content/browser/service_worker/service_worker_version.h
+++ b/chromium/content/browser/service_worker/service_worker_version.h
@@ -94,6 +94,7 @@ FORWARD_DECLARE_TEST(ServiceWorkerVersionTest, StaleUpdate_FreshWorker);
FORWARD_DECLARE_TEST(ServiceWorkerVersionTest, StaleUpdate_NonActiveWorker);
FORWARD_DECLARE_TEST(ServiceWorkerVersionTest, StaleUpdate_RunningWorker);
FORWARD_DECLARE_TEST(ServiceWorkerVersionTest, StaleUpdate_StartWorker);
+FORWARD_DECLARE_TEST(ServiceWorkerVersionTest, StartRequestWithNullContext);
} // namespace service_worker_version_unittest
namespace service_worker_registration_unittest {
@@ -490,6 +491,7 @@ class CONTENT_EXPORT ServiceWorkerVersion
}
static bool IsInstalled(ServiceWorkerVersion::Status status);
+ static std::string VersionStatusToString(ServiceWorkerVersion::Status status);
// For scheduling Soft Update after main resource requests. We schedule
// a Soft Update to happen "soon" after each main resource request, attempting
@@ -551,6 +553,9 @@ class CONTENT_EXPORT ServiceWorkerVersion
service_worker_version_unittest::ServiceWorkerVersionTest,
StaleUpdate_DoNotDeferTimer);
FRIEND_TEST_ALL_PREFIXES(
+ service_worker_version_unittest::ServiceWorkerVersionTest,
+ StartRequestWithNullContext);
+ FRIEND_TEST_ALL_PREFIXES(
service_worker_version_unittest::ServiceWorkerRequestTimeoutTest,
RequestTimeout);
FRIEND_TEST_ALL_PREFIXES(
@@ -840,7 +845,7 @@ class CONTENT_EXPORT ServiceWorkerVersion
std::map<std::string, ServiceWorkerProviderHost*> controllee_map_;
// Will be null while shutting down.
base::WeakPtr<ServiceWorkerContextCore> context_;
- base::ObserverList<Observer> observers_;
+ base::ObserverList<Observer>::Unchecked observers_;
ServiceWorkerScriptCacheMap script_cache_map_;
base::OneShotTimer update_timer_;
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 2b3f97091de..fddd9d4ccef 100644
--- a/chromium/content/browser/service_worker/service_worker_version_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_version_unittest.cc
@@ -559,7 +559,7 @@ TEST_F(ServiceWorkerVersionTest, Doom) {
true /* is_parent_frame_secure */, helper_->context()->AsWeakPtr(),
&remote_endpoint);
host->SetDocumentUrl(registration_->pattern());
- host->AssociateRegistration(registration_.get(), false);
+ host->SetControllerRegistration(registration_, false);
EXPECT_TRUE(version_->HasControllee());
EXPECT_TRUE(host->controller());
@@ -773,6 +773,51 @@ TEST_F(ServiceWorkerVersionTest, StaleUpdate_DoNotDeferTimer) {
EXPECT_EQ(run_time, version_->update_timer_.desired_run_time());
}
+TEST_F(ServiceWorkerVersionTest, StartRequestWithNullContext) {
+ StartWorker(version_.get(), ServiceWorkerMetrics::EventType::UNKNOWN);
+ version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
+ version_->context_ = nullptr;
+ version_->StartRequest(ServiceWorkerMetrics::EventType::PUSH,
+ base::DoNothing());
+ // Test passes if it doesn't crash.
+}
+
+// Tests the delay mechanism for self-updating service workers, to prevent
+// them from running forever (see https://crbug.com/805496).
+TEST_F(ServiceWorkerVersionTest, ResetUpdateDelay) {
+ const base::TimeDelta kMinute = base::TimeDelta::FromMinutes(1);
+ const base::TimeDelta kNoDelay = base::TimeDelta();
+
+ // Initialize the delay.
+ version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
+ registration_->SetActiveVersion(version_);
+ registration_->set_self_update_delay(kMinute);
+
+ // Events that can be triggered by a worker should not reset the delay.
+ // See the comment in ServiceWorkerVersion::StartRequestWithCustomTimeout.
+ SimulateDispatchEvent(ServiceWorkerMetrics::EventType::INSTALL);
+ SimulateDispatchEvent(ServiceWorkerMetrics::EventType::ACTIVATE);
+ SimulateDispatchEvent(ServiceWorkerMetrics::EventType::MESSAGE);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(kMinute, registration_->self_update_delay());
+
+ // Events that can only be triggered externally reset the delay.
+ // Repeat the test for several such events.
+ SimulateDispatchEvent(ServiceWorkerMetrics::EventType::SYNC);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(kNoDelay, registration_->self_update_delay());
+
+ registration_->set_self_update_delay(kMinute);
+ SimulateDispatchEvent(ServiceWorkerMetrics::EventType::NOTIFICATION_CLICK);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(kNoDelay, registration_->self_update_delay());
+
+ registration_->set_self_update_delay(kMinute);
+ SimulateDispatchEvent(ServiceWorkerMetrics::EventType::PUSH);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(kNoDelay, registration_->self_update_delay());
+}
+
TEST_F(ServiceWorkerVersionTest, UpdateCachedMetadata) {
CachedMetadataUpdateListener listener;
version_->AddObserver(&listener);
diff --git a/chromium/content/browser/service_worker/service_worker_write_to_cache_job.cc b/chromium/content/browser/service_worker/service_worker_write_to_cache_job.cc
index 25c0d8f11e2..33975df1026 100644
--- a/chromium/content/browser/service_worker/service_worker_write_to_cache_job.cc
+++ b/chromium/content/browser/service_worker/service_worker_write_to_cache_job.cc
@@ -353,10 +353,12 @@ void ServiceWorkerWriteToCacheJob::OnResponseStarted(net::URLRequest* request,
version_->embedded_worker()->OnNetworkAccessedForScriptLoad();
}
- http_info_.reset(new net::HttpResponseInfo(net_request_->response_info()));
+ http_info_ =
+ std::make_unique<net::HttpResponseInfo>(net_request_->response_info());
scoped_refptr<HttpResponseInfoIOBuffer> info_buffer =
- new HttpResponseInfoIOBuffer(
- new net::HttpResponseInfo(net_request_->response_info()));
+ base::MakeRefCounted<HttpResponseInfoIOBuffer>(
+ std::make_unique<net::HttpResponseInfo>(
+ net_request_->response_info()));
net::Error error = cache_writer_->MaybeWriteHeaders(
info_buffer.get(),
base::BindOnce(&ServiceWorkerWriteToCacheJob::OnWriteHeadersComplete,
diff --git a/chromium/content/browser/service_worker/service_worker_write_to_cache_job_unittest.cc b/chromium/content/browser/service_worker/service_worker_write_to_cache_job_unittest.cc
index 516c5b96b1a..bf253b43748 100644
--- a/chromium/content/browser/service_worker/service_worker_write_to_cache_job_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_write_to_cache_job_unittest.cc
@@ -38,8 +38,12 @@
#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"
#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
+// Note for S13nServiceWorker: All tests are skipped as we don't use
+// ServiceWorkerWriteToCacheJob when S13nServiceWorker is enabled.
+
namespace content {
namespace service_worker_write_to_cache_job_unittest {
@@ -446,6 +450,9 @@ class ServiceWorkerWriteToCacheJobTest : public testing::Test {
};
TEST_F(ServiceWorkerWriteToCacheJobTest, Normal) {
+ if (blink::ServiceWorkerUtils::IsServicificationEnabled())
+ return;
+
mock_protocol_handler_->SetCreateJobCallback(
base::Bind(&CreateNormalURLRequestJob));
request_->Start();
@@ -456,6 +463,9 @@ TEST_F(ServiceWorkerWriteToCacheJobTest, Normal) {
}
TEST_F(ServiceWorkerWriteToCacheJobTest, InvalidMimeType) {
+ if (blink::ServiceWorkerUtils::IsServicificationEnabled())
+ return;
+
mock_protocol_handler_->SetCreateJobCallback(
base::Bind(&CreateInvalidMimeTypeJob));
request_->Start();
@@ -467,6 +477,9 @@ TEST_F(ServiceWorkerWriteToCacheJobTest, InvalidMimeType) {
}
TEST_F(ServiceWorkerWriteToCacheJobTest, SSLCertificateError) {
+ if (blink::ServiceWorkerUtils::IsServicificationEnabled())
+ return;
+
mock_protocol_handler_->SetCreateJobCallback(
base::Bind(&CreateSSLCertificateErrorJob));
request_->Start();
@@ -488,6 +501,9 @@ class ServiceWorkerWriteToCacheLocalhostTest
TEST_F(ServiceWorkerWriteToCacheLocalhostTest,
SSLCertificateError_AllowInsecureLocalhost) {
+ if (blink::ServiceWorkerUtils::IsServicificationEnabled())
+ return;
+
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kAllowInsecureLocalhost);
@@ -502,6 +518,9 @@ TEST_F(ServiceWorkerWriteToCacheLocalhostTest,
}
TEST_F(ServiceWorkerWriteToCacheLocalhostTest, SSLCertificateError) {
+ if (blink::ServiceWorkerUtils::IsServicificationEnabled())
+ return;
+
mock_protocol_handler_->SetCreateJobCallback(
base::Bind(&CreateSSLCertificateErrorJob));
request_->Start();
@@ -514,6 +533,9 @@ TEST_F(ServiceWorkerWriteToCacheLocalhostTest, SSLCertificateError) {
TEST_F(ServiceWorkerWriteToCacheLocalhostTest,
CertStatusError_AllowInsecureLocalhost) {
+ if (blink::ServiceWorkerUtils::IsServicificationEnabled())
+ return;
+
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kAllowInsecureLocalhost);
@@ -528,6 +550,9 @@ TEST_F(ServiceWorkerWriteToCacheLocalhostTest,
}
TEST_F(ServiceWorkerWriteToCacheLocalhostTest, CertStatusError) {
+ if (blink::ServiceWorkerUtils::IsServicificationEnabled())
+ return;
+
mock_protocol_handler_->SetCreateJobCallback(
base::Bind(&CreateCertStatusErrorJob));
request_->Start();
@@ -539,6 +564,9 @@ TEST_F(ServiceWorkerWriteToCacheLocalhostTest, CertStatusError) {
}
TEST_F(ServiceWorkerWriteToCacheJobTest, CertStatusError) {
+ if (blink::ServiceWorkerUtils::IsServicificationEnabled())
+ return;
+
mock_protocol_handler_->SetCreateJobCallback(
base::Bind(&CreateCertStatusErrorJob));
request_->Start();
@@ -550,6 +578,9 @@ TEST_F(ServiceWorkerWriteToCacheJobTest, CertStatusError) {
}
TEST_F(ServiceWorkerWriteToCacheJobTest, Update_SameScript) {
+ if (blink::ServiceWorkerUtils::IsServicificationEnabled())
+ return;
+
std::string response = GenerateLongResponse();
CreateIncumbent(response);
scoped_refptr<ServiceWorkerVersion> version = UpdateScript(response);
@@ -557,6 +588,9 @@ TEST_F(ServiceWorkerWriteToCacheJobTest, Update_SameScript) {
}
TEST_F(ServiceWorkerWriteToCacheJobTest, Update_SameSizeScript) {
+ if (blink::ServiceWorkerUtils::IsServicificationEnabled())
+ return;
+
std::string response = GenerateLongResponse();
CreateIncumbent(response);
@@ -592,6 +626,9 @@ TEST_F(ServiceWorkerWriteToCacheJobTest, Update_SameSizeScript) {
}
TEST_F(ServiceWorkerWriteToCacheJobTest, Update_TruncatedScript) {
+ if (blink::ServiceWorkerUtils::IsServicificationEnabled())
+ return;
+
std::string response = GenerateLongResponse();
CreateIncumbent(response);
@@ -621,6 +658,9 @@ TEST_F(ServiceWorkerWriteToCacheJobTest, Update_TruncatedScript) {
}
TEST_F(ServiceWorkerWriteToCacheJobTest, Update_ElongatedScript) {
+ if (blink::ServiceWorkerUtils::IsServicificationEnabled())
+ return;
+
std::string original_response = GenerateLongResponse();
CreateIncumbent(original_response);
@@ -644,6 +684,9 @@ TEST_F(ServiceWorkerWriteToCacheJobTest, Update_ElongatedScript) {
}
TEST_F(ServiceWorkerWriteToCacheJobTest, Update_EmptyScript) {
+ if (blink::ServiceWorkerUtils::IsServicificationEnabled())
+ return;
+
// Create empty incumbent.
CreateIncumbent(std::string());
@@ -664,6 +707,9 @@ TEST_F(ServiceWorkerWriteToCacheJobTest, Update_EmptyScript) {
}
TEST_F(ServiceWorkerWriteToCacheJobTest, Error) {
+ if (blink::ServiceWorkerUtils::IsServicificationEnabled())
+ return;
+
mock_protocol_handler_->SetCreateJobCallback(
base::Bind(&CreateFailedURLRequestJob));
request_->Start();
@@ -675,6 +721,9 @@ TEST_F(ServiceWorkerWriteToCacheJobTest, Error) {
}
TEST_F(ServiceWorkerWriteToCacheJobTest, FailedWriteHeadersToCache) {
+ if (blink::ServiceWorkerUtils::IsServicificationEnabled())
+ return;
+
mock_protocol_handler_->SetCreateJobCallback(
base::Bind(&CreateNormalURLRequestJob));
DisableCache();
diff --git a/chromium/content/browser/session_history_browsertest.cc b/chromium/content/browser/session_history_browsertest.cc
index d07ea196aa2..561ac719fc5 100644
--- a/chromium/content/browser/session_history_browsertest.cc
+++ b/chromium/content/browser/session_history_browsertest.cc
@@ -487,23 +487,15 @@ IN_PROC_BROWSER_TEST_F(SessionHistoryScrollAnchorTest,
// http://code.google.com/p/chromium/issues/detail?id=56267
IN_PROC_BROWSER_TEST_F(SessionHistoryTest, HistoryLength) {
- int length;
- ASSERT_TRUE(ExecuteScriptAndExtractInt(
- shell(), "domAutomationController.send(history.length)", &length));
- EXPECT_EQ(1, length);
-
+ EXPECT_EQ(1, EvalJs(shell(), "history.length"));
NavigateToURL(shell(), GetURL("title1.html"));
- ASSERT_TRUE(ExecuteScriptAndExtractInt(
- shell(), "domAutomationController.send(history.length)", &length));
- EXPECT_EQ(2, length);
+ EXPECT_EQ(2, EvalJs(shell(), "history.length"));
// Now test that history.length is updated when the navigation is committed.
NavigateToURL(shell(), GetURL("record_length.html"));
- ASSERT_TRUE(ExecuteScriptAndExtractInt(
- shell(), "domAutomationController.send(history.length)", &length));
- EXPECT_EQ(3, length);
+ EXPECT_EQ(3, EvalJs(shell(), "history.length"));
GoBack();
GoBack();
@@ -511,9 +503,7 @@ IN_PROC_BROWSER_TEST_F(SessionHistoryTest, HistoryLength) {
// Ensure history.length is properly truncated.
NavigateToURL(shell(), GetURL("title2.html"));
- ASSERT_TRUE(ExecuteScriptAndExtractInt(
- shell(), "domAutomationController.send(history.length)", &length));
- EXPECT_EQ(2, length);
+ EXPECT_EQ(2, EvalJs(shell(), "history.length"));
}
// Test that verifies that a cross-process transfer doesn't lose session
@@ -537,8 +527,7 @@ IN_PROC_BROWSER_TEST_F(SessionHistoryTest, GoBackToCrossSitePostWithRedirect) {
// Submit the form.
TestNavigationObserver form_post_observer(shell()->web_contents(), 1);
- EXPECT_TRUE(
- ExecuteScript(shell(), "document.getElementById('text-form').submit();"));
+ EXPECT_TRUE(ExecJs(shell(), "document.getElementById('text-form').submit()"));
form_post_observer.Wait();
// Verify that we arrived at the expected, redirected location.
@@ -547,13 +536,9 @@ IN_PROC_BROWSER_TEST_F(SessionHistoryTest, GoBackToCrossSitePostWithRedirect) {
// Verify that POST body got preserved by 307 redirect. This expectation
// comes from: https://tools.ietf.org/html/rfc7231#section-6.4.7
- std::string body;
- EXPECT_TRUE(ExecuteScriptAndExtractString(
- shell(),
- "window.domAutomationController.send("
- "document.getElementsByTagName('pre')[0].innerText);",
- &body));
- EXPECT_EQ("text=value\n", body);
+ EXPECT_EQ(
+ "text=value\n",
+ EvalJs(shell(), "document.getElementsByTagName('pre')[0].innerText"));
// Navigate to a page from yet another site.
EXPECT_TRUE(NavigateToURL(shell(), page_to_go_back_from));
@@ -568,13 +553,9 @@ IN_PROC_BROWSER_TEST_F(SessionHistoryTest, GoBackToCrossSitePostWithRedirect) {
shell()->web_contents()->GetLastCommittedURL());
// Again verify that POST body got preserved by 307 redirect.
- std::string body_after_back_navigation;
- EXPECT_TRUE(ExecuteScriptAndExtractString(
- shell(),
- "window.domAutomationController.send("
- "document.getElementsByTagName('pre')[0].innerText);",
- &body_after_back_navigation));
- EXPECT_EQ("text=value\n", body_after_back_navigation);
+ EXPECT_EQ(
+ "text=value\n",
+ EvalJs(shell(), "document.getElementsByTagName('pre')[0].innerText"));
}
} // namespace content
diff --git a/chromium/content/browser/shared_worker/mock_shared_worker.cc b/chromium/content/browser/shared_worker/mock_shared_worker.cc
index 829d18dce64..b23879ffa4d 100644
--- a/chromium/content/browser/shared_worker/mock_shared_worker.cc
+++ b/chromium/content/browser/shared_worker/mock_shared_worker.cc
@@ -99,9 +99,11 @@ void MockSharedWorkerFactory::CreateSharedWorker(
bool pause_on_start,
const base::UnguessableToken& devtools_worker_token,
const RendererPreferences& renderer_preferences,
+ mojom::RendererPreferenceWatcherRequest preference_watcher_request,
blink::mojom::WorkerContentSettingsProxyPtr content_settings,
mojom::ServiceWorkerProviderInfoForSharedWorkerPtr
service_worker_provider_info,
+ int appcache_host_id,
network::mojom::URLLoaderFactoryAssociatedPtrInfo
script_loader_factory_ptr_info,
std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loaders,
diff --git a/chromium/content/browser/shared_worker/mock_shared_worker.h b/chromium/content/browser/shared_worker/mock_shared_worker.h
index 7d99113c488..954fbad4b54 100644
--- a/chromium/content/browser/shared_worker/mock_shared_worker.h
+++ b/chromium/content/browser/shared_worker/mock_shared_worker.h
@@ -68,9 +68,11 @@ class MockSharedWorkerFactory : public mojom::SharedWorkerFactory {
bool pause_on_start,
const base::UnguessableToken& devtools_worker_token,
const RendererPreferences& renderer_preferences,
+ mojom::RendererPreferenceWatcherRequest preference_watcher_request,
blink::mojom::WorkerContentSettingsProxyPtr content_settings,
mojom::ServiceWorkerProviderInfoForSharedWorkerPtr
service_worker_provider_info,
+ int appcache_host_id,
network::mojom::URLLoaderFactoryAssociatedPtrInfo
script_loader_factory_ptr_info,
std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loaders,
diff --git a/chromium/content/browser/shared_worker/shared_worker_host.cc b/chromium/content/browser/shared_worker/shared_worker_host.cc
index 407310cc763..a2f6eea00a8 100644
--- a/chromium/content/browser/shared_worker/shared_worker_host.cc
+++ b/chromium/content/browser/shared_worker/shared_worker_host.cc
@@ -9,6 +9,7 @@
#include "base/feature_list.h"
#include "base/metrics/histogram_macros.h"
#include "base/unguessable_token.h"
+#include "content/browser/appcache/appcache_navigation_handle.h"
#include "content/browser/devtools/shared_worker_devtools_manager.h"
#include "content/browser/interface_provider_filtering.h"
#include "content/browser/renderer_interface_binders.h"
@@ -22,8 +23,10 @@
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/content_client.h"
+#include "content/public/common/renderer_preference_watcher.mojom.h"
#include "services/network/public/cpp/features.h"
#include "third_party/blink/public/common/message_port/message_port_channel.h"
+#include "third_party/blink/public/common/service_worker/service_worker_utils.h"
#include "third_party/blink/public/platform/web_feature.mojom.h"
#include "third_party/blink/public/web/worker_content_settings_proxy.mojom.h"
@@ -39,7 +42,7 @@ void AllowFileSystemOnIOThreadResponse(base::OnceCallback<void(bool)> callback,
void AllowFileSystemOnIOThread(const GURL& url,
ResourceContext* resource_context,
- std::vector<std::pair<int, int>> render_frames,
+ std::vector<GlobalFrameRoutingId> render_frames,
base::OnceCallback<void(bool)> callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
GetContentClient()->browser()->AllowWorkerFileSystem(
@@ -50,7 +53,7 @@ void AllowFileSystemOnIOThread(const GURL& url,
bool AllowIndexedDBOnIOThread(const GURL& url,
const base::string16& name,
ResourceContext* resource_context,
- std::vector<std::pair<int, int>> render_frames) {
+ std::vector<GlobalFrameRoutingId> render_frames) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
return GetContentClient()->browser()->AllowWorkerIndexedDB(
url, name, resource_context, render_frames);
@@ -125,8 +128,9 @@ void SharedWorkerHost::Start(
mojom::SharedWorkerFactoryPtr factory,
mojom::ServiceWorkerProviderInfoForSharedWorkerPtr
service_worker_provider_info,
- network::mojom::URLLoaderFactoryAssociatedPtrInfo script_loader_factory,
- std::unique_ptr<URLLoaderFactoryBundleInfo> factory_bundle) {
+ network::mojom::URLLoaderFactoryAssociatedPtrInfo
+ main_script_loader_factory,
+ std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
AdvanceTo(Phase::kStarted);
@@ -146,6 +150,14 @@ void SharedWorkerHost::Start(
RenderProcessHost::FromID(process_id_)->GetBrowserContext(),
&renderer_preferences);
+ // Create a RendererPreferenceWatcher to observe updates in the preferences.
+ mojom::RendererPreferenceWatcherPtr watcher_ptr;
+ mojom::RendererPreferenceWatcherRequest preference_watcher_request =
+ mojo::MakeRequest(&watcher_ptr);
+ GetContentClient()->browser()->RegisterRendererPreferenceWatcherForWorkers(
+ RenderProcessHost::FromID(process_id_)->GetBrowserContext(),
+ std::move(watcher_ptr));
+
// Set up content settings interface.
blink::mojom::WorkerContentSettingsProxyPtr content_settings;
content_settings_ = std::make_unique<SharedWorkerContentSettingsProxyImpl>(
@@ -161,37 +173,43 @@ void SharedWorkerHost::Start(
mojom::kNavigation_SharedWorkerSpec, process_id_,
mojo::MakeRequest(&interface_provider)));
- // Add the network factory to the bundle to pass to the renderer. The bundle
- // is only provided (along with |script_loader_factory|) if
- // NetworkService/S13nSW is enabled.
- DCHECK(!script_loader_factory || factory_bundle);
- if (factory_bundle) {
- network::mojom::URLLoaderFactoryPtrInfo network_factory_info;
+ // Add the default factory to the bundle for subresource loading to pass to
+ // the renderer. The bundle is only provided if
+ // NetworkService/S13nServiceWorker is enabled.
+ // TODO(nhiroki): We might need to set the default factory to AppCache
+ // instead, as we do for frames, if requests from this shared worker are
+ // supposed to go through AppCache. Currently, we set the default factory to a
+ // direct network.
+ if (blink::ServiceWorkerUtils::IsServicificationEnabled()) {
+ DCHECK(subresource_loader_factories);
+ DCHECK(!subresource_loader_factories->default_factory_info());
if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
- // NetworkService is on: Use the network service.
+ network::mojom::URLLoaderFactoryPtrInfo network_factory_info;
CreateNetworkFactory(mojo::MakeRequest(&network_factory_info));
+ subresource_loader_factories->default_factory_info() =
+ std::move(network_factory_info);
} else {
- // NetworkService is off: RenderProcessHost gives us a non-NetworkService
- // network factory.
+ // Use the non-NetworkService network factory for the process when
+ // NetworkService is off.
+ network::mojom::URLLoaderFactoryPtr default_factory;
RenderProcessHost::FromID(process_id_)
- ->CreateURLLoaderFactory(mojo::MakeRequest(&network_factory_info));
+ ->CreateURLLoaderFactory(mojo::MakeRequest(&default_factory));
+ subresource_loader_factories->default_factory_info() =
+ default_factory.PassInterface();
}
- DCHECK(!factory_bundle->default_factory_info());
- factory_bundle->default_factory_info() = std::move(network_factory_info);
-
- // TODO(falken): We might need to set the default factory to AppCache
- // instead, as we do for frames, if requests from this shared worker are
- // supposed to go through AppCache.
}
// Send the CreateSharedWorker message.
factory_ = std::move(factory);
factory_->CreateSharedWorker(
std::move(info), pause_on_start, devtools_worker_token,
- renderer_preferences, std::move(content_settings),
- std::move(service_worker_provider_info), std::move(script_loader_factory),
- std::move(factory_bundle), std::move(host), std::move(worker_request_),
- std::move(interface_provider));
+ renderer_preferences, std::move(preference_watcher_request),
+ std::move(content_settings), std::move(service_worker_provider_info),
+ appcache_handle_ ? appcache_handle_->appcache_host_id()
+ : kAppCacheNoHostId,
+ std::move(main_script_loader_factory),
+ std::move(subresource_loader_factories), std::move(host),
+ std::move(worker_request_), std::move(interface_provider));
// Monitor the lifetime of the worker.
worker_.set_connection_error_handler(base::BindOnce(
@@ -366,11 +384,12 @@ void SharedWorkerHost::OnFeatureUsed(blink::mojom::WebFeature feature) {
info.client->OnFeatureUsed(feature);
}
-std::vector<std::pair<int, int>>
+std::vector<GlobalFrameRoutingId>
SharedWorkerHost::GetRenderFrameIDsForWorker() {
- std::vector<std::pair<int, int>> result;
+ std::vector<GlobalFrameRoutingId> result;
+ result.reserve(clients_.size());
for (const ClientInfo& info : clients_)
- result.push_back(std::make_pair(info.process_id, info.frame_id));
+ result.push_back(GlobalFrameRoutingId(info.process_id, info.frame_id));
return result;
}
@@ -416,6 +435,12 @@ void SharedWorkerHost::BindDevToolsAgent(
worker_->BindDevToolsAgent(std::move(request));
}
+void SharedWorkerHost::SetAppCacheHandle(
+ std::unique_ptr<AppCacheNavigationHandle> appcache_handle) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ appcache_handle_ = std::move(appcache_handle);
+}
+
void SharedWorkerHost::OnClientConnectionLost() {
// We'll get a notification for each dropped connection.
for (auto it = clients_.begin(); it != clients_.end(); ++it) {
diff --git a/chromium/content/browser/shared_worker/shared_worker_host.h b/chromium/content/browser/shared_worker/shared_worker_host.h
index 95f9f2c26fd..c75d9920a90 100644
--- a/chromium/content/browser/shared_worker/shared_worker_host.h
+++ b/chromium/content/browser/shared_worker/shared_worker_host.h
@@ -21,6 +21,7 @@
#include "content/common/shared_worker/shared_worker_client.mojom.h"
#include "content/common/shared_worker/shared_worker_factory.mojom.h"
#include "content/common/shared_worker/shared_worker_host.mojom.h"
+#include "content/public/browser/global_routing_id.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "services/service_manager/public/mojom/interface_provider.mojom.h"
@@ -33,6 +34,8 @@ class MessagePortChannel;
}
namespace content {
+
+class AppCacheNavigationHandle;
class SharedWorkerContentSettingsProxyImpl;
class SharedWorkerInstance;
class SharedWorkerServiceImpl;
@@ -59,16 +62,24 @@ class CONTENT_EXPORT SharedWorkerHost
// supporting the shared worker as a service worker client.
//
// S13nServiceWorker:
- // |script_loader_factory| is sent to the renderer process and is to be used
- // to request the shared worker's script. Currently it's only non-null when
- // S13nServiceWorker is enabled, to allow service worker machinery to observe
- // the request, but other web platform features may also use it someday.
+ // |main_script_loader_factory| is sent to the renderer process and is to be
+ // used to request the shared worker's main script. Currently it's only
+ // non-null when S13nServiceWorker is enabled, to allow service worker
+ // machinery to observe the request, but other web platform features may also
+ // use it someday.
+ //
+ // NetworkService:
+ // |subresource_loader_factories| is sent to the renderer process and is to be
+ // used to request subresources where applicable. For example, this allows the
+ // shared worker to load chrome-extension:// URLs which the renderer's default
+ // loader factory can't load.
void Start(
mojom::SharedWorkerFactoryPtr factory,
mojom::ServiceWorkerProviderInfoForSharedWorkerPtr
service_worker_provider_info,
- network::mojom::URLLoaderFactoryAssociatedPtrInfo script_loader_factory,
- std::unique_ptr<URLLoaderFactoryBundleInfo> factory_bundle);
+ network::mojom::URLLoaderFactoryAssociatedPtrInfo
+ main_script_loader_factory,
+ std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories);
void AllowFileSystem(const GURL& url,
base::OnceCallback<void(bool)> callback);
@@ -86,6 +97,9 @@ class CONTENT_EXPORT SharedWorkerHost
void BindDevToolsAgent(blink::mojom::DevToolsAgentAssociatedRequest request);
+ void SetAppCacheHandle(
+ std::unique_ptr<AppCacheNavigationHandle> appcache_handle);
+
SharedWorkerInstance* instance() { return instance_.get(); }
int process_id() const { return process_id_; }
bool IsAvailable() const;
@@ -127,8 +141,8 @@ class CONTENT_EXPORT SharedWorkerHost
void OnScriptLoadFailed() override;
void OnFeatureUsed(blink::mojom::WebFeature feature) override;
- // Return a vector of all the render process/render frame IDs.
- std::vector<std::pair<int, int>> GetRenderFrameIDsForWorker();
+ // Returns the frame ids of this worker's clients.
+ std::vector<GlobalFrameRoutingId> GetRenderFrameIDsForWorker();
void AllowFileSystemResponse(base::OnceCallback<void(bool)> callback,
bool allowed);
@@ -172,6 +186,11 @@ class CONTENT_EXPORT SharedWorkerHost
mojo::Binding<service_manager::mojom::InterfaceProvider>
interface_provider_binding_;
+ // NetworkService:
+ // The handle owns the precreated AppCacheHost until it's claimed by the
+ // renderer after main script loading finishes.
+ std::unique_ptr<AppCacheNavigationHandle> appcache_handle_;
+
Phase phase_ = Phase::kInitial;
base::WeakPtrFactory<SharedWorkerHost> weak_factory_;
diff --git a/chromium/content/browser/shared_worker/shared_worker_host_unittest.cc b/chromium/content/browser/shared_worker/shared_worker_host_unittest.cc
index f90a0342ef7..c5043d87b0f 100644
--- a/chromium/content/browser/shared_worker/shared_worker_host_unittest.cc
+++ b/chromium/content/browser/shared_worker/shared_worker_host_unittest.cc
@@ -10,6 +10,7 @@
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
+#include "content/browser/appcache/chrome_appcache_service.h"
#include "content/browser/shared_worker/mock_shared_worker.h"
#include "content/browser/shared_worker/shared_worker_connector_impl.h"
#include "content/browser/shared_worker/shared_worker_instance.h"
@@ -34,7 +35,9 @@ class SharedWorkerHostTest : public testing::Test {
public:
SharedWorkerHostTest()
: mock_render_process_host_(&browser_context_),
- service_(&storage_partition_, nullptr /* service_worker_context */) {
+ service_(&storage_partition_,
+ nullptr /* service_worker_context */,
+ nullptr /* appcache_service */) {
storage_partition_.set_network_context(&network_context_);
}
@@ -64,8 +67,8 @@ class SharedWorkerHostTest : public testing::Test {
void StartWorker(SharedWorkerHost* host,
mojom::SharedWorkerFactoryPtr factory) {
host->Start(std::move(factory), nullptr /* service_worker_provider_info */,
- {} /* script_loader_factory_info */,
- nullptr /* factory_bundle */);
+ {} /* main_script_loader_factory */,
+ nullptr /* subresource_loader_factories */);
}
MessagePortChannel AddClient(SharedWorkerHost* host,
@@ -195,8 +198,8 @@ TEST_F(SharedWorkerHostTest, TerminateAfterStarting) {
// Start the worker.
host->Start(std::move(factory), nullptr /* service_worker_provider_info */,
- {} /* script_loader_factory_info */,
- nullptr /* factory_bundle */);
+ {} /* main_script_loader_factory */,
+ nullptr /* subresource_loader_factories */);
// Add a client.
MockSharedWorkerClient client;
diff --git a/chromium/content/browser/shared_worker/shared_worker_script_loader.cc b/chromium/content/browser/shared_worker/shared_worker_script_loader.cc
index 81fb3763c49..0ded2f6fabd 100644
--- a/chromium/content/browser/shared_worker/shared_worker_script_loader.cc
+++ b/chromium/content/browser/shared_worker/shared_worker_script_loader.cc
@@ -4,7 +4,9 @@
#include "content/browser/shared_worker/shared_worker_script_loader.h"
+#include "content/browser/appcache/appcache_request_handler.h"
#include "content/browser/loader/navigation_loader_interceptor.h"
+#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/service_worker/service_worker_provider_host.h"
#include "content/public/browser/resource_context.h"
#include "net/url_request/redirect_util.h"
@@ -14,16 +16,19 @@
namespace content {
SharedWorkerScriptLoader::SharedWorkerScriptLoader(
+ int process_id,
int32_t routing_id,
int32_t request_id,
uint32_t options,
const network::ResourceRequest& resource_request,
network::mojom::URLLoaderClientPtr client,
base::WeakPtr<ServiceWorkerProviderHost> service_worker_provider_host,
+ base::WeakPtr<AppCacheHost> appcache_host,
ResourceContext* resource_context,
scoped_refptr<network::SharedURLLoaderFactory> default_loader_factory,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation)
- : routing_id_(routing_id),
+ : process_id_(process_id),
+ routing_id_(routing_id),
request_id_(request_id),
options_(options),
resource_request_(resource_request),
@@ -37,9 +42,19 @@ SharedWorkerScriptLoader::SharedWorkerScriptLoader(
DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled());
if (service_worker_provider_host_) {
- service_worker_interceptor_ =
+ std::unique_ptr<NavigationLoaderInterceptor> service_worker_interceptor =
ServiceWorkerRequestHandler::InitializeForSharedWorker(
resource_request_, service_worker_provider_host_);
+ if (service_worker_interceptor)
+ interceptors_.push_back(std::move(service_worker_interceptor));
+ }
+
+ if (appcache_host) {
+ std::unique_ptr<NavigationLoaderInterceptor> appcache_interceptor =
+ AppCacheRequestHandler::InitializeForMainResourceNetworkService(
+ resource_request_, appcache_host, default_loader_factory_);
+ if (appcache_interceptor)
+ interceptors_.push_back(std::move(appcache_interceptor));
}
Start();
@@ -48,21 +63,33 @@ SharedWorkerScriptLoader::SharedWorkerScriptLoader(
SharedWorkerScriptLoader::~SharedWorkerScriptLoader() = default;
void SharedWorkerScriptLoader::Start() {
- if (service_worker_interceptor_) {
- service_worker_interceptor_->MaybeCreateLoader(
+ if (interceptor_index_ < interceptors_.size()) {
+ auto* interceptor = interceptors_[interceptor_index_++].get();
+ interceptor->MaybeCreateLoader(
resource_request_, resource_context_,
base::BindOnce(&SharedWorkerScriptLoader::MaybeStartLoader,
- weak_factory_.GetWeakPtr(),
- service_worker_interceptor_.get()));
+ weak_factory_.GetWeakPtr(), interceptor),
+ base::BindOnce(&SharedWorkerScriptLoader::LoadFromNetwork,
+ weak_factory_.GetWeakPtr()));
return;
}
- LoadFromNetwork();
+ LoadFromNetwork(false);
}
void SharedWorkerScriptLoader::MaybeStartLoader(
NavigationLoaderInterceptor* interceptor,
SingleRequestURLLoaderFactory::RequestHandler single_request_handler) {
+ DCHECK(interceptor);
+
+ // TODO(nhiroki): Create SubresourceLoaderParams for intercepting subresource
+ // requests and populating the "controller" field in ServiceWorkerContainer,
+ // and send the params to the renderer when we create the SharedWorker.
+ // Note that we shouldn't try the next interceptor if this interceptor
+ // provides SubresourceLoaderParams. See comments on
+ // NavigationLoaderInterceptor::MaybeCreateSubresourceLoaderParams() for
+ // details.
+
if (single_request_handler) {
// The interceptor elected to handle the request. Use it.
network::mojom::URLLoaderClientPtr client;
@@ -76,11 +103,15 @@ void SharedWorkerScriptLoader::MaybeStartLoader(
return;
}
- LoadFromNetwork();
+ // Continue until all the interceptors are tried.
+ Start();
}
-void SharedWorkerScriptLoader::LoadFromNetwork() {
+void SharedWorkerScriptLoader::LoadFromNetwork(
+ bool reset_subresource_loader_params) {
network::mojom::URLLoaderClientPtr client;
+ if (url_loader_client_binding_)
+ url_loader_client_binding_.Unbind();
url_loader_client_binding_.Bind(mojo::MakeRequest(&client));
url_loader_factory_ = default_loader_factory_;
url_loader_factory_->CreateLoaderAndStart(
@@ -117,8 +148,15 @@ void SharedWorkerScriptLoader::FollowRedirect(
resource_request_.referrer_policy = redirect_info_->new_referrer_policy;
// Restart the request.
+ interceptor_index_ = 0;
url_loader_client_binding_.Unbind();
redirect_info_.reset();
+
+ // Cancel the request on ResourceDispatcherHost so that we can fall back
+ // to network again.
+ DCHECK(ResourceDispatcherHostImpl::Get());
+ ResourceDispatcherHostImpl::Get()->CancelRequest(process_id_, request_id_);
+
Start();
}
diff --git a/chromium/content/browser/shared_worker/shared_worker_script_loader.h b/chromium/content/browser/shared_worker/shared_worker_script_loader.h
index e7eb646e6a3..e8a876e5ca7 100644
--- a/chromium/content/browser/shared_worker/shared_worker_script_loader.h
+++ b/chromium/content/browser/shared_worker/shared_worker_script_loader.h
@@ -17,6 +17,8 @@ class SharedURLLoaderFactory;
} // namespace network
namespace content {
+
+class AppCacheHost;
class NavigationLoaderInterceptor;
class ResourceContext;
class ServiceWorkerProviderHost;
@@ -41,12 +43,14 @@ class SharedWorkerScriptLoader : public network::mojom::URLLoader,
// non-NetworkService factories used for non-http(s) URLs, e.g., a
// chrome-extension:// URL.
SharedWorkerScriptLoader(
+ int process_id,
int32_t routing_id,
int32_t request_id,
uint32_t options,
const network::ResourceRequest& resource_request,
network::mojom::URLLoaderClientPtr client,
base::WeakPtr<ServiceWorkerProviderHost> service_worker_provider_host,
+ base::WeakPtr<AppCacheHost> appcache_host,
ResourceContext* resource_context,
scoped_refptr<network::SharedURLLoaderFactory> default_loader_factory,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation);
@@ -83,11 +87,14 @@ class SharedWorkerScriptLoader : public network::mojom::URLLoader,
void MaybeStartLoader(
NavigationLoaderInterceptor* interceptor,
SingleRequestURLLoaderFactory::RequestHandler single_request_handler);
- void LoadFromNetwork();
+ void LoadFromNetwork(bool reset_subresource_loader_params);
- // TODO(falken): Add other interceptors like in NavigationURLLoaderImpl.
- std::unique_ptr<NavigationLoaderInterceptor> service_worker_interceptor_;
+ // The order of the interceptors is important. The former interceptor can
+ // preferentially get a chance to intercept a network request.
+ std::vector<std::unique_ptr<NavigationLoaderInterceptor>> interceptors_;
+ size_t interceptor_index_ = 0;
+ const int process_id_;
const int32_t routing_id_;
const int32_t request_id_;
const uint32_t options_;
diff --git a/chromium/content/browser/shared_worker/shared_worker_script_loader_factory.cc b/chromium/content/browser/shared_worker/shared_worker_script_loader_factory.cc
index 6a21c378c48..74eaef69a4b 100644
--- a/chromium/content/browser/shared_worker/shared_worker_script_loader_factory.cc
+++ b/chromium/content/browser/shared_worker/shared_worker_script_loader_factory.cc
@@ -10,6 +10,7 @@
#include "content/browser/service_worker/service_worker_provider_host.h"
#include "content/browser/service_worker/service_worker_version.h"
#include "content/browser/shared_worker/shared_worker_script_loader.h"
+#include "content/public/browser/browser_thread.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "services/network/public/cpp/resource_response.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
@@ -19,19 +20,26 @@
namespace content {
SharedWorkerScriptLoaderFactory::SharedWorkerScriptLoaderFactory(
+ int process_id,
ServiceWorkerContextWrapper* context,
base::WeakPtr<ServiceWorkerProviderHost> service_worker_provider_host,
+ base::WeakPtr<AppCacheHost> appcache_host,
ResourceContext* resource_context,
scoped_refptr<network::SharedURLLoaderFactory> loader_factory)
- : service_worker_provider_host_(service_worker_provider_host),
+ : process_id_(process_id),
+ service_worker_provider_host_(std::move(service_worker_provider_host)),
+ appcache_host_(std::move(appcache_host)),
resource_context_(resource_context),
loader_factory_(std::move(loader_factory)) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled());
DCHECK_EQ(service_worker_provider_host_->provider_type(),
blink::mojom::ServiceWorkerProviderType::kForSharedWorker);
}
-SharedWorkerScriptLoaderFactory::~SharedWorkerScriptLoaderFactory() {}
+SharedWorkerScriptLoaderFactory::~SharedWorkerScriptLoaderFactory() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+}
void SharedWorkerScriptLoaderFactory::CreateLoaderAndStart(
network::mojom::URLLoaderRequest request,
@@ -41,6 +49,8 @@ void SharedWorkerScriptLoaderFactory::CreateLoaderAndStart(
const network::ResourceRequest& resource_request,
network::mojom::URLLoaderClientPtr client,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
// Handle only the main script (RESOURCE_TYPE_SHARED_WORKER). Import scripts
// should go to the network loader or controller.
if (resource_request.resource_type != RESOURCE_TYPE_SHARED_WORKER) {
@@ -53,9 +63,9 @@ void SharedWorkerScriptLoaderFactory::CreateLoaderAndStart(
// Create a SharedWorkerScriptLoader to load the script.
mojo::MakeStrongBinding(
std::make_unique<SharedWorkerScriptLoader>(
- routing_id, request_id, options, resource_request, std::move(client),
- service_worker_provider_host_, resource_context_, loader_factory_,
- traffic_annotation),
+ process_id_, routing_id, request_id, options, resource_request,
+ std::move(client), service_worker_provider_host_, appcache_host_,
+ resource_context_, loader_factory_, traffic_annotation),
std::move(request));
}
diff --git a/chromium/content/browser/shared_worker/shared_worker_script_loader_factory.h b/chromium/content/browser/shared_worker/shared_worker_script_loader_factory.h
index 2e42cfaafa6..f54949bad5b 100644
--- a/chromium/content/browser/shared_worker/shared_worker_script_loader_factory.h
+++ b/chromium/content/browser/shared_worker/shared_worker_script_loader_factory.h
@@ -14,6 +14,7 @@ class SharedURLLoaderFactory;
namespace content {
+class AppCacheHost;
class ServiceWorkerContextWrapper;
class ServiceWorkerProviderHost;
class ResourceContext;
@@ -36,8 +37,10 @@ class SharedWorkerScriptLoaderFactory
// the NetworkService. However, it may internally contain non-NetworkService
// factories used for non-http(s) URLs, e.g., a chrome-extension:// URL.
SharedWorkerScriptLoaderFactory(
+ int process_id,
ServiceWorkerContextWrapper* context,
base::WeakPtr<ServiceWorkerProviderHost> provider_host,
+ base::WeakPtr<AppCacheHost> appcache_host,
ResourceContext* resource_context,
scoped_refptr<network::SharedURLLoaderFactory> loader_factory);
~SharedWorkerScriptLoaderFactory() override;
@@ -54,7 +57,9 @@ class SharedWorkerScriptLoaderFactory
void Clone(network::mojom::URLLoaderFactoryRequest request) override;
private:
+ const int process_id_;
base::WeakPtr<ServiceWorkerProviderHost> service_worker_provider_host_;
+ base::WeakPtr<AppCacheHost> appcache_host_;
ResourceContext* resource_context_ = nullptr;
scoped_refptr<network::SharedURLLoaderFactory> loader_factory_;
diff --git a/chromium/content/browser/shared_worker/shared_worker_service_impl.cc b/chromium/content/browser/shared_worker/shared_worker_service_impl.cc
index 0727104684b..51f91bdd7e2 100644
--- a/chromium/content/browser/shared_worker/shared_worker_service_impl.cc
+++ b/chromium/content/browser/shared_worker/shared_worker_service_impl.cc
@@ -10,9 +10,12 @@
#include <iterator>
#include "base/callback.h"
+#include "base/feature_list.h"
#include "base/logging.h"
#include "base/macros.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
+#include "content/browser/appcache/appcache_navigation_handle.h"
+#include "content/browser/appcache/appcache_navigation_handle_core.h"
#include "content/browser/file_url_loader_factory.h"
#include "content/browser/shared_worker/shared_worker_host.h"
#include "content/browser/shared_worker/shared_worker_instance.h"
@@ -30,6 +33,7 @@
#include "content/public/common/bind_interface_helpers.h"
#include "mojo/public/cpp/bindings/strong_associated_binding.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "services/network/public/cpp/features.h"
#include "third_party/blink/public/common/message_port/message_port_channel.h"
#include "third_party/blink/public/common/service_worker/service_worker_utils.h"
#include "url/origin.h"
@@ -71,7 +75,7 @@ std::unique_ptr<URLLoaderFactoryBundleInfo> CreateFactoryBundle(
auto file_factory = std::make_unique<FileURLLoaderFactory>(
storage_partition->browser_context()->GetPath(),
base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BACKGROUND,
+ {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}));
network::mojom::URLLoaderFactoryPtr file_factory_ptr;
mojo::MakeStrongBinding(std::move(file_factory),
@@ -79,15 +83,16 @@ std::unique_ptr<URLLoaderFactoryBundleInfo> CreateFactoryBundle(
factory_bundle->factories_info().emplace(url::kFileScheme,
file_factory_ptr.PassInterface());
}
+
return factory_bundle;
}
void CreateScriptLoaderOnIO(
scoped_refptr<URLLoaderFactoryGetter> loader_factory_getter,
std::unique_ptr<URLLoaderFactoryBundleInfo> factory_bundle_for_browser_info,
- std::unique_ptr<URLLoaderFactoryBundleInfo>
- factory_bundle_for_renderer_info,
+ std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories,
scoped_refptr<ServiceWorkerContextWrapper> context,
+ AppCacheNavigationHandleCore* appcache_handle_core,
std::unique_ptr<network::SharedURLLoaderFactoryInfo>
blob_url_loader_factory_info,
int process_id,
@@ -111,48 +116,67 @@ void CreateScriptLoaderOnIO(
url_loader_factory = network::SharedURLLoaderFactory::Create(
std::move(blob_url_loader_factory_info));
} else {
+ // Add the default factory to the bundle for browser.
+ DCHECK(!factory_bundle_for_browser_info->default_factory_info());
+
// Create a factory bundle to use.
scoped_refptr<URLLoaderFactoryBundle> factory_bundle =
base::MakeRefCounted<URLLoaderFactoryBundle>(
std::move(factory_bundle_for_browser_info));
- url_loader_factory = factory_bundle;
- // Add the network factory to the bundle. The factory from
- // CloneNetworkFactory() doesn't support reconnection to the network service
- // after a crash, but it's OK since it's used for a single shared worker
- // startup.
+ // Get the direct network factory from |loader_factory_getter|. When
+ // NetworkService is enabled, it returns a factory that doesn't support
+ // reconnection to the network service after a crash, but it's OK since it's
+ // used for a single shared worker startup.
network::mojom::URLLoaderFactoryPtr network_factory_ptr;
loader_factory_getter->CloneNetworkFactory(
mojo::MakeRequest(&network_factory_ptr));
factory_bundle->SetDefaultFactory(std::move(network_factory_ptr));
+
+ url_loader_factory = factory_bundle;
}
+ // It's safe for |appcache_handle_core| to be a raw pointer. The core is owned
+ // by AppCacheNavigationHandle on the UI thread, which posts a task to delete
+ // the core on the IO thread on destruction, which must happen after this
+ // task.
+ base::WeakPtr<AppCacheHost> appcache_host =
+ appcache_handle_core ? appcache_handle_core->host()->GetWeakPtr()
+ : nullptr;
+
// Create the SharedWorkerScriptLoaderFactory.
- network::mojom::URLLoaderFactoryAssociatedPtrInfo script_loader_factory;
+ network::mojom::URLLoaderFactoryAssociatedPtrInfo main_script_loader_factory;
mojo::MakeStrongAssociatedBinding(
std::make_unique<SharedWorkerScriptLoaderFactory>(
- context.get(), host->AsWeakPtr(), context->resource_context(),
+ process_id, context.get(), host->AsWeakPtr(),
+ std::move(appcache_host), context->resource_context(),
std::move(url_loader_factory)),
- mojo::MakeRequest(&script_loader_factory));
+ mojo::MakeRequest(&main_script_loader_factory));
// We continue in StartWorker.
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::BindOnce(std::move(callback), std::move(provider_info),
- std::move(script_loader_factory),
- std::move(factory_bundle_for_renderer_info)));
+ std::move(main_script_loader_factory),
+ std::move(subresource_loader_factories)));
}
} // namespace
SharedWorkerServiceImpl::SharedWorkerServiceImpl(
StoragePartition* storage_partition,
- scoped_refptr<ServiceWorkerContextWrapper> service_worker_context)
+ scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
+ scoped_refptr<ChromeAppCacheService> appcache_service)
: storage_partition_(storage_partition),
service_worker_context_(std::move(service_worker_context)),
- weak_factory_(this) {}
+ appcache_service_(std::move(appcache_service)),
+ weak_factory_(this) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+}
-SharedWorkerServiceImpl::~SharedWorkerServiceImpl() {}
+SharedWorkerServiceImpl::~SharedWorkerServiceImpl() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+}
bool SharedWorkerServiceImpl::TerminateWorker(
const GURL& url,
@@ -285,11 +309,11 @@ void SharedWorkerServiceImpl::CreateWorker(
auto weak_host = host->AsWeakPtr();
worker_hosts_.insert(std::move(host));
- StoragePartitionImpl* storage_partition =
- service_worker_context_->storage_partition();
- // Bounce to the IO thread to setup service worker support in case the request
- // for the worker script will need to be intercepted by service workers.
+ // Bounce to the IO thread to setup service worker and appcache support in
+ // case the request for the worker script will need to be intercepted by them.
if (blink::ServiceWorkerUtils::IsServicificationEnabled()) {
+ StoragePartitionImpl* storage_partition =
+ service_worker_context_->storage_partition();
if (!storage_partition) {
// The context is shutting down. Just drop the request.
return;
@@ -297,14 +321,25 @@ void SharedWorkerServiceImpl::CreateWorker(
// Set up the factory bundle for non-NetworkService URLs, e.g.,
// chrome-extension:// URLs. One factory bundle is consumed by the browser
- // for SharedWorkerScriptLoaderFactory, and one is sent to the renderer.
+ // for SharedWorkerScriptLoaderFactory, and one is sent to the renderer for
+ // subresource loading.
std::unique_ptr<URLLoaderFactoryBundleInfo> factory_bundle_for_browser =
CreateFactoryBundle(process_id, storage_partition,
constructor_uses_file_url);
- std::unique_ptr<URLLoaderFactoryBundleInfo> factory_bundle_for_renderer =
+ std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories =
CreateFactoryBundle(process_id, storage_partition,
constructor_uses_file_url);
+ // An appcache interceptor is available only when the network service is
+ // enabled.
+ AppCacheNavigationHandleCore* appcache_handle_core = nullptr;
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ auto appcache_handle =
+ std::make_unique<AppCacheNavigationHandle>(appcache_service_.get());
+ appcache_handle_core = appcache_handle->core();
+ weak_host->SetAppCacheHandle(std::move(appcache_handle));
+ }
+
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(
@@ -312,7 +347,8 @@ void SharedWorkerServiceImpl::CreateWorker(
service_worker_context_->storage_partition()
->url_loader_factory_getter(),
std::move(factory_bundle_for_browser),
- std::move(factory_bundle_for_renderer), service_worker_context_,
+ std::move(subresource_loader_factories), service_worker_context_,
+ appcache_handle_core,
blob_url_loader_factory ? blob_url_loader_factory->Clone()
: nullptr,
process_id,
@@ -337,8 +373,8 @@ void SharedWorkerServiceImpl::StartWorker(
mojom::ServiceWorkerProviderInfoForSharedWorkerPtr
service_worker_provider_info,
network::mojom::URLLoaderFactoryAssociatedPtrInfo
- script_loader_factory_info,
- std::unique_ptr<URLLoaderFactoryBundleInfo> factory_bundle) {
+ main_script_loader_factory,
+ std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
// The host may already be gone if something forcibly terminated the worker
@@ -365,7 +401,8 @@ void SharedWorkerServiceImpl::StartWorker(
BindInterface(process_host, &factory);
host->Start(std::move(factory), std::move(service_worker_provider_info),
- std::move(script_loader_factory_info), std::move(factory_bundle));
+ std::move(main_script_loader_factory),
+ std::move(subresource_loader_factories));
host->AddClient(std::move(client), process_id, frame_id, message_port);
}
diff --git a/chromium/content/browser/shared_worker/shared_worker_service_impl.h b/chromium/content/browser/shared_worker/shared_worker_service_impl.h
index 46810fa5d75..219003f234e 100644
--- a/chromium/content/browser/shared_worker/shared_worker_service_impl.h
+++ b/chromium/content/browser/shared_worker/shared_worker_service_impl.h
@@ -27,6 +27,8 @@ class MessagePortChannel;
}
namespace content {
+
+class ChromeAppCacheService;
class SharedWorkerInstance;
class SharedWorkerHost;
class StoragePartition;
@@ -36,7 +38,8 @@ class CONTENT_EXPORT SharedWorkerServiceImpl : public SharedWorkerService {
public:
SharedWorkerServiceImpl(
StoragePartition* storage_partition,
- scoped_refptr<ServiceWorkerContextWrapper> service_worker_context);
+ scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
+ scoped_refptr<ChromeAppCacheService> appcache_service);
~SharedWorkerServiceImpl() override;
// SharedWorkerService implementation.
@@ -71,17 +74,18 @@ class CONTENT_EXPORT SharedWorkerServiceImpl : public SharedWorkerService {
int frame_id,
const blink::MessagePortChannel& message_port,
scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory);
- void StartWorker(std::unique_ptr<SharedWorkerInstance> instance,
- base::WeakPtr<SharedWorkerHost> host,
- mojom::SharedWorkerClientPtr client,
- int process_id,
- int frame_id,
- const blink::MessagePortChannel& message_port,
- mojom::ServiceWorkerProviderInfoForSharedWorkerPtr
- service_worker_provider_info,
- network::mojom::URLLoaderFactoryAssociatedPtrInfo
- script_loader_factory_info,
- std::unique_ptr<URLLoaderFactoryBundleInfo> factory_bundle);
+ void StartWorker(
+ std::unique_ptr<SharedWorkerInstance> instance,
+ base::WeakPtr<SharedWorkerHost> host,
+ mojom::SharedWorkerClientPtr client,
+ int process_id,
+ int frame_id,
+ const blink::MessagePortChannel& message_port,
+ mojom::ServiceWorkerProviderInfoForSharedWorkerPtr
+ service_worker_provider_info,
+ network::mojom::URLLoaderFactoryAssociatedPtrInfo
+ main_script_loader_factory,
+ std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories);
// Returns nullptr if there is no such host.
SharedWorkerHost* FindSharedWorkerHost(int process_id, int route_id);
@@ -95,6 +99,7 @@ class CONTENT_EXPORT SharedWorkerServiceImpl : public SharedWorkerService {
// |storage_partition_| owns |this|.
StoragePartition* const storage_partition_;
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_;
+ scoped_refptr<ChromeAppCacheService> appcache_service_;
base::WeakPtrFactory<SharedWorkerServiceImpl> weak_factory_;
diff --git a/chromium/content/browser/shared_worker/shared_worker_service_impl_unittest.cc b/chromium/content/browser/shared_worker/shared_worker_service_impl_unittest.cc
index cf56ef37546..e5d67bd381d 100644
--- a/chromium/content/browser/shared_worker/shared_worker_service_impl_unittest.cc
+++ b/chromium/content/browser/shared_worker/shared_worker_service_impl_unittest.cc
@@ -21,6 +21,7 @@
#include "content/test/test_render_view_host.h"
#include "content/test/test_web_contents.h"
#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 "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/message_port/message_port_channel.h"
@@ -29,6 +30,42 @@ using blink::MessagePortChannel;
namespace content {
+namespace {
+
+// A mock URLLoaderFactory which just fails to create a loader. This is
+// sufficient because the tests don't exercise script loading. Used when
+// S13nServiceWorker is enabled.
+class NotImplementedNetworkURLLoaderFactory final
+ : public network::mojom::URLLoaderFactory {
+ public:
+ NotImplementedNetworkURLLoaderFactory() = 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 {
+ network::URLLoaderCompletionStatus status;
+ status.error_code = net::ERR_NOT_IMPLEMENTED;
+ 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(NotImplementedNetworkURLLoaderFactory);
+};
+
+} // namespace
+
class SharedWorkerServiceImplTest : public RenderViewHostImplTestHarness {
public:
mojom::SharedWorkerConnectorPtr MakeSharedWorkerConnector(
@@ -75,6 +112,8 @@ 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>();
}
void TearDown() override {
@@ -86,6 +125,7 @@ class SharedWorkerServiceImplTest : public RenderViewHostImplTestHarness {
static std::queue<mojom::SharedWorkerFactoryRequest>
s_factory_request_received_;
std::unique_ptr<MockRenderProcessHostFactory> render_process_host_factory_;
+ std::unique_ptr<NotImplementedNetworkURLLoaderFactory> url_loader_factory_;
private:
DISALLOW_COPY_AND_ASSIGN(SharedWorkerServiceImplTest);
@@ -127,6 +167,7 @@ TEST_F(SharedWorkerServiceImplTest, BasicTest) {
renderer_host->OverrideBinderForTesting(
mojom::SharedWorkerFactory::Name_,
base::Bind(&SharedWorkerServiceImplTest::BindSharedWorkerFactory));
+ renderer_host->OverrideURLLoaderFactory(url_loader_factory_.get());
MockSharedWorkerClient client;
MessagePortChannel local_port;
@@ -202,6 +243,7 @@ TEST_F(SharedWorkerServiceImplTest, TwoRendererTest) {
renderer_host0->OverrideBinderForTesting(
mojom::SharedWorkerFactory::Name_,
base::Bind(&SharedWorkerServiceImplTest::BindSharedWorkerFactory));
+ renderer_host0->OverrideURLLoaderFactory(url_loader_factory_.get());
MockSharedWorkerClient client0;
MessagePortChannel local_port0;
@@ -270,6 +312,7 @@ TEST_F(SharedWorkerServiceImplTest, TwoRendererTest) {
renderer_host1->OverrideBinderForTesting(
mojom::SharedWorkerFactory::Name_,
base::Bind(&SharedWorkerServiceImplTest::BindSharedWorkerFactory));
+ renderer_host1->OverrideURLLoaderFactory(url_loader_factory_.get());
MockSharedWorkerClient client1;
MessagePortChannel local_port1;
@@ -331,6 +374,7 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest_NormalCase) {
renderer_host0->OverrideBinderForTesting(
mojom::SharedWorkerFactory::Name_,
base::Bind(&SharedWorkerServiceImplTest::BindSharedWorkerFactory));
+ renderer_host0->OverrideURLLoaderFactory(url_loader_factory_.get());
// The second renderer host.
std::unique_ptr<TestWebContents> web_contents1 =
@@ -402,6 +446,7 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest_NormalCase_URLMismatch) {
renderer_host0->OverrideBinderForTesting(
mojom::SharedWorkerFactory::Name_,
base::Bind(&SharedWorkerServiceImplTest::BindSharedWorkerFactory));
+ renderer_host0->OverrideURLLoaderFactory(url_loader_factory_.get());
// The second renderer host.
std::unique_ptr<TestWebContents> web_contents1 =
@@ -411,6 +456,7 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest_NormalCase_URLMismatch) {
renderer_host1->OverrideBinderForTesting(
mojom::SharedWorkerFactory::Name_,
base::Bind(&SharedWorkerServiceImplTest::BindSharedWorkerFactory));
+ renderer_host1->OverrideURLLoaderFactory(url_loader_factory_.get());
// First client, creates worker.
@@ -485,6 +531,7 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest_NormalCase_NameMismatch) {
renderer_host0->OverrideBinderForTesting(
mojom::SharedWorkerFactory::Name_,
base::Bind(&SharedWorkerServiceImplTest::BindSharedWorkerFactory));
+ renderer_host0->OverrideURLLoaderFactory(url_loader_factory_.get());
// The second renderer host.
std::unique_ptr<TestWebContents> web_contents1 =
@@ -494,6 +541,7 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest_NormalCase_NameMismatch) {
renderer_host1->OverrideBinderForTesting(
mojom::SharedWorkerFactory::Name_,
base::Bind(&SharedWorkerServiceImplTest::BindSharedWorkerFactory));
+ renderer_host1->OverrideURLLoaderFactory(url_loader_factory_.get());
// First client, creates worker.
@@ -567,6 +615,7 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest_PendingCase) {
renderer_host0->OverrideBinderForTesting(
mojom::SharedWorkerFactory::Name_,
base::Bind(&SharedWorkerServiceImplTest::BindSharedWorkerFactory));
+ renderer_host0->OverrideURLLoaderFactory(url_loader_factory_.get());
// The second renderer host.
std::unique_ptr<TestWebContents> web_contents1 =
@@ -576,6 +625,7 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest_PendingCase) {
renderer_host1->OverrideBinderForTesting(
mojom::SharedWorkerFactory::Name_,
base::Bind(&SharedWorkerServiceImplTest::BindSharedWorkerFactory));
+ renderer_host1->OverrideURLLoaderFactory(url_loader_factory_.get());
// First client and second client are created before the worker starts.
@@ -640,6 +690,7 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest_PendingCase_URLMismatch) {
renderer_host0->OverrideBinderForTesting(
mojom::SharedWorkerFactory::Name_,
base::Bind(&SharedWorkerServiceImplTest::BindSharedWorkerFactory));
+ renderer_host0->OverrideURLLoaderFactory(url_loader_factory_.get());
// The second renderer host.
std::unique_ptr<TestWebContents> web_contents1 =
@@ -649,6 +700,7 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest_PendingCase_URLMismatch) {
renderer_host1->OverrideBinderForTesting(
mojom::SharedWorkerFactory::Name_,
base::Bind(&SharedWorkerServiceImplTest::BindSharedWorkerFactory));
+ renderer_host1->OverrideURLLoaderFactory(url_loader_factory_.get());
// First client and second client are created before the workers start.
@@ -727,6 +779,7 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest_PendingCase_NameMismatch) {
renderer_host0->OverrideBinderForTesting(
mojom::SharedWorkerFactory::Name_,
base::Bind(&SharedWorkerServiceImplTest::BindSharedWorkerFactory));
+ renderer_host0->OverrideURLLoaderFactory(url_loader_factory_.get());
// The second renderer host.
std::unique_ptr<TestWebContents> web_contents1 =
@@ -736,6 +789,7 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest_PendingCase_NameMismatch) {
renderer_host1->OverrideBinderForTesting(
mojom::SharedWorkerFactory::Name_,
base::Bind(&SharedWorkerServiceImplTest::BindSharedWorkerFactory));
+ renderer_host1->OverrideURLLoaderFactory(url_loader_factory_.get());
// First client and second client are created before the workers start.
@@ -814,6 +868,7 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerRaceTest) {
renderer_host0->OverrideBinderForTesting(
mojom::SharedWorkerFactory::Name_,
base::Bind(&SharedWorkerServiceImplTest::BindSharedWorkerFactory));
+ renderer_host0->OverrideURLLoaderFactory(url_loader_factory_.get());
std::unique_ptr<TestWebContents> web_contents1 =
CreateWebContents(GURL("http://example.com/"));
@@ -822,6 +877,7 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerRaceTest) {
renderer_host1->OverrideBinderForTesting(
mojom::SharedWorkerFactory::Name_,
base::Bind(&SharedWorkerServiceImplTest::BindSharedWorkerFactory));
+ renderer_host1->OverrideURLLoaderFactory(url_loader_factory_.get());
std::unique_ptr<TestWebContents> web_contents2 =
CreateWebContents(GURL("http://example.com/"));
@@ -830,6 +886,7 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerRaceTest) {
renderer_host2->OverrideBinderForTesting(
mojom::SharedWorkerFactory::Name_,
base::Bind(&SharedWorkerServiceImplTest::BindSharedWorkerFactory));
+ renderer_host2->OverrideURLLoaderFactory(url_loader_factory_.get());
MockSharedWorkerClient client0;
MessagePortChannel local_port0;
@@ -922,6 +979,7 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerRaceTest2) {
renderer_host0->OverrideBinderForTesting(
mojom::SharedWorkerFactory::Name_,
base::Bind(&SharedWorkerServiceImplTest::BindSharedWorkerFactory));
+ renderer_host0->OverrideURLLoaderFactory(url_loader_factory_.get());
std::unique_ptr<TestWebContents> web_contents1 =
CreateWebContents(GURL("http://example.com/"));
@@ -930,6 +988,7 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerRaceTest2) {
renderer_host1->OverrideBinderForTesting(
mojom::SharedWorkerFactory::Name_,
base::Bind(&SharedWorkerServiceImplTest::BindSharedWorkerFactory));
+ renderer_host1->OverrideURLLoaderFactory(url_loader_factory_.get());
std::unique_ptr<TestWebContents> web_contents2 =
CreateWebContents(GURL("http://example.com/"));
@@ -938,6 +997,7 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerRaceTest2) {
renderer_host2->OverrideBinderForTesting(
mojom::SharedWorkerFactory::Name_,
base::Bind(&SharedWorkerServiceImplTest::BindSharedWorkerFactory));
+ renderer_host2->OverrideURLLoaderFactory(url_loader_factory_.get());
MockSharedWorkerClient client0;
MessagePortChannel local_port0;
@@ -1007,6 +1067,7 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerRaceTest3) {
mojom::SharedWorkerFactory::Name_,
base::BindRepeating(
&SharedWorkerServiceImplTest::BindSharedWorkerFactory));
+ renderer_host0->OverrideURLLoaderFactory(url_loader_factory_.get());
// The second renderer host.
std::unique_ptr<TestWebContents> web_contents1 =
@@ -1017,6 +1078,7 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerRaceTest3) {
mojom::SharedWorkerFactory::Name_,
base::BindRepeating(
&SharedWorkerServiceImplTest::BindSharedWorkerFactory));
+ renderer_host1->OverrideURLLoaderFactory(url_loader_factory_.get());
// Both clients try to connect/create a worker.
diff --git a/chromium/content/browser/site_instance_impl.cc b/chromium/content/browser/site_instance_impl.cc
index bf59f2d42ca..073dc2d4f99 100644
--- a/chromium/content/browser/site_instance_impl.cc
+++ b/chromium/content/browser/site_instance_impl.cc
@@ -104,7 +104,8 @@ bool SiteInstanceImpl::HasProcess() const {
browsing_instance_->browser_context();
if (has_site_ &&
RenderProcessHost::ShouldUseProcessPerSite(browser_context, site_) &&
- RenderProcessHostImpl::GetProcessHostForSite(browser_context, site_)) {
+ RenderProcessHostImpl::GetSoleProcessHostForSite(browser_context, site_,
+ lock_url_)) {
return true;
}
@@ -133,8 +134,7 @@ RenderProcessHost* SiteInstanceImpl::GetProcess() {
process_reuse_policy_ = ProcessReusePolicy::DEFAULT;
}
- process_ = RenderProcessHostImpl::GetProcessHostForSiteInstance(
- browser_context, this);
+ process_ = RenderProcessHostImpl::GetProcessHostForSiteInstance(this);
CHECK(process_);
process_->AddObserver(this);
@@ -144,8 +144,8 @@ RenderProcessHost* SiteInstanceImpl::GetProcess() {
// at this time, we will register it in SetSite().)
if (process_reuse_policy_ == ProcessReusePolicy::PROCESS_PER_SITE &&
has_site_) {
- RenderProcessHostImpl::RegisterProcessHostForSite(browser_context,
- process_, site_);
+ RenderProcessHostImpl::RegisterSoleProcessHostForSite(browser_context,
+ process_, this);
}
TRACE_EVENT2("navigation", "SiteInstanceImpl::GetProcess",
@@ -182,8 +182,10 @@ void SiteInstanceImpl::SetSite(const GURL& url) {
// URL is invalid.
has_site_ = true;
BrowserContext* browser_context = browsing_instance_->browser_context();
- site_ = GetSiteForURL(browser_context, url);
+ site_ =
+ GetSiteForURL(browser_context, url, true /* should_use_effective_urls */);
original_url_ = url;
+ lock_url_ = DetermineProcessLockURL(browser_context, url);
// Now that we have a site, register it with the BrowsingInstance. This
// ensures that we won't create another SiteInstance for this site within
@@ -203,8 +205,8 @@ void SiteInstanceImpl::SetSite(const GURL& url) {
// Ensure the process is registered for this site if necessary.
if (should_use_process_per_site) {
- RenderProcessHostImpl::RegisterProcessHostForSite(
- browser_context, process_, site_);
+ RenderProcessHostImpl::RegisterSoleProcessHostForSite(browser_context,
+ process_, this);
}
}
}
@@ -249,20 +251,26 @@ bool SiteInstanceImpl::HasWrongProcessForURL(const GURL& url) {
if (IsRendererDebugURL(url))
return false;
- // Any process can host an about:blank URL. This check avoids a process
- // transfer for browser-initiated navigations to about:blank in a dedicated
- // process; without it, IsSuitableHost would consider this process unsuitable
- // for about:blank when it compares origin locks. Renderer-initiated
- // navigations will handle about:blank navigations elsewhere and leave them
- // in the source SiteInstance, along with about:srcdoc and data:.
- if (url == url::kAboutBlankURL)
+ // Any process can host an about:blank URL, except the one used for error
+ // pages, which should not commit successful navigations. This check avoids a
+ // process transfer for browser-initiated navigations to about:blank in a
+ // dedicated process; without it, IsSuitableHost would consider this process
+ // unsuitable for about:blank when it compares origin locks.
+ // Renderer-initiated navigations will handle about:blank navigations
+ // elsewhere and leave them in the source SiteInstance, along with
+ // about:srcdoc and data:.
+ if (url.IsAboutBlank() && site_ != GURL(kUnreachableWebDataURL))
return false;
// If the site URL is an extension (e.g., for hosted apps or WebUI) but the
// process is not (or vice versa), make sure we notice and fix it.
- GURL site_url = GetSiteForURL(browsing_instance_->browser_context(), url);
+ GURL site_url =
+ SiteInstance::GetSiteForURL(browsing_instance_->browser_context(), url);
+ GURL origin_lock =
+ DetermineProcessLockURL(browsing_instance_->browser_context(), url);
return !RenderProcessHostImpl::IsSuitableHost(
- GetProcess(), browsing_instance_->browser_context(), site_url);
+ GetProcess(), browsing_instance_->browser_context(), site_url,
+ origin_lock);
}
scoped_refptr<SiteInstanceImpl>
@@ -413,12 +421,32 @@ bool SiteInstanceImpl::IsSameWebSite(BrowserContext* browser_context,
// static
GURL SiteInstance::GetSiteForURL(BrowserContext* browser_context,
- const GURL& real_url) {
+ const GURL& url) {
+ // By default, GetSiteForURL will resolve |real_url| to an effective URL
+ // before computing its site.
+ return SiteInstanceImpl::GetSiteForURL(browser_context, url,
+ true /* should_use_effective_urls */);
+}
+
+// static
+GURL SiteInstanceImpl::DetermineProcessLockURL(BrowserContext* browser_context,
+ const GURL& url) {
+ // For the process lock URL, convert |url| to a site without resolving |url|
+ // to an effective URL.
+ return SiteInstanceImpl::GetSiteForURL(browser_context, url,
+ false /* should_use_effective_urls */);
+}
+
+GURL SiteInstanceImpl::GetSiteForURL(BrowserContext* browser_context,
+ const GURL& real_url,
+ bool should_use_effective_urls) {
// TODO(fsamuel, creis): For some reason appID is not recognized as a host.
if (real_url.SchemeIs(kGuestScheme))
return real_url;
- GURL url = SiteInstanceImpl::GetEffectiveURL(browser_context, real_url);
+ GURL url = should_use_effective_urls
+ ? SiteInstanceImpl::GetEffectiveURL(browser_context, real_url)
+ : real_url;
url::Origin origin = url::Origin::Create(url);
// Isolated origins should use the full origin as their site URL. A subdomain
@@ -442,6 +470,20 @@ GURL SiteInstance::GetSiteForURL(BrowserContext* browser_context,
std::string site = origin.scheme();
site += url::kStandardSchemeSeparator;
site += domain.empty() ? origin.host() : domain;
+
+ // If an effective URL was used, augment the effective site URL with the
+ // underlying web site in the hash. This is needed to keep
+ // navigations across sites covered by one hosted app in separate
+ // SiteInstances. See https://crbug.com/791796.
+ //
+ // TODO(https://crbug.com/734722): Consider replacing this hack with
+ // a proper security principal.
+ if (should_use_effective_urls && url != real_url) {
+ site += "#" + GetSiteForURL(browser_context, real_url,
+ false /* should_use_effective_urls */)
+ .spec();
+ }
+
return GURL(site);
}
@@ -520,7 +562,7 @@ bool SiteInstanceImpl::DoesSiteRequireDedicatedProcess(
return true;
// Always require a dedicated process for isolated origins.
- GURL site_url = GetSiteForURL(browser_context, url);
+ GURL site_url = SiteInstance::GetSiteForURL(browser_context, url);
auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
if (policy->IsIsolatedOrigin(url::Origin::Create(site_url)))
return true;
@@ -538,11 +580,10 @@ bool SiteInstanceImpl::DoesSiteRequireDedicatedProcess(
// static
bool SiteInstanceImpl::ShouldLockToOrigin(BrowserContext* browser_context,
- RenderProcessHost* host,
GURL site_url) {
// Don't lock to origin in --single-process mode, since this mode puts
// cross-site pages into the same process.
- if (host->run_renderer_in_process())
+ if (RenderProcessHost::run_renderer_in_process())
return false;
if (!DoesSiteRequireDedicatedProcess(browser_context, site_url))
@@ -604,8 +645,8 @@ void SiteInstanceImpl::LockToOriginIfNeeded() {
ChildProcessSecurityPolicyImpl* policy =
ChildProcessSecurityPolicyImpl::GetInstance();
- auto lock_state = policy->CheckOriginLock(process_->GetID(), site_);
- if (ShouldLockToOrigin(GetBrowserContext(), process_, site_)) {
+ auto lock_state = policy->CheckOriginLock(process_->GetID(), lock_url());
+ if (ShouldLockToOrigin(GetBrowserContext(), site_)) {
// Sanity check that this won't try to assign an origin lock to a <webview>
// process, which can't be locked.
CHECK(!process_->IsForGuestsOnly());
@@ -616,7 +657,9 @@ void SiteInstanceImpl::LockToOriginIfNeeded() {
// strong protection. If only some sites are isolated, we need
// additional logic to prevent the non-isolated sites from requesting
// resources for isolated sites. https://crbug.com/509125
- process_->LockToOrigin(site_);
+ TRACE_EVENT2("navigation", "SiteInstanceImpl::LockToOrigin", "site id",
+ id_, "lock", lock_url().possibly_invalid_spec());
+ process_->LockToOrigin(lock_url());
break;
}
case CheckOriginLockResult::HAS_WRONG_LOCK:
@@ -627,7 +670,7 @@ void SiteInstanceImpl::LockToOriginIfNeeded() {
base::debug::SetCrashKeyString(
bad_message::GetKilledProcessOriginLockKey(),
policy->GetOriginLock(process_->GetID()).spec());
- CHECK(false) << "Trying to lock a process to " << site_
+ CHECK(false) << "Trying to lock a process to " << lock_url()
<< " but the process is already locked to "
<< policy->GetOriginLock(process_->GetID());
break;
diff --git a/chromium/content/browser/site_instance_impl.h b/chromium/content/browser/site_instance_impl.h
index f2fa8e198bd..b53db35063a 100644
--- a/chromium/content/browser/site_instance_impl.h
+++ b/chromium/content/browser/site_instance_impl.h
@@ -116,11 +116,29 @@ class CONTENT_EXPORT SiteInstanceImpl final : public SiteInstance,
// May be empty if this SiteInstance does not have a |site_|.
const GURL& original_url() { return original_url_; }
+ // Returns the URL which should be used in a LockToOrigin call for this
+ // SiteInstance's process.
+ const GURL& lock_url() { return lock_url_; }
+
// True if |url| resolves to an effective URL that is different from |url|.
// See GetEffectiveURL(). This will be true for hosted apps as well as NTP
// URLs.
static bool HasEffectiveURL(BrowserContext* browser_context, const GURL& url);
+ // 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.
+ // |use_effective_urls| specifies whether to resolve |url| to an effective
+ // URL (via ContentBrowserClient::GetEffectiveURL()) before determining the
+ // site.
+ static GURL GetSiteForURL(BrowserContext* context,
+ const GURL& url,
+ bool use_effective_urls);
+
+ // Returns the URL to which a process should be locked for the given URL.
+ // This is computed similarly to the site URL (see GetSiteForURL), but
+ // without resolving effective URLs.
+ static GURL DetermineProcessLockURL(BrowserContext* context, const GURL& url);
+
// Returns the SiteInstance, related to this one, that should be used
// for subframes when an oopif is required, but a dedicated process is not.
// This SiteInstance will be created if it doesn't already exist. There is
@@ -203,18 +221,17 @@ class CONTENT_EXPORT SiteInstanceImpl final : public SiteInstance,
static bool DoesSiteRequireDedicatedProcess(BrowserContext* browser_context,
const GURL& url);
- // Returns true if a process |host| can be locked to a site |site_url|.
- // Returning true here also implies that |site_url| requires a dedicated
- // process. However, the converse does not hold: this might still return
- // false for certain special cases where an origin lock can't be applied even
- // when |site_url| requires a dedicated process (e.g., with
+ // Returns true if a process can be locked to a site |site_url|. Returning
+ // true here also implies that |site_url| requires a dedicated process.
+ // However, the converse does not hold: this might still return false for
+ // certain special cases where an origin lock can't be applied even when
+ // |site_url| requires a dedicated process (e.g., with
// --site-per-process). Examples of those cases include <webview> guests,
// WebUI, single-process mode, or extensions where a process is currently
// allowed to be reused for different extensions. Most of these special
// cases should eventually be removed, and this function should become
// equivalent to DoesSiteRequireDedicatedProcess().
static bool ShouldLockToOrigin(BrowserContext* browser_context,
- RenderProcessHost* host,
GURL site_url);
private:
@@ -276,6 +293,12 @@ class CONTENT_EXPORT SiteInstanceImpl final : public SiteInstance,
// The URL which was used to set the |site_| for this SiteInstance.
GURL original_url_;
+ // The URL to use when locking a process to this SiteInstance's site via
+ // LockToOrigin(). This is the same as |site_| except for cases involving
+ // effective URLs, such as hosted apps. In those cases, this URL is a site
+ // URL that is computed without the use of effective URLs.
+ GURL lock_url_;
+
// The ProcessReusePolicy to use when creating a RenderProcessHost for this
// SiteInstance.
ProcessReusePolicy process_reuse_policy_;
@@ -283,7 +306,7 @@ class CONTENT_EXPORT SiteInstanceImpl final : public SiteInstance,
// Whether the SiteInstance was created for a service worker.
bool is_for_service_worker_;
- base::ObserverList<Observer, true> observers_;
+ base::ObserverList<Observer, true>::Unchecked observers_;
DISALLOW_COPY_AND_ASSIGN(SiteInstanceImpl);
};
diff --git a/chromium/content/browser/site_instance_impl_unittest.cc b/chromium/content/browser/site_instance_impl_unittest.cc
index 66159134d65..ec3fa59c538 100644
--- a/chromium/content/browser/site_instance_impl_unittest.cc
+++ b/chromium/content/browser/site_instance_impl_unittest.cc
@@ -258,51 +258,51 @@ TEST_F(SiteInstanceTest, SetSite) {
TEST_F(SiteInstanceTest, GetSiteForURL) {
// Pages are irrelevant.
GURL test_url = GURL("http://www.google.com/index.html");
- GURL site_url = SiteInstanceImpl::GetSiteForURL(nullptr, test_url);
+ GURL site_url = SiteInstance::GetSiteForURL(nullptr, test_url);
EXPECT_EQ(GURL("http://google.com"), site_url);
EXPECT_EQ("http", site_url.scheme());
EXPECT_EQ("google.com", site_url.host());
// Ports are irrelevant.
test_url = GURL("https://www.google.com:8080");
- site_url = SiteInstanceImpl::GetSiteForURL(nullptr, test_url);
+ site_url = SiteInstance::GetSiteForURL(nullptr, test_url);
EXPECT_EQ(GURL("https://google.com"), site_url);
// Punycode is canonicalized.
test_url = GURL("http://☃snowperson☃.net:333/");
- site_url = SiteInstanceImpl::GetSiteForURL(nullptr, test_url);
+ site_url = SiteInstance::GetSiteForURL(nullptr, test_url);
EXPECT_EQ(GURL("http://xn--snowperson-di0gka.net"), site_url);
// Username and password are stripped out.
test_url = GURL("ftp://username:password@ftp.chromium.org/files/README");
- site_url = SiteInstanceImpl::GetSiteForURL(nullptr, test_url);
+ site_url = SiteInstance::GetSiteForURL(nullptr, test_url);
EXPECT_EQ(GURL("ftp://chromium.org"), site_url);
// Literal IP addresses of any flavor are okay.
test_url = GURL("http://127.0.0.1/a.html");
- site_url = SiteInstanceImpl::GetSiteForURL(nullptr, test_url);
+ site_url = SiteInstance::GetSiteForURL(nullptr, test_url);
EXPECT_EQ(GURL("http://127.0.0.1"), site_url);
EXPECT_EQ("127.0.0.1", site_url.host());
test_url = GURL("http://2130706433/a.html");
- site_url = SiteInstanceImpl::GetSiteForURL(nullptr, test_url);
+ site_url = SiteInstance::GetSiteForURL(nullptr, test_url);
EXPECT_EQ(GURL("http://127.0.0.1"), site_url);
EXPECT_EQ("127.0.0.1", site_url.host());
test_url = GURL("http://[::1]:2/page.html");
- site_url = SiteInstanceImpl::GetSiteForURL(nullptr, test_url);
+ site_url = SiteInstance::GetSiteForURL(nullptr, test_url);
EXPECT_EQ(GURL("http://[::1]"), site_url);
EXPECT_EQ("[::1]", site_url.host());
// Hostnames without TLDs are okay.
test_url = GURL("http://foo/a.html");
- site_url = SiteInstanceImpl::GetSiteForURL(nullptr, test_url);
+ site_url = SiteInstance::GetSiteForURL(nullptr, test_url);
EXPECT_EQ(GURL("http://foo"), site_url);
EXPECT_EQ("foo", site_url.host());
// File URLs should include the scheme.
test_url = GURL("file:///C:/Downloads/");
- site_url = SiteInstanceImpl::GetSiteForURL(nullptr, test_url);
+ site_url = SiteInstance::GetSiteForURL(nullptr, test_url);
EXPECT_EQ(GURL("file:"), site_url);
EXPECT_EQ("file", site_url.scheme());
EXPECT_FALSE(site_url.has_host());
@@ -311,7 +311,7 @@ TEST_F(SiteInstanceTest, GetSiteForURL) {
// maps *all* file://... URLs into "file://" origin) such file URLs still need
// to map into "file:" site URL. See also https://crbug.com/776160.
test_url = GURL("file://server/path");
- site_url = SiteInstanceImpl::GetSiteForURL(nullptr, test_url);
+ site_url = SiteInstance::GetSiteForURL(nullptr, test_url);
EXPECT_EQ(GURL("file:"), site_url);
EXPECT_EQ("file", site_url.scheme());
EXPECT_FALSE(site_url.has_host());
@@ -319,7 +319,7 @@ TEST_F(SiteInstanceTest, GetSiteForURL) {
// Data URLs should include the whole URL, except for the hash, when Site
// Isolation is enabled. Otherwise they just include the scheme.
test_url = GURL("data:text/html,foo");
- site_url = SiteInstanceImpl::GetSiteForURL(nullptr, test_url);
+ site_url = SiteInstance::GetSiteForURL(nullptr, test_url);
if (AreAllSitesIsolatedForTesting())
EXPECT_EQ(test_url, site_url);
else
@@ -327,7 +327,7 @@ TEST_F(SiteInstanceTest, GetSiteForURL) {
EXPECT_EQ("data", site_url.scheme());
EXPECT_FALSE(site_url.has_host());
test_url = GURL("data:text/html,foo#bar");
- site_url = SiteInstanceImpl::GetSiteForURL(nullptr, test_url);
+ site_url = SiteInstance::GetSiteForURL(nullptr, test_url);
EXPECT_FALSE(site_url.has_ref());
if (AreAllSitesIsolatedForTesting()) {
EXPECT_NE(test_url, site_url);
@@ -338,7 +338,7 @@ TEST_F(SiteInstanceTest, GetSiteForURL) {
// Javascript URLs should include the scheme.
test_url = GURL("javascript:foo();");
- site_url = SiteInstanceImpl::GetSiteForURL(nullptr, test_url);
+ site_url = SiteInstance::GetSiteForURL(nullptr, test_url);
EXPECT_EQ(GURL("javascript:"), site_url);
EXPECT_EQ("javascript", site_url.scheme());
EXPECT_FALSE(site_url.has_host());
@@ -347,12 +347,12 @@ TEST_F(SiteInstanceTest, GetSiteForURL) {
test_url = GURL(
"blob:gopher://www.ftp.chromium.org/"
"4d4ff040-6d61-4446-86d3-13ca07ec9ab9");
- site_url = SiteInstanceImpl::GetSiteForURL(nullptr, test_url);
+ site_url = SiteInstance::GetSiteForURL(nullptr, test_url);
EXPECT_EQ(GURL("gopher://chromium.org"), site_url);
// Blob URLs with file origin also extract the site from the origin.
test_url = GURL("blob:file:///1029e5a4-2983-4b90-a585-ed217563acfeb");
- site_url = SiteInstanceImpl::GetSiteForURL(nullptr, test_url);
+ site_url = SiteInstance::GetSiteForURL(nullptr, test_url);
EXPECT_EQ(GURL("file:"), site_url);
EXPECT_EQ("file", site_url.scheme());
EXPECT_FALSE(site_url.has_host());
@@ -361,13 +361,13 @@ TEST_F(SiteInstanceTest, GetSiteForURL) {
// when Site Isolation is enabled, except for the hash. Otherwise they just
// include the scheme.
test_url = GURL("blob:null/1029e5a4-2983-4b90-a585-ed217563acfeb");
- site_url = SiteInstanceImpl::GetSiteForURL(nullptr, test_url);
+ site_url = SiteInstance::GetSiteForURL(nullptr, test_url);
if (AreAllSitesIsolatedForTesting())
EXPECT_EQ(test_url, site_url);
else
EXPECT_EQ(GURL("blob:"), site_url);
test_url = GURL("blob:null/1029e5a4-2983-4b90-a585-ed217563acfeb#foo");
- site_url = SiteInstanceImpl::GetSiteForURL(nullptr, test_url);
+ site_url = SiteInstance::GetSiteForURL(nullptr, test_url);
EXPECT_FALSE(site_url.has_ref());
if (AreAllSitesIsolatedForTesting()) {
EXPECT_NE(test_url, site_url);
@@ -380,12 +380,12 @@ TEST_F(SiteInstanceTest, GetSiteForURL) {
test_url = GURL(
"blob:http://www.example.appspot.com:44/"
"4d4ff040-6d61-4446-86d3-13ca07ec9ab9");
- site_url = SiteInstanceImpl::GetSiteForURL(nullptr, test_url);
+ site_url = SiteInstance::GetSiteForURL(nullptr, test_url);
EXPECT_EQ(GURL("http://example.appspot.com"), site_url);
// The site of filesystem URLs is determined by the inner URL.
test_url = GURL("filesystem:http://www.google.com/foo/bar.html?foo#bar");
- site_url = SiteInstanceImpl::GetSiteForURL(nullptr, test_url);
+ site_url = SiteInstance::GetSiteForURL(nullptr, test_url);
EXPECT_EQ(GURL("http://google.com"), site_url);
// Guest URLs are special and need to have the path in the site as well,
@@ -393,12 +393,70 @@ TEST_F(SiteInstanceTest, GetSiteForURL) {
std::string guest_url(kGuestScheme);
guest_url.append("://abc123/path");
test_url = GURL(guest_url);
- site_url = SiteInstanceImpl::GetSiteForURL(nullptr, test_url);
+ site_url = SiteInstance::GetSiteForURL(nullptr, test_url);
EXPECT_EQ(test_url, site_url);
DrainMessageLoop();
}
+// Test that process lock URLs are computed without using effective URLs.
+TEST_F(SiteInstanceTest, ProcessLockDoesNotUseEffectiveURL) {
+ GURL test_url("https://some.app.foo.com/");
+ GURL nonapp_site_url("https://foo.com/");
+ GURL app_url("https://app.com/");
+ EffectiveURLContentBrowserClient modified_client(test_url, app_url);
+ ContentBrowserClient* regular_client =
+ SetBrowserClientForTesting(&modified_client);
+ std::unique_ptr<TestBrowserContext> browser_context(new TestBrowserContext());
+
+ // Sanity check that GetSiteForURL's |use_effective_urls| option works
+ // properly. When it's true, the site URL should include both the effective
+ // 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(
+ nullptr, test_url, false /* use_effective_urls */);
+ EXPECT_EQ(nonapp_site_url, site_url);
+
+ site_url = SiteInstanceImpl::GetSiteForURL(nullptr, test_url,
+ true /* use_effective_urls */);
+ EXPECT_EQ(expected_app_site_url, site_url);
+ }
+
+ // New SiteInstance in a new BrowsingInstance with a predetermined URL.
+ {
+ scoped_refptr<SiteInstanceImpl> site_instance =
+ SiteInstanceImpl::CreateForURL(browser_context.get(), test_url);
+ EXPECT_EQ(expected_app_site_url, site_instance->GetSiteURL());
+ EXPECT_EQ(nonapp_site_url, site_instance->lock_url());
+ }
+
+ // New related SiteInstance from an existing SiteInstance with a
+ // predetermined URL.
+ {
+ scoped_refptr<SiteInstanceImpl> bar_site_instance =
+ SiteInstanceImpl::CreateForURL(browser_context.get(),
+ GURL("https://bar.com/"));
+ scoped_refptr<SiteInstance> site_instance =
+ bar_site_instance->GetRelatedSiteInstance(test_url);
+ EXPECT_EQ(expected_app_site_url, site_instance->GetSiteURL());
+ EXPECT_EQ(nonapp_site_url,
+ static_cast<SiteInstanceImpl*>(site_instance.get())->lock_url());
+ }
+
+ // New SiteInstance with a lazily assigned site URL.
+ {
+ scoped_refptr<SiteInstanceImpl> site_instance =
+ SiteInstanceImpl::Create(browser_context.get());
+ EXPECT_FALSE(site_instance->HasSite());
+ site_instance->SetSite(test_url);
+ EXPECT_EQ(expected_app_site_url, site_instance->GetSiteURL());
+ EXPECT_EQ(nonapp_site_url, site_instance->lock_url());
+ }
+
+ SetBrowserClientForTesting(regular_client);
+}
+
// Test of distinguishing URLs from different sites. Most of this logic is
// tested in RegistryControlledDomainTest. This test focuses on URLs with
// different schemes or ports.
@@ -837,8 +895,10 @@ TEST_F(SiteInstanceTest, NoProcessPerSiteForEmptySite) {
EXPECT_TRUE(instance->GetSiteURL().is_empty());
host.reset(instance->GetProcess());
- EXPECT_FALSE(RenderProcessHostImpl::GetProcessHostForSite(
+ EXPECT_FALSE(RenderProcessHostImpl::GetSoleProcessHostForURL(
browser_context.get(), GURL()));
+ EXPECT_FALSE(RenderProcessHostImpl::GetSoleProcessHostForSite(
+ browser_context.get(), GURL(), GURL()));
DrainMessageLoop();
}
@@ -1203,11 +1263,15 @@ TEST_F(SiteInstanceTest, OriginalURL) {
SetBrowserClientForTesting(&modified_client);
std::unique_ptr<TestBrowserContext> browser_context(new TestBrowserContext());
+ // The site URL of of effective URL should include both the effective URL's
+ // site and the original URL's site.
+ GURL expected_site_url(app_url.spec() + "#" + original_url.spec());
+
// New SiteInstance in a new BrowsingInstance with a predetermined URL.
{
scoped_refptr<SiteInstanceImpl> site_instance =
SiteInstanceImpl::CreateForURL(browser_context.get(), original_url);
- EXPECT_EQ(app_url, site_instance->GetSiteURL());
+ EXPECT_EQ(expected_site_url, site_instance->GetSiteURL());
EXPECT_EQ(original_url, site_instance->original_url());
}
@@ -1219,7 +1283,7 @@ TEST_F(SiteInstanceTest, OriginalURL) {
GURL("https://bar.com/"));
scoped_refptr<SiteInstance> site_instance =
bar_site_instance->GetRelatedSiteInstance(original_url);
- EXPECT_EQ(app_url, site_instance->GetSiteURL());
+ EXPECT_EQ(expected_site_url, site_instance->GetSiteURL());
EXPECT_EQ(
original_url,
static_cast<SiteInstanceImpl*>(site_instance.get())->original_url());
@@ -1232,7 +1296,7 @@ TEST_F(SiteInstanceTest, OriginalURL) {
EXPECT_FALSE(site_instance->HasSite());
EXPECT_TRUE(site_instance->original_url().is_empty());
site_instance->SetSite(original_url);
- EXPECT_EQ(app_url, site_instance->GetSiteURL());
+ EXPECT_EQ(expected_site_url, site_instance->GetSiteURL());
EXPECT_EQ(original_url, site_instance->original_url());
}
diff --git a/chromium/content/browser/site_per_process_browsertest.cc b/chromium/content/browser/site_per_process_browsertest.cc
index e2cd0167869..396d50ce3cf 100644
--- a/chromium/content/browser/site_per_process_browsertest.cc
+++ b/chromium/content/browser/site_per_process_browsertest.cc
@@ -37,6 +37,7 @@
#include "base/test/test_timeouts.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "base/timer/timer.h"
#include "build/build_config.h"
#include "cc/input/touch_action.h"
#include "components/network_session_configurator/common/network_switches.h"
@@ -136,8 +137,12 @@
#include "content/browser/android/ime_adapter_android.h"
#include "content/browser/renderer_host/input/touch_selection_controller_client_manager_android.h"
#include "content/browser/renderer_host/render_widget_host_view_android.h"
+#include "content/browser/web_contents/web_contents_view_android.h"
#include "content/public/browser/android/child_process_importance.h"
#include "content/test/mock_overscroll_refresh_handler_android.h"
+#include "ui/android/view_android.h"
+#include "ui/android/window_android.h"
+#include "ui/events/android/event_handler_android.h"
#include "ui/events/android/motion_event_android.h"
#include "ui/gfx/geometry/point_f.h"
#endif
@@ -164,12 +169,7 @@ void PostMessageAndWaitForReply(FrameTreeNode* sender_ftn,
// else it might miss the message of interest. See https://crbug.com/518729.
DOMMessageQueue msg_queue;
- bool success = false;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(
- sender_ftn,
- "window.domAutomationController.send(" + post_message_script + ");",
- &success));
- EXPECT_TRUE(success);
+ EXPECT_EQ(true, EvalJs(sender_ftn, "(" + post_message_script + ");"));
std::string status;
while (msg_queue.WaitForMessage(&status)) {
@@ -182,11 +182,7 @@ void PostMessageAndWaitForReply(FrameTreeNode* sender_ftn,
// |sender_ftn| frame. This variable is used in post_message.html to count the
// number of messages received via postMessage by the current window.
int GetReceivedMessages(FrameTreeNode* ftn) {
- int received_messages = 0;
- EXPECT_TRUE(ExecuteScriptAndExtractInt(
- ftn, "window.domAutomationController.send(window.receivedMessages);",
- &received_messages));
- return received_messages;
+ return EvalJs(ftn, "window.receivedMessages;").ExtractInt();
}
// Helper function to perform a window.open from the |caller_frame| targeting a
@@ -194,13 +190,8 @@ int GetReceivedMessages(FrameTreeNode* ftn) {
void NavigateNamedFrame(const ToRenderFrameHost& caller_frame,
const GURL& url,
const std::string& name) {
- bool success = false;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(
- caller_frame,
- "window.domAutomationController.send("
- " !!window.open('" + url.spec() + "', '" + name + "'));",
- &success));
- EXPECT_TRUE(success);
+ EXPECT_EQ(true, EvalJs(caller_frame,
+ JsReplace("!!window.open($1, $2)", url, name)));
}
// Helper function to generate a click on the given RenderWidgetHost. The
@@ -216,20 +207,12 @@ void SimulateMouseClick(RenderWidgetHost* rwh, int x, int y) {
}
// Retrieve document.origin for the frame |ftn|.
-std::string GetDocumentOrigin(FrameTreeNode* ftn) {
- std::string origin;
- EXPECT_TRUE(ExecuteScriptAndExtractString(
- ftn, "domAutomationController.send(document.origin)", &origin));
- return origin;
+EvalJsResult GetDocumentOrigin(FrameTreeNode* ftn) {
+ return EvalJs(ftn, "document.origin;");
}
double GetFrameDeviceScaleFactor(const ToRenderFrameHost& adapter) {
- double device_scale_factor;
- const char kGetFrameDeviceScaleFactor[] =
- "window.domAutomationController.send(window.devicePixelRatio);";
- EXPECT_TRUE(ExecuteScriptAndExtractDouble(adapter, kGetFrameDeviceScaleFactor,
- &device_scale_factor));
- return device_scale_factor;
+ return EvalJs(adapter, "window.devicePixelRatio;").ExtractDouble();
}
class RedirectNotificationObserver : public NotificationObserver {
@@ -269,7 +252,7 @@ class RedirectNotificationObserver : public NotificationObserver {
NotificationSource source_;
NotificationDetails details_;
- scoped_refptr<MessageLoopRunner> message_loop_runner_;
+ base::RunLoop run_loop_;
DISALLOW_COPY_AND_ASSIGN(RedirectNotificationObserver);
};
@@ -290,8 +273,7 @@ void RedirectNotificationObserver::Wait() {
return;
running_ = true;
- message_loop_runner_ = new MessageLoopRunner;
- message_loop_runner_->Run();
+ run_loop_.Run();
EXPECT_TRUE(seen_);
}
@@ -306,7 +288,7 @@ void RedirectNotificationObserver::Observe(
if (!running_)
return;
- message_loop_runner_->Quit();
+ run_loop_.Quit();
running_ = false;
}
@@ -319,8 +301,7 @@ class RenderFrameHostCreatedObserver : public WebContentsObserver {
int expected_frame_count)
: WebContentsObserver(web_contents),
expected_frame_count_(expected_frame_count),
- frames_created_(0),
- message_loop_runner_(new MessageLoopRunner) {}
+ frames_created_(0) {}
~RenderFrameHostCreatedObserver() override;
@@ -338,8 +319,8 @@ class RenderFrameHostCreatedObserver : public WebContentsObserver {
// The number of RenderFrameHosts that have been created.
int frames_created_;
- // The MessageLoopRunner used to spin the message loop.
- scoped_refptr<MessageLoopRunner> message_loop_runner_;
+ // The RunLoop used to spin the message loop.
+ base::RunLoop run_loop_;
DISALLOW_COPY_AND_ASSIGN(RenderFrameHostCreatedObserver);
};
@@ -348,14 +329,14 @@ RenderFrameHostCreatedObserver::~RenderFrameHostCreatedObserver() {
}
void RenderFrameHostCreatedObserver::Wait() {
- message_loop_runner_->Run();
+ run_loop_.Run();
}
void RenderFrameHostCreatedObserver::RenderFrameCreated(
RenderFrameHost* render_frame_host) {
frames_created_++;
if (frames_created_ == expected_frame_count_) {
- message_loop_runner_->Quit();
+ run_loop_.Quit();
}
}
@@ -395,23 +376,6 @@ void FocusFrame(FrameTreeNode* frame) {
focus_observer.Wait();
}
-// A BrowserMessageFilter that drops SwapOut ACK messages.
-class SwapoutACKMessageFilter : public BrowserMessageFilter {
- public:
- SwapoutACKMessageFilter() : BrowserMessageFilter(FrameMsgStart) {}
-
- protected:
- ~SwapoutACKMessageFilter() override {}
-
- private:
- // BrowserMessageFilter:
- bool OnMessageReceived(const IPC::Message& message) override {
- return message.type() == FrameHostMsg_SwapOut_ACK::ID;
- }
-
- DISALLOW_COPY_AND_ASSIGN(SwapoutACKMessageFilter);
-};
-
class RenderWidgetHostVisibilityObserver : public RenderWidgetHostObserver {
public:
explicit RenderWidgetHostVisibilityObserver(RenderWidgetHostImpl* rwhi,
@@ -530,6 +494,35 @@ void CheckFrameDepth(unsigned int expected_depth, FrameTreeNode* node) {
node->current_frame_host()->GetProcess()->GetFrameDepth());
}
+// Check |intersects_viewport| on widget and process.
+bool CheckIntersectsViewport(bool expected, FrameTreeNode* node) {
+ RenderProcessHost::Priority priority =
+ node->current_frame_host()->GetRenderWidgetHost()->GetPriority();
+ return priority.intersects_viewport == expected &&
+ node->current_frame_host()->GetProcess()->GetIntersectsViewport() ==
+ expected;
+}
+
+// Layout child frames in cross_site_iframe_factory.html so that they are the
+// same width as the viewport, and 75% of the height of the window. This is for
+// testing viewport intersection. Note this does not recurse into child frames
+// and re-layout in the same way since children might be in a different origin.
+void LayoutNonRecursiveForTestingViewportIntersection(
+ WebContents* web_contents) {
+ static const char* script =
+ "function relayoutNonRecursiveForTestingViewportIntersection() {\
+ var width = window.innerWidth;\
+ var height = window.innerHeight * 0.75;\
+ for (var i = 0; i < window.frames.length; i++) {\
+ child = document.getElementById(\"child-\" + i);\
+ child.width = width;\
+ child.height = height;\
+ }\
+ }\
+ relayoutNonRecursiveForTestingViewportIntersection();";
+ EXPECT_TRUE(ExecuteScript(web_contents, script));
+}
+
void GenerateTapDownGesture(RenderWidgetHost* rwh) {
blink::WebGestureEvent gesture_tap_down(
blink::WebGestureEvent::kGestureTapDown,
@@ -540,6 +533,86 @@ void GenerateTapDownGesture(RenderWidgetHost* rwh) {
rwh->ForwardGestureEvent(gesture_tap_down);
}
+// Class to monitor incoming FrameHostMsg_UpdateViewportIntersection messages.
+class UpdateViewportIntersectionMessageFilter
+ : public content::BrowserMessageFilter {
+ public:
+ UpdateViewportIntersectionMessageFilter()
+ : content::BrowserMessageFilter(FrameMsgStart), msg_received_(false) {}
+
+ bool OnMessageReceived(const IPC::Message& message) override {
+ IPC_BEGIN_MESSAGE_MAP(UpdateViewportIntersectionMessageFilter, message)
+ IPC_MESSAGE_HANDLER(FrameHostMsg_UpdateViewportIntersection,
+ OnUpdateViewportIntersection)
+ IPC_END_MESSAGE_MAP()
+ return false;
+ }
+
+ gfx::Rect GetCompositingRect() const { return compositing_rect_; }
+ gfx::Rect GetViewportIntersection() const { return viewport_intersection_; }
+ bool GetOccludedOrObscured() const { return occluded_or_obscured_; }
+
+ void Wait() {
+ DCHECK(!run_loop_);
+ if (msg_received_) {
+ msg_received_ = false;
+ return;
+ }
+ std::unique_ptr<base::RunLoop> run_loop(new base::RunLoop);
+ run_loop_ = run_loop.get();
+ run_loop_->Run();
+ run_loop_ = nullptr;
+ msg_received_ = false;
+ }
+
+ void set_run_loop(base::RunLoop* run_loop) { run_loop_ = run_loop; }
+
+ private:
+ ~UpdateViewportIntersectionMessageFilter() override {}
+
+ void OnUpdateViewportIntersection(const gfx::Rect& viewport_intersection,
+ const gfx::Rect& compositing_rect,
+ bool occluded_or_obscured) {
+ // The message is going to be posted to UI thread after
+ // OnUpdateViewportIntersection returns. This additional post on the IO
+ // thread guarantees that by the time OnUpdateViewportIntersectionOnUI runs,
+ // the message has been handled on the UI thread.
+ content::BrowserThread::PostTask(
+ content::BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&UpdateViewportIntersectionMessageFilter::
+ OnUpdateViewportIntersectionPostOnIO,
+ this, viewport_intersection, compositing_rect,
+ occluded_or_obscured));
+ }
+ void OnUpdateViewportIntersectionPostOnIO(
+ const gfx::Rect& viewport_intersection,
+ const gfx::Rect& compositing_rect,
+ bool occluded_or_obscured) {
+ content::BrowserThread::PostTask(
+ content::BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&UpdateViewportIntersectionMessageFilter::
+ OnUpdateViewportIntersectionOnUI,
+ this, viewport_intersection, compositing_rect,
+ occluded_or_obscured));
+ }
+ void OnUpdateViewportIntersectionOnUI(const gfx::Rect& viewport_intersection,
+ const gfx::Rect& compositing_rect,
+ bool occluded_or_obscured) {
+ viewport_intersection_ = viewport_intersection;
+ compositing_rect_ = compositing_rect;
+ occluded_or_obscured_ = occluded_or_obscured;
+ msg_received_ = true;
+ if (run_loop_)
+ run_loop_->Quit();
+ }
+ base::RunLoop* run_loop_ = nullptr;
+ bool msg_received_;
+ gfx::Rect compositing_rect_;
+ gfx::Rect viewport_intersection_;
+ bool occluded_or_obscured_ = false;
+ DISALLOW_COPY_AND_ASSIGN(UpdateViewportIntersectionMessageFilter);
+};
+
} // namespace
//
@@ -1075,9 +1148,16 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
rwhv_nested->GetCompositorViewportPixelSize());
}
+// Disable on Android: crbug/851049
+#if defined(OS_ANDROID)
+#define MAYBE_NoResizeAfterIframeLoad DISABLED_NoResizeAfterIframeLoad
+#else
+#define MAYBE_NoResizeAfterIframeLoad NoResizeAfterIframeLoad
+#endif
// Verify an OOPIF resize handler doesn't fire immediately after load without
// the frame having been resized. See https://crbug.com/826457.
-IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, NoResizeAfterIframeLoad) {
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ MAYBE_NoResizeAfterIframeLoad) {
GURL main_url(embedded_test_server()->GetURL(
"a.com", "/cross_site_iframe_factory.html?a(a)"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -1089,6 +1169,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, NoResizeAfterIframeLoad) {
GURL site_url =
embedded_test_server()->GetURL("b.com", "/page_with_resize_handler.html");
NavigateFrameToURL(iframe, site_url);
+ base::RunLoop().RunUntilIdle();
int resizes = -1;
EXPECT_TRUE(ExecuteScriptAndExtractInt(
@@ -2170,6 +2251,42 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessProgrammaticScrollTest,
#endif
}
+// This test verifies that smooth scrolling works correctly inside nested OOPIFs
+// which are same origin with the parent. Note that since the frame tree has
+// a A(B(A1())) structure, if and A1 and A2 shared the same
+// SmoothScrollSequencer, then this test would time out or at best be flaky with
+// random time outs. See https://crbug.com/865446 for more context.
+IN_PROC_BROWSER_TEST_F(SitePerProcessProgrammaticScrollTest,
+ SmoothScrollInNestedSameProcessOOPIF) {
+ GURL main_frame(
+ embedded_test_server()->GetURL("a.com", kIframeOutOfViewHTML));
+ GURL child_url_b(
+ embedded_test_server()->GetURL("b.com", kIframeOutOfViewHTML));
+ GURL same_origin(
+ embedded_test_server()->GetURL("a.com", kIframeOutOfViewHTML));
+
+ // This will set up the page frame tree as A(B(A1(A2()))) where A1 is later
+ // asked to scroll the <iframe> element of A2 into view. The important bit
+ // here is that the inner frame A1 is recursively scrolling (smoothly) an
+ // element inside its document into view (A2's origin is irrelevant here).
+ ASSERT_TRUE(NavigateToURL(shell(), main_frame));
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+ WaitForOnLoad(root);
+ NavigateFrameToURL(root->child_at(0), child_url_b);
+ WaitForOnLoad(root->child_at(0));
+ auto* nested_ftn = root->child_at(0)->child_at(0);
+ NavigateFrameToURL(nested_ftn, same_origin);
+ WaitForOnLoad(nested_ftn);
+
+ // *Smoothly* scroll the inner most frame into view.
+ ASSERT_TRUE(ExecuteScript(
+ nested_ftn,
+ "document.querySelector('iframe').scrollIntoView({behavior: 'smooth'})"));
+ WaitForElementVisible(root, kIframeSelector);
+ WaitForElementVisible(root->child_at(0), kIframeSelector);
+ WaitForElementVisible(nested_ftn, kIframeSelector);
+}
+
// Tests OOPIF rendering by checking that the RWH of the iframe generates
// OnSwapCompositorFrame message.
IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, CompositorFrameSwapped) {
@@ -3614,17 +3731,14 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Also note that just comparing clientHeight and scrollHeight of the frame's
// document will not work.
auto has_scrollbar = [](RenderFrameHostImpl* rfh) {
- int client_width;
- EXPECT_TRUE(ExecuteScriptAndExtractInt(
- rfh, "window.domAutomationController.send(document.body.clientWidth);",
- &client_width));
+ int client_width = EvalJs(rfh, "document.body.clientWidth").ExtractInt();
const int kFrameElementWidth = 200;
return client_width < kFrameElementWidth;
};
auto set_scrolling_property = [](RenderFrameHostImpl* parent_rfh,
const std::string& value) {
- EXPECT_TRUE(ExecuteScript(
+ EXPECT_TRUE(ExecJs(
parent_rfh,
base::StringPrintf("document.getElementById('child-1').setAttribute("
" 'scrolling', '%s');",
@@ -3671,21 +3785,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
FrameTreeNode* child = root->child_at(0);
- std::string margin_width;
- EXPECT_TRUE(ExecuteScriptAndExtractString(
- child,
- "window.domAutomationController.send("
- "document.body.getAttribute('marginwidth'));",
- &margin_width));
- EXPECT_EQ("10", margin_width);
-
- std::string margin_height;
- EXPECT_TRUE(ExecuteScriptAndExtractString(
- child,
- "window.domAutomationController.send("
- "document.body.getAttribute('marginheight'));",
- &margin_height));
- EXPECT_EQ("50", margin_height);
+ EXPECT_EQ("10", EvalJs(child, "document.body.getAttribute('marginwidth');"));
+ EXPECT_EQ("50", EvalJs(child, "document.body.getAttribute('marginheight');"));
// Run the test over variety of parent/child cases.
GURL urls[] = {// Remote to remote.
@@ -3703,34 +3804,19 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// correctly after the navigation has completed.
for (size_t i = 0; i < arraysize(urls); ++i) {
// Change marginwidth and marginheight before navigating.
- EXPECT_TRUE(ExecuteScript(
- root,
- base::StringPrintf("document.getElementById('child-1').setAttribute("
- " 'marginwidth', '%d');",
- current_margin_width)));
- EXPECT_TRUE(ExecuteScript(
+ EXPECT_TRUE(ExecJs(
root,
- base::StringPrintf("document.getElementById('child-1').setAttribute("
- " 'marginheight', '%d');",
- current_margin_height)));
+ base::StringPrintf("var child = document.getElementById('child-1');"
+ "child.setAttribute('marginwidth', '%d');"
+ "child.setAttribute('marginheight', '%d');",
+ current_margin_width, current_margin_height)));
NavigateFrameToURL(child, urls[i]);
- std::string actual_margin_width;
- EXPECT_TRUE(ExecuteScriptAndExtractString(
- child,
- "window.domAutomationController.send("
- "document.body.getAttribute('marginwidth'));",
- &actual_margin_width));
- EXPECT_EQ(base::IntToString(current_margin_width), actual_margin_width);
-
- std::string actual_margin_height;
- EXPECT_TRUE(ExecuteScriptAndExtractString(
- child,
- "window.domAutomationController.send("
- "document.body.getAttribute('marginheight'));",
- &actual_margin_height));
- EXPECT_EQ(base::IntToString(current_margin_height), actual_margin_height);
+ EXPECT_EQ(base::IntToString(current_margin_width),
+ EvalJs(child, "document.body.getAttribute('marginwidth');"));
+ EXPECT_EQ(base::IntToString(current_margin_height),
+ EvalJs(child, "document.body.getAttribute('marginheight');"));
current_margin_width += 5;
current_margin_height += 10;
@@ -3758,13 +3844,9 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessEmbedderCSPEnforcementBrowserTest,
FrameTreeNode* child = root->child_at(0);
- std::string csp;
- EXPECT_TRUE(ExecuteScriptAndExtractString(
- root,
- "window.domAutomationController.send("
- "document.getElementById('child-1').getAttribute('csp'));",
- &csp));
- EXPECT_EQ("object-src \'none\'", csp);
+ EXPECT_EQ(
+ "object-src \'none\'",
+ EvalJs(root, "document.getElementById('child-1').getAttribute('csp');"));
// Run the test over variety of parent/child cases.
GURL urls[] = {// Remote to remote.
@@ -3815,9 +3897,12 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, OriginReplication) {
" C = http://c.com/",
DepictFrameTree(root));
- std::string a_origin = embedded_test_server()->GetURL("a.com", "/").spec();
- std::string b_origin = embedded_test_server()->GetURL("b.com", "/").spec();
- std::string c_origin = embedded_test_server()->GetURL("c.com", "/").spec();
+ url::Origin a_origin =
+ url::Origin::Create(embedded_test_server()->GetURL("a.com", "/"));
+ url::Origin b_origin =
+ url::Origin::Create(embedded_test_server()->GetURL("b.com", "/"));
+ url::Origin c_origin =
+ url::Origin::Create(embedded_test_server()->GetURL("c.com", "/"));
FrameTreeNode* tiptop_child = root->child_at(0);
FrameTreeNode* middle_child = root->child_at(0)->child_at(0);
FrameTreeNode* lowest_child = root->child_at(0)->child_at(0)->child_at(0);
@@ -3826,18 +3911,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, OriginReplication) {
// origin for the parent. The origin should have been replicated as part of
// the mojom::Renderer::CreateView message that created the parent's
// RenderFrameProxy in b.com's process.
- int ancestor_origins_length = 0;
- EXPECT_TRUE(ExecuteScriptAndExtractInt(
- tiptop_child,
- "window.domAutomationController.send(location.ancestorOrigins.length);",
- &ancestor_origins_length));
- EXPECT_EQ(1, ancestor_origins_length);
- std::string result;
- EXPECT_TRUE(ExecuteScriptAndExtractString(
- tiptop_child,
- "window.domAutomationController.send(location.ancestorOrigins[0]);",
- &result));
- EXPECT_EQ(a_origin, result + "/");
+ EXPECT_EQ(ListValueOf(a_origin),
+ EvalJs(tiptop_child, "Array.from(location.ancestorOrigins);"));
// Check that c.com frame's location.ancestorOrigins contains the correct
// origin for its two ancestors. The topmost parent origin should be
@@ -3845,44 +3920,13 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, OriginReplication) {
// (b.com's) origin should be replicated as part of
// mojom::Renderer::CreateFrameProxy sent for b.com's frame in c.com's
// process.
- EXPECT_TRUE(ExecuteScriptAndExtractInt(
- middle_child,
- "window.domAutomationController.send(location.ancestorOrigins.length);",
- &ancestor_origins_length));
- EXPECT_EQ(2, ancestor_origins_length);
- EXPECT_TRUE(ExecuteScriptAndExtractString(
- middle_child,
- "window.domAutomationController.send(location.ancestorOrigins[0]);",
- &result));
- EXPECT_EQ(b_origin, result + "/");
- EXPECT_TRUE(ExecuteScriptAndExtractString(
- middle_child,
- "window.domAutomationController.send(location.ancestorOrigins[1]);",
- &result));
- EXPECT_EQ(a_origin, result + "/");
+ EXPECT_EQ(ListValueOf(b_origin, a_origin),
+ EvalJs(middle_child, "Array.from(location.ancestorOrigins);"));
// Check that the nested a.com frame's location.ancestorOrigins contains the
// correct origin for its three ancestors.
- EXPECT_TRUE(ExecuteScriptAndExtractInt(
- lowest_child,
- "window.domAutomationController.send(location.ancestorOrigins.length);",
- &ancestor_origins_length));
- EXPECT_EQ(3, ancestor_origins_length);
- EXPECT_TRUE(ExecuteScriptAndExtractString(
- lowest_child,
- "window.domAutomationController.send(location.ancestorOrigins[0]);",
- &result));
- EXPECT_EQ(c_origin, result + "/");
- EXPECT_TRUE(ExecuteScriptAndExtractString(
- lowest_child,
- "window.domAutomationController.send(location.ancestorOrigins[1]);",
- &result));
- EXPECT_EQ(b_origin, result + "/");
- EXPECT_TRUE(ExecuteScriptAndExtractString(
- lowest_child,
- "window.domAutomationController.send(location.ancestorOrigins[2]);",
- &result));
- EXPECT_EQ(a_origin, result + "/");
+ EXPECT_EQ(ListValueOf(c_origin, b_origin, a_origin),
+ EvalJs(lowest_child, "Array.from(location.ancestorOrigins);"));
}
// Test that HasReceivedUserGesture and HasReceivedUserGestureBeforeNavigation
@@ -3969,6 +4013,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcesScrollAnchorTest,
// Check that iframe sandbox flags are replicated correctly.
IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, SandboxFlagsReplication) {
GURL main_url(embedded_test_server()->GetURL("/sandboxed_frames.html"));
+ const url::Origin main_origin = url::Origin::Create(main_url);
EXPECT_TRUE(NavigateToURL(shell(), main_url));
// It is safe to obtain the root frame tree node here, as it doesn't change.
@@ -3995,72 +4040,34 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, SandboxFlagsReplication) {
EXPECT_EQ(bar_url, observer.last_navigation_url());
// Opening a popup in the sandboxed foo.com iframe should fail.
- bool success = false;
- EXPECT_TRUE(
- ExecuteScriptAndExtractBool(root->child_at(1),
- "window.domAutomationController.send("
- "!window.open('data:text/html,dataurl'));",
- &success));
- EXPECT_TRUE(success);
+ EXPECT_EQ(false, EvalJs(root->child_at(1),
+ "!!window.open('data:text/html,dataurl');"));
EXPECT_EQ(1u, Shell::windows().size());
// Opening a popup in a frame whose parent is sandboxed should also fail.
// Here, bar.com frame's sandboxed parent frame is a remote frame in
// bar.com's process.
- success = false;
- EXPECT_TRUE(
- ExecuteScriptAndExtractBool(root->child_at(1)->child_at(0),
- "window.domAutomationController.send("
- "!window.open('data:text/html,dataurl'));",
- &success));
- EXPECT_TRUE(success);
+ EXPECT_EQ(false, EvalJs(root->child_at(1)->child_at(0),
+ "!!window.open('data:text/html,dataurl');"));
EXPECT_EQ(1u, Shell::windows().size());
// Same, but now try the case where bar.com frame's sandboxed parent is a
// local frame in bar.com's process.
- success = false;
- EXPECT_TRUE(
- ExecuteScriptAndExtractBool(root->child_at(2)->child_at(0),
- "window.domAutomationController.send("
- "!window.open('data:text/html,dataurl'));",
- &success));
- EXPECT_TRUE(success);
+ EXPECT_EQ(false, EvalJs(root->child_at(2)->child_at(0),
+ "!!window.open('data:text/html,dataurl');"));
EXPECT_EQ(1u, Shell::windows().size());
// Check that foo.com frame's location.ancestorOrigins contains the correct
// origin for the parent, which should be unaffected by sandboxing.
- int ancestor_origins_length = 0;
- EXPECT_TRUE(ExecuteScriptAndExtractInt(
- root->child_at(1),
- "window.domAutomationController.send(location.ancestorOrigins.length);",
- &ancestor_origins_length));
- EXPECT_EQ(1, ancestor_origins_length);
- std::string result;
- EXPECT_TRUE(ExecuteScriptAndExtractString(
- root->child_at(1),
- "window.domAutomationController.send(location.ancestorOrigins[0]);",
- &result));
- EXPECT_EQ(result + "/", main_url.GetOrigin().spec());
+ EXPECT_EQ(ListValueOf(main_origin),
+ EvalJs(root->child_at(1), "Array.from(location.ancestorOrigins);"));
// Now check location.ancestorOrigins for the bar.com frame. The middle frame
// (foo.com's) origin should be unique, since that frame is sandboxed, and
// the top frame should match |main_url|.
- FrameTreeNode* bottom_child = root->child_at(1)->child_at(0);
- EXPECT_TRUE(ExecuteScriptAndExtractInt(
- bottom_child,
- "window.domAutomationController.send(location.ancestorOrigins.length);",
- &ancestor_origins_length));
- EXPECT_EQ(2, ancestor_origins_length);
- EXPECT_TRUE(ExecuteScriptAndExtractString(
- bottom_child,
- "window.domAutomationController.send(location.ancestorOrigins[0]);",
- &result));
- EXPECT_EQ("null", result);
- EXPECT_TRUE(ExecuteScriptAndExtractString(
- bottom_child,
- "window.domAutomationController.send(location.ancestorOrigins[1]);",
- &result));
- EXPECT_EQ(main_url.GetOrigin().spec(), result + "/");
+ EXPECT_EQ(ListValueOf("null", main_origin),
+ EvalJs(root->child_at(1)->child_at(0),
+ "Array.from(location.ancestorOrigins);"));
}
// Check that dynamic updates to iframe sandbox flags are propagated correctly.
@@ -4141,13 +4148,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, DynamicSandboxFlags) {
root->child_at(0)->effective_frame_policy().sandbox_flags);
// Opening a popup in the now-sandboxed frame should fail.
- bool success = false;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(
- root->child_at(0),
- "window.domAutomationController.send("
- " !window.open('data:text/html,dataurl'));",
- &success));
- EXPECT_TRUE(success);
+ EXPECT_EQ(false, EvalJs(root->child_at(0),
+ "!!window.open('data:text/html,dataurl');"));
EXPECT_EQ(1u, Shell::windows().size());
// Navigate the child of the now-sandboxed frame to a page on baz.com. The
@@ -4171,13 +4173,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, DynamicSandboxFlags) {
DepictFrameTree(root));
// Opening a popup in the child of a sandboxed frame should fail.
- success = false;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(
- root->child_at(0)->child_at(0),
- "window.domAutomationController.send("
- " !window.open('data:text/html,dataurl'));",
- &success));
- EXPECT_TRUE(success);
+ EXPECT_EQ(false, EvalJs(root->child_at(0)->child_at(0),
+ "!!window.open('data:text/html,dataurl');"));
EXPECT_EQ(1u, Shell::windows().size());
// Child of a sandboxed frame should also be sandboxed on the browser side.
@@ -4235,24 +4232,14 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
root->child_at(1)->effective_frame_policy().sandbox_flags);
// Opening a popup in the sandboxed second frame should fail.
- bool success = false;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(
- root->child_at(1),
- "window.domAutomationController.send("
- " !window.open('data:text/html,dataurl'));",
- &success));
- EXPECT_TRUE(success);
+ EXPECT_EQ(false, EvalJs(root->child_at(1),
+ "!!window.open('data:text/html,dataurl');"));
EXPECT_EQ(1u, Shell::windows().size());
// Make sure that the child frame inherits the sandbox flags of its
// now-sandboxed parent frame.
- success = false;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(
- root->child_at(1)->child_at(0),
- "window.domAutomationController.send("
- " !window.open('data:text/html,dataurl'));",
- &success));
- EXPECT_TRUE(success);
+ EXPECT_EQ(false, EvalJs(root->child_at(1)->child_at(0),
+ "!!window.open('data:text/html,dataurl');"));
EXPECT_EQ(1u, Shell::windows().size());
}
@@ -4314,13 +4301,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
root->child_at(0)->effective_frame_policy().sandbox_flags);
// Opening a popup in the now-sandboxed frame should fail.
- bool success = false;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(
- root->child_at(0),
- "window.domAutomationController.send("
- " !window.open('data:text/html,dataurl'));",
- &success));
- EXPECT_TRUE(success);
+ EXPECT_EQ(false, EvalJs(root->child_at(0),
+ "!!window.open('data:text/html,dataurl');"));
EXPECT_EQ(1u, Shell::windows().size());
}
@@ -4382,18 +4364,8 @@ IN_PROC_BROWSER_TEST_F(
// Use location.ancestorOrigins to check that the grandchild on baz.com sees
// correct origin for its parent.
- int ancestor_origins_length = 0;
- EXPECT_TRUE(ExecuteScriptAndExtractInt(
- bottom_child,
- "window.domAutomationController.send(location.ancestorOrigins.length);",
- &ancestor_origins_length));
- EXPECT_EQ(2, ancestor_origins_length);
- std::string parent_origin;
- EXPECT_TRUE(ExecuteScriptAndExtractString(
- bottom_child,
- "window.domAutomationController.send(location.ancestorOrigins[0]);",
- &parent_origin));
- EXPECT_EQ(main_url.GetOrigin().spec(), parent_origin + "/");
+ EXPECT_EQ(ListValueOf(url::Origin::Create(main_url)),
+ EvalJs(bottom_child, "Array.from(location.ancestorOrigins);"));
// Check that the sandbox flags in the browser process are correct.
// "allow-scripts" resets both WebSandboxFlags::Scripts and
@@ -4409,13 +4381,8 @@ IN_PROC_BROWSER_TEST_F(
// should not be able to create popups.
EXPECT_EQ(expected_flags,
bottom_child->effective_frame_policy().sandbox_flags);
- bool success = false;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(
- bottom_child,
- "window.domAutomationController.send("
- " !window.open('data:text/html,dataurl'));",
- &success));
- EXPECT_TRUE(success);
+ EXPECT_EQ(false,
+ EvalJs(bottom_child, "!!window.open('data:text/html,dataurl')"));
EXPECT_EQ(1u, Shell::windows().size());
}
@@ -4442,11 +4409,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, WindowNameReplication) {
// Check that the window.name seen by the frame matches the name attribute
// specified by its parent in the iframe tag.
- std::string result;
- EXPECT_TRUE(ExecuteScriptAndExtractString(
- root->child_at(0), "window.domAutomationController.send(window.name);",
- &result));
- EXPECT_EQ("3-1-name", result);
+ EXPECT_EQ("3-1-name", EvalJs(root->child_at(0), "window.name;"));
}
// Verify that dynamic updates to a frame's window.name propagate to the
@@ -4480,26 +4443,15 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, DynamicWindowName) {
// The proxy in the parent process should also receive the updated name.
// Now iframe's name and the content window's name differ, so it shouldn't
// be possible to access to the content window with the updated name.
- bool success = false;
- EXPECT_TRUE(
- ExecuteScriptAndExtractBool(shell(),
- "window.domAutomationController.send("
- " frames['updated-name'] === undefined);",
- &success));
- // TODO(yukishiino): The following expectation should be TRUE, but we're
+ //
+ // TODO(yukishiino): The following expectation should be |true|, but we're
// intentionally disabling the name and origin check of the named access on
// window. See also crbug.com/538562 and crbug.com/701489.
- EXPECT_FALSE(success);
+ EXPECT_EQ(false, EvalJs(shell(), "frames['updated-name'] === undefined;"));
// Change iframe's name to match the content window's name so that it can
// reference the child frame by its new name in case of cross origin.
EXPECT_TRUE(ExecuteScript(root, "window['3-1-id'].name = 'updated-name';"));
- success = false;
- EXPECT_TRUE(
- ExecuteScriptAndExtractBool(shell(),
- "window.domAutomationController.send("
- " frames['updated-name'] == frames[0]);",
- &success));
- EXPECT_TRUE(success);
+ EXPECT_EQ(true, EvalJs(shell(), "frames['updated-name'] == frames[0];"));
// Issue a renderer-initiated navigation from the root frame to the child
// frame using the frame's name. Make sure correct frame is navigated.
@@ -4925,26 +4877,9 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, IndexedFrameAccess) {
DepictFrameTree(root));
// Check that each subframe sees itself at correct index in parent.frames.
- bool success = false;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(
- child0,
- "window.domAutomationController.send(window === parent.frames[0]);",
- &success));
- EXPECT_TRUE(success);
-
- success = false;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(
- child1,
- "window.domAutomationController.send(window === parent.frames[1]);",
- &success));
- EXPECT_TRUE(success);
-
- success = false;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(
- child2,
- "window.domAutomationController.send(window === parent.frames[2]);",
- &success));
- EXPECT_TRUE(success);
+ EXPECT_EQ(true, EvalJs(child0, "window === parent.frames[0];"));
+ EXPECT_EQ(true, EvalJs(child1, "window === parent.frames[1];"));
+ EXPECT_EQ(true, EvalJs(child2, "window === parent.frames[2];"));
// Send a postMessage from B to parent.frames[1], which should go to C, and
// wait for reply.
@@ -5059,12 +4994,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, OpenPopupWithRemoteParent) {
->root();
EXPECT_EQ(root->child_at(0), popup_root->opener());
- std::string opener_url;
- EXPECT_TRUE(ExecuteScriptAndExtractString(
- popup_root,
- "window.domAutomationController.send(window.opener.location.href);",
- &opener_url));
- EXPECT_EQ(frame_url.spec(), opener_url);
+ EXPECT_EQ(frame_url.spec(),
+ EvalJs(popup_root, "window.opener.location.href;"));
// Now try the same with a cross-site popup and make sure it ends up in a new
// process and with a correct opener.
@@ -5087,13 +5018,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, OpenPopupWithRemoteParent) {
// Ensure the popup's window.opener points to the right subframe. Note that
// we can't check the opener's location as above since it's cross-origin.
- bool success = false;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(
- cross_site_popup_root,
- "window.domAutomationController.send("
- " window.opener === window.opener.top.frames[0]);",
- &success));
- EXPECT_TRUE(success);
+ EXPECT_EQ(true, EvalJs(cross_site_popup_root,
+ "window.opener === window.opener.top.frames[0];"));
}
// Test that cross-process popups can't be navigated to disallowed URLs by
@@ -5271,45 +5197,27 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, UpdateSubframeOpener) {
// Update the popup's opener to the second subframe on the main page (which
// is same-origin with the top frame, i.e., foo.com).
- bool success = false;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(
- root->child_at(1),
- "window.domAutomationController.send(!!window.open('','popup'));",
- &success));
- EXPECT_TRUE(success);
+ EXPECT_EQ(true, EvalJs(root->child_at(1), "!!window.open('','popup');"));
// Check that updated opener propagated to the browser process and the
// popup's bar.com process.
EXPECT_EQ(root->child_at(1), popup_root->opener());
- success = false;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(
- popup_shell,
- "window.domAutomationController.send("
- " window.opener === window.opener.parent.frames['frame2']);",
- &success));
- EXPECT_TRUE(success);
+ EXPECT_EQ(true,
+ EvalJs(popup_shell,
+ "window.opener === window.opener.parent.frames['frame2'];"));
// Now update opener on the popup's second subframe (foo.com) to the main
// page's first subframe (bar.com).
- success = false;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(
- root->child_at(0),
- "window.domAutomationController.send(!!window.open('','subframe2'));",
- &success));
- EXPECT_TRUE(success);
+ EXPECT_EQ(true, EvalJs(root->child_at(0), "!!window.open('','subframe2');"));
// Check that updated opener propagated to the browser process and the
// foo.com process.
EXPECT_EQ(root->child_at(0), popup_root->child_at(1)->opener());
- success = false;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(
- popup_root->child_at(1),
- "window.domAutomationController.send("
- " window.opener === window.opener.parent.frames['frame1']);",
- &success));
- EXPECT_TRUE(success);
+ EXPECT_EQ(true,
+ EvalJs(popup_root->child_at(1),
+ "window.opener === window.opener.parent.frames['frame1'];"));
}
// Check that when a subframe navigates to a new SiteInstance, the new
@@ -5343,19 +5251,12 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Check that the new subframe process still sees correct opener for its
// parent by sending a postMessage to subframe's parent.opener.
- bool success = false;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(
- popup_root->child_at(0),
- "window.domAutomationController.send(!!parent.opener);", &success));
- EXPECT_TRUE(success);
+ EXPECT_EQ(true, EvalJs(popup_root->child_at(0), "!!parent.opener;"));
base::string16 expected_title = base::ASCIIToUTF16("msg");
TitleWatcher title_watcher(shell()->web_contents(), expected_title);
- EXPECT_TRUE(ExecuteScriptAndExtractBool(
- popup_root->child_at(0),
- "window.domAutomationController.send(postToOpenerOfParent('msg','*'));",
- &success));
- EXPECT_TRUE(success);
+ EXPECT_EQ(true, EvalJs(popup_root->child_at(0),
+ "postToOpenerOfParent('msg','*');"));
EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
}
@@ -5376,47 +5277,30 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, NavigateSubframeWithOpener) {
DepictFrameTree(root));
// Update the first (cross-site) subframe's opener to root frame.
- bool success = false;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(
- root, "window.domAutomationController.send(!!window.open('','frame1'));",
- &success));
- EXPECT_TRUE(success);
+ EXPECT_EQ(true, EvalJs(root, "!!window.open('','frame1');"));
// Check that updated opener propagated to the browser process and subframe's
// process.
EXPECT_EQ(root, root->child_at(0)->opener());
- success = false;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(
- root->child_at(0),
- "window.domAutomationController.send(window.opener === window.parent);",
- &success));
- EXPECT_TRUE(success);
+ EXPECT_EQ(true,
+ EvalJs(root->child_at(0), "window.opener === window.parent;"));
// Navigate the subframe with opener to another site.
GURL frame_url(embedded_test_server()->GetURL("baz.com", "/title1.html"));
NavigateFrameToURL(root->child_at(0), frame_url);
// Check that the subframe still sees correct opener in its new process.
- success = false;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(
- root->child_at(0),
- "window.domAutomationController.send(window.opener === window.parent);",
- &success));
- EXPECT_TRUE(success);
+ EXPECT_EQ(true,
+ EvalJs(root->child_at(0), "window.opener === window.parent;"));
// Navigate second subframe to a new site. Check that the proxy that's
// created for the first subframe in the new SiteInstance has correct opener.
GURL frame2_url(embedded_test_server()->GetURL("qux.com", "/title1.html"));
NavigateFrameToURL(root->child_at(1), frame2_url);
- success = false;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(
- root->child_at(1),
- "window.domAutomationController.send("
- " parent.frames['frame1'].opener === parent);",
- &success));
- EXPECT_TRUE(success);
+ EXPECT_EQ(true, EvalJs(root->child_at(1),
+ "parent.frames['frame1'].opener === parent;"));
}
// Check that if a subframe has an opener, that opener is preserved when a new
@@ -5452,24 +5336,15 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Update the popup's second subframe's opener to root frame. This is
// allowed because that subframe is in the same foo.com SiteInstance as the
// root frame.
- bool success = false;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(
- root,
- "window.domAutomationController.send(!!window.open('','subframe2'));",
- &success));
- EXPECT_TRUE(success);
+ EXPECT_EQ(true, EvalJs(root, "!!window.open('','subframe2');"));
// Check that the opener update propagated to the browser process and bar.com
// process.
EXPECT_EQ(root, popup_root->child_at(1)->opener());
- success = false;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(
- popup_root->child_at(0),
- "window.domAutomationController.send("
- " parent.frames['subframe2'].opener && "
- " parent.frames['subframe2'].opener === parent.opener);",
- &success));
- EXPECT_TRUE(success);
+ EXPECT_EQ(true,
+ EvalJs(popup_root->child_at(0),
+ "parent.frames['subframe2'].opener && "
+ " parent.frames['subframe2'].opener === parent.opener;"));
// Navigate the popup's first subframe to another site.
GURL frame_url(
@@ -5478,23 +5353,15 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Check that the second subframe's opener is still correct in the first
// subframe's new process. Verify it both in JS and with a postMessage.
- success = false;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(
- popup_root->child_at(0),
- "window.domAutomationController.send("
- " parent.frames['subframe2'].opener && "
- " parent.frames['subframe2'].opener === parent.opener);",
- &success));
- EXPECT_TRUE(success);
+ EXPECT_EQ(true,
+ EvalJs(popup_root->child_at(0),
+ "parent.frames['subframe2'].opener && "
+ " parent.frames['subframe2'].opener === parent.opener;"));
base::string16 expected_title = base::ASCIIToUTF16("msg");
TitleWatcher title_watcher(shell()->web_contents(), expected_title);
- EXPECT_TRUE(ExecuteScriptAndExtractBool(
- popup_root->child_at(0),
- "window.domAutomationController.send("
- " postToOpenerOfSibling('subframe2', 'msg', '*'));",
- &success));
- EXPECT_TRUE(success);
+ EXPECT_EQ(true, EvalJs(popup_root->child_at(0),
+ "postToOpenerOfSibling('subframe2', 'msg', '*');"));
EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
}
@@ -5542,19 +5409,13 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// RenderFrameHost should be pending deletion after the last navigation.
EXPECT_FALSE(rfh->is_active());
- // Wait for process A to exit so we can reinitialize it cleanly for the next
- // navigation. Since process A doesn't have any active views, it will
- // initiate shutdown via ChildProcessHostMsg_ShutdownRequest. After process
- // A shuts down, the |rfh| and |rvh| should get destroyed via
- // OnRenderProcessGone.
- //
- // Not waiting for process shutdown here could lead to the |rvh| being
- // reused, now that there is no notion of pending deletion RenderViewHosts.
- // This would also be fine; however, the race in https://crbug.com/535246
- // still needs to be addressed and tested in that case.
- RenderProcessHostWatcher process_exit_observer(
- rvh->GetProcess(), RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
- process_exit_observer.Wait();
+ // Without the SwapOut ACK and timer, the process A will never shutdown.
+ // Simulate the process being killed now.
+ content::RenderProcessHostWatcher crash_observer(
+ rvh->GetProcess(),
+ content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
+ EXPECT_TRUE(rvh->GetProcess()->Shutdown(0));
+ crash_observer.Wait();
// Verify that the RVH and RFH for A were cleaned up.
EXPECT_FALSE(root->frame_tree()->GetRenderViewHost(site_instance));
@@ -5702,11 +5563,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, DocumentActiveElement) {
const std::string& property,
const std::string& expected_value) {
std::string script = base::StringPrintf(
- "window.domAutomationController.send(document.activeElement.%s);",
- property.c_str());
- std::string result;
- EXPECT_TRUE(ExecuteScriptAndExtractString(rfh, script, &result));
- EXPECT_EQ(expected_value, base::ToLowerASCII(result));
+ "document.activeElement.%s.toLowerCase();", property.c_str());
+ EXPECT_EQ(expected_value, EvalJs(rfh, script));
};
// Verify that document.activeElement on main frame points to the <iframe>
@@ -5764,17 +5622,33 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, SubframeWindowFocus) {
// The main frame should be focused to start with.
EXPECT_EQ(root, root->frame_tree()->GetFocusedFrame());
- DOMMessageQueue msg_queue;
-
// Register focus and blur events that will send messages when each frame's
- // window gets or loses focus.
- const char kSetupFocusEvents[] =
- "window.addEventListener('focus', function() {"
- " domAutomationController.send('%s-got-focus');"
- "});"
- "window.addEventListener('blur', function() {"
- " domAutomationController.send('%s-lost-focus');"
- "});";
+ // window gets or loses focus, and configure some utility functions useful for
+ // waiting for these messages.
+ const char kSetupFocusEvents[] = R"(
+ window.addEventListener('focus', function() {
+ window.top.postMessage('%s-got-focus', '*');
+ });
+ window.addEventListener('blur', function() {
+ window.top.postMessage('%s-lost-focus', '*');
+ });
+ function onEvent(target, eventName, property, value) {
+ return new Promise((resolve, reject) => {
+ function listener(event) {
+ if (event[property] == value) {
+ resolve();
+ target.removeEventListener(eventName, listener);
+ }
+ };
+ target.addEventListener(eventName, listener);
+ });
+ }
+ function expectMessages(messageList) {
+ var promiseList = messageList.map(
+ (dataValue) => onEvent(window, 'message', 'data', dataValue));
+ return Promise.all(promiseList);
+ }
+ )";
std::string script = base::StringPrintf(kSetupFocusEvents, "main", "main");
ExecuteScriptAsync(shell(), script);
script = base::StringPrintf(kSetupFocusEvents, "child1", "child1");
@@ -5783,51 +5657,52 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, SubframeWindowFocus) {
ExecuteScriptAsync(child2, script);
// Execute window.focus on the B subframe from the A main frame.
- ExecuteScriptAsync(root, "frames[0].focus()");
-
- // Helper to wait for two specified messages to arrive on the specified
- // DOMMessageQueue, assuming that the two messages can arrive in any order.
- auto wait_for_two_messages = [](DOMMessageQueue* msg_queue,
- const std::string& msg1,
- const std::string& msg2) {
- bool msg1_received = false;
- bool msg2_received = false;
- std::string status;
- while (msg_queue->WaitForMessage(&status)) {
- if (status == msg1)
- msg1_received = true;
- if (status == msg2)
- msg2_received = true;
- if (msg1_received && msg2_received)
- break;
- }
- };
-
// Process A should fire a blur event, and process B should fire a focus
// event. Wait for both events.
- wait_for_two_messages(&msg_queue, "\"main-lost-focus\"",
- "\"child1-got-focus\"");
+ EXPECT_EQ(true, EvalJs(root, R"((async function() {
+ allMessages = [];
+ window.addEventListener('message', (event) => {
+ allMessages.push(event.data);
+ });
+
+ var messages = expectMessages(['main-lost-focus', 'child1-got-focus']);
+ frames[0].focus();
+ await messages;
+
+ return allMessages.length == 2 || allMessages;
+ })())"));
- // The B subframe should now be focused in the browser process.
EXPECT_EQ(child1, root->frame_tree()->GetFocusedFrame());
// Now, execute window.focus on the C subframe from A main frame. This
// checks that we can shift focus from one remote frame to another.
- ExecuteScriptAsync(root, "frames[1].focus()");
-
+ //
// Wait for the two subframes (B and C) to fire blur and focus events.
- wait_for_two_messages(&msg_queue, "\"child1-lost-focus\"",
- "\"child2-got-focus\"");
+ EXPECT_EQ(true, EvalJs(root, R"((async function() {
+ var messages = expectMessages(['child1-lost-focus', 'child2-got-focus']);
+ frames[1].focus();
+ await messages;
+ return allMessages.length == 4 || allMessages;
+ })())"));
// The C subframe should now be focused.
EXPECT_EQ(child2, root->frame_tree()->GetFocusedFrame());
+ // Install event listeners in the A main frame, expecting the main frame to
+ // obtain focus.
+ EXPECT_TRUE(
+ ExecJs(root,
+ "var messages = "
+ " expectMessages(['child2-lost-focus', 'main-got-focus']);"));
+
// window.focus the main frame from the C subframe.
ExecuteScriptAsync(child2, "parent.focus()");
- // Wait for the C subframe to blur and main frame to focus.
- wait_for_two_messages(&msg_queue, "\"child2-lost-focus\"",
- "\"main-got-focus\"");
+ // Wait for the messages to arrive in the A main frame.
+ EXPECT_EQ(true, EvalJs(root, R"((async function() {
+ await messages;
+ return allMessages.length == 6 || allMessages;
+ })())"));
// The main frame should now be focused.
EXPECT_EQ(root, root->frame_tree()->GetFocusedFrame());
@@ -5928,10 +5803,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Make sure the main frame renderer does not crash and ignores the
// navigation to the frame that's already been deleted.
- int child_count = 0;
- EXPECT_TRUE(ExecuteScriptAndExtractInt(
- root, "domAutomationController.send(frames.length)", &child_count));
- EXPECT_EQ(1, child_count);
+ EXPECT_EQ(1, EvalJs(root, "frames.length"));
}
// Test for a variation of https://crbug.com/526304, where a child frame does a
@@ -5967,10 +5839,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
EXPECT_EQ(1U, root->child_count());
// Make sure the a.com renderer does not crash.
- int child_count = 0;
- EXPECT_TRUE(ExecuteScriptAndExtractInt(
- root, "domAutomationController.send(frames.length)", &child_count));
- EXPECT_EQ(1, child_count);
+ EXPECT_EQ(1, EvalJs(root, "frames.length;"));
}
// Similar to NavigateProxyAndDetachBeforeCommit, but uses a synchronous
@@ -5997,10 +5866,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, NavigateAboutBlankAndDetach) {
observer.Wait();
// Make sure the a.com renderer does not crash and the frame is removed.
- int child_count = 0;
- EXPECT_TRUE(ExecuteScriptAndExtractInt(
- root, "domAutomationController.send(frames.length)", &child_count));
- EXPECT_EQ(0, child_count);
+ EXPECT_EQ(0, EvalJs(root, "frames.length;"));
}
// Test for https://crbug.com/568670. In A-embed-B, simultaneously have B
@@ -6051,10 +5917,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
EXPECT_EQ(0U, root->child_count());
// Make sure process A did not crash.
- int child_count = 0;
- EXPECT_TRUE(ExecuteScriptAndExtractInt(
- root, "domAutomationController.send(frames.length)", &child_count));
- EXPECT_EQ(0, child_count);
+ EXPECT_EQ(0, EvalJs(root, "frames.length;"));
}
// This test ensures that the RenderFrame isn't leaked in the renderer process
@@ -6609,7 +6472,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Check that the grandchild frame isn't sandboxed on the renderer side. If
// sandboxed, its origin would be unique ("null").
- EXPECT_EQ(frame_url.GetOrigin().spec(), GetDocumentOrigin(grandchild) + "/");
+ std::string expected_origin = url::Origin::Create(frame_url).Serialize();
+ EXPECT_EQ(expected_origin, GetDocumentOrigin(grandchild));
}
// Verify that popups opened from sandboxed frames inherit sandbox flags from
@@ -6755,11 +6619,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
foo_root->effective_frame_policy().sandbox_flags);
// The popup's origin should match |b_url|, since it's not sandboxed.
- std::string popup_origin;
- EXPECT_TRUE(ExecuteScriptAndExtractString(
- foo_root, "domAutomationController.send(document.origin)",
- &popup_origin));
- EXPECT_EQ(b_url.GetOrigin().spec(), popup_origin + "/");
+ EXPECT_EQ(url::Origin::Create(b_url).Serialize(),
+ EvalJs(foo_root, "document.origin;"));
}
// Tests that the WebContents is notified when passive mixed content is
@@ -6993,29 +6854,53 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
"document.querySelector('iframe').onload = "
" function() { document.title = 'loaded'; };"));
- GURL blocked_urls[] = {
- embedded_test_server()->GetURL("b.com", "/frame-ancestors-none.html"),
- embedded_test_server()->GetURL("b.com", "/x-frame-options-deny.html")
+ const struct {
+ const char* url;
+ bool use_error_page;
+ } kTestCases[] = {
+ {"/frame-ancestors-none.html", false},
+ {"/x-frame-options-deny.html", true},
};
- for (size_t i = 0; i < arraysize(blocked_urls); ++i) {
+ for (const auto& test : kTestCases) {
+ GURL blocked_url = embedded_test_server()->GetURL("b.com", test.url);
EXPECT_TRUE(ExecuteScript(shell(), "document.title = 'not loaded';"));
base::string16 expected_title(base::UTF8ToUTF16("loaded"));
TitleWatcher title_watcher(shell()->web_contents(), expected_title);
// Navigate the subframe to a blocked URL.
TestNavigationObserver load_observer(shell()->web_contents());
- EXPECT_TRUE(ExecuteScript(shell(), "frames[0].location.href = '" +
- blocked_urls[i].spec() + "';"));
+ EXPECT_TRUE(ExecuteScript(
+ shell(), "frames[0].location.href = '" + blocked_url.spec() + "';"));
load_observer.Wait();
// The blocked frame's origin should become unique.
EXPECT_EQ("null", root->child_at(0)->current_origin().Serialize());
- // Ensure that we don't use the blocked URL as the blocked frame's last
- // committed URL (see https://crbug.com/622385).
- EXPECT_NE(root->child_at(0)->current_frame_host()->GetLastCommittedURL(),
- blocked_urls[i]);
+ // X-Frame-Options and CSP frame-ancestors behave differently. XFO commits
+ // an error page, while CSP commits a "data:," URL.
+ // TODO(https://crbug.com/870815): Use an error page for both.
+ if (test.use_error_page) {
+ EXPECT_FALSE(load_observer.last_navigation_succeeded());
+ EXPECT_EQ(net::ERR_BLOCKED_BY_RESPONSE,
+ load_observer.last_net_error_code());
+ EXPECT_EQ(root->child_at(0)->current_frame_host()->GetLastCommittedURL(),
+ blocked_url);
+ EXPECT_EQ("Error", EvalJs(root->child_at(0), "document.title"));
+ } else {
+ EXPECT_TRUE(load_observer.last_navigation_succeeded());
+ EXPECT_EQ(net::OK, load_observer.last_net_error_code());
+ // Ensure that we don't use the blocked URL as the blocked frame's last
+ // committed URL (see https://crbug.com/622385).
+ EXPECT_EQ(root->child_at(0)->current_frame_host()->GetLastCommittedURL(),
+ GURL("data:,"));
+
+ // The blocked navigation should behave like an empty 200 response. Make
+ // sure that the frame's document.title is empty: this double-checks both
+ // that the blocked URL's contents wasn't loaded, and that the old page
+ // isn't active anymore (both of these pages have non-empty titles).
+ EXPECT_EQ("", EvalJs(root->child_at(0), "document.title"));
+ }
// The blocked frame should still fire a load event in its parent's process.
EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
@@ -7023,16 +6908,6 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Check that the current RenderFrameHost has stopped loading.
EXPECT_FALSE(root->child_at(0)->current_frame_host()->is_loading());
- // The blocked navigation should behave like an empty 200 response. Make
- // sure that the frame's document.title is empty: this double-checks both
- // that the blocked URL's contents wasn't loaded, and that the old page
- // isn't active anymore (both of these pages have non-empty titles).
- std::string frame_title;
- EXPECT_TRUE(ExecuteScriptAndExtractString(
- root->child_at(0), "domAutomationController.send(document.title)",
- &frame_title));
- EXPECT_EQ("", frame_title);
-
// Navigate the subframe to another cross-origin page and ensure that this
// navigation succeeds. Use a renderer-initiated navigation to test the
// transfer logic, which used to have some issues with this.
@@ -7103,19 +6978,11 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// The page should get the title of an error page (i.e "Error") and not the
// title of the blocked page.
- std::string frame_title;
- EXPECT_TRUE(ExecuteScriptAndExtractString(
- root->child_at(0), "domAutomationController.send(document.title)",
- &frame_title));
- EXPECT_EQ("Error", frame_title);
+ EXPECT_EQ("Error", EvalJs(root->child_at(0), "document.title"));
// Navigate to a URL without CSP.
EXPECT_TRUE(NavigateToURL(
shell(), embedded_test_server()->GetURL("a.com", "/title1.html")));
-
- // Verify that the frame's CSP got correctly reset to an empty set.
- EXPECT_EQ(0u,
- root->current_replication_state().accumulated_csp_headers.size());
}
// Test that a cross-origin frame's navigation can be blocked by CSP frame-src.
@@ -7135,12 +7002,12 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
NavigateFrameToURL(root->child_at(0), old_subframe_url);
// Add frame-src CSP via a new <meta> element.
- EXPECT_TRUE(ExecuteScript(
- shell(),
- "var meta = document.createElement('meta');"
- "meta.httpEquiv = 'Content-Security-Policy';"
- "meta.content = 'frame-src https://a.com:*';"
- "document.getElementsByTagName('head')[0].appendChild(meta);"));
+ EXPECT_TRUE(
+ ExecJs(shell(),
+ "var meta = document.createElement('meta');"
+ "meta.httpEquiv = 'Content-Security-Policy';"
+ "meta.content = 'frame-src https://a.com:*';"
+ "document.getElementsByTagName('head')[0].appendChild(meta);"));
// Sanity-check that the test page has the expected shape for testing.
// (the CSP should not have an effect on the already loaded frames).
@@ -7152,18 +7019,18 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
EXPECT_EQ("frame-src https://a.com:*", root_csp[0].header_value);
// Monitor subframe's load events via main frame's title.
- EXPECT_TRUE(ExecuteScript(shell(),
- "document.querySelector('iframe').onload = "
- " function() { document.title = 'loaded'; };"));
- EXPECT_TRUE(ExecuteScript(shell(), "document.title = 'not loaded';"));
+ EXPECT_TRUE(ExecJs(shell(),
+ "document.querySelector('iframe').onload = "
+ " function() { document.title = 'loaded'; };"));
+ EXPECT_TRUE(ExecJs(shell(), "document.title = 'not loaded';"));
base::string16 expected_title(base::UTF8ToUTF16("loaded"));
TitleWatcher title_watcher(shell()->web_contents(), expected_title);
// Try to navigate the subframe to a blocked URL.
TestNavigationObserver load_observer2(shell()->web_contents());
GURL blocked_url = embedded_test_server()->GetURL("c.com", "/title3.html");
- EXPECT_TRUE(ExecuteScript(root->child_at(0), "window.location.href = '" +
- blocked_url.spec() + "';"));
+ EXPECT_TRUE(ExecJs(root->child_at(0),
+ JsReplace("window.location.href = $1;", blocked_url)));
// The blocked frame should still fire a load event in its parent's process.
EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
@@ -7182,11 +7049,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// The page should get the title of an error page (i.e "Error") and not the
// title of the blocked page.
- std::string frame_title;
- EXPECT_TRUE(ExecuteScriptAndExtractString(
- root->child_at(0), "domAutomationController.send(document.title)",
- &frame_title));
- EXPECT_EQ("Error", frame_title);
+ EXPECT_EQ("Error", EvalJs(root->child_at(0), "document.title"));
}
// Test that a cross-origin frame's navigation can be blocked by CSP frame-src.
@@ -7219,24 +7082,23 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Monitor navigating_frame's load events via srcdoc_frame posting
// a message to the parent frame.
+ EXPECT_TRUE(ExecJs(root,
+ "window.addEventListener('message', function(event) {"
+ " document.title = event.data;"
+ "});"));
EXPECT_TRUE(
- ExecuteScript(root,
- "window.addEventListener('message', function(event) {"
- " document.title = event.data;"
- "});"));
- EXPECT_TRUE(ExecuteScript(
- srcdoc_frame,
- "document.querySelector('iframe').onload = "
- " function() { window.top.postMessage('loaded', '*'); };"));
- EXPECT_TRUE(ExecuteScript(shell(), "document.title = 'not loaded';"));
+ ExecJs(srcdoc_frame,
+ "document.querySelector('iframe').onload = "
+ " function() { window.top.postMessage('loaded', '*'); };"));
+ EXPECT_TRUE(ExecJs(shell(), "document.title = 'not loaded';"));
base::string16 expected_title(base::UTF8ToUTF16("loaded"));
TitleWatcher title_watcher(shell()->web_contents(), expected_title);
// Try to navigate the subframe to a blocked URL.
TestNavigationObserver load_observer2(shell()->web_contents());
GURL blocked_url = embedded_test_server()->GetURL("c.com", "/title3.html");
- EXPECT_TRUE(ExecuteScript(navigating_frame, "window.location.href = '" +
- blocked_url.spec() + "';"));
+ EXPECT_TRUE(ExecJs(navigating_frame,
+ JsReplace("window.location.href = $1;", blocked_url)));
// The blocked frame should still fire a load event in its parent's process.
EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
@@ -7255,11 +7117,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// The page should get the title of an error page (i.e "Error") and not the
// title of the blocked page.
- std::string frame_title;
- EXPECT_TRUE(ExecuteScriptAndExtractString(
- navigating_frame, "domAutomationController.send(document.title)",
- &frame_title));
- EXPECT_EQ("Error", frame_title);
+ EXPECT_EQ("Error", EvalJs(navigating_frame, "document.title"));
// Navigate the subframe to a URL without CSP.
NavigateFrameToURL(srcdoc_frame,
@@ -7283,16 +7141,9 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, ScreenCoordinates) {
"outerHeight"};
for (const char* property : properties) {
- std::string script = "window.domAutomationController.send(window.";
- script += property;
- script += ");";
- int root_value = 1;
- int child_value = 2;
- EXPECT_TRUE(ExecuteScriptAndExtractInt(root, script.c_str(), &root_value));
-
- EXPECT_TRUE(
- ExecuteScriptAndExtractInt(child, script.c_str(), &child_value));
-
+ std::string script = base::StringPrintf("window.%s;", property);
+ int root_value = EvalJs(root, script).ExtractInt();
+ int child_value = EvalJs(child, script).ExtractInt();
EXPECT_EQ(root_value, child_value);
}
}
@@ -7337,28 +7188,6 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
EXPECT_FALSE(rvh->is_swapped_out_);
}
-// Helper class to wait for a ShutdownRequest message to arrive.
-class ShutdownObserver : public RenderProcessHostObserver {
- public:
- ShutdownObserver() : message_loop_runner_(new MessageLoopRunner) {}
-
- void RenderProcessShutdownRequested(RenderProcessHost* host) override {
- has_received_shutdown_request_ = true;
- message_loop_runner_->Quit();
- }
-
- void Wait() { message_loop_runner_->Run(); }
-
- bool has_received_shutdown_request() {
- return has_received_shutdown_request_;
- }
-
- private:
- scoped_refptr<MessageLoopRunner> message_loop_runner_;
- bool has_received_shutdown_request_ = false;
- DISALLOW_COPY_AND_ASSIGN(ShutdownObserver);
-};
-
// Test for https://crbug.com/568836. From an A-embed-B page, navigate the
// subframe from B to A. This cleans up the process for B, but the test delays
// the browser side from killing the B process right away. This allows the
@@ -7395,26 +7224,16 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Navigate the subframe away from b.com. Since this is the last active
// frame in the b.com process, this causes the RenderWidget and RenderView to
- // be closed. If this succeeds without crashing, the renderer will release
- // the process and send a ShutdownRequest to the browser
- // process to ask whether it's ok to terminate. Thus, wait for this message
- // to ensure that the RenderView and widget were closed without crashing.
- ShutdownObserver shutdown_observer;
- subframe_process->AddObserver(&shutdown_observer);
+ // be closed.
NavigateFrameToURL(root->child_at(0),
embedded_test_server()->GetURL("a.com", "/title1.html"));
- shutdown_observer.Wait();
- subframe_process->RemoveObserver(&shutdown_observer);
-
- // TODO(alexmos): Navigating the subframe back to b.com at this point would
- // trigger the race in https://crbug.com/535246, where the browser process
- // tries to reuse the b.com process thinking it's still initialized, whereas
- // the process has actually been destroyed by the renderer (but the browser
- // process hasn't heard the OnChannelError yet). This race will need to be
- // fixed.
+ // Release the process.
+ RenderProcessHostWatcher process_shutdown_observer(
+ subframe_process, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
subframe_process->DecrementKeepAliveRefCount(
RenderProcessHostImpl::KeepAliveClientType::kFetch);
+ process_shutdown_observer.Wait();
}
// Tests that an input event targeted to a out-of-process iframe correctly
@@ -7839,11 +7658,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, DetachInUnloadHandler) {
" B = http://b.com/",
DepictFrameTree(root));
- int child_count = 0;
- EXPECT_TRUE(ExecuteScriptAndExtractInt(
- root->child_at(0), "window.domAutomationController.send(frames.length);",
- &child_count));
- EXPECT_EQ(1, child_count);
+ EXPECT_EQ(1, EvalJs(root->child_at(0), "frames.length;"));
RenderFrameDeletedObserver deleted_observer(
root->child_at(0)->child_at(0)->current_frame_host());
@@ -7865,10 +7680,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, DetachInUnloadHandler) {
deleted_observer.WaitUntilDeleted();
- EXPECT_TRUE(ExecuteScriptAndExtractInt(
- root->child_at(0), "window.domAutomationController.send(frames.length);",
- &child_count));
- EXPECT_EQ(0, child_count);
+ EXPECT_EQ(0, EvalJs(root->child_at(0), "frames.length;"));
EXPECT_EQ(
" Site A ------------ proxies for B\n"
@@ -7885,8 +7697,7 @@ class PendingWidgetMessageFilter : public BrowserMessageFilter {
public:
PendingWidgetMessageFilter()
: BrowserMessageFilter(kMessageClasses, arraysize(kMessageClasses)),
- routing_id_(MSG_ROUTING_NONE),
- message_loop_runner_(new MessageLoopRunner) {}
+ routing_id_(MSG_ROUTING_NONE) {}
bool OnMessageReceived(const IPC::Message& message) override {
bool handled = true;
@@ -7898,9 +7709,7 @@ class PendingWidgetMessageFilter : public BrowserMessageFilter {
return handled;
}
- void Wait() {
- message_loop_runner_->Run();
- }
+ void Wait() { run_loop_.Run(); }
int routing_id() { return routing_id_; }
@@ -7926,11 +7735,11 @@ class PendingWidgetMessageFilter : public BrowserMessageFilter {
void OnReceivedRoutingIDOnUI(int widget_routing_id) {
routing_id_ = widget_routing_id;
- message_loop_runner_->Quit();
+ run_loop_.Quit();
}
int routing_id_;
- scoped_refptr<MessageLoopRunner> message_loop_runner_;
+ base::RunLoop run_loop_;
DISALLOW_COPY_AND_ASSIGN(PendingWidgetMessageFilter);
};
@@ -7975,10 +7784,10 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// At this point, we should have two pending WebContents.
EXPECT_TRUE(base::ContainsKey(
web_contents()->pending_contents_,
- std::make_pair(process1->GetID(), filter1->routing_id())));
+ GlobalRoutingID(process1->GetID(), filter1->routing_id())));
EXPECT_TRUE(base::ContainsKey(
web_contents()->pending_contents_,
- std::make_pair(process2->GetID(), filter2->routing_id())));
+ GlobalRoutingID(process2->GetID(), filter2->routing_id())));
// Both subframes were set up in the same way, so the next routing ID for the
// new popup windows should match up (this led to the collision in the
@@ -8053,10 +7862,10 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// At this point, we should have two pending widgets.
EXPECT_TRUE(base::ContainsKey(
web_contents()->pending_widget_views_,
- std::make_pair(process1->GetID(), filter1->routing_id())));
+ GlobalRoutingID(process1->GetID(), filter1->routing_id())));
EXPECT_TRUE(base::ContainsKey(
web_contents()->pending_widget_views_,
- std::make_pair(process2->GetID(), filter2->routing_id())));
+ GlobalRoutingID(process2->GetID(), filter2->routing_id())));
// Both subframes were set up in the same way, so the next routing ID for the
// new popup widgets should match up (this led to the collision in the
@@ -8070,10 +7879,10 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
false, gfx::Rect());
EXPECT_FALSE(base::ContainsKey(
web_contents()->pending_widget_views_,
- std::make_pair(process1->GetID(), filter1->routing_id())));
+ GlobalRoutingID(process1->GetID(), filter1->routing_id())));
EXPECT_FALSE(base::ContainsKey(
web_contents()->pending_widget_views_,
- std::make_pair(process2->GetID(), filter2->routing_id())));
+ GlobalRoutingID(process2->GetID(), filter2->routing_id())));
}
#endif
@@ -8100,13 +7909,9 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, FileChooserInSubframe) {
// Also, extract the file from the renderer process to ensure that the
// response made it over successfully and the proper filename is set.
- std::string file_name;
- EXPECT_TRUE(ExecuteScriptAndExtractString(
- root->child_at(0),
- "window.domAutomationController.send("
- "document.getElementById('fileinput').files[0].name);",
- &file_name));
- EXPECT_EQ("bar", file_name);
+ EXPECT_EQ("bar",
+ EvalJs(root->child_at(0),
+ "document.getElementById('fileinput').files[0].name;"));
}
// Tests that an out-of-process iframe receives the visibilitychange event.
@@ -8126,26 +7931,19 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, VisibilityChange) {
" B = http://b.com/",
DepictFrameTree(root));
- EXPECT_TRUE(ExecuteScript(
- root->child_at(0)->current_frame_host(),
- "var event_fired = 0;\n"
- "document.addEventListener('visibilitychange',\n"
- " function() { event_fired++; });\n"));
+ EXPECT_TRUE(
+ ExecJs(root->child_at(0),
+ "var event_fired = 0;\n"
+ "document.addEventListener('visibilitychange',\n"
+ " function() { event_fired++; });\n"));
shell()->web_contents()->WasHidden();
- int event_fired = 0;
- EXPECT_TRUE(ExecuteScriptAndExtractInt(
- root->child_at(0)->current_frame_host(),
- "window.domAutomationController.send(event_fired);", &event_fired));
- EXPECT_EQ(1, event_fired);
+ EXPECT_EQ(1, EvalJs(root->child_at(0), "event_fired"));
shell()->web_contents()->WasShown();
- EXPECT_TRUE(ExecuteScriptAndExtractInt(
- root->child_at(0)->current_frame_host(),
- "window.domAutomationController.send(event_fired);", &event_fired));
- EXPECT_EQ(2, event_fired);
+ EXPECT_EQ(2, EvalJs(root->child_at(0), "event_fired"));
}
// Test that the pending RenderFrameHost is canceled and destroyed when its
@@ -8336,12 +8134,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, SessionHistoryReplication) {
// Helper to retrieve the history length from a given frame.
auto history_length = [](FrameTreeNode* ftn) {
- int history_length = -1;
- EXPECT_TRUE(ExecuteScriptAndExtractInt(
- ftn->current_frame_host(),
- "window.domAutomationController.send(history.length);",
- &history_length));
- return history_length;
+ return EvalJs(ftn->current_frame_host(), "history.length;");
};
// All frames should see a history length of 1 to start with.
@@ -8484,11 +8277,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, NavigateInUnloadHandler) {
" B = http://b.com/",
DepictFrameTree(root));
- int child_count = 0;
- EXPECT_TRUE(ExecuteScriptAndExtractInt(
- root->child_at(0)->current_frame_host(),
- "window.domAutomationController.send(frames.length);", &child_count));
- EXPECT_EQ(1, child_count);
+ EXPECT_EQ(1,
+ EvalJs(root->child_at(0)->current_frame_host(), "frames.length;"));
// Add an unload handler to B's subframe.
EXPECT_TRUE(
@@ -8514,10 +8304,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, NavigateInUnloadHandler) {
// Check that C's subframe is alive and the navigation in the unload handler
// was ignored.
- EXPECT_TRUE(ExecuteScriptAndExtractInt(
- root->child_at(0)->child_at(0)->current_frame_host(),
- "window.domAutomationController.send(frames.length);", &child_count));
- EXPECT_EQ(0, child_count);
+ EXPECT_EQ(0, EvalJs(root->child_at(0)->child_at(0)->current_frame_host(),
+ "frames.length;"));
EXPECT_EQ(
" Site A ------------ proxies for B C\n"
@@ -8874,13 +8662,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessFeaturePolicyJavaScriptBrowserTest,
// feature. If its parent frame's policy was replicated correctly to the
// proxy, then this will be enabled. Otherwise, it will be disabled, as
// geolocation is disabled by default in cross-origin frames.
- bool success = false;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(
- root->child_at(1)->child_at(0),
- "window.domAutomationController.send("
- "document.policy.allowsFeature('geolocation'));",
- &success));
- EXPECT_TRUE(success);
+ EXPECT_EQ(true, EvalJs(root->child_at(1)->child_at(0),
+ "document.policy.allowsFeature('geolocation')"));
// Now navigate the iframe to a page with no policy, and the same nested
// cross-site iframe. The policy should be cleared in the proxy.
@@ -8893,13 +8676,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessFeaturePolicyJavaScriptBrowserTest,
// Ask the deepest iframe to report the enabled state of the geolocation
// feature. If its parent frame's policy was replicated correctly to the
// proxy, then this will now be disabled.
- success = true;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(
- root->child_at(1)->child_at(0),
- "window.domAutomationController.send("
- "document.policy.allowsFeature('geolocation'));",
- &success));
- EXPECT_FALSE(success);
+ EXPECT_EQ(false, EvalJs(root->child_at(1)->child_at(0),
+ "document.policy.allowsFeature('geolocation')"));
}
// Test that the constructed feature policy is correct in sandboxed
@@ -9096,18 +8874,10 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Ensure the subframe is correctly attached in the frame tree, and that it
// has correct content.
- int child_count = 0;
- EXPECT_TRUE(ExecuteScriptAndExtractInt(
- root, "window.domAutomationController.send(frames.length);",
- &child_count));
- EXPECT_EQ(1, child_count);
+ EXPECT_EQ(1, EvalJs(root, "frames.length;"));
- std::string result;
- EXPECT_TRUE(ExecuteScriptAndExtractString(
- root,
- "window.domAutomationController.send(frames[0].document.body.innerText);",
- &result));
- EXPECT_EQ("This page has no title.", result);
+ EXPECT_EQ("This page has no title.",
+ EvalJs(root, "frames[0].document.body.innerText;"));
}
// Tests that trying to open a context menu in the old RFH after commiting a
@@ -9204,12 +8974,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Helper to check if a frame is allowed to go fullscreen on the renderer
// side.
auto is_fullscreen_allowed = [](FrameTreeNode* ftn) {
- bool fullscreen_allowed = false;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(
- ftn,
- "window.domAutomationController.send(document.webkitFullscreenEnabled)",
- &fullscreen_allowed));
- return fullscreen_allowed;
+ return EvalJs(ftn, "document.webkitFullscreenEnabled;");
};
// Load a page with an <iframe> without allowFullscreen.
@@ -9224,13 +8989,13 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// No change is expected to the container policy for dynamic modification of
// a loaded frame.
- EXPECT_FALSE(is_fullscreen_allowed(root->child_at(0)));
+ EXPECT_EQ(false, is_fullscreen_allowed(root->child_at(0)));
// Cross-site navigation should update the container policy in the new render
// frame.
NavigateFrameToURL(root->child_at(0),
embedded_test_server()->GetURL("c.com", "/title1.html"));
- EXPECT_TRUE(is_fullscreen_allowed(root->child_at(0)));
+ EXPECT_EQ(true, is_fullscreen_allowed(root->child_at(0)));
}
// Test that dynamic updates to iframe sandbox attribute correctly set the
@@ -9528,13 +9293,6 @@ class SitePerProcessAndroidImeTest : public SitePerProcessBrowserTest {
->ime_adapter_for_testing();
}
- std::string GetInputValue(RenderFrameHostImpl* frame) {
- std::string result;
- EXPECT_TRUE(ExecuteScriptAndExtractString(
- frame, "window.domAutomationController.send(input.value);", &result));
- return result;
- }
-
void FocusInputInFrame(RenderFrameHostImpl* frame) {
ASSERT_TRUE(ExecuteScript(frame, "window.focus(); input.focus();"));
}
@@ -9737,12 +9495,9 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, PostTargetSubFrame) {
// Verify that POST body was correctly passed to the server and ended up in
// the body of the page.
- std::string body;
- EXPECT_TRUE(ExecuteScriptAndExtractString(root->child_at(0), R"(
- var body = document.getElementsByTagName('pre')[0].innerText;
- window.domAutomationController.send(body);)",
- &body));
- EXPECT_EQ("my_token=my_value\n", body);
+ EXPECT_EQ("my_token=my_value\n",
+ EvalJs(root->child_at(0),
+ "document.getElementsByTagName('pre')[0].innerText;"));
}
// Tests that POST method and body is not lost when an OOPIF submits a form
@@ -9853,7 +9608,6 @@ class SetIsInertMessageFilter : public content::BrowserMessageFilter {
public:
SetIsInertMessageFilter()
: content::BrowserMessageFilter(FrameMsgStart),
- message_loop_runner_(new content::MessageLoopRunner),
msg_received_(false) {}
bool OnMessageReceived(const IPC::Message& message) override {
@@ -9865,7 +9619,7 @@ class SetIsInertMessageFilter : public content::BrowserMessageFilter {
bool is_inert() const { return is_inert_; }
- void Wait() { message_loop_runner_->Run(); }
+ void Wait() { run_loop_.Run(); }
private:
~SetIsInertMessageFilter() override {}
@@ -9880,10 +9634,10 @@ class SetIsInertMessageFilter : public content::BrowserMessageFilter {
is_inert_ = is_inert;
if (!msg_received_) {
msg_received_ = true;
- message_loop_runner_->Quit();
+ run_loop_.Quit();
}
}
- scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
+ base::RunLoop run_loop_;
bool msg_received_;
bool is_inert_;
DISALLOW_COPY_AND_ASSIGN(SetIsInertMessageFilter);
@@ -10348,6 +10102,76 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
}
#if defined(OS_ANDROID)
+
+namespace {
+
+class MockEventHandlerAndroid : public ui::EventHandlerAndroid {
+ public:
+ bool OnTouchEvent(const ui::MotionEventAndroid& event) override {
+ did_receive_event_ = true;
+ return true;
+ }
+
+ bool did_receive_event() { return did_receive_event_; }
+
+ private:
+ bool did_receive_event_ = false;
+};
+
+} // namespace
+
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ SpeculativeRenderFrameHostDoesNotReceiveInput) {
+ GURL url1(embedded_test_server()->GetURL("a.com", "/title1.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), url1));
+
+ RenderWidgetHostViewAndroid* rwhva =
+ static_cast<RenderWidgetHostViewAndroid*>(
+ shell()->web_contents()->GetRenderWidgetHostView());
+ ui::ViewAndroid* rwhva_native_view = rwhva->GetNativeView();
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+
+ // Start a cross-site navigation.
+ GURL url2(embedded_test_server()->GetURL("b.com", "/title2.html"));
+ TestNavigationManager nav_manager(web_contents(), url2);
+ shell()->LoadURL(url2);
+
+ // Wait for the request, but don't commit it yet. This should create a
+ // speculative RenderFrameHost.
+ ASSERT_TRUE(nav_manager.WaitForRequestStart());
+ RenderFrameHostImpl* root_speculative_rfh =
+ root->render_manager()->speculative_frame_host();
+ EXPECT_TRUE(root_speculative_rfh);
+ RenderWidgetHostViewAndroid* rwhv_speculative =
+ static_cast<RenderWidgetHostViewAndroid*>(
+ root_speculative_rfh->GetView());
+ ui::ViewAndroid* rwhv_speculative_native_view =
+ rwhv_speculative->GetNativeView();
+
+ ui::ViewAndroid* root_view = web_contents()->GetView()->GetNativeView();
+ EXPECT_TRUE(root_view);
+
+ MockEventHandlerAndroid mock_handler;
+ rwhva_native_view->set_event_handler(&mock_handler);
+ MockEventHandlerAndroid mock_handler_speculative;
+ rwhv_speculative_native_view->set_event_handler(&mock_handler_speculative);
+ // Avoid having the root try to handle the following event.
+ root_view->set_event_handler(nullptr);
+
+ auto size = root_view->GetSize();
+ float x = size.width() / 2;
+ float y = size.height() / 2;
+ ui::MotionEventAndroid::Pointer pointer0(0, x, y, 0, 0, 0, 0, 0);
+ ui::MotionEventAndroid::Pointer pointer1(0, 0, 0, 0, 0, 0, 0, 0);
+ ui::MotionEventAndroid event(nullptr, nullptr, 1.f / root_view->GetDipScale(),
+ 0.f, 0.f, 0.f, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ false, &pointer0, &pointer1);
+ root_view->OnTouchEventForTesting(event);
+
+ EXPECT_TRUE(mock_handler.did_receive_event());
+ EXPECT_FALSE(mock_handler_speculative.did_receive_event());
+}
+
IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, TestChildProcessImportance) {
web_contents()->SetMainFrameImportance(ChildProcessImportance::MODERATE);
@@ -11789,6 +11613,100 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, VisibilityFrameDepthTest) {
EXPECT_EQ(0u, popup_process->GetFrameDepth());
}
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ FrameViewportIntersectionTestSimple) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b(c),d,e(f))"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+ scoped_refptr<UpdateViewportIntersectionMessageFilter> root_filter =
+ new UpdateViewportIntersectionMessageFilter();
+ root->current_frame_host()->GetProcess()->AddFilter(root_filter.get());
+
+ scoped_refptr<UpdateViewportIntersectionMessageFilter> child0_filter =
+ new UpdateViewportIntersectionMessageFilter();
+ root->child_at(0)->current_frame_host()->GetProcess()->AddFilter(
+ child0_filter.get());
+
+ scoped_refptr<UpdateViewportIntersectionMessageFilter> child2_filter =
+ new UpdateViewportIntersectionMessageFilter();
+ root->child_at(2)->current_frame_host()->GetProcess()->AddFilter(
+ child2_filter.get());
+
+ // Each immediate child is sized to 100% width and 75% height.
+ LayoutNonRecursiveForTestingViewportIntersection(shell()->web_contents());
+
+ while (true) {
+ base::RunLoop run_loop;
+ root_filter->set_run_loop(&run_loop);
+ child0_filter->set_run_loop(&run_loop);
+ child2_filter->set_run_loop(&run_loop);
+ run_loop.Run();
+ root_filter->set_run_loop(nullptr);
+ child0_filter->set_run_loop(nullptr);
+ child2_filter->set_run_loop(nullptr);
+
+ if ( // Root should always intersect.
+ CheckIntersectsViewport(true, root) &&
+ // Child 0 should be entirely in viewport.
+ CheckIntersectsViewport(true, root->child_at(0)) &&
+ // Grand child should match parent.
+ CheckIntersectsViewport(true, root->child_at(0)->child_at(0)) &&
+ // Child 1 should be partially in viewport.
+ CheckIntersectsViewport(true, root->child_at(1)) &&
+ // Child 2 should be not be in viewport.
+ CheckIntersectsViewport(false, root->child_at(2)) &&
+ // Grand child should match parent.
+ CheckIntersectsViewport(false, root->child_at(2)->child_at(0))) {
+ break;
+ }
+ }
+}
+
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ FrameViewportIntersectionTestAggregate) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b,c,a,b)"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+ scoped_refptr<UpdateViewportIntersectionMessageFilter> filter =
+ new UpdateViewportIntersectionMessageFilter();
+ root->current_frame_host()->GetProcess()->AddFilter(filter.get());
+
+ // Each immediate child is sized to 100% width and 75% height.
+ LayoutNonRecursiveForTestingViewportIntersection(shell()->web_contents());
+
+ while (true) {
+ filter->Wait();
+
+ bool pass = true;
+ {
+ // Child 2 does not intersect, but shares widget with the main frame.
+ FrameTreeNode* node = root->child_at(2);
+ RenderProcessHost::Priority priority =
+ node->current_frame_host()->GetRenderWidgetHost()->GetPriority();
+ pass = pass && priority.intersects_viewport;
+ pass = pass &&
+ node->current_frame_host()->GetProcess()->GetIntersectsViewport();
+ }
+
+ {
+ // Child 3 does not intersect, but shares a process with child 0.
+ FrameTreeNode* node = root->child_at(3);
+ RenderProcessHost::Priority priority =
+ node->current_frame_host()->GetRenderWidgetHost()->GetPriority();
+ pass = pass && !priority.intersects_viewport;
+ pass = pass &&
+ node->current_frame_host()->GetProcess()->GetIntersectsViewport();
+ }
+
+ if (pass)
+ break;
+ }
+}
+
// Ensure that after a main frame with an OOPIF is navigated cross-site, the
// unload handler in the OOPIF sees correct main frame origin, namely the old
// and not the new origin. See https://crbug.com/825283.
@@ -11935,14 +11853,11 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
namespace {
// A helper class that watches for SwapOut ACK messages, allowing them
-// to go through but remembering that the message was received. It also
-// watches for any ShutdownRequests coming from the renderer and ensures that
-// the SwapOut ACK is received prior to those.
+// to go through but remembering that the message was received.
class SwapoutACKReceivedFilter : public BrowserMessageFilter {
public:
explicit SwapoutACKReceivedFilter(RenderProcessHost* process)
: BrowserMessageFilter(FrameMsgStart) {
- process->AddObserver(&shutdown_observer_);
process->AddFilter(this);
}
@@ -11955,17 +11870,12 @@ class SwapoutACKReceivedFilter : public BrowserMessageFilter {
// BrowserMessageFilter:
bool OnMessageReceived(const IPC::Message& message) override {
if (message.type() == FrameHostMsg_SwapOut_ACK::ID) {
- // This ensures that the SwapOut ACK arrived before any
- // renderer-initiated process shutdown requests.
- EXPECT_FALSE(shutdown_observer_.has_received_shutdown_request())
- << " Shutdown request should be received after the swapout ACK";
received_ = true;
}
return false;
}
bool received_ = false;
- ShutdownObserver shutdown_observer_;
DISALLOW_COPY_AND_ASSIGN(SwapoutACKReceivedFilter);
};
@@ -11998,62 +11908,6 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
EXPECT_TRUE(watcher.did_exit_normally());
}
-// Class to monitor incoming FrameHostMsg_UpdateViewportIntersection messages.
-class UpdateViewportIntersectionMessageFilter
- : public content::BrowserMessageFilter {
- public:
- UpdateViewportIntersectionMessageFilter()
- : content::BrowserMessageFilter(FrameMsgStart), msg_received_(false) {}
-
- bool OnMessageReceived(const IPC::Message& message) override {
- IPC_BEGIN_MESSAGE_MAP(UpdateViewportIntersectionMessageFilter, message)
- IPC_MESSAGE_HANDLER(FrameHostMsg_UpdateViewportIntersection,
- OnUpdateViewportIntersection)
- IPC_END_MESSAGE_MAP()
- return false;
- }
-
- gfx::Rect GetCompositingRect() const { return compositing_rect_; }
- gfx::Rect GetViewportIntersection() const { return viewport_intersection_; }
-
- void Wait() {
- DCHECK(!run_loop_);
- if (msg_received_) {
- msg_received_ = false;
- return;
- }
- run_loop_.reset(new base::RunLoop());
- run_loop_->Run();
- run_loop_.reset();
- msg_received_ = false;
- }
-
- private:
- ~UpdateViewportIntersectionMessageFilter() override {}
-
- void OnUpdateViewportIntersection(const gfx::Rect& viewport_intersection,
- const gfx::Rect& compositing_rect) {
- content::BrowserThread::PostTask(
- content::BrowserThread::UI, FROM_HERE,
- base::BindOnce(&UpdateViewportIntersectionMessageFilter::
- OnUpdateViewportIntersectionOnUI,
- this, viewport_intersection, compositing_rect));
- }
- void OnUpdateViewportIntersectionOnUI(const gfx::Rect& viewport_intersection,
- const gfx::Rect& compositing_rect) {
- compositing_rect_ = compositing_rect;
- viewport_intersection_ = viewport_intersection;
- msg_received_ = true;
- if (run_loop_)
- run_loop_->Quit();
- }
- std::unique_ptr<base::RunLoop> run_loop_;
- bool msg_received_;
- gfx::Rect compositing_rect_;
- gfx::Rect viewport_intersection_;
- DISALLOW_COPY_AND_ASSIGN(UpdateViewportIntersectionMessageFilter);
-};
-
// Tests that when a large OOPIF has been scaled, the compositor raster area
// sent from the embedder is correct.
#if defined(OS_ANDROID) || defined(OS_MACOSX)
@@ -12259,8 +12113,16 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Test to verify that viewport intersection is propagated to nested OOPIFs
// even when a parent OOPIF has been throttled.
+// TODO(crbug.com/869758) The test is flaky on android
+#if defined(OS_ANDROID)
+#define MAYBE_NestedFrameViewportIntersectionUpdated \
+ DISABLED_NestedFrameViewportIntersectionUpdated
+#else
+#define MAYBE_NestedFrameViewportIntersectionUpdated \
+ NestedFrameViewportIntersectionUpdated
+#endif
IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
- NestedFrameViewportIntersectionUpdated) {
+ MAYBE_NestedFrameViewportIntersectionUpdated) {
GURL main_url(embedded_test_server()->GetURL(
"foo.com", "/frame_tree/scrollable_page_with_positioned_frame.html"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -12939,13 +12801,12 @@ namespace {
// |web_contents|.
class SameDocumentCommitObserver : public WebContentsObserver {
public:
- SameDocumentCommitObserver(WebContents* web_contents)
- : WebContentsObserver(web_contents),
- message_loop_runner_(new MessageLoopRunner) {
+ explicit SameDocumentCommitObserver(WebContents* web_contents)
+ : WebContentsObserver(web_contents) {
EXPECT_TRUE(web_contents);
}
- void Wait() { message_loop_runner_->Run(); }
+ void Wait() { run_loop_.Run(); }
const GURL& last_committed_url() { return last_committed_url_; }
@@ -12953,12 +12814,12 @@ class SameDocumentCommitObserver : public WebContentsObserver {
void DidFinishNavigation(NavigationHandle* navigation_handle) override {
if (navigation_handle->IsSameDocument()) {
last_committed_url_ = navigation_handle->GetURL();
- message_loop_runner_->Quit();
+ run_loop_.Quit();
}
}
GURL last_committed_url_;
- scoped_refptr<MessageLoopRunner> message_loop_runner_;
+ base::RunLoop run_loop_;
DISALLOW_COPY_AND_ASSIGN(SameDocumentCommitObserver);
};
@@ -13196,4 +13057,172 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
EXPECT_TRUE(b_process_observer.did_exit_normally());
}
+// This observer waits until WebContentsObserver::OnRendererUnresponsive
+// notification.
+class UnresponsiveRendererObserver : public WebContentsObserver {
+ public:
+ explicit UnresponsiveRendererObserver(WebContents* web_contents)
+ : WebContentsObserver(web_contents) {}
+
+ ~UnresponsiveRendererObserver() override {}
+
+ RenderProcessHost* Wait(base::TimeDelta timeout = base::TimeDelta::Max()) {
+ if (!captured_render_process_host_) {
+ base::OneShotTimer timer;
+ timer.Start(FROM_HERE, timeout, run_loop_.QuitClosure());
+ run_loop_.Run();
+ timer.Stop();
+ }
+ return captured_render_process_host_;
+ }
+
+ private:
+ void OnRendererUnresponsive(RenderProcessHost* render_process_host) override {
+ captured_render_process_host_ = render_process_host;
+ run_loop_.Quit();
+ }
+
+ RenderProcessHost* captured_render_process_host_ = nullptr;
+ base::RunLoop run_loop_;
+
+ DISALLOW_COPY_AND_ASSIGN(UnresponsiveRendererObserver);
+};
+
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ CommitTimeoutForHungRenderer) {
+ // Navigate first tab to a.com.
+ GURL a_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), a_url));
+ RenderProcessHost* a_process =
+ shell()->web_contents()->GetMainFrame()->GetProcess();
+
+ // Open b.com in a second tab. Using a renderer-initiated navigation is
+ // important to leave a.com and b.com SiteInstances in the same
+ // BrowsingInstance (so the b.com -> a.com navigation in the next test step
+ // will reuse the process associated with the first a.com tab).
+ GURL b_url(embedded_test_server()->GetURL("b.com", "/title2.html"));
+ Shell* new_shell = OpenPopup(shell()->web_contents(), b_url, "newtab");
+ WebContents* new_contents = new_shell->web_contents();
+ EXPECT_TRUE(WaitForLoadStop(new_contents));
+ RenderProcessHost* b_process = new_contents->GetMainFrame()->GetProcess();
+ EXPECT_NE(a_process, b_process);
+
+ // Hang the first tab's renderer.
+ const char* kHungScript = "setTimeout(function() { for (;;) {}; }, 0);";
+ EXPECT_TRUE(ExecuteScript(shell()->web_contents(), kHungScript));
+
+ // Attempt to navigate the second tab to a.com. This will attempt to reuse
+ // the hung process.
+ NavigationHandleImpl::SetCommitTimeoutForTesting(
+ base::TimeDelta::FromMilliseconds(100));
+ GURL hung_url(embedded_test_server()->GetURL("a.com", "/title3.html"));
+ UnresponsiveRendererObserver unresponsive_renderer_observer(new_contents);
+ EXPECT_TRUE(
+ ExecJs(new_contents, JsReplace("window.location = $1", hung_url)));
+
+ // Verify that we will be notified about the unresponsive renderer. Before
+ // changes in https://crrev.com/c/1089797, the test would hang here forever.
+ RenderProcessHost* hung_process = unresponsive_renderer_observer.Wait();
+ EXPECT_EQ(hung_process, a_process);
+
+ // Reset the timeout.
+ NavigationHandleImpl::SetCommitTimeoutForTesting(base::TimeDelta());
+}
+
+// This is a regression test for https://crbug.com/881812 which complained that
+// the hung renderer dialog used to undesirably show up for background tabs
+// (typically during session restore when many navigations would be happening in
+// backgrounded processes).
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ CommitTimeoutForInvisibleWebContents) {
+ // Navigate first tab to a.com.
+ GURL a_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), a_url));
+ RenderProcessHost* a_process =
+ shell()->web_contents()->GetMainFrame()->GetProcess();
+
+ // Open b.com in a second tab. Using a renderer-initiated navigation is
+ // important to leave a.com and b.com SiteInstances in the same
+ // BrowsingInstance (so the b.com -> a.com navigation in the next test step
+ // will reuse the process associated with the first a.com tab).
+ GURL b_url(embedded_test_server()->GetURL("b.com", "/title2.html"));
+ Shell* new_shell = OpenPopup(shell()->web_contents(), b_url, "newtab");
+ WebContents* new_contents = new_shell->web_contents();
+ EXPECT_TRUE(WaitForLoadStop(new_contents));
+ RenderProcessHost* b_process = new_contents->GetMainFrame()->GetProcess();
+ EXPECT_NE(a_process, b_process);
+
+ // Hang the first tab's renderer.
+ const char* kHungScript = "setTimeout(function() { for (;;) {}; }, 0);";
+ EXPECT_TRUE(ExecuteScript(shell()->web_contents(), kHungScript));
+
+ // Hide the second tab. This should prevent reporting of hangs in this tab
+ // (see https://crbug.com/881812).
+ new_contents->WasHidden();
+ EXPECT_EQ(Visibility::HIDDEN, new_contents->GetVisibility());
+
+ // Attempt to navigate the second tab to a.com. This will attempt to reuse
+ // the hung process.
+ base::TimeDelta kTimeout = base::TimeDelta::FromMilliseconds(100);
+ NavigationHandleImpl::SetCommitTimeoutForTesting(kTimeout);
+ GURL hung_url(embedded_test_server()->GetURL("a.com", "/title3.html"));
+ UnresponsiveRendererObserver unresponsive_renderer_observer(new_contents);
+ EXPECT_TRUE(
+ ExecJs(new_contents, JsReplace("window.location = $1", hung_url)));
+
+ // Verify that we will not be notified about the unresponsive renderer.
+ // Before changes in https://crrev.com/c/1089797, the test would get notified
+ // and therefore |hung_process| would be non-null.
+ RenderProcessHost* hung_process =
+ unresponsive_renderer_observer.Wait(kTimeout * 10);
+ EXPECT_FALSE(hung_process);
+
+ // Reset the timeout.
+ NavigationHandleImpl::SetCommitTimeoutForTesting(base::TimeDelta());
+}
+
+// Tests that an inner WebContents will reattach to its outer WebContents after
+// a navigation that causes a process swap.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, ProcessSwapOnInnerContents) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(a)"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ FrameTreeNode* child_frame =
+ web_contents()->GetFrameTree()->root()->child_at(0);
+ WebContentsImpl* inner_contents =
+ static_cast<WebContentsImpl*>(CreateAndAttachInnerContents(
+ ToRenderFrameHost(child_frame).render_frame_host()));
+ FrameTreeNode* inner_contents_root = inner_contents->GetFrameTree()->root();
+ RenderFrameProxyHost* outer_proxy =
+ inner_contents_root->render_manager()->GetProxyToOuterDelegate();
+ CrossProcessFrameConnector* outer_connector =
+ outer_proxy->cross_process_frame_connector();
+ EXPECT_NE(nullptr, outer_connector->get_view_for_testing());
+
+ GURL a_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+ NavigateFrameToURL(inner_contents_root, a_url);
+ SiteInstance* a_site_instance =
+ inner_contents->GetMainFrame()->GetSiteInstance();
+ RenderProcessHost* a_process = a_site_instance->GetProcess();
+ RenderWidgetHostViewChildFrame* a_view =
+ outer_connector->get_view_for_testing();
+
+ GURL b_url(embedded_test_server()->GetURL("b.com", "/title1.html"));
+ NavigateFrameToURL(inner_contents_root, b_url);
+ SiteInstance* b_site_instance =
+ inner_contents->GetMainFrame()->GetSiteInstance();
+ RenderProcessHost* b_process = b_site_instance->GetProcess();
+ RenderWidgetHostViewChildFrame* b_view =
+ outer_connector->get_view_for_testing();
+
+ // Ensure that the SiteInstances have changed, we've completed a process swap
+ // and reattached the inner WebContents creating a new RenderWidgetHostView.
+ EXPECT_NE(a_site_instance, b_site_instance);
+ EXPECT_NE(a_process, b_process);
+ EXPECT_NE(nullptr, a_view);
+ EXPECT_NE(nullptr, b_view);
+ EXPECT_NE(a_view, b_view);
+}
+
} // 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 c8ab9dd5684..dc73deb2e4c 100644
--- a/chromium/content/browser/site_per_process_hit_test_browsertest.cc
+++ b/chromium/content/browser/site_per_process_hit_test_browsertest.cc
@@ -14,7 +14,9 @@
#include "base/test/test_timeouts.h"
#include "build/build_config.h"
#include "components/viz/common/features.h"
+#include "content/browser/compositor/surface_utils.h"
#include "content/browser/renderer_host/cursor_manager.h"
+#include "content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h"
#include "content/browser/renderer_host/input/synthetic_tap_gesture.h"
#include "content/browser/renderer_host/input/touch_emulator.h"
#include "content/browser/renderer_host/render_widget_host_input_event_router.h"
@@ -37,12 +39,14 @@
#include "ui/events/base_event_utils.h"
#include "ui/events/gesture_detection/gesture_configuration.h"
#include "ui/events/gesture_detection/gesture_provider_config_helper.h"
+#include "ui/gfx/geometry/quad_f.h"
#if defined(USE_AURA)
#include "content/browser/renderer_host/render_widget_host_view_aura.h"
#include "content/public/browser/overscroll_configuration.h"
#include "content/test/mock_overscroll_controller_delegate_aura.h"
#include "ui/aura/window_tree_host.h"
+#include "ui/events/event_rewriter.h"
#endif
#if defined(OS_MACOSX)
@@ -54,6 +58,10 @@
#include "content/test/mock_overscroll_refresh_handler_android.h"
#endif
+#if defined(OS_WIN)
+#include "base/debug/stack_trace.h"
+#endif
+
namespace content {
namespace {
@@ -190,8 +198,10 @@ void RouteMouseEventAndWaitUntilDispatch(
waiter.Wait();
}
+// Dispatch |event| to the specified view using browser process hit testing.
void DispatchMouseEventAndWaitUntilDispatch(
WebContentsImpl* web_contents,
+ blink::WebMouseEvent& event,
RenderWidgetHostViewBase* location_view,
const gfx::PointF& location,
RenderWidgetHostViewBase* expected_target,
@@ -202,22 +212,37 @@ void DispatchMouseEventAndWaitUntilDispatch(
expected_target->GetRenderWidgetHost());
gfx::PointF root_location =
location_view->TransformPointToRootCoordSpaceF(location);
- blink::WebMouseEvent down_event(
- blink::WebInputEvent::kMouseDown, blink::WebInputEvent::kNoModifiers,
- blink::WebInputEvent::GetStaticTimeStampForTests());
- down_event.button = blink::WebPointerProperties::Button::kLeft;
- down_event.click_count = 1;
FrameTreeNode* root = web_contents->GetFrameTree()->root();
auto* root_view = static_cast<RenderWidgetHostViewBase*>(
root->current_frame_host()->GetRenderWidgetHost()->GetView());
- SetWebEventPositions(&down_event, root_location, root_view);
+ SetWebEventPositions(&event, root_location, root_view);
RouteMouseEventAndWaitUntilDispatch(router, root_view, expected_target,
- &down_event);
+ &event);
EXPECT_TRUE(monitor.EventWasReceived());
- EXPECT_NEAR(expected_location.x(), monitor.event().PositionInWidget().x, 2);
+ EXPECT_NEAR(expected_location.x(), monitor.event().PositionInWidget().x, 2)
+ << " & original location was " << location.x() << ", " << location.y()
+ << " & root_location was " << root_location.x() << ", "
+ << root_location.y();
EXPECT_NEAR(expected_location.y(), monitor.event().PositionInWidget().y, 2);
}
+// Wrapper for the above method that creates a MouseDown to send.
+void DispatchMouseEventAndWaitUntilDispatch(
+ WebContentsImpl* web_contents,
+ RenderWidgetHostViewBase* location_view,
+ const gfx::PointF& location,
+ RenderWidgetHostViewBase* expected_target,
+ const gfx::PointF& expected_location) {
+ blink::WebMouseEvent down_event(
+ blink::WebInputEvent::kMouseDown, blink::WebInputEvent::kNoModifiers,
+ blink::WebInputEvent::GetStaticTimeStampForTests());
+ down_event.button = blink::WebPointerProperties::Button::kLeft;
+ down_event.click_count = 1;
+ DispatchMouseEventAndWaitUntilDispatch(web_contents, down_event,
+ location_view, location,
+ expected_target, expected_location);
+}
+
// Helper function that performs a surface hittest.
void SurfaceHitTestTestHelper(
Shell* shell,
@@ -288,6 +313,71 @@ void OverlapSurfaceHitTestHelper(
gfx::PointF(95, 95));
}
+void NonFlatTransformedSurfaceHitTestHelper(
+ Shell* shell,
+ net::test_server::EmbeddedTestServer* embedded_test_server) {
+ GURL main_url(embedded_test_server->GetURL(
+ "/frame_tree/page_with_non_flat_transformed_frame.html"));
+ EXPECT_TRUE(NavigateToURL(shell, main_url));
+ auto* web_contents = static_cast<WebContentsImpl*>(shell->web_contents());
+
+ FrameTreeNode* root = web_contents->GetFrameTree()->root();
+ ASSERT_EQ(1U, root->child_count());
+
+ FrameTreeNode* child_node = root->child_at(0);
+ GURL site_url(embedded_test_server->GetURL("baz.com", "/title1.html"));
+ EXPECT_EQ(site_url, child_node->current_url());
+ EXPECT_NE(shell->web_contents()->GetSiteInstance(),
+ child_node->current_frame_host()->GetSiteInstance());
+
+ RenderWidgetHostViewBase* rwhv_child = static_cast<RenderWidgetHostViewBase*>(
+ child_node->current_frame_host()->GetRenderWidgetHost()->GetView());
+
+ WaitForHitTestDataOrChildSurfaceReady(child_node->current_frame_host());
+
+ DispatchMouseEventAndWaitUntilDispatch(web_contents, rwhv_child,
+ gfx::PointF(5, 5), rwhv_child,
+ gfx::PointF(5, 5));
+}
+
+void PerspectiveTransformedSurfaceHitTestHelper(
+ Shell* shell,
+ net::test_server::EmbeddedTestServer* embedded_test_server) {
+ GURL main_url(embedded_test_server->GetURL(
+ "/frame_tree/page_with_perspective_transformed_frame.html"));
+ EXPECT_TRUE(NavigateToURL(shell, main_url));
+ auto* web_contents = static_cast<WebContentsImpl*>(shell->web_contents());
+
+ RenderFrameSubmissionObserver render_frame_submission_observer(web_contents);
+
+ FrameTreeNode* root = web_contents->GetFrameTree()->root();
+ ASSERT_EQ(1U, root->child_count());
+
+ FrameTreeNode* child_node = root->child_at(0);
+ GURL site_url(embedded_test_server->GetURL("baz.com", "/title1.html"));
+ EXPECT_EQ(site_url, child_node->current_url());
+ EXPECT_NE(shell->web_contents()->GetSiteInstance(),
+ child_node->current_frame_host()->GetSiteInstance());
+
+ RenderWidgetHostViewBase* rwhv_root = static_cast<RenderWidgetHostViewBase*>(
+ root->current_frame_host()->GetRenderWidgetHost()->GetView());
+ RenderWidgetHostViewBase* rwhv_child = static_cast<RenderWidgetHostViewBase*>(
+ child_node->current_frame_host()->GetRenderWidgetHost()->GetView());
+
+ WaitForHitTestDataOrChildSurfaceReady(child_node->current_frame_host());
+
+ // (90, 75) hit tests into the child frame that is positioned at (50, 50).
+ // Without other transformations this should result in a translated point
+ // of (40, 25), but the 45 degree 3-dimensional rotation of the frame about
+ // a vertical axis skews it.
+ // We can't allow DispatchMouseEventAndWaitUntilDispatch to compute the
+ // coordinates in the root space unless browser conversions with
+ // perspective transforms are first fixed. See https://crbug.com/854257.
+ DispatchMouseEventAndWaitUntilDispatch(web_contents, rwhv_root,
+ gfx::PointF(90, 75), rwhv_child,
+ gfx::PointF(33, 23));
+}
+
// Helper function that performs a surface hittest in nested frame.
void NestedSurfaceHitTestTestHelper(
Shell* shell,
@@ -416,10 +506,14 @@ void HitTestWatermark(
// Set 'pointer-events: none' on the div.
EXPECT_TRUE(ExecuteScript(web_contents, "W.style.pointerEvents = 'none';"));
+ // TODO(sunxd): Re-enable this test when surface layer hit test is able to
+ // handle pointer-events none. See https://crbug.com/841358.
// Dispatch another event at the same location. It should reach the oopif this
// time.
- DispatchMouseEventAndWaitUntilDispatch(
- web_contents, rwhv_child, child_location, rwhv_child, child_location);
+ if (!features::IsVizHitTestingSurfaceLayerEnabled()) {
+ DispatchMouseEventAndWaitUntilDispatch(
+ web_contents, rwhv_child, child_location, rwhv_child, child_location);
+ }
}
#if defined(USE_AURA)
@@ -569,6 +663,34 @@ class SetMouseCaptureInterceptor
DISALLOW_COPY_AND_ASSIGN(SetMouseCaptureInterceptor);
};
+#if defined(USE_AURA)
+// A class to allow intercepting and discarding of system-level mouse events
+// that might otherwise cause unpredictable behaviour in tests.
+class MouseEventRewriter : public ui::EventRewriter {
+ public:
+ MouseEventRewriter() = default;
+ ~MouseEventRewriter() override {}
+
+ private:
+ ui::EventRewriteStatus RewriteEvent(
+ const ui::Event& event,
+ std::unique_ptr<ui::Event>* new_event) override {
+ if (event.IsMouseEvent())
+ return ui::EVENT_REWRITE_DISCARD;
+ return ui::EVENT_REWRITE_CONTINUE;
+ }
+
+ ui::EventRewriteStatus NextDispatchEvent(
+ const ui::Event& event,
+ std::unique_ptr<ui::Event>* new_event) override {
+ NOTREACHED();
+ return ui::EVENT_REWRITE_CONTINUE;
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(MouseEventRewriter);
+};
+#endif
+
} // namespace
class SitePerProcessHitTestBrowserTest
@@ -577,6 +699,19 @@ class SitePerProcessHitTestBrowserTest
public:
SitePerProcessHitTestBrowserTest() {}
+#if defined(USE_AURA)
+ void PreRunTestOnMainThread() override {
+ SitePerProcessBrowserTest::PreRunTestOnMainThread();
+ // Disable system mouse events, which can interfere with tests.
+ shell()->window()->GetHost()->AddEventRewriter(&event_rewriter);
+ }
+
+ void PostRunTestOnMainThread() override {
+ shell()->window()->GetHost()->RemoveEventRewriter(&event_rewriter);
+ SitePerProcessBrowserTest::PostRunTestOnMainThread();
+ }
+#endif
+
protected:
void SetUpCommandLine(base::CommandLine* command_line) override {
SitePerProcessBrowserTest::SetUpCommandLine(command_line);
@@ -592,6 +727,9 @@ class SitePerProcessHitTestBrowserTest
}
base::test::ScopedFeatureList feature_list_;
+#if defined(USE_AURA)
+ MouseEventRewriter event_rewriter;
+#endif
};
//
@@ -1042,14 +1180,6 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
scroll_end_observer.Wait();
}
-#if defined(OS_LINUX)
-// The test is flaky on Linux: https://crbug.com/833380.
-#define MAYBE_BubbledScrollEventsTransformedCorrectly \
- DISABLED_BubbledScrollEventsTransformedCorrectly
-#else
-#define MAYBE_BubbledScrollEventsTransformedCorrectly \
- BubbledScrollEventsTransformedCorrectly
-#endif
// When a scroll event is bubbled, ensure that the bubbled event's coordinates
// are correctly updated to the ancestor's coordinate space. In particular,
// ensure that the transformation considers CSS scaling of the child where
@@ -1057,7 +1187,7 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
// coordinates in the ancestor's coordinate space.
// See https://crbug.com/817392
IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
- MAYBE_BubbledScrollEventsTransformedCorrectly) {
+ BubbledScrollEventsTransformedCorrectly) {
GURL main_url(embedded_test_server()->GetURL(
"/frame_tree/page_with_positioned_scaled_frame.html"));
ASSERT_TRUE(NavigateToURL(shell(), main_url));
@@ -1125,10 +1255,57 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
root_scroll_begin_observer.Wait();
}
+#if defined(OS_WIN)
+// Add temporary TouchMove event observer to detect spurious TouchMove events
+// leading to test flake.
+// https://crbug.com/833380.
+class EmulatedTouchTouchMoveInputObserver
+ : public RenderWidgetHost::InputEventObserver {
+ public:
+ explicit EmulatedTouchTouchMoveInputObserver(RenderWidgetHost* host)
+ : host_(host), first_touch_move_seen_(false) {
+ host_->AddInputEventObserver(this);
+ }
+ ~EmulatedTouchTouchMoveInputObserver() override {
+ host_->RemoveInputEventObserver(this);
+ }
+
+ void OnInputEvent(const blink::WebInputEvent& event) override {
+ if (event.GetType() != blink::WebInputEvent::kTouchMove)
+ return;
+
+ const blink::WebTouchEvent& touch_event =
+ static_cast<const blink::WebTouchEvent&>(event);
+ blink::WebFloatPoint pos_in_widget =
+ touch_event.touches[0].PositionInWidget();
+ blink::WebFloatPoint pos_in_screen =
+ touch_event.touches[0].PositionInScreen();
+ LOG(ERROR) << "TouchMove seen: widget @ (" << pos_in_widget.x << ","
+ << pos_in_widget.y << "), screen @ (" << pos_in_screen.x << ","
+ << pos_in_screen.y << ")";
+
+ if (first_touch_move_seen_)
+ return;
+
+ first_touch_move_seen_ = true;
+ base::debug::StackTrace().Print();
+ }
+
+ private:
+ RenderWidgetHost* host_;
+ bool first_touch_move_seen_;
+};
+#endif
+
class SitePerProcessEmulatedTouchBrowserTest
: public SitePerProcessHitTestBrowserTest {
public:
- enum TestType { ScrollBubbling, PinchGoesToMainFrame, TouchActionBubbling };
+ enum TestType {
+ ScrollBubbling,
+ PinchGoesToMainFrame,
+ TouchActionBubbling,
+ ShowPressHasTouchID
+ };
~SitePerProcessEmulatedTouchBrowserTest() override {}
@@ -1167,6 +1344,17 @@ class SitePerProcessEmulatedTouchBrowserTest
[](blink::WebInputEvent::Type expected_type,
const gfx::Point& expected_position, content::InputEventAckSource,
content::InputEventAckState, const blink::WebInputEvent& event) {
+#if defined(OS_WIN)
+ // Add some logging to diagnose a potential source of flake:
+ // the hypothesis is that something is causing the gesture
+ // stream to cancel before kGestureShowPress is generated, so
+ // we'll dump the event stream that we actually see in this case.
+ // https://crbug.com/833380.
+ if (expected_type == blink::WebInputEvent::kGestureShowPress) {
+ LOG(ERROR) << "Waiting for: kGestureShowPress: ack seen for "
+ << blink::WebInputEvent::GetName(event.GetType());
+ }
+#endif
if (event.GetType() != expected_type)
return false;
@@ -1178,6 +1366,10 @@ class SitePerProcessEmulatedTouchBrowserTest
1);
EXPECT_EQ(blink::kWebGestureDeviceTouchscreen,
gesture_event.SourceDevice());
+ // We expect all gesture events to have non-zero ids otherwise they
+ // can force hit-testing in RenderWidgetHostInputEventRouter even
+ // when it's unnecessary.
+ EXPECT_NE(0U, gesture_event.unique_touch_event_id);
return true;
});
@@ -1190,10 +1382,22 @@ class SitePerProcessEmulatedTouchBrowserTest
case PinchGoesToMainFrame:
expected_gesture_type = blink::WebInputEvent::kGesturePinchBegin;
break;
+ case ShowPressHasTouchID:
+ expected_gesture_type = blink::WebInputEvent::kGestureShowPress;
+ break;
default:
ASSERT_TRUE(false);
}
+#if defined(OS_WIN)
+ {
+ gfx::Rect view_bounds = root_rwhv->GetViewBounds();
+ LOG(ERROR) << "Root view bounds = (" << view_bounds.x() << ","
+ << view_bounds.y() << ") " << view_bounds.width() << " x "
+ << view_bounds.height();
+ }
+#endif
+
gfx::Point position_in_child(5, 5);
InputEventAckWaiter child_gesture_event_observer(
child_rwhv->GetRenderWidgetHost(),
@@ -1251,9 +1455,29 @@ class SitePerProcessEmulatedTouchBrowserTest
simulated_event_time += simulated_event_time_delta;
mouse_up_event.SetTimeStamp(simulated_event_time);
+#if defined(OS_WIN)
+ // Add temporary TouchMove event observer to detect spurious TouchMove
+ // events leading to test flake.
+ // https://crbug.com/833380.
+ std::unique_ptr<EmulatedTouchTouchMoveInputObserver> touch_move_observer;
+ if (test_type == ShowPressHasTouchID) {
+ touch_move_observer.reset(new EmulatedTouchTouchMoveInputObserver(
+ child_rwhv->GetRenderWidgetHost()));
+ }
+#endif
+
// Send mouse events and wait for GesturePinchBegin.
router->RouteMouseEvent(root_rwhv, &mouse_move_event, ui::LatencyInfo());
router->RouteMouseEvent(root_rwhv, &mouse_down_event, ui::LatencyInfo());
+ if (test_type == ShowPressHasTouchID) {
+ // Wait for child to receive GestureShowPress. If this test fails, it
+ // will either DCHECK or time out.
+ child_gesture_event_observer.Wait();
+#if defined(OS_WIN)
+ touch_move_observer.reset();
+#endif
+ return;
+ }
router->RouteMouseEvent(root_rwhv, &mouse_drag_event, ui::LatencyInfo());
router->RouteMouseEvent(root_rwhv, &mouse_up_event, ui::LatencyInfo());
@@ -1271,43 +1495,126 @@ class SitePerProcessEmulatedTouchBrowserTest
}
};
-#if defined(OS_CHROMEOS)
-// Flaky: https://crbug.com/833380
-#define MAYBE_EmulatedTouchScrollBubbles DISABLED_EmulatedTouchScrollBubbles
-#else
-#define MAYBE_EmulatedTouchScrollBubbles EmulatedTouchScrollBubbles
-#endif
+IN_PROC_BROWSER_TEST_P(SitePerProcessEmulatedTouchBrowserTest,
+ EmulatedTouchShowPressHasTouchID) {
+ RunTest(ShowPressHasTouchID);
+}
IN_PROC_BROWSER_TEST_P(SitePerProcessEmulatedTouchBrowserTest,
- MAYBE_EmulatedTouchScrollBubbles) {
+ EmulatedTouchScrollBubbles) {
RunTest(ScrollBubbling);
}
-#if defined(OS_LINUX)
-// Flaky: https://crbug.com/833380
-#define MAYBE_EmulatedTouchPinchGoesToMainFrame \
- DISABLED_EmulatedTouchPinchGoesToMainFrame
-#else
-#define MAYBE_EmulatedTouchPinchGoesToMainFrame \
- EmulatedTouchPinchGoesToMainFrame
-#endif
IN_PROC_BROWSER_TEST_P(SitePerProcessEmulatedTouchBrowserTest,
- MAYBE_EmulatedTouchPinchGoesToMainFrame) {
+ EmulatedTouchPinchGoesToMainFrame) {
RunTest(PinchGoesToMainFrame);
}
-#if defined(OS_CHROMEOS)
-// Flaky timeouts: https://crbug.com/833380
-#define MAYBE_EmulatedGestureScrollBubbles DISABLED_EmulatedGestureScrollBubbles
-#else
-#define MAYBE_EmulatedGestureScrollBubbles EmulatedGestureScrollBubbles
-#endif
-
IN_PROC_BROWSER_TEST_P(SitePerProcessEmulatedTouchBrowserTest,
- MAYBE_EmulatedGestureScrollBubbles) {
+ EmulatedGestureScrollBubbles) {
RunTest(TouchActionBubbling);
}
+#if defined(OS_ANDROID) || defined(USE_AURA)
+namespace {
+// This function is used in TouchActionAckTimeout and
+// SubframeGestureEventRouting, which is defined either under Android or Aura.
+void OnSyntheticGestureCompleted(scoped_refptr<MessageLoopRunner> runner,
+ SyntheticGesture::Result result) {
+ EXPECT_EQ(SyntheticGesture::GESTURE_FINISHED, result);
+ runner->Quit();
+}
+
+#if defined(OS_ANDROID)
+void GiveItSomeTime(int t) {
+ base::RunLoop run_loop;
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE, run_loop.QuitClosure(), base::TimeDelta::FromMilliseconds(t));
+ run_loop.Run();
+}
+#endif // defined(OS_ANDROID)
+
+} // namespace
+#endif // defined(OS_ANDROID) || defined(USE_AURA)
+
+// Regression test for https://crbug.com/851644. The test passes as long as it
+// doesn't crash.
+// Touch action ack timeout is enabled on Android only.
+// Flaky, see https://crbug.com/871062.
+#if defined(OS_ANDROID)
+IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
+ DISABLED_TouchActionAckTimeout) {
+ GURL main_url(
+ embedded_test_server()->GetURL("/frame_tree/page_with_janky_frame.html"));
+ ASSERT_TRUE(NavigateToURL(shell(), main_url));
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+ ASSERT_EQ(1U, root->child_count());
+ GURL frame_url(embedded_test_server()->GetURL(
+ "baz.com", "/page_with_touch_start_janking_main_thread.html"));
+ auto* child_frame_host = root->child_at(0)->current_frame_host();
+
+ RenderWidgetHostViewBase* rwhv_root = static_cast<RenderWidgetHostViewBase*>(
+ root->current_frame_host()->GetRenderWidgetHost()->GetView());
+ RenderWidgetHostViewChildFrame* rwhv_child =
+ static_cast<RenderWidgetHostViewChildFrame*>(
+ child_frame_host->GetRenderWidgetHost()->GetView());
+
+ WaitForHitTestDataOrChildSurfaceReady(child_frame_host);
+
+ // Compute the point so that the gesture event can target the child frame.
+ const gfx::Rect root_bounds = rwhv_root->GetViewBounds();
+ const gfx::Rect child_bounds = rwhv_child->GetViewBounds();
+ RenderFrameSubmissionObserver render_frame_submission_observer(
+ shell()->web_contents());
+ const float page_scale_factor =
+ render_frame_submission_observer.LastRenderFrameMetadata()
+ .page_scale_factor;
+ const gfx::PointF point_in_child(
+ (child_bounds.x() - root_bounds.x() + 25) * page_scale_factor,
+ (child_bounds.y() - root_bounds.y() + 25) * page_scale_factor);
+
+ SyntheticSmoothScrollGestureParams params;
+ params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
+ params.anchor = gfx::PointF(point_in_child.x(), point_in_child.y());
+ params.distances.push_back(gfx::Vector2dF(0, -10));
+ // Make this scroll slow so that the second scroll will be queued even before
+ // this one ends.
+ params.speed_in_pixels_s = 1000;
+ std::unique_ptr<SyntheticSmoothScrollGesture> gesture(
+ new SyntheticSmoothScrollGesture(params));
+
+ scoped_refptr<MessageLoopRunner> runner = new MessageLoopRunner();
+ RenderWidgetHostImpl* render_widget_host =
+ root->current_frame_host()->GetRenderWidgetHost();
+ render_widget_host->QueueSyntheticGesture(
+ std::move(gesture), base::BindOnce(OnSyntheticGestureCompleted, runner));
+ // The first gesture takes 100ms, so wait for 120ms to ensure that it has
+ // finished.
+ runner->Run();
+ GiveItSomeTime(120);
+
+ SyntheticSmoothScrollGestureParams params2;
+ params2.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
+ params2.anchor = gfx::PointF(point_in_child.x(), point_in_child.y());
+ params2.distances.push_back(gfx::Vector2dF(0, -10));
+ params2.speed_in_pixels_s = 100000;
+ std::unique_ptr<SyntheticSmoothScrollGesture> gesture2(
+ new SyntheticSmoothScrollGesture(params2));
+ render_widget_host->QueueSyntheticGesture(
+ std::move(gesture2), base::BindOnce(OnSyntheticGestureCompleted, runner));
+
+ runner->Run();
+ runner = nullptr;
+
+ // Give enough time to make sure all gesture are flushed and handled.
+ base::RunLoop run_loop;
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE, run_loop.QuitClosure(),
+ base::TimeDelta::FromMilliseconds(2500));
+ run_loop.Run();
+}
+#endif // defined(OS_ANDROID)
+
#if defined(USE_AURA) || defined(OS_ANDROID)
// When unconsumed scrolls in a child bubble to the root and start an
@@ -1316,14 +1623,6 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessEmulatedTouchBrowserTest,
// overscroll gesture.
IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
RootConsumesScrollDuringOverscrollGesture) {
-#if defined(OS_ANDROID)
- // TODO(835058): Fix flakiness on android with viz hit testing.
- if (features::IsVizHitTestingEnabled()) {
- LOG(INFO) << "Skipping test due to https://crbug.com/835058";
- return;
- }
-#endif
-
GURL main_url(embedded_test_server()->GetURL(
"a.com", "/cross_site_iframe_factory.html?a(b)"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -1668,7 +1967,11 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
// Since we are targeting child, event dispatch should not happen
// synchronously. Validate that the expected target does not receive the
// event immediately.
- EXPECT_FALSE(child_frame_monitor.EventWasReceived());
+ // When V2 surface layer hit testing is enabled, we expect to do synchronous
+ // event targeting on a child under some circumstances, so we expect the event
+ // immediately dispatched to the child.
+ if (!features::IsVizHitTestingSurfaceLayerEnabled())
+ EXPECT_FALSE(child_frame_monitor.EventWasReceived());
waiter.Wait();
EXPECT_TRUE(child_frame_monitor.EventWasReceived());
@@ -1731,19 +2034,44 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHighDPIHitTestBrowserTest,
NestedSurfaceHitTestTestHelper(shell(), embedded_test_server());
}
-#if defined(OS_LINUX)
-// Flaky timeouts and failures: https://crbug.com/833380
-#define MAYBE_OverlapSurfaceHitTestTest DISABLED_OverlapSurfaceHitTestTest
+IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
+ NonFlatTransformedSurfaceHitTestTest) {
+ NonFlatTransformedSurfaceHitTestHelper(shell(), embedded_test_server());
+}
+
+IN_PROC_BROWSER_TEST_P(SitePerProcessHighDPIHitTestBrowserTest,
+ NonFlatTransformedSurfaceHitTestTest) {
+ NonFlatTransformedSurfaceHitTestHelper(shell(), embedded_test_server());
+}
+
+// TODO(kenrb): Running this test on Android bots has slight discrepancies in
+// transformed event coordinates when we do manual calculation of expected
+// values. We can't rely on browser side transformation because it is broken
+// for perspective transforms. See https://crbug.com/854247.
+#if defined(OS_ANDROID)
+#define MAYBE_PerspectiveTransformedSurfaceHitTestTest \
+ DISABLED_PerspectiveTransformedSurfaceHitTestTest
#else
-#define MAYBE_OverlapSurfaceHitTestTest OverlapSurfaceHitTestTest
+#define MAYBE_PerspectiveTransformedSurfaceHitTestTest \
+ PerspectiveTransformedSurfaceHitTestTest
#endif
+IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
+ MAYBE_PerspectiveTransformedSurfaceHitTestTest) {
+ PerspectiveTransformedSurfaceHitTestHelper(shell(), embedded_test_server());
+}
+
+IN_PROC_BROWSER_TEST_P(SitePerProcessHighDPIHitTestBrowserTest,
+ MAYBE_PerspectiveTransformedSurfaceHitTestTest) {
+ PerspectiveTransformedSurfaceHitTestHelper(shell(), embedded_test_server());
+}
+
IN_PROC_BROWSER_TEST_P(SitePerProcessHighDPIHitTestBrowserTest,
- MAYBE_OverlapSurfaceHitTestTest) {
+ OverlapSurfaceHitTestTest) {
OverlapSurfaceHitTestHelper(shell(), embedded_test_server());
}
IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
- MAYBE_OverlapSurfaceHitTestTest) {
+ OverlapSurfaceHitTestTest) {
OverlapSurfaceHitTestHelper(shell(), embedded_test_server());
}
@@ -1780,12 +2108,13 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHighDPIHitTestBrowserTest,
}
#if defined(USE_AURA)
-IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest, RootWindowTransform) {
+IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
+ DISABLED_RootWindowTransform) {
HitTestRootWindowTransform(shell(), embedded_test_server());
}
IN_PROC_BROWSER_TEST_P(SitePerProcessHighDPIHitTestBrowserTest,
- RootWindowTransform) {
+ DISABLED_RootWindowTransform) {
HitTestRootWindowTransform(shell(), embedded_test_server());
}
#endif // defined(USE_AURA)
@@ -1882,6 +2211,12 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
// pointer-events: none.
IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
MAYBE_SurfaceHitTestPointerEventsNone) {
+ // TODO(sunxd): Fix pointer-events none for surface layer viz hit testing. See
+ // https://crbug.com/841358.
+ if (features::IsVizHitTestingSurfaceLayerEnabled()) {
+ LOG(INFO) << "Skipping test due to https://crbug.com/841358";
+ return;
+ }
GURL main_url(embedded_test_server()->GetURL(
"/frame_tree/page_with_positioned_frame_pointer-events_none.html"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -2355,8 +2690,14 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
// TODO(kenrb): This currently only works for scrollbar dragging.
// Other reasons for a node to capture mouse input need to be addressed. See
// https://crbug.com/647378.
+#if defined(OS_CHROMEOS)
+// TODO: Flaky on Chrome OS. crbug.com/868409
+#define MAYBE_CrossProcessMouseCapture DISABLED_CrossProcessMouseCapture
+#else
+#define MAYBE_CrossProcessMouseCapture CrossProcessMouseCapture
+#endif
IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
- CrossProcessMouseCapture) {
+ MAYBE_CrossProcessMouseCapture) {
GURL main_url(embedded_test_server()->GetURL(
"/frame_tree/page_with_large_scrollable_frame.html"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -2496,6 +2837,113 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
#endif // !defined(OS_MACOSX) && !defined(OS_ANDROID)
}
+IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
+ MouseCaptureOnDragSelection) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "/frame_tree/page_with_positioned_frame.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ RenderFrameSubmissionObserver render_frame_submission_observer(
+ shell()->web_contents());
+
+ // It is safe to obtain the root frame tree node here, as it doesn't change.
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+ ASSERT_EQ(1U, root->child_count());
+
+ FrameTreeNode* child_node = root->child_at(0);
+ ASSERT_EQ(
+ " Site A ------------ proxies for B\n"
+ " +--Site B ------- proxies for A\n"
+ "Where A = http://127.0.0.1/\n"
+ " B = http://baz.com/",
+ DepictFrameTree(root));
+
+ // Create listeners for mouse events.
+ RenderWidgetHostMouseEventMonitor main_frame_monitor(
+ root->current_frame_host()->GetRenderWidgetHost());
+ RenderWidgetHostMouseEventMonitor child_frame_monitor(
+ child_node->current_frame_host()->GetRenderWidgetHost());
+
+ RenderWidgetHostViewBase* rwhv_child = static_cast<RenderWidgetHostViewBase*>(
+ child_node->current_frame_host()->GetRenderWidgetHost()->GetView());
+
+ WaitForHitTestDataOrChildSurfaceReady(child_node->current_frame_host());
+
+ // Target MouseDown to child frame.
+ blink::WebMouseEvent mouse_event(
+ blink::WebInputEvent::kMouseDown, blink::WebInputEvent::kNoModifiers,
+ blink::WebInputEvent::GetStaticTimeStampForTests());
+ mouse_event.button = blink::WebPointerProperties::Button::kLeft;
+ mouse_event.click_count = 1;
+ main_frame_monitor.ResetEventReceived();
+ child_frame_monitor.ResetEventReceived();
+ DispatchMouseEventAndWaitUntilDispatch(web_contents(), mouse_event,
+ rwhv_child, gfx::PointF(15.0, 5.0),
+ rwhv_child, gfx::PointF(15.0, 5.0));
+
+ EXPECT_FALSE(main_frame_monitor.EventWasReceived());
+ EXPECT_TRUE(child_frame_monitor.EventWasReceived());
+ main_frame_monitor.ResetEventReceived();
+ child_frame_monitor.ResetEventReceived();
+
+ scoped_refptr<SetMouseCaptureInterceptor> interceptor =
+ new SetMouseCaptureInterceptor(static_cast<RenderWidgetHostImpl*>(
+ child_node->current_frame_host()->GetRenderWidgetHost()));
+
+ // Target MouseMove to child frame to start drag. This should cause the
+ // child to start capturing mouse input.
+ mouse_event.SetType(blink::WebInputEvent::kMouseMove);
+ mouse_event.SetModifiers(blink::WebInputEvent::kLeftButtonDown);
+ DispatchMouseEventAndWaitUntilDispatch(web_contents(), mouse_event,
+ rwhv_child, gfx::PointF(5.0, 5.0),
+ rwhv_child, gfx::PointF(5.0, 5.0));
+
+ // Dispatch twice because the router generates an extra MouseLeave for the
+ // main frame.
+ main_frame_monitor.ResetEventReceived();
+ child_frame_monitor.ResetEventReceived();
+ DispatchMouseEventAndWaitUntilDispatch(web_contents(), mouse_event,
+ rwhv_child, gfx::PointF(5.0, 5.0),
+ rwhv_child, gfx::PointF(5.0, 5.0));
+
+ EXPECT_FALSE(main_frame_monitor.EventWasReceived());
+ EXPECT_TRUE(child_frame_monitor.EventWasReceived());
+ main_frame_monitor.ResetEventReceived();
+ child_frame_monitor.ResetEventReceived();
+
+ // Wait for the mouse capture message.
+ interceptor->Wait();
+ EXPECT_TRUE(interceptor->Capturing());
+ // Yield the thread, in order to let the capture message be processed by its
+ // actual handler.
+ {
+ base::RunLoop loop;
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ loop.QuitClosure());
+ loop.Run();
+ }
+
+ // Now that the child frame is capturing, a MouseMove targeted to the main
+ // frame should be received by the child frame.
+ DispatchMouseEventAndWaitUntilDispatch(web_contents(), mouse_event,
+ rwhv_child, gfx::PointF(-25.0, -25.0),
+ rwhv_child, gfx::PointF(-25.0, -25.0));
+ EXPECT_FALSE(main_frame_monitor.EventWasReceived());
+ EXPECT_TRUE(child_frame_monitor.EventWasReceived());
+ main_frame_monitor.ResetEventReceived();
+ child_frame_monitor.ResetEventReceived();
+
+ // A MouseUp sent anywhere should cancel the mouse capture.
+ mouse_event.SetType(blink::WebInputEvent::kMouseUp);
+ mouse_event.SetModifiers(0);
+ DispatchMouseEventAndWaitUntilDispatch(web_contents(), mouse_event,
+ rwhv_child, gfx::PointF(-25.0, -25.0),
+ rwhv_child, gfx::PointF(-25.0, -25.0));
+
+ interceptor->Wait();
+ EXPECT_FALSE(interceptor->Capturing());
+}
+
// There are no cursors on Android.
#if !defined(OS_ANDROID)
class CursorMessageFilter : public content::BrowserMessageFilter {
@@ -2916,9 +3364,9 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
// will trigger kTouchActionNone being sent back to the browser.
RenderWidgetHostImpl* child_render_widget_host =
root->child_at(0)->current_frame_host()->GetRenderWidgetHost();
- EXPECT_EQ(true, child_render_widget_host->input_router()
- ->AllowedTouchAction()
- .has_value());
+ EXPECT_FALSE(child_render_widget_host->input_router()
+ ->AllowedTouchAction()
+ .has_value());
InputEventAckWaiter waiter(child_render_widget_host,
blink::WebInputEvent::kTouchStart);
@@ -2992,8 +3440,7 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
// browser.
RenderWidgetHostImpl* render_widget_host =
root->current_frame_host()->GetRenderWidgetHost();
- EXPECT_EQ(
- true,
+ EXPECT_FALSE(
render_widget_host->input_router()->AllowedTouchAction().has_value());
// Simulate touch event to sub-frame.
@@ -3034,17 +3481,6 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
render_widget_host->input_router()->AllowedTouchAction());
}
-namespace {
-
-// Declared here to be close to the SubframeGestureEventRouting test.
-void OnSyntheticGestureCompleted(scoped_refptr<MessageLoopRunner> runner,
- SyntheticGesture::Result result) {
- EXPECT_EQ(SyntheticGesture::GESTURE_FINISHED, result);
- runner->Quit();
-}
-
-} // anonymous namespace
-
// https://crbug.com/592320
IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
DISABLED_SubframeGestureEventRouting) {
@@ -3242,8 +3678,12 @@ void SendTouchpadPinchSequenceWithExpectedTarget(
// targeting first. So event dispatch should not happen synchronously.
// Validate that the expected target does not receive the event immediately in
// such cases.
- if (root_view != expected_target)
+ // V2 surface layer hit testing cannot handle pointer-events: none elements
+ // yet, see https://crbug.com/841358.
+ if (root_view != expected_target &&
+ !features::IsVizHitTestingSurfaceLayerEnabled()) {
EXPECT_FALSE(target_monitor.EventWasReceived());
+ }
waiter.Wait();
EXPECT_TRUE(target_monitor.EventWasReceived());
EXPECT_EQ(expected_target, router_touchpad_gesture_target);
@@ -3294,13 +3734,20 @@ void SendTouchpadFlingSequenceWithExpectedTarget(
InputEventAckWaiter fling_start_waiter(
expected_target->GetRenderWidgetHost(),
blink::WebInputEvent::kGestureFlingStart);
+ InputMsgWatcher gestrue_scroll_end_waiter(
+ expected_target->GetRenderWidgetHost(),
+ blink::WebInputEvent::kGestureScrollEnd);
root_view_aura->OnScrollEvent(&fling_start);
// If the expected target is not the root, then we should be doing async
// targeting first. So event dispatch should not happen synchronously.
// Validate that the expected target does not receive the event immediately in
// such cases.
- if (root_view != expected_target)
+ // When V2 surface layer hit testing is enabled, we should synchronously
+ // target the event to the child.
+ if (root_view != expected_target &&
+ !features::IsVizHitTestingSurfaceLayerEnabled()) {
EXPECT_FALSE(target_monitor.EventWasReceived());
+ }
fling_start_waiter.Wait();
EXPECT_TRUE(target_monitor.EventWasReceived());
EXPECT_EQ(expected_target, router_wheel_target);
@@ -3309,9 +3756,6 @@ void SendTouchpadFlingSequenceWithExpectedTarget(
// Send a GFC event, the fling_controller will process the GFC and stop the
// fling by generating a wheel event with phaseEnded. The
// mouse_wheel_event_queue will process the wheel event and generate a GSE.
- InputEventAckWaiter gestrue_scroll_end_waiter(
- expected_target->GetRenderWidgetHost(),
- blink::WebInputEvent::kGestureScrollEnd);
InputEventAckWaiter fling_cancel_waiter(
expected_target->GetRenderWidgetHost(),
blink::WebInputEvent::kGestureFlingCancel);
@@ -3319,7 +3763,9 @@ void SendTouchpadFlingSequenceWithExpectedTarget(
ui::EventTimeForNow(), 0, 1, 0, 1, 0, 1);
UpdateEventRootLocation(&fling_cancel, root_view_aura);
root_view_aura->OnScrollEvent(&fling_cancel);
- gestrue_scroll_end_waiter.Wait();
+ // Since the fling velocity is small, sometimes the fling is over before
+ // sending the GFC event.
+ gestrue_scroll_end_waiter.GetAckStateWaitIfNecessary();
fling_cancel_waiter.Wait();
}
#endif // !defined(OS_WIN)
@@ -3508,14 +3954,6 @@ IN_PROC_BROWSER_TEST_P(
IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
InputEventRouterTouchpadGestureTargetTest) {
-#if defined(OS_WIN)
- // TODO(838835): Flaky with viz hit testing
- if (features::IsVizHitTestingEnabled()) {
- LOG(INFO) << "Skipping test due to https://crbug.com/838835";
- return;
- }
-#endif
-
GURL main_url(embedded_test_server()->GetURL(
"/frame_tree/page_with_positioned_nested_frames.html"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -3609,13 +4047,7 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
// wheel events to the child and causes the page scale factor to change for
// the main frame (given that the child did not consume the wheel).
IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
- TouchpadPinchOverOOPIF) {
- // TODO(crbug.com/853761): Flaky with viz hit testing
- if (features::IsVizHitTestingEnabled()) {
- LOG(INFO) << "Skipping test due to https://crbug.com/853761";
- return;
- }
-
+ MAYBE_TouchpadPinchOverOOPIF) {
GURL main_url(embedded_test_server()->GetURL(
"/frame_tree/page_with_positioned_frame.html"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -4262,6 +4694,89 @@ class SitePerProcessGestureHitTestBrowserTest
rwhi_root_ = root_node->current_frame_host()->GetRenderWidgetHost();
}
+ void SubframeGesturePinchTestHelper(const std::string& url,
+ bool reset_root_touch_action) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b)"));
+
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ // It is safe to obtain the root frame tree node here, as it doesn't change.
+ FrameTreeNode* root_node =
+ static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+ ASSERT_EQ(1U, root_node->child_count());
+
+ FrameTreeNode* child_node = root_node->child_at(0);
+ GURL b_url(embedded_test_server()->GetURL("b.com", url));
+ NavigateFrameToURL(child_node, b_url);
+
+ ASSERT_EQ(
+ " Site A ------------ proxies for B\n"
+ " +--Site B ------- proxies for A\n"
+ "Where A = http://a.com/\n"
+ " B = http://b.com/",
+ DepictFrameTree(root_node));
+
+ rwhv_child_ = static_cast<RenderWidgetHostViewBase*>(
+ child_node->current_frame_host()->GetRenderWidgetHost()->GetView());
+
+ rwhva_root_ = static_cast<RenderWidgetHostViewAura*>(
+ shell()->web_contents()->GetRenderWidgetHostView());
+
+ WaitForHitTestDataOrChildSurfaceReady(child_node->current_frame_host());
+
+ MainThreadFrameObserver observer(rwhv_child_->GetRenderWidgetHost());
+ observer.Wait();
+
+ rwhi_child_ = child_node->current_frame_host()->GetRenderWidgetHost();
+ rwhi_root_ = root_node->current_frame_host()->GetRenderWidgetHost();
+
+ TestInputEventObserver root_frame_monitor(rwhi_root_);
+ TestInputEventObserver child_frame_monitor(rwhi_child_);
+
+ gfx::Rect bounds = rwhv_child_->GetViewBounds();
+ bounds.Offset(gfx::Point() - rwhva_root_->GetViewBounds().origin());
+
+ // The pinch gesture will always sent to the root frame even if the fingers
+ // are targeting the iframe. In this case, the test should not crash.
+ if (reset_root_touch_action) {
+ static_cast<InputRouterImpl*>(
+ static_cast<RenderWidgetHostImpl*>(rwhva_root_->GetRenderWidgetHost())
+ ->input_router())
+ ->OnHasTouchEventHandlersForTest(true);
+ }
+ SendPinchBeginEndSequence(rwhva_root_, bounds.CenterPoint(), rwhi_child_);
+
+ if (reset_root_touch_action)
+ return;
+
+ // Verify that root-RWHI gets nothing.
+ EXPECT_FALSE(root_frame_monitor.EventWasReceived());
+ // Verify that child-RWHI gets TS/GTD/GSB/GPB/GPE/GSE/TE.
+ EXPECT_EQ(blink::WebInputEvent::kTouchStart,
+ child_frame_monitor.events_received()[0]);
+ EXPECT_EQ(blink::WebInputEvent::kGestureTapDown,
+ child_frame_monitor.events_received()[1]);
+ EXPECT_EQ(blink::WebInputEvent::kGestureScrollBegin,
+ child_frame_monitor.events_received()[2]);
+ EXPECT_EQ(blink::WebInputEvent::kGesturePinchBegin,
+ child_frame_monitor.events_received()[3]);
+ EXPECT_EQ(blink::WebInputEvent::kGesturePinchEnd,
+ child_frame_monitor.events_received()[4]);
+ EXPECT_EQ(blink::WebInputEvent::kGestureScrollEnd,
+ child_frame_monitor.events_received()[5]);
+ EXPECT_EQ(blink::WebInputEvent::kTouchEnd,
+ child_frame_monitor.events_received()[6]);
+
+ // Verify that the pinch gestures are consumed by browser.
+ EXPECT_EQ(InputEventAckSource::BROWSER,
+ child_frame_monitor.events_acked()[3]);
+ EXPECT_EQ(InputEventAckSource::BROWSER,
+ child_frame_monitor.events_acked()[4]);
+ }
+
protected:
RenderWidgetHostViewBase* rwhv_child_;
RenderWidgetHostViewAura* rwhva_root_;
@@ -4347,75 +4862,12 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessGestureHitTestBrowserTest,
IN_PROC_BROWSER_TEST_P(SitePerProcessGestureHitTestBrowserTest,
SubframeGesturePinchDeniedBySubframeTouchAction) {
- GURL main_url(embedded_test_server()->GetURL(
- "a.com", "/cross_site_iframe_factory.html?a(b)"));
-
- EXPECT_TRUE(NavigateToURL(shell(), main_url));
-
- // It is safe to obtain the root frame tree node here, as it doesn't change.
- FrameTreeNode* root_node =
- static_cast<WebContentsImpl*>(shell()->web_contents())
- ->GetFrameTree()
- ->root();
- ASSERT_EQ(1U, root_node->child_count());
-
- FrameTreeNode* child_node = root_node->child_at(0);
- GURL b_url(embedded_test_server()->GetURL(
- "b.com", "/div_with_touch_action_none.html"));
- NavigateFrameToURL(child_node, b_url);
-
- ASSERT_EQ(
- " Site A ------------ proxies for B\n"
- " +--Site B ------- proxies for A\n"
- "Where A = http://a.com/\n"
- " B = http://b.com/",
- DepictFrameTree(root_node));
-
- rwhv_child_ = static_cast<RenderWidgetHostViewBase*>(
- child_node->current_frame_host()->GetRenderWidgetHost()->GetView());
-
- rwhva_root_ = static_cast<RenderWidgetHostViewAura*>(
- shell()->web_contents()->GetRenderWidgetHostView());
-
- WaitForHitTestDataOrChildSurfaceReady(child_node->current_frame_host());
-
- MainThreadFrameObserver observer(rwhv_child_->GetRenderWidgetHost());
- observer.Wait();
-
- rwhi_child_ = child_node->current_frame_host()->GetRenderWidgetHost();
- rwhi_root_ = root_node->current_frame_host()->GetRenderWidgetHost();
-
- TestInputEventObserver root_frame_monitor(rwhi_root_);
- TestInputEventObserver child_frame_monitor(rwhi_child_);
-
- gfx::Rect bounds = rwhv_child_->GetViewBounds();
- bounds.Offset(gfx::Point() - rwhva_root_->GetViewBounds().origin());
-
- SendPinchBeginEndSequence(rwhva_root_, bounds.CenterPoint(), rwhi_child_);
-
- // Verify that root-RWHI gets nothing.
- EXPECT_FALSE(root_frame_monitor.EventWasReceived());
- // Verify that child-RWHI gets TS/GTD/GSB/GPB/GPE/GSE/TE.
- EXPECT_EQ(blink::WebInputEvent::kTouchStart,
- child_frame_monitor.events_received()[0]);
- EXPECT_EQ(blink::WebInputEvent::kGestureTapDown,
- child_frame_monitor.events_received()[1]);
- EXPECT_EQ(blink::WebInputEvent::kGestureScrollBegin,
- child_frame_monitor.events_received()[2]);
- EXPECT_EQ(blink::WebInputEvent::kGesturePinchBegin,
- child_frame_monitor.events_received()[3]);
- EXPECT_EQ(blink::WebInputEvent::kGesturePinchEnd,
- child_frame_monitor.events_received()[4]);
- EXPECT_EQ(blink::WebInputEvent::kGestureScrollEnd,
- child_frame_monitor.events_received()[5]);
- EXPECT_EQ(blink::WebInputEvent::kTouchEnd,
- child_frame_monitor.events_received()[6]);
+ SubframeGesturePinchTestHelper("/div_with_touch_action_none.html", false);
+}
- // Verify that the pinch gestures are consumed by browser.
- EXPECT_EQ(InputEventAckSource::BROWSER,
- child_frame_monitor.events_acked()[3]);
- EXPECT_EQ(InputEventAckSource::BROWSER,
- child_frame_monitor.events_acked()[4]);
+IN_PROC_BROWSER_TEST_P(SitePerProcessGestureHitTestBrowserTest,
+ SubframeGesturePinchNoCrash) {
+ SubframeGesturePinchTestHelper("/div_with_touch_action_auto.html", true);
}
#endif // defined(USE_AURA)
@@ -4526,40 +4978,379 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest, HitTestNestedFrames) {
{
base::RunLoop run_loop;
viz::FrameSinkId received_frame_sink_id;
+ gfx::PointF returned_point;
base::Closure quit_closure =
content::GetDeferredQuitTaskForRunLoop(&run_loop);
DCHECK_NE(child_node->current_frame_host()->GetInputTargetClient(),
nullptr);
child_node->current_frame_host()->GetInputTargetClient()->FrameSinkIdAt(
point_in_child,
- base::BindLambdaForTesting([&](const viz::FrameSinkId& id) {
- received_frame_sink_id = id;
- quit_closure.Run();
- }));
+ base::BindLambdaForTesting(
+ [&](const viz::FrameSinkId& id, const gfx::PointF& point) {
+ received_frame_sink_id = id;
+ returned_point = point;
+ quit_closure.Run();
+ }));
content::RunThisRunLoop(&run_loop);
// |point_in_child| should hit test to the view for |child_node|.
ASSERT_EQ(rwhv_child->GetFrameSinkId(), received_frame_sink_id);
+ ASSERT_EQ(gfx::PointF(1, 1), returned_point);
}
{
base::RunLoop run_loop;
viz::FrameSinkId received_frame_sink_id;
+ gfx::PointF returned_point;
base::Closure quit_closure =
content::GetDeferredQuitTaskForRunLoop(&run_loop);
DCHECK_NE(child_node->current_frame_host()->GetInputTargetClient(),
nullptr);
child_node->current_frame_host()->GetInputTargetClient()->FrameSinkIdAt(
gfx::ToCeiledPoint(point_in_nested_child),
- base::BindLambdaForTesting([&](const viz::FrameSinkId& id) {
- received_frame_sink_id = id;
- quit_closure.Run();
- }));
+ base::BindLambdaForTesting(
+ [&](const viz::FrameSinkId& id, const gfx::PointF& point) {
+ received_frame_sink_id = id;
+ returned_point = point;
+ quit_closure.Run();
+ }));
content::RunThisRunLoop(&run_loop);
// |point_in_nested_child| should hit test to |rwhv_grandchild|.
ASSERT_EQ(rwhv_grandchild->GetFrameSinkId(), received_frame_sink_id);
+ EXPECT_NEAR(returned_point.x(), 5, 2);
+ EXPECT_NEAR(returned_point.y(), 5, 2);
}
}
+class SitePerProcessHitTestDataGenerationBrowserTest
+ : public SitePerProcessHitTestBrowserTest {
+ public:
+ SitePerProcessHitTestDataGenerationBrowserTest() {}
+
+ protected:
+ // Load the page |host_name| and retrieve the hit test data from HitTestQuery.
+ std::vector<viz::AggregatedHitTestRegion> SetupAndGetHitTestData(
+ const std::string& host_name) {
+ GURL main_url(embedded_test_server()->GetURL(host_name));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+
+ RenderWidgetHostViewBase* rwhv_root =
+ static_cast<RenderWidgetHostViewBase*>(
+ root->current_frame_host()->GetRenderWidgetHost()->GetView());
+
+ for (unsigned i = 0; i < root->child_count(); i++) {
+ WaitForHitTestDataOrChildSurfaceReady(
+ root->child_at(i)->current_frame_host());
+ }
+
+ HitTestRegionObserver observer(rwhv_root->GetRootFrameSinkId());
+ observer.WaitForHitTestData();
+
+ device_scale_factor_ = rwhv_root->GetDeviceScaleFactor();
+ DCHECK_GT(device_scale_factor_, 0);
+
+ return observer.GetHitTestData();
+ }
+
+ float current_device_scale_factor() const { return device_scale_factor_; }
+
+ gfx::QuadF TransformRectToQuadF(const gfx::Rect& rect,
+ const gfx::Transform& transform,
+ bool use_scale_factor = true) {
+ gfx::Rect scaled_rect =
+ use_scale_factor ? gfx::ScaleToEnclosingRect(rect, device_scale_factor_,
+ device_scale_factor_)
+ : rect;
+ gfx::PointF p1(scaled_rect.origin());
+ gfx::PointF p2(scaled_rect.top_right());
+ gfx::PointF p3(scaled_rect.bottom_right());
+ gfx::PointF p4(scaled_rect.bottom_left());
+ transform.TransformPoint(&p1);
+ transform.TransformPoint(&p2);
+ transform.TransformPoint(&p3);
+ transform.TransformPoint(&p4);
+ return gfx::QuadF(p1, p2, p3, p4);
+ }
+
+ gfx::QuadF TransformRectToQuadF(
+ const viz::AggregatedHitTestRegion& hit_test_region) {
+ return TransformRectToQuadF(hit_test_region.rect,
+ hit_test_region.transform(), false);
+ }
+
+ bool ApproximatelyEqual(const gfx::PointF& p1, const gfx::PointF& p2) const {
+ return std::abs(p1.x() - p2.x()) <= 1 && std::abs(p1.y() - p2.y()) <= 1;
+ }
+
+ bool ApproximatelyEqual(const gfx::QuadF& quad,
+ const gfx::QuadF& other) const {
+ return ApproximatelyEqual(quad.p1(), other.p1()) &&
+ ApproximatelyEqual(quad.p2(), other.p2()) &&
+ ApproximatelyEqual(quad.p3(), other.p3()) &&
+ ApproximatelyEqual(quad.p4(), other.p4());
+ }
+
+ gfx::Rect AxisAlignedLayoutRectFromHitTest(
+ const viz::AggregatedHitTestRegion& hit_test_region) {
+ DCHECK(hit_test_region.transform().Preserves2dAxisAlignment());
+ gfx::RectF rect(hit_test_region.rect);
+ hit_test_region.transform().TransformRect(&rect);
+ return gfx::ToEnclosingRect(rect);
+ }
+
+ public:
+ static const uint32_t kFastHitTestFlags;
+ static const uint32_t kSlowHitTestFlags;
+ float device_scale_factor_;
+};
+
+const uint32_t
+ SitePerProcessHitTestDataGenerationBrowserTest::kFastHitTestFlags =
+ viz::HitTestRegionFlags::kHitTestMine |
+ viz::HitTestRegionFlags::kHitTestChildSurface |
+ viz::HitTestRegionFlags::kHitTestMouse |
+ viz::HitTestRegionFlags::kHitTestTouch;
+
+const uint32_t
+ SitePerProcessHitTestDataGenerationBrowserTest::kSlowHitTestFlags =
+ SitePerProcessHitTestDataGenerationBrowserTest::kFastHitTestFlags |
+ viz::HitTestRegionFlags::kHitTestAsk;
+
+IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestDataGenerationBrowserTest,
+ TransformedOOPIF) {
+ if (!features::IsVizHitTestingEnabled())
+ return;
+ auto hit_test_data =
+ SetupAndGetHitTestData("/frame_tree/page_with_transformed_iframe.html");
+ float device_scale_factor = current_device_scale_factor();
+
+ // Compute screen space transform for iframe element.
+ gfx::Transform expected_transform;
+ gfx::Transform translate;
+ expected_transform.RotateAboutZAxis(-45);
+ translate.Translate(-100 * device_scale_factor, -100 * device_scale_factor);
+ expected_transform.PreconcatTransform(translate);
+
+ DCHECK(hit_test_data.size() >= 3);
+ // The iframe element in main page is transformed and also clips the content
+ // of the subframe, so we expect to do slow path hit testing in this case.
+ // TODO(sunxd): We should do fast path hit testing in this case. See
+ // https://crbug.com/851507.
+ EXPECT_TRUE(ApproximatelyEqual(
+ TransformRectToQuadF(gfx::Rect(100, 100), expected_transform),
+ TransformRectToQuadF(hit_test_data[2])));
+ EXPECT_EQ(kSlowHitTestFlags, hit_test_data[2].flags);
+}
+
+IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestDataGenerationBrowserTest,
+ ClippedOOPIFFastPath) {
+ if (!features::IsVizHitTestingEnabled())
+ return;
+ auto hit_test_data =
+ SetupAndGetHitTestData("/frame_tree/page_with_clipped_iframe.html");
+ float device_scale_factor = current_device_scale_factor();
+ gfx::Transform expected_transform;
+ // In V1 hit testing or V2 hit testing slow path, we expected unclipped iframe
+ // bounds in its own space.
+ gfx::Rect original_region(200, 200);
+ gfx::Rect expected_transformed_region = gfx::ScaleToEnclosingRect(
+ original_region, device_scale_factor, device_scale_factor);
+
+ uint32_t expected_flags = kFastHitTestFlags;
+ // Clip2 has overflow: visible property, so it does not apply clip to iframe.
+ // Clip1 and clip3 all preserve 2d axis alignment, so we should allow fast
+ // path hit testing for the iframe in V2 hit testing.
+ // When VizDisplayCompositor is enabled, HitTestDataProviderDrawQuad will
+ // override LTHI's hit test data.
+ if (features::IsVizHitTestingDrawQuadEnabled()) {
+ // In V1 hit testing, we expect slow path and the submitted region should be
+ // equivalent to the unclipped iframe bounds.
+ expected_flags = kSlowHitTestFlags;
+ } else if (features::IsVizHitTestingSurfaceLayerEnabled()) {
+ // In V2 hit testing fast path, we expect precise clipped iframe bounds in
+ // its own space.
+ expected_transformed_region = gfx::ScaleToEnclosingRect(
+ gfx::Rect(100, 100), device_scale_factor, device_scale_factor);
+ }
+
+ // Apart from the iframe, it also contains data for root and main frame.
+ DCHECK(hit_test_data.size() >= 3);
+ EXPECT_TRUE(expected_transformed_region.ApproximatelyEqual(
+ AxisAlignedLayoutRectFromHitTest(hit_test_data[2]),
+ gfx::ToRoundedInt(device_scale_factor) + 2));
+ EXPECT_TRUE(
+ expected_transform.ApproximatelyEqual(hit_test_data[2].transform()));
+ EXPECT_EQ(expected_flags, hit_test_data[2].flags);
+}
+
+IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestDataGenerationBrowserTest,
+ RotatedClippedOOPIF) {
+ if (!features::IsVizHitTestingEnabled())
+ return;
+ auto hit_test_data = SetupAndGetHitTestData(
+ "/frame_tree/page_with_rotated_clipped_iframe.html");
+ float device_scale_factor = current_device_scale_factor();
+ // +-Root
+ // +---clip1
+ // +-----clip2 rotateZ(45)
+ // +-------clip3 rotateZ(-45)
+ // +---------iframe
+ //
+ // +----------------300px--------------+
+ // |\ |
+ // | \ |
+ // | \ 100px
+ // |- x --\ |
+ // | / |
+ // +-----------------------------------+
+ //
+ // Clipped region: x=100/sqrt(2), y=100.
+ gfx::Transform expected_transform;
+ gfx::Rect expected_region = gfx::ScaleToEnclosingRect(
+ gfx::Rect(200, 200), device_scale_factor, device_scale_factor);
+ if (!features::IsVizHitTestingDrawQuadEnabled()) {
+ expected_region = gfx::ScaleToEnclosingRect(
+ gfx::Rect(100 / 1.414, 100), device_scale_factor, device_scale_factor);
+ }
+
+ // Compute screen space transform for iframe element, since clip2 is rotated
+ // and also clips the iframe, we expect to do slow path hit test on the
+ // iframe.
+ DCHECK(hit_test_data.size() >= 3);
+ EXPECT_TRUE(expected_region.ApproximatelyEqual(hit_test_data[2].rect,
+ 1 + device_scale_factor));
+ EXPECT_TRUE(
+ expected_transform.ApproximatelyEqual(hit_test_data[2].transform()));
+ EXPECT_EQ(kSlowHitTestFlags, hit_test_data[2].flags);
+}
+
+IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestDataGenerationBrowserTest,
+ ClippedRotatedOOPIF) {
+ if (!features::IsVizHitTestingEnabled())
+ return;
+ auto hit_test_data = SetupAndGetHitTestData(
+ "/frame_tree/page_with_clipped_rotated_iframe.html");
+ float device_scale_factor = current_device_scale_factor();
+ // +-Root
+ // +---clip1
+ // +---------iframe rotateZ(45deg)
+ //
+ // There are actually 2 clips applied to surface layer, in root space they
+ // are:
+ // bounding box of clip1: rect 0, 0 300x100, transform = identity;
+ // bounding box of iframe itself: rect -100*sqrt(2), 0 200*sqrt(2)x200*sqrt(2)
+ // transform: rotateZ(45).
+ // In root space the two clips accumulates to:
+ // rect 0, 0 100*sqrt(2)x100, transform=identity
+ // Transform this to layer's local space, the clip rect is:
+ // rect 0, -100/sqrt(2) (100+100/sqrt(2))x(100/sqrt(2))
+ // So the intersected visible layer rect is:
+ // rect 0, 0, (100+100/sqrt(2)), 100/sqrt(2).
+ // +----------------300px--------------+
+ // |\ |
+ // | \ |
+ // | \x 100px
+ // | / \ |
+ // | /y \ |
+ // +-----------------------------------+
+ gfx::Transform expected_transform;
+ expected_transform.RotateAboutZAxis(-45);
+ gfx::Rect expected_region = gfx::ScaleToEnclosingRect(
+ gfx::Rect(200, 200), device_scale_factor, device_scale_factor);
+ if (!features::IsVizHitTestingDrawQuadEnabled()) {
+ expected_region =
+ gfx::ScaleToEnclosingRect(gfx::Rect(100 + 100 / 1.414f, 100 / 1.414f),
+ device_scale_factor, device_scale_factor);
+ }
+
+ // Since iframe is clipped into an octagon, we expect to do slow path hit
+ // test on the iframe.
+ DCHECK(hit_test_data.size() >= 3);
+ EXPECT_TRUE(expected_region.ApproximatelyEqual(hit_test_data[2].rect,
+ 1 + device_scale_factor));
+ EXPECT_TRUE(
+ expected_transform.ApproximatelyEqual(hit_test_data[2].transform()));
+ EXPECT_EQ(kSlowHitTestFlags, hit_test_data[2].flags);
+}
+
+IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestDataGenerationBrowserTest,
+ ClipPathOOPIF) {
+ if (!features::IsVizHitTestingEnabled())
+ return;
+ auto hit_test_data =
+ SetupAndGetHitTestData("/frame_tree/page_with_clip_path_iframe.html");
+ float device_scale_factor = current_device_scale_factor();
+ gfx::Transform expected_transform;
+ gfx::Rect expected_region = gfx::ScaleToEnclosingRect(
+ gfx::Rect(100, 100), device_scale_factor, device_scale_factor);
+ if (!features::IsVizHitTestingDrawQuadEnabled()) {
+ expected_region = gfx::ScaleToEnclosingRect(
+ gfx::Rect(80, 80), device_scale_factor, device_scale_factor);
+ }
+
+ // Since iframe is clipped into an octagon, we expect to do slow path hit
+ // test on the iframe.
+ DCHECK(hit_test_data.size() >= 3);
+ EXPECT_TRUE(expected_region.ApproximatelyEqual(hit_test_data[2].rect,
+ 1 + device_scale_factor));
+ EXPECT_TRUE(
+ expected_transform.ApproximatelyEqual(hit_test_data[2].transform()));
+ EXPECT_EQ(kSlowHitTestFlags, hit_test_data[2].flags);
+}
+
+IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestDataGenerationBrowserTest,
+ OverlappedOOPIF) {
+ if (!features::IsVizHitTestingEnabled())
+ return;
+ auto hit_test_data =
+ SetupAndGetHitTestData("/frame_tree/page_with_overlapped_iframes.html");
+ float device_scale_factor = current_device_scale_factor();
+ gfx::Transform expected_transform1;
+ gfx::Transform expected_transform2;
+ expected_transform2.matrix().postTranslate(-100 * device_scale_factor, 0, 0);
+
+ gfx::Rect expected_region = gfx::ScaleToEnclosingRect(
+ gfx::Rect(100, 100), device_scale_factor, device_scale_factor);
+
+ // Since iframe is occluded by a div in parent frame, we expect to do slow hit
+ // test.
+ DCHECK(hit_test_data.size() >= 4);
+ EXPECT_EQ(expected_region.ToString(), hit_test_data[3].rect.ToString());
+ EXPECT_TRUE(
+ expected_transform1.ApproximatelyEqual(hit_test_data[3].transform()));
+ EXPECT_EQ(kSlowHitTestFlags, hit_test_data[3].flags);
+ EXPECT_EQ(expected_region.ToString(), hit_test_data[2].rect.ToString());
+ EXPECT_TRUE(
+ expected_transform2.ApproximatelyEqual(hit_test_data[2].transform()));
+ if (features::IsVizHitTestingDrawQuadEnabled())
+ EXPECT_EQ(kSlowHitTestFlags, hit_test_data[2].flags);
+ else if (features::IsVizHitTestingSurfaceLayerEnabled())
+ EXPECT_EQ(kFastHitTestFlags, hit_test_data[2].flags);
+}
+
+IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestDataGenerationBrowserTest,
+ MaskedOOPIF) {
+ if (!features::IsVizHitTestingEnabled())
+ return;
+ auto hit_test_data =
+ SetupAndGetHitTestData("/frame_tree/page_with_masked_iframe.html");
+ float device_scale_factor = current_device_scale_factor();
+ gfx::Transform expected_transform;
+ gfx::Rect expected_region = gfx::ScaleToEnclosingRect(
+ gfx::Rect(200, 200), device_scale_factor, device_scale_factor);
+
+ // Since iframe clipped by clip-path and has a mask layer, we expect to do
+ // slow path hit testing.
+ DCHECK(hit_test_data.size() >= 3);
+ EXPECT_EQ(expected_region.ToString(), hit_test_data[2].rect.ToString());
+ EXPECT_TRUE(
+ expected_transform.ApproximatelyEqual(hit_test_data[2].transform()));
+ EXPECT_EQ(kSlowHitTestFlags, hit_test_data[2].flags);
+}
+
static const int kHitTestOption[] = {0, 1, 2};
static const float kOneScale[] = {1.f};
@@ -4583,6 +5374,11 @@ INSTANTIATE_TEST_CASE_P(/* no prefix */,
SitePerProcessEmulatedTouchBrowserTest,
testing::Combine(testing::ValuesIn(kHitTestOption),
testing::ValuesIn(kOneScale)));
+
+INSTANTIATE_TEST_CASE_P(/* no prefix */,
+ SitePerProcessHitTestDataGenerationBrowserTest,
+ testing::Combine(testing::ValuesIn(kHitTestOption),
+ testing::ValuesIn(kOneScale)));
#if defined(USE_AURA)
static const float kMultiScale[] = {1.f, 1.5f, 2.f};
diff --git a/chromium/content/browser/speech/speech_recognition_dispatcher_host.cc b/chromium/content/browser/speech/speech_recognition_dispatcher_host.cc
index 4e8664ea9da..1658119876a 100644
--- a/chromium/content/browser/speech/speech_recognition_dispatcher_host.cc
+++ b/chromium/content/browser/speech/speech_recognition_dispatcher_host.cc
@@ -16,11 +16,13 @@
#include "content/browser/speech/speech_recognition_manager_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/speech_recognition_manager_delegate.h"
#include "content/public/browser/speech_recognition_session_config.h"
#include "content/public/browser/speech_recognition_session_context.h"
#include "content/public/browser/storage_partition.h"
+#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
@@ -131,8 +133,9 @@ void SpeechRecognitionDispatcherHost::StartRequestOnUI(
->delegate()
->FilterProfanities(embedder_render_process_id);
+ content::BrowserContext* browser_context = web_contents->GetBrowserContext();
StoragePartition* storage_partition = BrowserContext::GetStoragePartition(
- web_contents->GetBrowserContext(), web_contents->GetSiteInstance());
+ browser_context, web_contents->GetSiteInstance());
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
@@ -142,7 +145,7 @@ void SpeechRecognitionDispatcherHost::StartRequestOnUI(
embedder_render_process_id, embedder_render_frame_id,
filter_profanities,
storage_partition->GetURLLoaderFactoryForBrowserProcessIOThread(),
- base::WrapRefCounted(storage_partition->GetURLRequestContext())));
+ GetContentClient()->browser()->GetAcceptLangs(browser_context)));
}
void SpeechRecognitionDispatcherHost::StartSessionOnIO(
@@ -152,7 +155,7 @@ void SpeechRecognitionDispatcherHost::StartSessionOnIO(
bool filter_profanities,
std::unique_ptr<network::SharedURLLoaderFactoryInfo>
shared_url_loader_factory_info,
- scoped_refptr<net::URLRequestContextGetter> deprecated_context_getter) {
+ const std::string& accept_language) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
SpeechRecognitionSessionContext context;
@@ -167,13 +170,12 @@ void SpeechRecognitionDispatcherHost::StartSessionOnIO(
SpeechRecognitionSessionConfig config;
config.language = params->language;
+ config.accept_language = accept_language;
config.max_hypotheses = params->max_hypotheses;
config.origin = params->origin;
config.initial_context = context;
config.shared_url_loader_factory = network::SharedURLLoaderFactory::Create(
std::move(shared_url_loader_factory_info));
- config.deprecated_url_request_context_getter =
- std::move(deprecated_context_getter);
config.filter_profanities = filter_profanities;
config.continuous = params->continuous;
config.interim_results = params->interim_results;
@@ -201,7 +203,11 @@ SpeechRecognitionSession::SpeechRecognitionSession(
: session_id_(SpeechRecognitionManager::kSessionIDInvalid),
client_(std::move(client_ptr_info)),
stopped_(false),
- weak_factory_(this) {}
+ weak_factory_(this) {
+ client_.set_connection_error_handler(
+ base::BindOnce(&SpeechRecognitionSession::ConnectionErrorHandler,
+ base::Unretained(this)));
+}
SpeechRecognitionSession::~SpeechRecognitionSession() {
// If a connection error happens and the session hasn't been stopped yet,
@@ -273,4 +279,9 @@ void SpeechRecognitionSession::OnAudioLevelsChange(int session_id,
void SpeechRecognitionSession::OnEnvironmentEstimationComplete(int session_id) {
}
+void SpeechRecognitionSession::ConnectionErrorHandler() {
+ if (!stopped_)
+ Abort();
+}
+
} // namespace content
diff --git a/chromium/content/browser/speech/speech_recognition_dispatcher_host.h b/chromium/content/browser/speech/speech_recognition_dispatcher_host.h
index ffa9bd51448..2ae15969b20 100644
--- a/chromium/content/browser/speech/speech_recognition_dispatcher_host.h
+++ b/chromium/content/browser/speech/speech_recognition_dispatcher_host.h
@@ -6,6 +6,7 @@
#define CONTENT_BROWSER_SPEECH_SPEECH_RECOGNITION_DISPATCHER_HOST_H_
#include <memory>
+#include <string>
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
@@ -14,7 +15,6 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/speech_recognition_event_listener.h"
#include "mojo/public/cpp/bindings/binding.h"
-#include "net/url_request/url_request_context_getter.h"
#include "third_party/blink/public/mojom/speech/speech_recognizer.mojom.h"
namespace network {
@@ -57,7 +57,7 @@ class CONTENT_EXPORT SpeechRecognitionDispatcherHost
bool filter_profanities,
std::unique_ptr<network::SharedURLLoaderFactoryInfo>
shared_url_loader_factory_info,
- scoped_refptr<net::URLRequestContextGetter> deprecated_context_getter);
+ const std::string& accept_language);
const int render_process_id_;
const int render_frame_id_;
@@ -109,6 +109,8 @@ class SpeechRecognitionSession : public blink::mojom::SpeechRecognitionSession,
float noise_volume) override;
private:
+ void ConnectionErrorHandler();
+
int session_id_;
blink::mojom::SpeechRecognitionSessionClientPtr client_;
bool stopped_;
diff --git a/chromium/content/browser/speech/speech_recognition_engine.cc b/chromium/content/browser/speech/speech_recognition_engine.cc
index 275129d367e..3bb628ae218 100644
--- a/chromium/content/browser/speech/speech_recognition_engine.cc
+++ b/chromium/content/browser/speech/speech_recognition_engine.cc
@@ -22,11 +22,6 @@
#include "net/base/escape.h"
#include "net/base/load_flags.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
-#include "net/url_request/http_user_agent_settings.h"
-#include "net/url_request/url_fetcher.h"
-#include "net/url_request/url_request_context.h"
-#include "net/url_request/url_request_context_getter.h"
-#include "net/url_request/url_request_status.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/simple_url_loader.h"
#include "services/network/public/mojom/chunked_data_pipe_getter.mojom.h"
@@ -293,11 +288,9 @@ const int SpeechRecognitionEngine::kWebserviceStatusErrorNoMatch = 5;
SpeechRecognitionEngine::SpeechRecognitionEngine(
scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
- scoped_refptr<net::URLRequestContextGetter>
- deprecated_url_request_context_getter)
+ const std::string& accept_language)
: shared_url_loader_factory_(std::move(shared_url_loader_factory)),
- deprecated_url_request_context_getter_(
- std::move(deprecated_url_request_context_getter)),
+ accept_language_(accept_language),
got_last_definitive_result_(false),
is_dispatching_event_(false),
use_framed_post_data_(false),
@@ -872,23 +865,13 @@ SpeechRecognitionEngine::NotFeasible(const FSMEventArgs& event_args) {
std::string SpeechRecognitionEngine::GetAcceptedLanguages() const {
std::string langs = config_.language;
- if (langs.empty() && deprecated_url_request_context_getter_.get()) {
+ if (langs.empty() && !accept_language_.empty()) {
// If no language is provided then we use the first from the accepted
// language list. If this list is empty then it defaults to "en-US".
// Example of the contents of this list: "es,en-GB;q=0.8", ""
- net::URLRequestContext* request_context =
- deprecated_url_request_context_getter_->GetURLRequestContext();
- DCHECK(request_context);
- // TODO(pauljensen): SpeechRecognitionEngine should be constructed with
- // a reference to the HttpUserAgentSettings rather than accessing the
- // accept language through the URLRequestContext.
- if (request_context->http_user_agent_settings()) {
- std::string accepted_language_list =
- request_context->http_user_agent_settings()->GetAcceptLanguage();
- size_t separator = accepted_language_list.find_first_of(",;");
- if (separator != std::string::npos)
- langs = accepted_language_list.substr(0, separator);
- }
+ size_t separator = accept_language_.find_first_of(",;");
+ if (separator != std::string::npos)
+ langs = accept_language_.substr(0, separator);
}
if (langs.empty())
langs = "en-US";
diff --git a/chromium/content/browser/speech/speech_recognition_engine.h b/chromium/content/browser/speech/speech_recognition_engine.h
index 5119585cdd2..1f3501200e5 100644
--- a/chromium/content/browser/speech/speech_recognition_engine.h
+++ b/chromium/content/browser/speech/speech_recognition_engine.h
@@ -24,10 +24,6 @@
#include "third_party/blink/public/mojom/speech/speech_recognition_grammar.mojom.h"
#include "third_party/blink/public/mojom/speech/speech_recognition_result.mojom.h"
-namespace net {
-class URLRequestContextGetter;
-}
-
namespace network {
class SharedURLLoaderFactory;
}
@@ -104,14 +100,10 @@ class CONTENT_EXPORT SpeechRecognitionEngine {
// Duration of each audio packet.
static const int kAudioPacketIntervalMs;
- // |deprecated_url_request_context_getter| is only for poking at the
- // Accept-Language header.
- // TODO(mmenke): Remove |deprecated_url_request_context_getter| as an
- // argument.
+ // |accept_language| is the default Accept-Language header.
SpeechRecognitionEngine(
scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
- scoped_refptr<net::URLRequestContextGetter>
- deprecated_url_request_context_getter);
+ const std::string& accept_language);
~SpeechRecognitionEngine();
// Sets the URL requests are sent to for tests.
@@ -215,8 +207,7 @@ class CONTENT_EXPORT SpeechRecognitionEngine {
std::unique_ptr<UpstreamLoader> upstream_loader_;
std::unique_ptr<DownstreamLoader> downstream_loader_;
scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory_;
- scoped_refptr<net::URLRequestContextGetter>
- deprecated_url_request_context_getter_;
+ const std::string accept_language_;
std::unique_ptr<AudioEncoder> encoder_;
std::unique_ptr<AudioEncoder> preamble_encoder_;
ChunkedByteBuffer chunked_byte_buffer_;
diff --git a/chromium/content/browser/speech/speech_recognition_engine_unittest.cc b/chromium/content/browser/speech/speech_recognition_engine_unittest.cc
index e5cc0943b11..e67d2517559 100644
--- a/chromium/content/browser/speech/speech_recognition_engine_unittest.cc
+++ b/chromium/content/browser/speech/speech_recognition_engine_unittest.cc
@@ -489,7 +489,7 @@ void SpeechRecognitionEngineTest::SetUp() {
engine_under_test_.reset(new SpeechRecognitionEngine(
base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
&url_loader_factory_),
- nullptr /*URLRequestContextGetter*/));
+ "" /* accept_language */));
engine_under_test_->set_delegate(this);
}
diff --git a/chromium/content/browser/speech/speech_recognition_manager_impl.cc b/chromium/content/browser/speech/speech_recognition_manager_impl.cc
index 0fe2c51770a..08bcec68559 100644
--- a/chromium/content/browser/speech/speech_recognition_manager_impl.cc
+++ b/chromium/content/browser/speech/speech_recognition_manager_impl.cc
@@ -282,9 +282,8 @@ int SpeechRecognitionManagerImpl::CreateSession(
remote_engine_config.auth_scope = config.auth_scope;
remote_engine_config.preamble = config.preamble;
- SpeechRecognitionEngine* google_remote_engine =
- new SpeechRecognitionEngine(config.shared_url_loader_factory,
- config.deprecated_url_request_context_getter);
+ SpeechRecognitionEngine* google_remote_engine = new SpeechRecognitionEngine(
+ config.shared_url_loader_factory, config.accept_language);
google_remote_engine->SetConfig(remote_engine_config);
session->recognizer = new SpeechRecognizerImpl(
diff --git a/chromium/content/browser/speech/speech_recognizer_impl.h b/chromium/content/browser/speech/speech_recognizer_impl.h
index fd6d57b8b8f..5636b18cbf5 100644
--- a/chromium/content/browser/speech/speech_recognizer_impl.h
+++ b/chromium/content/browser/speech/speech_recognizer_impl.h
@@ -15,7 +15,6 @@
#include "content/browser/speech/speech_recognition_engine.h"
#include "content/browser/speech/speech_recognizer.h"
#include "media/base/audio_capturer_source.h"
-#include "net/url_request/url_request_context_getter.h"
#include "third_party/blink/public/mojom/speech/speech_recognition_error.mojom.h"
#include "third_party/blink/public/mojom/speech/speech_recognition_result.mojom.h"
diff --git a/chromium/content/browser/speech/speech_recognizer_impl_unittest.cc b/chromium/content/browser/speech/speech_recognizer_impl_unittest.cc
index 0ef14a5d5ea..8c4fa526886 100644
--- a/chromium/content/browser/speech/speech_recognizer_impl_unittest.cc
+++ b/chromium/content/browser/speech/speech_recognizer_impl_unittest.cc
@@ -85,7 +85,7 @@ class SpeechRecognizerImplTest : public SpeechRecognitionEventListener,
SpeechRecognitionEngine* sr_engine = new SpeechRecognitionEngine(
base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
&url_loader_factory_),
- nullptr /* URLRequestContextGetter */);
+ "" /* accept_language */);
SpeechRecognitionEngine::Config config;
config.audio_num_bits_per_sample =
SpeechRecognizerImpl::kNumBitsPerAudioSample;
diff --git a/chromium/content/browser/storage_partition_impl.cc b/chromium/content/browser/storage_partition_impl.cc
index ab6a04d6ec9..ee48d130400 100644
--- a/chromium/content/browser/storage_partition_impl.cc
+++ b/chromium/content/browser/storage_partition_impl.cc
@@ -25,6 +25,7 @@
#include "content/browser/browser_main_loop.h"
#include "content/browser/browsing_data/storage_partition_http_cache_data_remover.h"
#include "content/browser/child_process_security_policy_impl.h"
+#include "content/browser/code_cache/generated_code_cache_context.h"
#include "content/browser/cookie_store/cookie_store_context.h"
#include "content/browser/fileapi/browser_file_system_helper.h"
#include "content/browser/gpu/shader_cache_factory.h"
@@ -40,6 +41,7 @@
#include "content/public/browser/indexed_db_context.h"
#include "content/public/browser/local_storage_usage_info.h"
#include "content/public/browser/network_service_instance.h"
+#include "content/public/browser/permission_controller.h"
#include "content/public/browser/session_storage_usage_info.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_features.h"
@@ -493,6 +495,7 @@ StoragePartitionImpl::StoragePartitionImpl(
storage::SpecialStoragePolicy* special_storage_policy)
: partition_path_(partition_path),
special_storage_policy_(special_storage_policy),
+ network_context_client_binding_(this),
browser_context_(browser_context),
deletion_helpers_running_(0),
weak_factory_(this) {}
@@ -551,7 +554,8 @@ StoragePartitionImpl::~StoragePartitionImpl() {
std::unique_ptr<StoragePartitionImpl> StoragePartitionImpl::Create(
BrowserContext* context,
bool in_memory,
- const base::FilePath& relative_partition_path) {
+ const base::FilePath& relative_partition_path,
+ const std::string& partition_domain) {
// Ensure that these methods are called on the UI thread, except for
// unittests where a UI thread might not have been created.
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) ||
@@ -606,11 +610,12 @@ std::unique_ptr<StoragePartitionImpl> StoragePartitionImpl::Create(
partition->service_worker_context_ = new ServiceWorkerContextWrapper(context);
partition->service_worker_context_->set_storage_partition(partition.get());
- partition->shared_worker_service_ = std::make_unique<SharedWorkerServiceImpl>(
- partition.get(), partition->service_worker_context_);
-
partition->appcache_service_ =
- new ChromeAppCacheService(quota_manager_proxy.get());
+ base::MakeRefCounted<ChromeAppCacheService>(quota_manager_proxy.get());
+
+ partition->shared_worker_service_ = std::make_unique<SharedWorkerServiceImpl>(
+ partition.get(), partition->service_worker_context_,
+ partition->appcache_service_);
partition->push_messaging_context_ =
new PushMessagingContext(context, partition->service_worker_context_);
@@ -630,7 +635,7 @@ std::unique_ptr<StoragePartitionImpl> StoragePartitionImpl::Create(
partition->background_fetch_context_ =
base::MakeRefCounted<BackgroundFetchContext>(
context, partition->service_worker_context_,
- partition->cache_storage_context_);
+ partition->cache_storage_context_, quota_manager_proxy);
partition->background_sync_context_ =
base::MakeRefCounted<BackgroundSyncContext>();
@@ -670,6 +675,36 @@ std::unique_ptr<StoragePartitionImpl> StoragePartitionImpl::Create(
partition->cookie_store_context_->Initialize(
partition->service_worker_context_, base::DoNothing());
+ if (base::FeatureList::IsEnabled(features::kIsolatedCodeCache)) {
+ // TODO(crbug.com/867552): Currently we misuse GetCachePath to check if
+ // code caching is enabled. Fix this by having a better API.
+
+ // For Incognito mode, we should not persist anything on the disk so
+ // we do not create a code cache. Caching the generated code in memory
+ // is not useful, since V8 already maintains one copy in memory.
+ if (!in_memory && !context->GetCachePath().empty()) {
+ partition->generated_code_cache_context_ =
+ base::MakeRefCounted<GeneratedCodeCacheContext>();
+
+ base::FilePath code_cache_path;
+ if (partition_domain.empty()) {
+ code_cache_path = context->GetCachePath().AppendASCII("Code Cache");
+ } else {
+ // For site isolated partitions use the config directory.
+ code_cache_path = context->GetPath()
+ .Append(relative_partition_path)
+ .AppendASCII("Code Cache");
+ }
+
+ // TODO(crbug.com/867552): Currently we set it to 0 and let the disk_cache
+ // backend selects the size based on some heuristics. Add support to let
+ // the embedder override the default value.
+ constexpr int kSizeInBytes = 0;
+ partition->GetGeneratedCodeCacheContext()->Initialize(code_cache_path,
+ kSizeInBytes);
+ }
+ }
+
return partition;
}
@@ -687,23 +722,8 @@ StoragePartitionImpl::GetMediaURLRequestContext() {
}
network::mojom::NetworkContext* StoragePartitionImpl::GetNetworkContext() {
- if (!network_context_.is_bound() || network_context_.encountered_error()) {
- network_context_ = GetContentClient()->browser()->CreateNetworkContext(
- browser_context_, is_in_memory_, relative_partition_path_);
- if (!network_context_) {
- // TODO(mmenke): Remove once https://crbug.com/827928 is fixed.
- CHECK(url_request_context_);
-
- DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
- DCHECK(!network_context_owner_);
- network_context_owner_ = std::make_unique<NetworkContextOwner>();
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&NetworkContextOwner::Initialize,
- base::Unretained(network_context_owner_.get()),
- MakeRequest(&network_context_), url_request_context_));
- }
- }
+ if (!network_context_.is_bound())
+ InitNetworkContext();
return network_context_.get();
}
@@ -830,6 +850,11 @@ CookieStoreContext* StoragePartitionImpl::GetCookieStoreContext() {
return cookie_store_context_.get();
}
+GeneratedCodeCacheContext*
+StoragePartitionImpl::GetGeneratedCodeCacheContext() {
+ return generated_code_cache_context_.get();
+}
+
void StoragePartitionImpl::OpenLocalStorage(
const url::Origin& origin,
blink::mojom::StorageAreaRequest request) {
@@ -848,9 +873,30 @@ void StoragePartitionImpl::OpenSessionStorage(
blink::mojom::SessionStorageNamespaceRequest request) {
int process_id = bindings_.dispatch_context();
dom_storage_context_->OpenSessionStorage(process_id, namespace_id,
+ bindings_.GetBadMessageCallback(),
std::move(request));
}
+void StoragePartitionImpl::OnCanSendReportingReports(
+ const std::vector<url::Origin>& origins,
+ OnCanSendReportingReportsCallback callback) {
+ PermissionController* permission_controller =
+ BrowserContext::GetPermissionController(browser_context_);
+ DCHECK(permission_controller);
+
+ std::vector<url::Origin> origins_out;
+ for (auto& origin : origins) {
+ GURL origin_url = origin.GetURL();
+ bool allowed = permission_controller->GetPermissionStatus(
+ PermissionType::BACKGROUND_SYNC, origin_url,
+ origin_url) == blink::mojom::PermissionStatus::GRANTED;
+ if (allowed)
+ origins_out.push_back(origin);
+ }
+
+ std::move(callback).Run(origins_out);
+}
+
void StoragePartitionImpl::ClearDataImpl(
uint32_t remove_mask,
uint32_t quota_storage_remove_mask,
@@ -1178,6 +1224,12 @@ void StoragePartitionImpl::Flush() {
GetDOMStorageContext()->Flush();
}
+void StoragePartitionImpl::ResetURLLoaderFactories() {
+ GetNetworkContext()->ResetURLLoaderFactories();
+ url_loader_factory_for_browser_process_.reset();
+ url_loader_factory_getter_->Initialize(this);
+}
+
void StoragePartitionImpl::ClearBluetoothAllowedDevicesMapForTesting() {
bluetooth_allowed_devices_map_->Clear();
}
@@ -1187,6 +1239,8 @@ void StoragePartitionImpl::FlushNetworkInterfaceForTesting() {
network_context_.FlushForTesting();
if (url_loader_factory_for_browser_process_)
url_loader_factory_for_browser_process_.FlushForTesting();
+ if (cookie_manager_for_browser_process_)
+ cookie_manager_for_browser_process_.FlushForTesting();
}
void StoragePartitionImpl::WaitForDeletionTasksForTesting() {
@@ -1197,10 +1251,6 @@ void StoragePartitionImpl::WaitForDeletionTasksForTesting() {
}
}
-void StoragePartitionImpl::ResetURLLoaderFactoryForBrowserProcessForTesting() {
- url_loader_factory_for_browser_process_.reset();
-}
-
BrowserContext* StoragePartitionImpl::browser_context() const {
return browser_context_;
}
@@ -1237,6 +1287,30 @@ void StoragePartitionImpl::GetQuotaSettings(
std::move(callback));
}
+void StoragePartitionImpl::InitNetworkContext() {
+ network_context_ = GetContentClient()->browser()->CreateNetworkContext(
+ browser_context_, is_in_memory_, relative_partition_path_);
+ if (!network_context_) {
+ // TODO(mmenke): Remove once https://crbug.com/827928 is fixed.
+ CHECK(url_request_context_);
+
+ DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
+ DCHECK(!network_context_owner_);
+ network_context_owner_ = std::make_unique<NetworkContextOwner>();
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&NetworkContextOwner::Initialize,
+ base::Unretained(network_context_owner_.get()),
+ MakeRequest(&network_context_), url_request_context_));
+ }
+ network::mojom::NetworkContextClientPtr client_ptr;
+ network_context_client_binding_.Close();
+ network_context_client_binding_.Bind(mojo::MakeRequest(&client_ptr));
+ network_context_->SetClient(std::move(client_ptr));
+ network_context_.set_connection_error_handler(base::BindOnce(
+ &StoragePartitionImpl::InitNetworkContext, weak_factory_.GetWeakPtr()));
+}
+
network::mojom::URLLoaderFactory*
StoragePartitionImpl::GetURLLoaderFactoryForBrowserProcessInternal() {
// Create the URLLoaderFactory as needed, but make sure not to reuse a
@@ -1257,8 +1331,12 @@ StoragePartitionImpl::GetURLLoaderFactoryForBrowserProcessInternal() {
switches::kDisableWebSecurity);
if (g_url_loader_factory_callback_for_test.Get().is_null()) {
auto request = mojo::MakeRequest(&url_loader_factory_for_browser_process_);
- GetContentClient()->browser()->WillCreateURLLoaderFactory(
- browser_context(), nullptr, false /* is_navigation */, &request);
+
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ GetContentClient()->browser()->WillCreateURLLoaderFactory(
+ browser_context(), nullptr, false /* is_navigation */, GURL(),
+ &request);
+ }
GetNetworkContext()->CreateURLLoaderFactory(std::move(request),
std::move(params));
is_test_url_loader_factory_for_browser_process_ = false;
diff --git a/chromium/content/browser/storage_partition_impl.h b/chromium/content/browser/storage_partition_impl.h
index e79f8775a1b..78110a30b23 100644
--- a/chromium/content/browser/storage_partition_impl.h
+++ b/chromium/content/browser/storage_partition_impl.h
@@ -34,6 +34,7 @@
#include "content/public/browser/storage_partition.h"
#include "mojo/public/cpp/bindings/binding_set.h"
#include "services/network/public/mojom/cookie_manager.mojom.h"
+#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/network_service.mojom.h"
#include "storage/browser/quota/special_storage_policy.h"
#include "third_party/blink/public/mojom/dom_storage/storage_partition_service.mojom.h"
@@ -49,10 +50,12 @@ class CookieStoreContext;
class BlobRegistryWrapper;
class PrefetchURLLoaderService;
class WebPackageContextImpl;
+class GeneratedCodeCacheContext;
class CONTENT_EXPORT StoragePartitionImpl
: public StoragePartition,
- public blink::mojom::StoragePartitionService {
+ public blink::mojom::StoragePartitionService,
+ public network::mojom::NetworkContextClient {
public:
// It is guaranteed that storage partitions are destructed before the
// browser context starts shutting down its corresponding IO thread residents
@@ -99,6 +102,7 @@ class CONTENT_EXPORT StoragePartitionImpl
CacheStorageContextImpl* GetCacheStorageContext() override;
ServiceWorkerContextWrapper* GetServiceWorkerContext() override;
SharedWorkerServiceImpl* GetSharedWorkerService() override;
+ GeneratedCodeCacheContext* GetGeneratedCodeCacheContext() override;
#if !defined(OS_ANDROID)
HostZoomMap* GetHostZoomMap() override;
HostZoomLevelContext* GetHostZoomLevelContext() override;
@@ -129,10 +133,10 @@ class CONTENT_EXPORT StoragePartitionImpl
const base::Callback<bool(const GURL&)>& url_matcher,
base::OnceClosure callback) override;
void Flush() override;
+ void ResetURLLoaderFactories() override;
void ClearBluetoothAllowedDevicesMapForTesting() override;
void FlushNetworkInterfaceForTesting() override;
void WaitForDeletionTasksForTesting() override;
- void ResetURLLoaderFactoryForBrowserProcessForTesting() override;
BackgroundFetchContext* GetBackgroundFetchContext();
BackgroundSyncContext* GetBackgroundSyncContext();
@@ -150,6 +154,11 @@ class CONTENT_EXPORT StoragePartitionImpl
const std::string& namespace_id,
blink::mojom::SessionStorageNamespaceRequest request) override;
+ // network::mojom::NetworkContextClient interface.
+ void OnCanSendReportingReports(
+ const std::vector<url::Origin>& origins,
+ OnCanSendReportingReportsCallback callback) override;
+
scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter() {
return url_loader_factory_getter_;
}
@@ -234,7 +243,8 @@ class CONTENT_EXPORT StoragePartitionImpl
static std::unique_ptr<StoragePartitionImpl> Create(
BrowserContext* context,
bool in_memory,
- const base::FilePath& relative_partition_path);
+ const base::FilePath& relative_partition_path,
+ const std::string& partition_domain);
StoragePartitionImpl(BrowserContext* browser_context,
const base::FilePath& partition_path,
@@ -274,6 +284,10 @@ class CONTENT_EXPORT StoragePartitionImpl
// storage configuration info.
void GetQuotaSettings(storage::OptionalQuotaSettingsCallback callback);
+ // Called to initialize |network_context_| when |GetNetworkContext()| is
+ // first called or there is an error.
+ void InitNetworkContext();
+
network::mojom::URLLoaderFactory*
GetURLLoaderFactoryForBrowserProcessInternal();
@@ -310,6 +324,7 @@ class CONTENT_EXPORT StoragePartitionImpl
scoped_refptr<BlobRegistryWrapper> blob_registry_;
scoped_refptr<PrefetchURLLoaderService> prefetch_url_loader_service_;
scoped_refptr<CookieStoreContext> cookie_store_context_;
+ scoped_refptr<GeneratedCodeCacheContext> generated_code_cache_context_;
// BindingSet for StoragePartitionService, using the process id as the
// binding context type. The process id can subsequently be used during
@@ -324,6 +339,9 @@ class CONTENT_EXPORT StoragePartitionImpl
// by |network_context_owner_|.
network::mojom::NetworkContextPtr network_context_;
+ mojo::Binding<network::mojom::NetworkContextClient>
+ network_context_client_binding_;
+
scoped_refptr<URLLoaderFactoryForBrowserProcess>
shared_url_loader_factory_for_browser_process_;
diff --git a/chromium/content/browser/storage_partition_impl_map.cc b/chromium/content/browser/storage_partition_impl_map.cc
index 9f56c4c29c5..c93fd1e67ba 100644
--- a/chromium/content/browser/storage_partition_impl_map.cc
+++ b/chromium/content/browser/storage_partition_impl_map.cc
@@ -18,13 +18,14 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "content/browser/appcache/appcache_interceptor.h"
#include "content/browser/appcache/chrome_appcache_service.h"
#include "content/browser/background_fetch/background_fetch_context.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
+#include "content/browser/code_cache/generated_code_cache_context.h"
#include "content/browser/cookie_store/cookie_store_context.h"
#include "content/browser/devtools/devtools_url_request_interceptor.h"
#include "content/browser/fileapi/browser_file_system_helper.h"
@@ -44,6 +45,7 @@
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/common/content_constants.h"
+#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h"
#include "crypto/sha2.h"
@@ -369,7 +371,7 @@ StoragePartitionImplMap::StoragePartitionImplMap(
BrowserContext* browser_context)
: browser_context_(browser_context),
file_access_runner_(base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BACKGROUND})),
+ {base::MayBlock(), base::TaskPriority::BEST_EFFORT})),
resource_context_initialized_(false) {}
StoragePartitionImplMap::~StoragePartitionImplMap() {
@@ -396,7 +398,7 @@ StoragePartitionImpl* StoragePartitionImplMap::Get(
std::unique_ptr<StoragePartitionImpl> partition_ptr(
StoragePartitionImpl::Create(browser_context_, in_memory,
- relative_partition_path));
+ relative_partition_path, partition_domain));
StoragePartitionImpl* partition = partition_ptr.get();
partitions_[partition_config] = std::move(partition_ptr);
@@ -500,7 +502,7 @@ void StoragePartitionImplMap::AsyncObliterate(
GetStoragePartitionDomainPath(partition_domain));
base::PostTaskWithTraits(
- FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND},
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
base::BindOnce(&BlockingObliteratePath, browser_context_->GetPath(),
domain_root, paths_to_keep,
base::ThreadTaskRunnerHandle::Get(), on_gc_required));
diff --git a/chromium/content/browser/storage_partition_impl_unittest.cc b/chromium/content/browser/storage_partition_impl_unittest.cc
index b151ad3c097..d58a94c0a62 100644
--- a/chromium/content/browser/storage_partition_impl_unittest.cc
+++ b/chromium/content/browser/storage_partition_impl_unittest.cc
@@ -13,11 +13,14 @@
#include "base/threading/thread.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/services/leveldb/public/cpp/util.h"
+#include "content/browser/code_cache/generated_code_cache.h"
+#include "content/browser/code_cache/generated_code_cache_context.h"
#include "content/browser/dom_storage/local_storage_database.pb.h"
#include "content/browser/gpu/shader_cache_factory.h"
#include "content/browser/storage_partition_impl.h"
#include "content/public/browser/local_storage_usage_info.h"
#include "content/public/browser/storage_partition.h"
+#include "content/public/common/content_features.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_browser_thread.h"
#include "content/public/test/test_browser_thread_bundle.h"
@@ -58,6 +61,7 @@ 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 kTestURL[] = "http://host4/script.js";
#if BUILDFLAG(ENABLE_PLUGINS)
const char kWidevineCdmPluginId[] = "application_x-ppapi-widevine-cdm";
@@ -68,6 +72,7 @@ const GURL kOrigin1(kTestOrigin1);
const GURL kOrigin2(kTestOrigin2);
const GURL kOrigin3(kTestOrigin3);
const GURL kOriginDevTools(kTestOriginDevTools);
+const GURL kResourceURL(kTestURL);
const blink::mojom::StorageType kTemporary =
blink::mojom::StorageType::kTemporary;
@@ -272,6 +277,49 @@ class RemoveLocalStorageTester {
DISALLOW_COPY_AND_ASSIGN(RemoveLocalStorageTester);
};
+class RemoveCodeCacheTester {
+ public:
+ explicit RemoveCodeCacheTester(GeneratedCodeCacheContext* code_cache_context)
+ : code_cache_context_(code_cache_context) {}
+
+ bool ContainsEntry(GURL url, url::Origin origin) {
+ entry_exists_ = false;
+ GeneratedCodeCache::ReadDataCallback callback = base::BindRepeating(
+ &RemoveCodeCacheTester::FetchEntryCallback, base::Unretained(this));
+ code_cache_context_->generated_code_cache()->FetchEntry(url, origin,
+ callback);
+ await_completion_.BlockUntilNotified();
+ return entry_exists_;
+ }
+
+ void AddEntry(GURL url, url::Origin origin, const std::string& data) {
+ std::vector<uint8_t> data_vector(data.begin(), data.end());
+ code_cache_context_->generated_code_cache()->WriteData(
+ url, origin, base::Time::Now(), data_vector);
+ base::RunLoop().RunUntilIdle();
+ }
+
+ std::string received_data() { return received_data_; }
+
+ private:
+ void FetchEntryCallback(const base::Time& response_time,
+ const std::vector<uint8_t>& data) {
+ if (!response_time.is_null()) {
+ entry_exists_ = true;
+ received_data_ = std::string(data.begin(), data.end());
+ } else {
+ entry_exists_ = false;
+ }
+ await_completion_.Notify();
+ }
+
+ bool entry_exists_;
+ AwaitCompletionHelper await_completion_;
+ GeneratedCodeCacheContext* code_cache_context_;
+ std::string received_data_;
+ DISALLOW_COPY_AND_ASSIGN(RemoveCodeCacheTester);
+};
+
#if BUILDFLAG(ENABLE_PLUGINS)
class RemovePluginPrivateDataTester {
public:
@@ -605,6 +653,15 @@ void ClearData(content::StoragePartition* partition,
time, time, run_loop->QuitClosure());
}
+void ClearCodeCache(content::StoragePartition* partition,
+ base::RunLoop* run_loop) {
+ base::Time delete_begin;
+ base::Time delete_end;
+ partition->ClearHttpAndMediaCaches(
+ delete_begin, delete_end, base::RepeatingCallback<bool(const GURL&)>(),
+ run_loop->QuitClosure());
+}
+
#if BUILDFLAG(ENABLE_PLUGINS)
void ClearPluginPrivateData(content::StoragePartition* partition,
const GURL& storage_origin,
@@ -1255,6 +1312,32 @@ TEST_F(StoragePartitionImplTest, RemoveLocalStorageForLastWeek) {
EXPECT_TRUE(tester.DOMStorageExistsForOrigin(kOrigin3));
}
+TEST_F(StoragePartitionImplTest, ClearCodeCache) {
+ // Run this test only when the IsolatedCodeCache feature is enabled
+ if (!base::FeatureList::IsEnabled(features::kIsolatedCodeCache))
+ return;
+
+ StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
+ BrowserContext::GetDefaultStoragePartition(browser_context()));
+ // Ensure code cache is initialized.
+ base::RunLoop().RunUntilIdle();
+
+ RemoveCodeCacheTester tester(partition->GetGeneratedCodeCacheContext());
+
+ url::Origin origin = url::Origin::Create(kOrigin1);
+ std::string data("SomeData");
+ tester.AddEntry(kResourceURL, origin, data);
+ EXPECT_TRUE(tester.ContainsEntry(kResourceURL, origin));
+ EXPECT_EQ(tester.received_data(), data);
+
+ base::RunLoop run_loop;
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(&ClearCodeCache, partition, &run_loop));
+ run_loop.Run();
+
+ EXPECT_FALSE(tester.ContainsEntry(kResourceURL, origin));
+}
+
#if BUILDFLAG(ENABLE_PLUGINS)
TEST_F(StoragePartitionImplTest, RemovePluginPrivateDataForever) {
StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
diff --git a/chromium/content/browser/tracing/DEPS b/chromium/content/browser/tracing/DEPS
index fddb5c8f0f1..1c6a0616ed7 100644
--- a/chromium/content/browser/tracing/DEPS
+++ b/chromium/content/browser/tracing/DEPS
@@ -1,7 +1,6 @@
include_rules = [
# Generated by the local tracing_resources.gyp:tracing_resources
"+grit/tracing_resources.h",
- "+tools/battor_agent",
]
specific_include_rules = {
diff --git a/chromium/content/browser/tracing/background_startup_tracing_observer.cc b/chromium/content/browser/tracing/background_startup_tracing_observer.cc
new file mode 100644
index 00000000000..307e5e5f44e
--- /dev/null
+++ b/chromium/content/browser/tracing/background_startup_tracing_observer.cc
@@ -0,0 +1,130 @@
+// 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/tracing/background_startup_tracing_observer.h"
+
+#include "components/tracing/common/trace_startup_config.h"
+#include "content/browser/tracing/background_tracing_rule.h"
+#include "content/public/browser/browser_thread.h"
+
+namespace content {
+namespace {
+
+const char kStartupTracingConfig[] = "startup-config";
+
+class PreferenceManagerImpl
+ : public BackgroundStartupTracingObserver::PreferenceManager {
+ public:
+ void SetBackgroundStartupTracingEnabled(bool enabled) override {
+ tracing::TraceStartupConfig::GetInstance()
+ ->SetBackgroundStartupTracingEnabled(enabled);
+ }
+
+ bool GetBackgroundStartupTracingEnabled() const override {
+ return tracing::TraceStartupConfig::GetInstance()
+ ->GetBackgroundStartupTracingEnabled();
+ }
+};
+
+} // namespace
+
+// static
+BackgroundStartupTracingObserver*
+BackgroundStartupTracingObserver::GetInstance() {
+ static BackgroundStartupTracingObserver* instance =
+ new BackgroundStartupTracingObserver;
+ return instance;
+}
+
+// static
+const BackgroundTracingRule*
+BackgroundStartupTracingObserver::FindStartupRuleInConfig(
+ const BackgroundTracingConfigImpl& config) {
+ for (const auto& rule : config.rules()) {
+ if (rule->category_preset() ==
+ BackgroundTracingConfigImpl::CategoryPreset::BENCHMARK_STARTUP) {
+ return rule.get();
+ }
+ }
+ return nullptr;
+}
+
+BackgroundStartupTracingObserver::BackgroundStartupTracingObserver()
+ : enabled_in_current_session_(false),
+ preferences_(new PreferenceManagerImpl) {}
+
+BackgroundStartupTracingObserver::~BackgroundStartupTracingObserver() {}
+
+void BackgroundStartupTracingObserver::OnScenarioActivated(
+ const BackgroundTracingConfigImpl* config) {
+ if (!enabled_in_current_session_)
+ return;
+ const BackgroundTracingRule* startup_rule = FindStartupRuleInConfig(*config);
+ DCHECK(startup_rule);
+ // Post task to avoid reentrancy.
+ content::BrowserThread::PostTask(
+ content::BrowserThread::UI, FROM_HERE,
+ base::BindOnce(
+ &BackgroundTracingManagerImpl::OnRuleTriggered,
+ base::Unretained(BackgroundTracingManagerImpl::GetInstance()),
+ base::Unretained(startup_rule),
+ BackgroundTracingManager::StartedFinalizingCallback()));
+}
+
+void BackgroundStartupTracingObserver::OnScenarioAborted() {
+ enabled_in_current_session_ = false;
+}
+
+void BackgroundStartupTracingObserver::OnTracingEnabled(
+ BackgroundTracingConfigImpl::CategoryPreset preset) {}
+
+void BackgroundStartupTracingObserver::SetPreferenceManagerForTesting(
+ std::unique_ptr<PreferenceManager> preferences) {
+ preferences_ = std::move(preferences);
+}
+
+std::unique_ptr<BackgroundTracingConfigImpl>
+BackgroundStartupTracingObserver::IncludeStartupConfigIfNeeded(
+ std::unique_ptr<BackgroundTracingConfigImpl> config) {
+ enabled_in_current_session_ =
+ preferences_->GetBackgroundStartupTracingEnabled();
+
+ const BackgroundTracingRule* startup_rule = nullptr;
+ if (config)
+ startup_rule = FindStartupRuleInConfig(*config);
+ // Reset the flag if startup tracing was enabled again in current session.
+ if (startup_rule) {
+ preferences_->SetBackgroundStartupTracingEnabled(true);
+ } else {
+ preferences_->SetBackgroundStartupTracingEnabled(false);
+ }
+
+ // If enabled in current session and startup rule already exists, then do not
+ // add another rule.
+ if (!enabled_in_current_session_ || startup_rule)
+ return config;
+
+ std::unique_ptr<base::DictionaryValue> rules_dict(
+ new base::DictionaryValue());
+ rules_dict->SetString("rule", "MONITOR_AND_DUMP_WHEN_TRIGGER_NAMED");
+ rules_dict->SetString("trigger_name", kStartupTracingConfig);
+ rules_dict->SetInteger("trigger_delay", 30);
+ rules_dict->SetString("category", "BENCHMARK_STARTUP");
+
+ if (config) {
+ config->AddReactiveRule(
+ rules_dict.get(),
+ BackgroundTracingConfigImpl::CategoryPreset::BENCHMARK_STARTUP);
+ } else {
+ base::DictionaryValue dict;
+ std::unique_ptr<base::ListValue> rules_list(new base::ListValue());
+ rules_list->Append(std::move(rules_dict));
+ dict.Set("configs", std::move(rules_list));
+ config = BackgroundTracingConfigImpl::ReactiveFromDict(&dict);
+ }
+ DCHECK(FindStartupRuleInConfig(*config));
+ return config;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/tracing/background_startup_tracing_observer.h b/chromium/content/browser/tracing/background_startup_tracing_observer.h
new file mode 100644
index 00000000000..3acb9c602bb
--- /dev/null
+++ b/chromium/content/browser/tracing/background_startup_tracing_observer.h
@@ -0,0 +1,69 @@
+// 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_TRACING_BACKGROUND_STARTUP_TRACING_OBSERVER_H_
+#define CONTENT_BROWSER_TRACING_BACKGROUND_STARTUP_TRACING_OBSERVER_H_
+
+#include <memory>
+
+#include "content/browser/tracing/background_tracing_manager_impl.h"
+
+namespace content {
+
+// Observes for startup tracing config and sets up preferences to trace on next
+// startup.
+class CONTENT_EXPORT BackgroundStartupTracingObserver
+ : public BackgroundTracingManagerImpl::EnabledStateObserver {
+ public:
+ // Delegate to store and read application preferences for startup tracing, to
+ // isolate the feature for testing.
+ class PreferenceManager {
+ public:
+ virtual void SetBackgroundStartupTracingEnabled(bool enabled) = 0;
+ virtual bool GetBackgroundStartupTracingEnabled() const = 0;
+ virtual ~PreferenceManager() = default;
+ };
+
+ static BackgroundStartupTracingObserver* GetInstance();
+
+ // Returns startup tracing rule from the given config, null if doesn't exist.
+ static const BackgroundTracingRule* FindStartupRuleInConfig(
+ const BackgroundTracingConfigImpl& config);
+
+ // BackgroundTracingManagerImpl::EnabledStateObserver implementation.
+ void OnScenarioActivated(const BackgroundTracingConfigImpl* config) override;
+ void OnScenarioAborted() override;
+ void OnTracingEnabled(
+ BackgroundTracingConfigImpl::CategoryPreset preset) override;
+
+ // Reads the preference for startup tracing set on the previous startup and
+ // includes config for startup tracing if enabled. Also sets or resets the
+ // preference for next session based on current config containing startup
+ // rule. Returns the config after the changes.
+ std::unique_ptr<BackgroundTracingConfigImpl> IncludeStartupConfigIfNeeded(
+ std::unique_ptr<BackgroundTracingConfigImpl> config);
+
+ // Returns true if startup tracing was set on the previous session and is
+ // active now.
+ bool enabled_in_current_session() const {
+ return enabled_in_current_session_;
+ }
+
+ void SetPreferenceManagerForTesting(
+ std::unique_ptr<PreferenceManager> preferences);
+
+ private:
+ BackgroundStartupTracingObserver();
+ ~BackgroundStartupTracingObserver() override;
+
+ bool enabled_in_current_session_;
+
+ std::unique_ptr<PreferenceManager> preferences_;
+
+ DISALLOW_COPY_AND_ASSIGN(BackgroundStartupTracingObserver);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_TRACING_BACKGROUND_STARTUP_TRACING_OBSERVER_H_
diff --git a/chromium/content/browser/tracing/background_startup_tracing_observer_unittest.cc b/chromium/content/browser/tracing/background_startup_tracing_observer_unittest.cc
new file mode 100644
index 00000000000..b6ad697b018
--- /dev/null
+++ b/chromium/content/browser/tracing/background_startup_tracing_observer_unittest.cc
@@ -0,0 +1,135 @@
+// 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/tracing/background_startup_tracing_observer.h"
+
+#include "build/build_config.h"
+#include "content/browser/tracing/background_tracing_rule.h"
+#include "content/public/test/test_browser_thread.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+namespace {
+
+class TestPreferenceManagerImpl
+ : public BackgroundStartupTracingObserver::PreferenceManager {
+ public:
+ void SetBackgroundStartupTracingEnabled(bool enabled) override {
+ enabled_ = enabled;
+ }
+
+ bool GetBackgroundStartupTracingEnabled() const override { return enabled_; }
+
+ private:
+ bool enabled_ = false;
+};
+
+void TestStartupRuleExists(const BackgroundTracingConfigImpl& config,
+ bool exists) {
+ const auto* rule =
+ BackgroundStartupTracingObserver::FindStartupRuleInConfig(config);
+ if (exists) {
+ ASSERT_TRUE(rule);
+ EXPECT_EQ(BackgroundTracingConfigImpl::CategoryPreset::BENCHMARK_STARTUP,
+ rule->category_preset());
+ EXPECT_EQ(30, rule->GetTraceDelay());
+ EXPECT_FALSE(rule->stop_tracing_on_repeated_reactive());
+ } else {
+ EXPECT_FALSE(rule);
+ }
+}
+
+} // namespace
+
+TEST(BackgroundStartupTracingObserverTest, IncludeStartupConfigIfNeeded) {
+ BackgroundStartupTracingObserver* observer =
+ BackgroundStartupTracingObserver::GetInstance();
+ std::unique_ptr<TestPreferenceManagerImpl> test_preferences(
+ new TestPreferenceManagerImpl);
+ TestPreferenceManagerImpl* preferences = test_preferences.get();
+ observer->SetPreferenceManagerForTesting(std::move(test_preferences));
+
+ // Empty config without preference set should not do anything.
+ std::unique_ptr<content::BackgroundTracingConfigImpl> config_impl;
+ config_impl = observer->IncludeStartupConfigIfNeeded(std::move(config_impl));
+ EXPECT_FALSE(config_impl);
+ EXPECT_FALSE(observer->enabled_in_current_session());
+
+ // Empty config with preference set should create a startup config, and reset
+ // preference.
+ EXPECT_FALSE(preferences->GetBackgroundStartupTracingEnabled());
+ preferences->SetBackgroundStartupTracingEnabled(true);
+ config_impl = observer->IncludeStartupConfigIfNeeded(std::move(config_impl));
+ EXPECT_TRUE(observer->enabled_in_current_session());
+ EXPECT_FALSE(preferences->GetBackgroundStartupTracingEnabled());
+ ASSERT_TRUE(config_impl);
+ EXPECT_EQ(1u, config_impl->rules().size());
+ EXPECT_EQ(BackgroundTracingConfig::TracingMode::REACTIVE,
+ config_impl->tracing_mode());
+ TestStartupRuleExists(*config_impl, true);
+
+ // Startup config with preference set should keep config and preference same.
+ preferences->SetBackgroundStartupTracingEnabled(true);
+ config_impl = observer->IncludeStartupConfigIfNeeded(std::move(config_impl));
+ EXPECT_TRUE(observer->enabled_in_current_session());
+ EXPECT_TRUE(preferences->GetBackgroundStartupTracingEnabled());
+ ASSERT_TRUE(config_impl);
+ EXPECT_EQ(1u, config_impl->rules().size());
+ TestStartupRuleExists(*config_impl, true);
+
+ // Startup config without preference set should keep config and set
+ // preference.
+ preferences->SetBackgroundStartupTracingEnabled(false);
+ config_impl = observer->IncludeStartupConfigIfNeeded(std::move(config_impl));
+ EXPECT_FALSE(observer->enabled_in_current_session());
+ EXPECT_TRUE(preferences->GetBackgroundStartupTracingEnabled());
+ ASSERT_TRUE(config_impl);
+ EXPECT_EQ(1u, config_impl->rules().size());
+ TestStartupRuleExists(*config_impl, true);
+
+ // A GPU config without preference set should not set preference and keep
+ // config same.
+ std::unique_ptr<base::DictionaryValue> rules_dict(
+ new base::DictionaryValue());
+ rules_dict->SetString("rule", "MONITOR_AND_DUMP_WHEN_TRIGGER_NAMED");
+ rules_dict->SetString("trigger_name", "test");
+ rules_dict->SetString("category", "BENCHMARK_GPU");
+ base::DictionaryValue dict;
+ std::unique_ptr<base::ListValue> rules_list(new base::ListValue());
+ rules_list->Append(std::move(rules_dict));
+ dict.Set("configs", std::move(rules_list));
+ config_impl = BackgroundTracingConfigImpl::ReactiveFromDict(&dict);
+ ASSERT_TRUE(config_impl);
+
+ preferences->SetBackgroundStartupTracingEnabled(false);
+ config_impl = observer->IncludeStartupConfigIfNeeded(std::move(config_impl));
+ EXPECT_FALSE(observer->enabled_in_current_session());
+ EXPECT_FALSE(preferences->GetBackgroundStartupTracingEnabled());
+ EXPECT_EQ(1u, config_impl->rules().size());
+ TestStartupRuleExists(*config_impl, false);
+
+ // A GPU config with preference set should include startup config and disable
+ // preference.
+ preferences->SetBackgroundStartupTracingEnabled(true);
+ config_impl = observer->IncludeStartupConfigIfNeeded(std::move(config_impl));
+ EXPECT_TRUE(observer->enabled_in_current_session());
+ EXPECT_FALSE(preferences->GetBackgroundStartupTracingEnabled());
+ ASSERT_TRUE(config_impl);
+ EXPECT_EQ(2u, config_impl->rules().size());
+ EXPECT_EQ(BackgroundTracingConfig::TracingMode::REACTIVE,
+ config_impl->tracing_mode());
+ TestStartupRuleExists(*config_impl, true);
+
+ bool found_gpu = false;
+ for (const auto& rule : config_impl->rules()) {
+ if (rule->category_preset() ==
+ BackgroundTracingConfigImpl::CategoryPreset::BENCHMARK_GPU) {
+ found_gpu = true;
+ }
+ }
+ EXPECT_TRUE(found_gpu);
+ preferences->SetBackgroundStartupTracingEnabled(false);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/tracing/background_tracing_config_impl.cc b/chromium/content/browser/tracing/background_tracing_config_impl.cc
index b5d5c9afaa0..691e0c7d974 100644
--- a/chromium/content/browser/tracing/background_tracing_config_impl.cc
+++ b/chromium/content/browser/tracing/background_tracing_config_impl.cc
@@ -35,6 +35,7 @@ const char kConfigCategoryBenchmarkMemoryHeavy[] = "BENCHMARK_MEMORY_HEAVY";
const char kConfigCategoryBenchmarkMemoryLight[] = "BENCHMARK_MEMORY_LIGHT";
const char kConfigCategoryBenchmarkExecutionMetric[] =
"BENCHMARK_EXECUTION_METRIC";
+const char kConfigCategoryBenchmarkNavigation[] = "BENCHMARK_NAVIGATION";
const char kConfigCategoryBlinkStyle[] = "BLINK_STYLE";
} // namespace
@@ -67,6 +68,8 @@ std::string BackgroundTracingConfigImpl::CategoryPresetToString(
return kConfigCategoryBenchmarkMemoryLight;
case BackgroundTracingConfigImpl::BENCHMARK_EXECUTION_METRIC:
return kConfigCategoryBenchmarkExecutionMetric;
+ case BackgroundTracingConfigImpl::BENCHMARK_NAVIGATION:
+ return kConfigCategoryBenchmarkNavigation;
case BackgroundTracingConfigImpl::BLINK_STYLE:
return kConfigCategoryBlinkStyle;
case BackgroundTracingConfigImpl::CATEGORY_PRESET_UNSET:
@@ -124,6 +127,11 @@ bool BackgroundTracingConfigImpl::StringToCategoryPreset(
return true;
}
+ if (category_preset_string == kConfigCategoryBenchmarkNavigation) {
+ *category_preset = BackgroundTracingConfigImpl::BENCHMARK_NAVIGATION;
+ return true;
+ }
+
if (category_preset_string == kConfigCategoryBlinkStyle) {
*category_preset = BackgroundTracingConfigImpl::BLINK_STYLE;
return true;
@@ -279,4 +287,4 @@ BackgroundTracingConfigImpl::ReactiveFromDict(
return config;
}
-} // namspace content
+} // namespace content
diff --git a/chromium/content/browser/tracing/background_tracing_config_impl.h b/chromium/content/browser/tracing/background_tracing_config_impl.h
index 58ed5e87287..9d8915e1d4f 100644
--- a/chromium/content/browser/tracing/background_tracing_config_impl.h
+++ b/chromium/content/browser/tracing/background_tracing_config_impl.h
@@ -37,6 +37,7 @@ class CONTENT_EXPORT BackgroundTracingConfigImpl
BENCHMARK_MEMORY_HEAVY,
BENCHMARK_MEMORY_LIGHT,
BENCHMARK_EXECUTION_METRIC,
+ BENCHMARK_NAVIGATION,
BLINK_STYLE
};
diff --git a/chromium/content/browser/tracing/background_tracing_config_unittest.cc b/chromium/content/browser/tracing/background_tracing_config_unittest.cc
index 7124ddff9f0..12de19fa40d 100644
--- a/chromium/content/browser/tracing/background_tracing_config_unittest.cc
+++ b/chromium/content/browser/tracing/background_tracing_config_unittest.cc
@@ -287,6 +287,7 @@ TEST_F(BackgroundTracingConfigTest, ValidPreemptiveCategoryToString) {
BackgroundTracingConfigImpl::BENCHMARK_MEMORY_HEAVY,
BackgroundTracingConfigImpl::BENCHMARK_MEMORY_LIGHT,
BackgroundTracingConfigImpl::BENCHMARK_EXECUTION_METRIC,
+ BackgroundTracingConfigImpl::BENCHMARK_NAVIGATION,
BackgroundTracingConfigImpl::BLINK_STYLE,
};
@@ -299,6 +300,7 @@ TEST_F(BackgroundTracingConfigTest, ValidPreemptiveCategoryToString) {
"BENCHMARK_MEMORY_HEAVY",
"BENCHMARK_MEMORY_LIGHT",
"BENCHMARK_EXECUTION_METRIC",
+ "BENCHMARK_NAVIGATION",
"BLINK_STYLE"};
for (size_t i = 0;
i <
@@ -630,4 +632,4 @@ TEST_F(BackgroundTracingConfigTest, ValidReactiveConfigToString) {
}
}
-} // namspace content
+} // namespace content
diff --git a/chromium/content/browser/tracing/background_tracing_manager_browsertest.cc b/chromium/content/browser/tracing/background_tracing_manager_browsertest.cc
index d419bace500..cea17d06e49 100644
--- a/chromium/content/browser/tracing/background_tracing_manager_browsertest.cc
+++ b/chromium/content/browser/tracing/background_tracing_manager_browsertest.cc
@@ -16,6 +16,7 @@
#include "base/run_loop.h"
#include "base/strings/pattern.h"
#include "base/trace_event/trace_event.h"
+#include "content/browser/tracing/background_startup_tracing_observer.h"
#include "content/browser/tracing/background_tracing_manager_impl.h"
#include "content/browser/tracing/background_tracing_rule.h"
#include "content/public/browser/browser_thread.h"
@@ -95,6 +96,19 @@ void TestBackgroundTracingObserver::OnTracingEnabled(
tracing_enabled_callback_.Run();
}
+class TestStartupPreferenceManagerImpl
+ : public BackgroundStartupTracingObserver::PreferenceManager {
+ public:
+ void SetBackgroundStartupTracingEnabled(bool enabled) override {
+ enabled_ = enabled;
+ }
+
+ bool GetBackgroundStartupTracingEnabled() const override { return enabled_; }
+
+ private:
+ bool enabled_ = false;
+};
+
} // namespace
class BackgroundTracingManagerBrowserTest : public ContentBrowserTest {
@@ -1588,4 +1602,123 @@ IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest,
}
}
+IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest,
+ SetupStartupTracing) {
+ SetupBackgroundTracingManager();
+ std::unique_ptr<TestStartupPreferenceManagerImpl> preferences_moved(
+ new TestStartupPreferenceManagerImpl);
+ TestStartupPreferenceManagerImpl* preferences = preferences_moved.get();
+ BackgroundStartupTracingObserver::GetInstance()
+ ->SetPreferenceManagerForTesting(std::move(preferences_moved));
+ preferences->SetBackgroundStartupTracingEnabled(false);
+ BackgroundTracingManagerUploadConfigWrapper upload_config_wrapper(
+ (base::OnceClosure()));
+
+ base::DictionaryValue dict;
+ std::unique_ptr<base::ListValue> rules_list(new base::ListValue());
+ {
+ std::unique_ptr<base::DictionaryValue> rules_dict(
+ new base::DictionaryValue());
+ rules_dict->SetString("rule", "MONITOR_AND_DUMP_WHEN_TRIGGER_NAMED");
+ rules_dict->SetString("trigger_name", "startup-config");
+ rules_dict->SetBoolean("stop_tracing_on_repeated_reactive", false);
+ rules_dict->SetInteger("trigger_delay", 10);
+ rules_dict->SetString("category", "BENCHMARK_STARTUP");
+ rules_list->Append(std::move(rules_dict));
+ }
+ dict.Set("configs", std::move(rules_list));
+
+ std::unique_ptr<BackgroundTracingConfig> config(
+ BackgroundTracingConfigImpl::ReactiveFromDict(&dict));
+
+ base::RunLoop wait_for_tracing_enabled;
+ TestBackgroundTracingObserver observer(
+ wait_for_tracing_enabled.QuitClosure());
+ EXPECT_TRUE(BackgroundTracingManager::GetInstance()->SetActiveScenario(
+ std::move(config), upload_config_wrapper.get_receive_callback(),
+ BackgroundTracingManager::NO_DATA_FILTERING));
+
+ BackgroundTracingManager::GetInstance()->WhenIdle(
+ base::BindRepeating(&DisableScenarioWhenIdle));
+
+ base::RunLoop().RunUntilIdle();
+
+ // Since we specified a delay in the scenario, we should still be tracing
+ // at this point.
+ EXPECT_FALSE(
+ BackgroundTracingManagerImpl::GetInstance()->IsTracingForTesting());
+ EXPECT_TRUE(preferences->GetBackgroundStartupTracingEnabled());
+}
+
+IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest, RunStartupTracing) {
+ SetupBackgroundTracingManager();
+ std::unique_ptr<TestStartupPreferenceManagerImpl> preferences_moved(
+ new TestStartupPreferenceManagerImpl);
+ TestStartupPreferenceManagerImpl* preferences = preferences_moved.get();
+ BackgroundStartupTracingObserver::GetInstance()
+ ->SetPreferenceManagerForTesting(std::move(preferences_moved));
+ preferences->SetBackgroundStartupTracingEnabled(true);
+ TraceLog::GetInstance()->SetArgumentFilterPredicate(
+ base::BindRepeating(&IsTraceEventArgsWhitelisted));
+ base::RunLoop wait_for_trace_log_enabled;
+ std::unique_ptr<TestEnabledStateObserver> trace_log_observer(
+ new TestEnabledStateObserver(wait_for_trace_log_enabled.QuitClosure()));
+
+ base::RunLoop run_loop;
+ BackgroundTracingManagerUploadConfigWrapper upload_config_wrapper(
+ run_loop.QuitClosure());
+
+ base::DictionaryValue dict;
+ std::unique_ptr<base::ListValue> rules_list(new base::ListValue());
+ {
+ std::unique_ptr<base::DictionaryValue> rules_dict(
+ new base::DictionaryValue());
+ rules_dict->SetString("rule", "MONITOR_AND_DUMP_WHEN_TRIGGER_NAMED");
+ rules_dict->SetString("trigger_name", "gpu-config");
+ rules_dict->SetBoolean("stop_tracing_on_repeated_reactive", false);
+ rules_dict->SetInteger("trigger_delay", 10);
+ rules_dict->SetString("category", "BENCHMARK_GPU");
+ rules_list->Append(std::move(rules_dict));
+ }
+ dict.Set("configs", std::move(rules_list));
+
+ std::unique_ptr<BackgroundTracingConfig> config(
+ BackgroundTracingConfigImpl::ReactiveFromDict(&dict));
+
+ base::RunLoop wait_for_tracing_enabled;
+ TestBackgroundTracingObserver observer(
+ wait_for_tracing_enabled.QuitClosure());
+ EXPECT_TRUE(BackgroundTracingManager::GetInstance()->SetActiveScenario(
+ std::move(config), upload_config_wrapper.get_receive_callback(),
+ BackgroundTracingManager::NO_DATA_FILTERING));
+
+ BackgroundTracingManager::GetInstance()->WhenIdle(
+ base::BindRepeating(&DisableScenarioWhenIdle));
+
+ wait_for_tracing_enabled.Run();
+ wait_for_trace_log_enabled.Run();
+ trace_log_observer.reset();
+
+ EXPECT_TRUE(BackgroundTracingManagerImpl::GetInstance()
+ ->requires_anonymized_data_for_testing());
+ EXPECT_TRUE(base::trace_event::TraceLog::GetInstance()
+ ->GetCurrentTraceConfig()
+ .IsArgumentFilterEnabled());
+
+ // Since we specified a delay in the scenario, we should still be tracing
+ // at this point.
+ EXPECT_TRUE(
+ BackgroundTracingManagerImpl::GetInstance()->IsTracingForTesting());
+
+ BackgroundTracingManager::GetInstance()->FireTimerForTesting();
+
+ EXPECT_FALSE(
+ BackgroundTracingManagerImpl::GetInstance()->IsTracingForTesting());
+
+ run_loop.Run();
+
+ EXPECT_TRUE(upload_config_wrapper.get_receive_count() == 1);
+ EXPECT_FALSE(preferences->GetBackgroundStartupTracingEnabled());
+}
+
} // 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 30d131e9d11..444fb27438d 100644
--- a/chromium/content/browser/tracing/background_tracing_manager_impl.cc
+++ b/chromium/content/browser/tracing/background_tracing_manager_impl.cc
@@ -16,7 +16,9 @@
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "base/values.h"
+#include "components/tracing/common/trace_startup_config.h"
#include "content/browser/tracing/background_memory_tracing_observer.h"
+#include "content/browser/tracing/background_startup_tracing_observer.h"
#include "content/browser/tracing/background_tracing_rule.h"
#include "content/browser/tracing/trace_message_filter.h"
#include "content/browser/tracing/tracing_controller_impl.h"
@@ -27,6 +29,8 @@
#include "content/public/common/content_switches.h"
#include "services/tracing/public/cpp/trace_event_agent.h"
+using base::trace_event::TraceConfig;
+
namespace content {
namespace {
@@ -48,6 +52,7 @@ enum BackgroundTracingMetrics {
SCENARIO_ACTION_FAILED_LOWRES_CLOCK = 9,
UPLOAD_FAILED = 10,
UPLOAD_SUCCEEDED = 11,
+ STARTUP_SCENARIO_TRIGGERED = 12,
NUMBER_OF_BACKGROUND_TRACING_METRICS,
};
@@ -100,6 +105,7 @@ BackgroundTracingManagerImpl::BackgroundTracingManagerImpl()
trigger_handle_ids_(0),
triggered_named_event_handle_(-1) {
AddEnabledStateObserver(BackgroundMemoryTracingObserver::GetInstance());
+ AddEnabledStateObserver(BackgroundStartupTracingObserver::GetInstance());
}
BackgroundTracingManagerImpl::~BackgroundTracingManagerImpl() {
@@ -125,7 +131,8 @@ bool BackgroundTracingManagerImpl::SetActiveScenario(
BackgroundTracingManager::ReceiveCallback receive_callback,
DataFiltering data_filtering) {
CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
- RecordBackgroundTracingMetric(SCENARIO_ACTIVATION_REQUESTED);
+ if (config)
+ RecordBackgroundTracingMetric(SCENARIO_ACTIVATION_REQUESTED);
if (is_tracing_)
return false;
@@ -133,10 +140,31 @@ bool BackgroundTracingManagerImpl::SetActiveScenario(
// If we don't have a high resolution timer available, traces will be
// too inaccurate to be useful.
if (!base::TimeTicks::IsHighResolution()) {
- RecordBackgroundTracingMetric(SCENARIO_ACTION_FAILED_LOWRES_CLOCK);
+ if (config)
+ RecordBackgroundTracingMetric(SCENARIO_ACTION_FAILED_LOWRES_CLOCK);
return false;
}
+ std::unique_ptr<content::BackgroundTracingConfigImpl> config_impl(
+ static_cast<BackgroundTracingConfigImpl*>(config.release()));
+ config_impl = BackgroundStartupTracingObserver::GetInstance()
+ ->IncludeStartupConfigIfNeeded(std::move(config_impl));
+ if (BackgroundStartupTracingObserver::GetInstance()
+ ->enabled_in_current_session()) {
+ // Anonymize data for startup tracing by default. We currently do not
+ // support storing the config in preferences for next session.
+ data_filtering = DataFiltering::ANONYMIZE_DATA;
+ RecordBackgroundTracingMetric(STARTUP_SCENARIO_TRIGGERED);
+ } else {
+ // If startup config was not set and tracing was enabled, then do not set
+ // any scenario.
+ if (base::trace_event::TraceLog::GetInstance()->IsEnabled())
+ return false;
+ }
+
+ if (!config_impl)
+ return false;
+
bool requires_anonymized_data = (data_filtering == ANONYMIZE_DATA);
// If the profile hasn't loaded or been created yet, this is a startup
@@ -144,9 +172,9 @@ bool BackgroundTracingManagerImpl::SetActiveScenario(
// that the scenario can run.
if (!delegate_ || delegate_->IsProfileLoaded()) {
// TODO(oysteine): Retry when time_until_allowed has elapsed.
- if (config && delegate_ &&
+ if (config_impl && delegate_ &&
!delegate_->IsAllowedToBeginBackgroundScenario(
- *config.get(), requires_anonymized_data)) {
+ *config_impl.get(), requires_anonymized_data)) {
return false;
}
} else {
@@ -156,9 +184,6 @@ bool BackgroundTracingManagerImpl::SetActiveScenario(
base::Unretained(this)));
}
- std::unique_ptr<const content::BackgroundTracingConfigImpl> config_impl(
- static_cast<BackgroundTracingConfigImpl*>(config.release()));
-
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
if (config_impl) {
@@ -185,20 +210,18 @@ bool BackgroundTracingManagerImpl::SetActiveScenario(
receive_callback_ = std::move(receive_callback);
requires_anonymized_data_ = requires_anonymized_data;
- if (config_) {
- DCHECK(!config_->rules().empty());
- for (const auto& rule : config_->rules())
- rule->Install();
+ DCHECK(!config_->rules().empty());
+ for (const auto& rule : config_->rules())
+ rule->Install();
- if (!config_->enable_blink_features().empty()) {
- command_line->AppendSwitchASCII(switches::kEnableBlinkFeatures,
- config_->enable_blink_features());
- }
+ if (!config_->enable_blink_features().empty()) {
+ command_line->AppendSwitchASCII(switches::kEnableBlinkFeatures,
+ config_->enable_blink_features());
+ }
- if (!config_->disable_blink_features().empty()) {
- command_line->AppendSwitchASCII(switches::kDisableBlinkFeatures,
- config_->disable_blink_features());
- }
+ if (!config_->disable_blink_features().empty()) {
+ command_line->AppendSwitchASCII(switches::kDisableBlinkFeatures,
+ config_->disable_blink_features());
}
// Notify observers before starting tracing.
@@ -374,7 +397,11 @@ void BackgroundTracingManagerImpl::TriggerNamedEvent(
void BackgroundTracingManagerImpl::OnRuleTriggered(
const BackgroundTracingRule* triggered_rule,
StartedFinalizingCallback callback) {
- CHECK(config_);
+ // Config can be null here if scenario was aborted when validation and rule
+ // was triggered just before validation. If validation kicked in after this
+ // point, we still check before uploading.
+ if (!config_)
+ return;
double trigger_chance = triggered_rule->trigger_chance();
if (trigger_chance < 1.0 && base::RandDouble() > trigger_chance) {
@@ -472,27 +499,13 @@ void BackgroundTracingManagerImpl::FireTimerForTesting() {
void BackgroundTracingManagerImpl::StartTracing(
BackgroundTracingConfigImpl::CategoryPreset preset,
base::trace_event::TraceRecordMode record_mode) {
- base::trace_event::TraceConfig trace_config(
- GetCategoryFilterStringForCategoryPreset(preset), record_mode);
+ TraceConfig config = GetConfigForCategoryPreset(preset, record_mode);
if (requires_anonymized_data_)
- trace_config.EnableArgumentFilter();
-
- if (preset ==
- BackgroundTracingConfigImpl::CategoryPreset::BENCHMARK_MEMORY_LIGHT) {
- // On memory light mode, the periodic memory dumps are disabled.
- // TODO(ssid): Remove this when memory-infra supports peak detection
- // crbug.com/609935.
- base::trace_event::TraceConfig::MemoryDumpConfig memory_config;
- memory_config.allowed_dump_modes =
- std::set<base::trace_event::MemoryDumpLevelOfDetail>(
- {base::trace_event::MemoryDumpLevelOfDetail::BACKGROUND});
- trace_config.ResetMemoryDumpConfig(memory_config);
- }
+ config.EnableArgumentFilter();
is_tracing_ = TracingControllerImpl::GetInstance()->StartTracing(
- trace_config,
- base::Bind(&BackgroundTracingManagerImpl::OnStartTracingDone,
- base::Unretained(this), preset));
+ config, base::Bind(&BackgroundTracingManagerImpl::OnStartTracingDone,
+ base::Unretained(this), preset));
RecordBackgroundTracingMetric(RECORDING_ENABLED);
}
@@ -561,8 +574,7 @@ bool BackgroundTracingManagerImpl::IsAllowedFinalization() const {
std::unique_ptr<base::DictionaryValue>
BackgroundTracingManagerImpl::GenerateMetadataDict() {
- if (!IsAllowedFinalization())
- return nullptr;
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
auto metadata_dict = std::make_unique<base::DictionaryValue>();
if (config_) {
@@ -627,39 +639,65 @@ void BackgroundTracingManagerImpl::AbortScenario() {
observer->OnScenarioAborted();
}
-std::string
-BackgroundTracingManagerImpl::GetCategoryFilterStringForCategoryPreset(
- BackgroundTracingConfigImpl::CategoryPreset preset) const {
+TraceConfig BackgroundTracingManagerImpl::GetConfigForCategoryPreset(
+ BackgroundTracingConfigImpl::CategoryPreset preset,
+ base::trace_event::TraceRecordMode record_mode) const {
switch (preset) {
case BackgroundTracingConfigImpl::CategoryPreset::BENCHMARK:
- return "benchmark,toplevel";
+ return TraceConfig("benchmark,toplevel", record_mode);
case BackgroundTracingConfigImpl::CategoryPreset::BENCHMARK_DEEP:
- return "*,disabled-by-default-benchmark.detailed,"
- "disabled-by-default-v8.cpu_profile,"
- "disabled-by-default-v8.runtime_stats";
+ return TraceConfig(
+ "*,disabled-by-default-benchmark.detailed,"
+ "disabled-by-default-v8.cpu_profile,"
+ "disabled-by-default-v8.runtime_stats",
+ record_mode);
case BackgroundTracingConfigImpl::CategoryPreset::BENCHMARK_GPU:
- return "benchmark,toplevel,gpu";
+ return TraceConfig("benchmark,toplevel,gpu", record_mode);
case BackgroundTracingConfigImpl::CategoryPreset::BENCHMARK_IPC:
- return "benchmark,toplevel,ipc";
- case BackgroundTracingConfigImpl::CategoryPreset::BENCHMARK_STARTUP:
- return "benchmark,toplevel,startup,disabled-by-default-file,"
- "disabled-by-default-toplevel.flow,"
- "disabled-by-default-ipc.flow";
+ return TraceConfig("benchmark,toplevel,ipc", record_mode);
+ case BackgroundTracingConfigImpl::CategoryPreset::BENCHMARK_STARTUP: {
+ auto config =
+ tracing::TraceStartupConfig::GetDefaultBrowserStartupConfig();
+ config.SetTraceRecordMode(record_mode);
+ return config;
+ }
case BackgroundTracingConfigImpl::CategoryPreset::BENCHMARK_BLINK_GC:
- return "blink_gc,disabled-by-default-blink_gc";
- case BackgroundTracingConfigImpl::CategoryPreset::BENCHMARK_MEMORY_HEAVY:
- case BackgroundTracingConfigImpl::CategoryPreset::BENCHMARK_MEMORY_LIGHT:
- return "-*,disabled-by-default-memory-infra";
+ return TraceConfig("blink_gc,disabled-by-default-blink_gc", record_mode);
case BackgroundTracingConfigImpl::CategoryPreset::
BENCHMARK_EXECUTION_METRIC:
- return "blink.console,v8";
+ return TraceConfig("blink.console,v8", record_mode);
+ case BackgroundTracingConfigImpl::CategoryPreset::BENCHMARK_NAVIGATION: {
+ auto config = TraceConfig(
+ "benchmark,toplevel,ipc,base,browser,navigation,omnibox,"
+ "safe_browsing,disabled-by-default-system_stats",
+ record_mode);
+ // Filter only browser process events.
+ base::trace_event::TraceConfig::ProcessFilterConfig process_config(
+ {base::GetCurrentProcId()});
+ config.SetProcessFilterConfig(process_config);
+ return config;
+ }
case BackgroundTracingConfigImpl::CategoryPreset::BLINK_STYLE:
- return "blink_style";
+ return TraceConfig("blink_style", record_mode);
+
+ case BackgroundTracingConfigImpl::CategoryPreset::BENCHMARK_MEMORY_HEAVY:
+ return TraceConfig("-*,disabled-by-default-memory-infra", record_mode);
+ case BackgroundTracingConfigImpl::CategoryPreset::BENCHMARK_MEMORY_LIGHT: {
+ // On memory light mode, the periodic memory dumps are disabled.
+ base::trace_event::TraceConfig::MemoryDumpConfig memory_config;
+ memory_config.allowed_dump_modes =
+ std::set<base::trace_event::MemoryDumpLevelOfDetail>(
+ {base::trace_event::MemoryDumpLevelOfDetail::BACKGROUND});
+ TraceConfig config("-*,disabled-by-default-memory-infra", record_mode);
+ config.ResetMemoryDumpConfig(memory_config);
+ return config;
+ }
+
case BackgroundTracingConfigImpl::CategoryPreset::CATEGORY_PRESET_UNSET:
NOTREACHED();
}
NOTREACHED();
- return "";
+ return TraceConfig();
}
-} // namspace content
+} // namespace content
diff --git a/chromium/content/browser/tracing/background_tracing_manager_impl.h b/chromium/content/browser/tracing/background_tracing_manager_impl.h
index d5c8fe92c1b..d242895ccdb 100644
--- a/chromium/content/browser/tracing/background_tracing_manager_impl.h
+++ b/chromium/content/browser/tracing/background_tracing_manager_impl.h
@@ -93,6 +93,9 @@ class BackgroundTracingManagerImpl : public BackgroundTracingManager {
const base::Closure& callback);
void FireTimerForTesting() override;
CONTENT_EXPORT bool IsTracingForTesting();
+ CONTENT_EXPORT bool requires_anonymized_data_for_testing() const {
+ return requires_anonymized_data_;
+ }
private:
BackgroundTracingManagerImpl();
@@ -118,8 +121,9 @@ class BackgroundTracingManagerImpl : public BackgroundTracingManager {
TriggerHandle handle) const;
bool IsSupportedConfig(BackgroundTracingConfigImpl* config);
- std::string GetCategoryFilterStringForCategoryPreset(
- BackgroundTracingConfigImpl::CategoryPreset) const;
+ base::trace_event::TraceConfig GetConfigForCategoryPreset(
+ BackgroundTracingConfigImpl::CategoryPreset,
+ base::trace_event::TraceRecordMode) const;
class TracingTimer {
public:
diff --git a/chromium/content/browser/tracing/background_tracing_rule.cc b/chromium/content/browser/tracing/background_tracing_rule.cc
index f69616755c8..88b260a0bcf 100644
--- a/chromium/content/browser/tracing/background_tracing_rule.cc
+++ b/chromium/content/browser/tracing/background_tracing_rule.cc
@@ -267,6 +267,12 @@ class HistogramRule
return;
}
+ // Add the histogram name and its corresponding value to the trace.
+ TRACE_EVENT_INSTANT2("toplevel",
+ "BackgroundTracingRule::OnHistogramTrigger",
+ TRACE_EVENT_SCOPE_THREAD, "histogram_name",
+ histogram_name, "value", actual_value);
+
OnHistogramTrigger(histogram_name);
}
@@ -373,9 +379,10 @@ class TraceAtRandomIntervalsRule : public BackgroundTracingRule {
void StartTimer() {
int time_to_wait = base::RandInt(kReactiveTraceRandomStartTimeMin,
kReactiveTraceRandomStartTimeMax);
- trigger_timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(time_to_wait),
- base::Bind(&TraceAtRandomIntervalsRule::OnTriggerTimer,
- base::Unretained(this)));
+ trigger_timer_.Start(
+ FROM_HERE, base::TimeDelta::FromSeconds(time_to_wait),
+ base::BindOnce(&TraceAtRandomIntervalsRule::OnTriggerTimer,
+ base::Unretained(this)));
}
int GetTraceDelay() const override {
diff --git a/chromium/content/browser/tracing/cast_tracing_agent.cc b/chromium/content/browser/tracing/cast_tracing_agent.cc
index 29e016250bc..77909801efc 100644
--- a/chromium/content/browser/tracing/cast_tracing_agent.cc
+++ b/chromium/content/browser/tracing/cast_tracing_agent.cc
@@ -9,7 +9,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/logging.h"
-#include "base/task_scheduler/task_scheduler.h"
+#include "base/task/post_task.h"
#include "base/trace_event/trace_config.h"
#include "chromecast/tracing/system_tracing_common.h"
#include "content/public/browser/browser_thread.h"
@@ -47,10 +47,9 @@ CastTracingAgent::CastTracingAgent(service_manager::Connector* connector)
tracing::mojom::TraceDataType::STRING,
false /* supports_explicit_clock_sync */,
base::kNullProcessId) {
- task_runner_ =
- base::TaskScheduler::GetInstance()->CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BACKGROUND,
- base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
+ task_runner_ = base::CreateSequencedTaskRunnerWithTraits(
+ {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+ base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
}
CastTracingAgent::~CastTracingAgent() = default;
diff --git a/chromium/content/browser/tracing/cros_tracing_agent.cc b/chromium/content/browser/tracing/cros_tracing_agent.cc
index 7a1cb3536ab..476789e6f4a 100644
--- a/chromium/content/browser/tracing/cros_tracing_agent.cc
+++ b/chromium/content/browser/tracing/cros_tracing_agent.cc
@@ -10,7 +10,7 @@
#include "base/bind_helpers.h"
#include "base/logging.h"
#include "base/memory/ref_counted_memory.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "base/trace_event/trace_config.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/debug_daemon_client.h"
diff --git a/chromium/content/browser/tracing/power_tracing_agent.cc b/chromium/content/browser/tracing/power_tracing_agent.cc
deleted file mode 100644
index c1b6bb29b29..00000000000
--- a/chromium/content/browser/tracing/power_tracing_agent.cc
+++ /dev/null
@@ -1,197 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/tracing/power_tracing_agent.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/lazy_instance.h"
-#include "base/memory/singleton.h"
-#include "base/task_scheduler/post_task.h"
-#include "base/task_scheduler/task_traits.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/time/time.h"
-#include "base/trace_event/trace_config.h"
-#include "base/trace_event/trace_event_impl.h"
-#include "mojo/public/cpp/bindings/interface_request.h"
-#include "services/service_manager/public/cpp/connector.h"
-#include "services/tracing/public/mojom/constants.mojom.h"
-#include "tools/battor_agent/battor_finder.h"
-
-namespace content {
-
-namespace {
-
-const char kPowerTraceLabel[] = "powerTraceAsString";
-
-} // namespace
-
-// static
-PowerTracingAgent* PowerTracingAgent::GetInstance() {
- return base::Singleton<PowerTracingAgent>::get();
-}
-
-PowerTracingAgent::PowerTracingAgent(service_manager::Connector* connector)
- : binding_(this) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- // Connect to the agent registry interface.
- tracing::mojom::AgentRegistryPtr agent_registry;
- connector->BindInterface(tracing::mojom::kServiceName, &agent_registry);
-
- // Register this agent.
- tracing::mojom::AgentPtr agent;
- binding_.Bind(mojo::MakeRequest(&agent));
- agent_registry->RegisterAgent(
- std::move(agent), kPowerTraceLabel, tracing::mojom::TraceDataType::STRING,
- true /* supports_explicit_clock_sync */, base::kNullProcessId);
-}
-
-PowerTracingAgent::PowerTracingAgent() : binding_(this) {}
-PowerTracingAgent::~PowerTracingAgent() = default;
-
-void PowerTracingAgent::StartTracing(const std::string& config,
- base::TimeTicks coordinator_time,
- Agent::StartTracingCallback callback) {
- base::trace_event::TraceConfig trace_config(config);
- if (!trace_config.IsSystraceEnabled()) {
- std::move(callback).Run(false /* success */);
- return;
- }
-
- base::PostTaskWithTraits(
- FROM_HERE, {base::TaskPriority::BACKGROUND, base::MayBlock()},
- base::BindOnce(&PowerTracingAgent::FindBattOrOnBackgroundThread,
- base::Unretained(this), std::move(callback)));
-}
-
-void PowerTracingAgent::FindBattOrOnBackgroundThread(
- Agent::StartTracingCallback callback) {
- std::string path = battor::BattOrFinder::FindBattOr();
- if (path.empty()) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(std::move(callback), false /* success */));
- return;
- }
-
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&PowerTracingAgent::StartTracingOnIOThread,
- base::Unretained(this), path, std::move(callback)));
-}
-
-void PowerTracingAgent::StartTracingOnIOThread(
- const std::string& path,
- Agent::StartTracingCallback callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- battor_agent_.reset(new battor::BattOrAgent(
- path, this, BrowserThread::GetTaskRunnerForThread(BrowserThread::UI)));
-
- start_tracing_callback_ = std::move(callback);
- battor_agent_->StartTracing();
-}
-
-void PowerTracingAgent::OnStartTracingComplete(battor::BattOrError error) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- bool success = (error == battor::BATTOR_ERROR_NONE);
- if (!success)
- battor_agent_.reset();
-
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(std::move(start_tracing_callback_), success));
-}
-
-void PowerTracingAgent::StopAndFlush(tracing::mojom::RecorderPtr recorder) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&PowerTracingAgent::StopAndFlushOnIOThread,
- base::Unretained(this), std::move(recorder)));
-}
-
-void PowerTracingAgent::StopAndFlushOnIOThread(
- tracing::mojom::RecorderPtr recorder) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- // This makes sense only when the battor agent exists.
- if (battor_agent_) {
- recorder_ = std::move(recorder);
- battor_agent_->StopTracing();
- }
-}
-
-void PowerTracingAgent::OnStopTracingComplete(
- const battor::BattOrResults& results,
- battor::BattOrError error) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- if (error == battor::BATTOR_ERROR_NONE)
- recorder_->AddChunk(results.ToString());
- recorder_.reset();
- battor_agent_.reset();
-}
-
-void PowerTracingAgent::RequestClockSyncMarker(
- const std::string& sync_id,
- Agent::RequestClockSyncMarkerCallback callback) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&PowerTracingAgent::RequestClockSyncMarkerOnIOThread,
- base::Unretained(this), sync_id, std::move(callback)));
-}
-
-void PowerTracingAgent::RequestClockSyncMarkerOnIOThread(
- const std::string& sync_id,
- Agent::RequestClockSyncMarkerCallback callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- // This makes sense only when the battor agent exists.
- if (!battor_agent_) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(std::move(callback), base::TimeTicks(),
- base::TimeTicks()));
- return;
- }
-
- request_clock_sync_marker_callback_ = std::move(callback);
- request_clock_sync_marker_start_time_ = TRACE_TIME_TICKS_NOW();
- battor_agent_->RecordClockSyncMarker(sync_id);
-}
-
-void PowerTracingAgent::OnRecordClockSyncMarkerComplete(
- battor::BattOrError error) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- base::TimeTicks issue_start_ts = request_clock_sync_marker_start_time_;
- base::TimeTicks issue_end_ts = TRACE_TIME_TICKS_NOW();
-
- if (error != battor::BATTOR_ERROR_NONE)
- issue_start_ts = issue_end_ts = base::TimeTicks();
-
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(std::move(request_clock_sync_marker_callback_),
- issue_start_ts, issue_end_ts));
- request_clock_sync_marker_start_time_ = base::TimeTicks();
-}
-
-void PowerTracingAgent::OnGetFirmwareGitHashComplete(
- const std::string& version, battor::BattOrError error) {
- return;
-}
-
-void PowerTracingAgent::GetCategories(Agent::GetCategoriesCallback callback) {
- std::move(callback).Run("");
-}
-
-void PowerTracingAgent::RequestBufferStatus(
- Agent::RequestBufferStatusCallback callback) {
- std::move(callback).Run(0, 0);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/tracing/power_tracing_agent.h b/chromium/content/browser/tracing/power_tracing_agent.h
deleted file mode 100644
index 6623bc121d5..00000000000
--- a/chromium/content/browser/tracing/power_tracing_agent.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_BROWSER_TRACING_POWER_TRACING_AGENT_H_
-#define CONTENT_BROWSER_TRACING_POWER_TRACING_AGENT_H_
-
-#include <memory>
-#include <string>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted_memory.h"
-#include "base/threading/thread.h"
-#include "content/public/browser/browser_thread.h"
-#include "mojo/public/cpp/bindings/binding.h"
-#include "services/tracing/public/mojom/tracing.mojom.h"
-#include "tools/battor_agent/battor_agent.h"
-#include "tools/battor_agent/battor_error.h"
-
-namespace base {
-template <typename Type>
-struct DefaultSingletonTraits;
-} // namespace base
-
-namespace service_manager {
-class Connector;
-} // namespace service_manager
-
-namespace content {
-
-using tracing::mojom::Agent;
-
-class PowerTracingAgent : public Agent, public battor::BattOrAgent::Listener {
- public:
- // Retrieve the singleton instance.
- static PowerTracingAgent* GetInstance();
-
- explicit PowerTracingAgent(service_manager::Connector* connector);
-
- // BattOrAgent::Listener implementation.
- void OnStartTracingComplete(battor::BattOrError error) override;
- void OnStopTracingComplete(const battor::BattOrResults& results,
- battor::BattOrError error) override;
- void OnRecordClockSyncMarkerComplete(battor::BattOrError error) override;
- void OnGetFirmwareGitHashComplete(const std::string& version,
- battor::BattOrError error) override;
-
- private:
- // This allows constructor and destructor to be private and usable only
- // by the Singleton class.
- friend struct base::DefaultSingletonTraits<PowerTracingAgent>;
- friend std::default_delete<PowerTracingAgent>;
-
- PowerTracingAgent();
- ~PowerTracingAgent() override;
-
- // tracing::mojom::Agent. Called by Mojo internals on the UI thread.
- void StartTracing(const std::string& config,
- base::TimeTicks coordinator_time,
- Agent::StartTracingCallback callback) override;
- void StopAndFlush(tracing::mojom::RecorderPtr recorder) override;
- void RequestClockSyncMarker(
- const std::string& sync_id,
- Agent::RequestClockSyncMarkerCallback callback) override;
- void GetCategories(Agent::GetCategoriesCallback callback) override;
- void RequestBufferStatus(
- Agent::RequestBufferStatusCallback callback) override;
-
- void FindBattOrOnBackgroundThread(Agent::StartTracingCallback callback);
- void StartTracingOnIOThread(const std::string& path,
- Agent::StartTracingCallback callback);
- void StopAndFlushOnIOThread(tracing::mojom::RecorderPtr recorder);
- void RequestClockSyncMarkerOnIOThread(
- const std::string& sync_id,
- Agent::RequestClockSyncMarkerCallback callback);
-
- // Returns the path of a BattOr (e.g. /dev/ttyUSB0), or an empty string if
- // none are found.
- std::string GetBattOrPath();
-
- // All interactions with the BattOrAgent (after construction) must happen on
- // the IO thread.
- std::unique_ptr<battor::BattOrAgent, BrowserThread::DeleteOnIOThread>
- battor_agent_;
-
- Agent::StartTracingCallback start_tracing_callback_;
- tracing::mojom::RecorderPtr recorder_;
- base::TimeTicks request_clock_sync_marker_start_time_;
- Agent::RequestClockSyncMarkerCallback request_clock_sync_marker_callback_;
-
- mojo::Binding<tracing::mojom::Agent> binding_;
-
- DISALLOW_COPY_AND_ASSIGN(PowerTracingAgent);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_TRACING_POWER_TRACING_AGENT_H_
diff --git a/chromium/content/browser/tracing/tracing_controller_browsertest.cc b/chromium/content/browser/tracing/tracing_controller_browsertest.cc
index 680c54845a5..40ee6778dd5 100644
--- a/chromium/content/browser/tracing/tracing_controller_browsertest.cc
+++ b/chromium/content/browser/tracing/tracing_controller_browsertest.cc
@@ -23,6 +23,7 @@
#include "content/public/test/content_browser_test_utils.h"
#include "content/shell/browser/shell.h"
#include "content/test/test_content_browser_client.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/tracing/public/cpp/trace_event_agent.h"
using base::trace_event::RECORD_CONTINUOUSLY;
@@ -104,7 +105,7 @@ class TracingTestBrowserClient : public TestContentBrowserClient {
class TestTracingDelegate : public TracingDelegate {
public:
std::unique_ptr<TraceUploader> GetTraceUploader(
- net::URLRequestContextGetter* request_context) override {
+ scoped_refptr<network::SharedURLLoaderFactory>) override {
return nullptr;
}
MetadataFilterPredicate GetMetadataFilterPredicate() override {
@@ -161,7 +162,7 @@ class TracingControllerTest : public ContentBrowserTest {
const base::FilePath& file_path) {
disable_recording_done_callback_count_++;
{
- base::ThreadRestrictions::ScopedAllowIO allow_io_for_test_verifications;
+ base::ScopedAllowBlockingForTesting allow_blocking;
EXPECT_TRUE(PathExists(file_path));
int64_t file_size;
base::GetFileSize(file_path, &file_size);
@@ -357,7 +358,13 @@ class TracingControllerTest : public ContentBrowserTest {
std::string last_data_;
};
-IN_PROC_BROWSER_TEST_F(TracingControllerTest, GetCategories) {
+// TODO(crbug.com/871770): Disabled for failing on ASAN.
+#if defined(ADDRESS_SANITIZER)
+#define MAYBE_GetCategories DISABLED_GetCategories
+#else
+#define MAYBE_GetCategories GetCategories
+#endif
+IN_PROC_BROWSER_TEST_F(TracingControllerTest, MAYBE_GetCategories) {
Navigate(shell());
TracingController* controller = TracingController::GetInstance();
@@ -372,11 +379,25 @@ IN_PROC_BROWSER_TEST_F(TracingControllerTest, GetCategories) {
EXPECT_EQ(get_categories_done_callback_count(), 1);
}
-IN_PROC_BROWSER_TEST_F(TracingControllerTest, EnableAndStopTracing) {
+// TODO(crbug.com/871770): Disabled for failing on ASAN.
+#if defined(ADDRESS_SANITIZER)
+#define MAYBE_EnableAndStopTracing DISABLED_EnableAndStopTracing
+#else
+#define MAYBE_EnableAndStopTracing EnableAndStopTracing
+#endif
+IN_PROC_BROWSER_TEST_F(TracingControllerTest, MAYBE_EnableAndStopTracing) {
TestStartAndStopTracingString();
}
-IN_PROC_BROWSER_TEST_F(TracingControllerTest, DisableRecordingStoresMetadata) {
+// TODO(crbug.com/871770): Disabled for failing on ASAN.
+#if defined(ADDRESS_SANITIZER)
+#define MAYBE_DisableRecordingStoresMetadata \
+ DISABLED_DisableRecordingStoresMetadata
+#else
+#define MAYBE_DisableRecordingStoresMetadata DisableRecordingStoresMetadata
+#endif
+IN_PROC_BROWSER_TEST_F(TracingControllerTest,
+ MAYBE_DisableRecordingStoresMetadata) {
TestStartAndStopTracingString();
// Check that a number of important keys exist in the metadata dictionary. The
// values are not checked to ensure the test is robust.
@@ -434,24 +455,47 @@ IN_PROC_BROWSER_TEST_F(TracingControllerTest,
EXPECT_TRUE(last_data().find("this_not_found") == std::string::npos);
}
+// TODO(crbug.com/871770): Disabled for failing on ASAN.
+#if defined(ADDRESS_SANITIZER)
+#define MAYBE_EnableAndStopTracingWithFilePath \
+ DISABLED_EnableAndStopTracingWithFilePath
+#else
+#define MAYBE_EnableAndStopTracingWithFilePath EnableAndStopTracingWithFilePath
+#endif
IN_PROC_BROWSER_TEST_F(TracingControllerTest,
- EnableAndStopTracingWithFilePath) {
+ MAYBE_EnableAndStopTracingWithFilePath) {
base::FilePath file_path;
{
- base::ThreadRestrictions::ScopedAllowIO allow_io_for_creating_test_file;
+ base::ScopedAllowBlockingForTesting allow_blocking;
base::CreateTemporaryFile(&file_path);
}
TestStartAndStopTracingFile(file_path);
EXPECT_EQ(file_path.value(), last_actual_recording_file_path().value());
}
+// TODO(crbug.com/871770): Disabled for failing on ASAN.
+#if defined(ADDRESS_SANITIZER)
+#define MAYBE_EnableAndStopTracingWithCompression \
+ DISABLED_EnableAndStopTracingWithCompression
+#else
+#define MAYBE_EnableAndStopTracingWithCompression \
+ EnableAndStopTracingWithCompression
+#endif
IN_PROC_BROWSER_TEST_F(TracingControllerTest,
- EnableAndStopTracingWithCompression) {
+ MAYBE_EnableAndStopTracingWithCompression) {
TestStartAndStopTracingCompressed();
}
+// TODO(crbug.com/871770): Disabled for failing on ASAN.
+#if defined(ADDRESS_SANITIZER)
+#define MAYBE_EnableAndStopTracingWithEmptyFile \
+ DISABLED_EnableAndStopTracingWithEmptyFile
+#else
+#define MAYBE_EnableAndStopTracingWithEmptyFile \
+ EnableAndStopTracingWithEmptyFile
+#endif
IN_PROC_BROWSER_TEST_F(TracingControllerTest,
- EnableAndStopTracingWithEmptyFile) {
+ MAYBE_EnableAndStopTracingWithEmptyFile) {
Navigate(shell());
base::RunLoop run_loop;
@@ -470,7 +514,13 @@ IN_PROC_BROWSER_TEST_F(TracingControllerTest,
run_loop.Run();
}
-IN_PROC_BROWSER_TEST_F(TracingControllerTest, DoubleStopTracing) {
+// TODO(crbug.com/871770): Disabled for failing on ASAN.
+#if defined(ADDRESS_SANITIZER)
+#define MAYBE_DoubleStopTracing DISABLED_DoubleStopTracing
+#else
+#define MAYBE_DoubleStopTracing DoubleStopTracing
+#endif
+IN_PROC_BROWSER_TEST_F(TracingControllerTest, MAYBE_DoubleStopTracing) {
Navigate(shell());
base::RunLoop run_loop;
diff --git a/chromium/content/browser/tracing/tracing_controller_impl.cc b/chromium/content/browser/tracing/tracing_controller_impl.cc
index ee4fa86896e..424c2447cc0 100644
--- a/chromium/content/browser/tracing/tracing_controller_impl.cc
+++ b/chromium/content/browser/tracing/tracing_controller_impl.cc
@@ -38,15 +38,6 @@
#include "services/tracing/public/mojom/constants.mojom.h"
#include "v8/include/v8-version-string.h"
-#if (defined(OS_POSIX) && defined(USE_UDEV)) || defined(OS_WIN) || \
- defined(OS_MACOSX)
-#define ENABLE_POWER_TRACING
-#endif
-
-#if defined(ENABLE_POWER_TRACING)
-#include "content/browser/tracing/power_tracing_agent.h"
-#endif
-
#if defined(OS_CHROMEOS)
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/debug_daemon_client.h"
@@ -140,11 +131,6 @@ void TracingControllerImpl::AddAgents() {
content::ServiceManagerConnection::GetForProcess()->GetConnector();
connector->BindInterface(tracing::mojom::kServiceName, &coordinator_);
-// Register tracing agents.
-#if defined(ENABLE_POWER_TRACING)
- agents_.push_back(std::make_unique<PowerTracingAgent>(connector));
-#endif
-
#if defined(OS_CHROMEOS)
agents_.push_back(std::make_unique<CrOSTracingAgent>(connector));
#elif defined(CAST_TRACING_AGENT)
@@ -175,6 +161,7 @@ tracing::TraceEventAgent* TracingControllerImpl::GetTraceEventAgent() const {
std::unique_ptr<base::DictionaryValue>
TracingControllerImpl::GenerateMetadataDict() const {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
auto metadata_dict = std::make_unique<base::DictionaryValue>();
// trace_config_ can be null if the tracing controller finishes flushing
diff --git a/chromium/content/browser/tracing/tracing_controller_impl_data_endpoint.cc b/chromium/content/browser/tracing/tracing_controller_impl_data_endpoint.cc
index 4fcd026465f..6f3d4facd74 100644
--- a/chromium/content/browser/tracing/tracing_controller_impl_data_endpoint.cc
+++ b/chromium/content/browser/tracing/tracing_controller_impl_data_endpoint.cc
@@ -10,7 +10,7 @@
#include "base/memory/ref_counted_memory.h"
#include "base/sequenced_task_runner.h"
#include "base/strings/pattern.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "content/browser/tracing/tracing_controller_impl.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/tracing_controller.h"
@@ -118,7 +118,7 @@ class FileTraceDataEndpoint : public TracingController::TraceDataEndpoint {
FILE* file_;
const scoped_refptr<base::SequencedTaskRunner> background_task_runner_ =
base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BACKGROUND});
+ {base::MayBlock(), base::TaskPriority::BEST_EFFORT});
DISALLOW_COPY_AND_ASSIGN(FileTraceDataEndpoint);
};
@@ -132,7 +132,7 @@ class CompressedTraceDataEndpoint
already_tried_open_(false),
background_task_runner_(base::CreateSequencedTaskRunnerWithTraits(
{compress_with_background_priority
- ? base::TaskPriority::BACKGROUND
+ ? base::TaskPriority::BEST_EFFORT
: base::TaskPriority::USER_VISIBLE})) {}
void ReceiveTraceChunk(std::unique_ptr<std::string> chunk) override {
diff --git a/chromium/content/browser/tracing/tracing_ui.cc b/chromium/content/browser/tracing/tracing_ui.cc
index fd922b3e90f..dec9a194057 100644
--- a/chromium/content/browser/tracing/tracing_ui.cc
+++ b/chromium/content/browser/tracing/tracing_ui.cc
@@ -237,14 +237,13 @@ void TracingUI::DoUploadInternal(const std::string& file_contents,
TraceUploader::UploadProgressCallback progress_callback =
base::Bind(&TracingUI::OnTraceUploadProgress,
weak_factory_.GetWeakPtr());
- TraceUploader::UploadDoneCallback done_callback =
- base::Bind(&TracingUI::OnTraceUploadComplete,
- weak_factory_.GetWeakPtr());
+ TraceUploader::UploadDoneCallback done_callback = base::BindOnce(
+ &TracingUI::OnTraceUploadComplete, weak_factory_.GetWeakPtr());
trace_uploader_ = delegate_->GetTraceUploader(
BrowserContext::GetDefaultStoragePartition(
- web_ui()->GetWebContents()->GetBrowserContext())->
- GetURLRequestContext());
+ web_ui()->GetWebContents()->GetBrowserContext())
+ ->GetURLLoaderFactoryForBrowserProcess());
DCHECK(trace_uploader_);
trace_uploader_->DoUpload(file_contents, upload_mode, nullptr,
std::move(progress_callback),
diff --git a/chromium/content/browser/url_loader_factory_getter.cc b/chromium/content/browser/url_loader_factory_getter.cc
index d3f03804253..abcd580a115 100644
--- a/chromium/content/browser/url_loader_factory_getter.cc
+++ b/chromium/content/browser/url_loader_factory_getter.cc
@@ -111,13 +111,18 @@ URLLoaderFactoryGetter::URLLoaderFactoryForIOThreadInfo::CreateFactory() {
// -----------------------------------------------------------------------------
-URLLoaderFactoryGetter::URLLoaderFactoryGetter() {}
+URLLoaderFactoryGetter::URLLoaderFactoryGetter() = default;
void URLLoaderFactoryGetter::Initialize(StoragePartitionImpl* partition) {
DCHECK(partition);
- DCHECK(!pending_network_factory_request_.is_pending());
-
partition_ = partition;
+
+ // Create a URLLoaderFactoryPtr synchronously and push it to the IO thread. If
+ // the pipe errors out later due to a network service crash, the pipe is
+ // created on the IO thread, and the request send back to the UI thread.
+ // TODO(mmenke): Is one less thread hop on startup worth the extra complexity
+ // of two different pipe creation paths?
+ DCHECK(!pending_network_factory_request_.is_pending());
network::mojom::URLLoaderFactoryPtr network_factory;
pending_network_factory_request_ = MakeRequest(&network_factory);
@@ -160,19 +165,26 @@ URLLoaderFactoryGetter::GetNetworkFactoryInfo() {
network::mojom::URLLoaderFactory*
URLLoaderFactoryGetter::GetURLLoaderFactory() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (g_get_network_factory_callback.Get() && !test_factory_)
- g_get_network_factory_callback.Get().Run(this);
- if (test_factory_)
- return test_factory_;
-
- if (!network_factory_.is_bound() || network_factory_.encountered_error()) {
+ // This needs to be done before returning |test_factory_|, as the
+ // |test_factory_| may fall back to |network_factory_|. The |is_bound()| check
+ // is only needed by unit tests.
+ if (network_factory_.encountered_error() || !network_factory_.is_bound()) {
+ network::mojom::URLLoaderFactoryPtr network_factory;
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::BindOnce(
&URLLoaderFactoryGetter::HandleNetworkFactoryRequestOnUIThread,
- this, mojo::MakeRequest(&network_factory_)));
+ this, mojo::MakeRequest(&network_factory)));
+ ReinitializeOnIOThread(std::move(network_factory));
}
+
+ if (g_get_network_factory_callback.Get() && !test_factory_)
+ g_get_network_factory_callback.Get().Run(this);
+
+ if (test_factory_)
+ return test_factory_;
+
return network_factory_.get();
}
@@ -201,25 +213,40 @@ void URLLoaderFactoryGetter::SetGetNetworkFactoryCallbackForTesting(
void URLLoaderFactoryGetter::FlushNetworkInterfaceOnIOThreadForTesting() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
base::RunLoop run_loop;
- BrowserThread::PostTaskAndReply(
+ BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(&URLLoaderFactoryGetter::FlushNetworkInterfaceForTesting,
- this),
- run_loop.QuitClosure());
+ this, run_loop.QuitClosure()));
run_loop.Run();
}
-void URLLoaderFactoryGetter::FlushNetworkInterfaceForTesting() {
+void URLLoaderFactoryGetter::FlushNetworkInterfaceForTesting(
+ base::OnceClosure callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (network_factory_)
- network_factory_.FlushForTesting();
+ network_factory_.FlushAsyncForTesting(std::move(callback));
}
URLLoaderFactoryGetter::~URLLoaderFactoryGetter() {}
void URLLoaderFactoryGetter::InitializeOnIOThread(
network::mojom::URLLoaderFactoryPtrInfo network_factory) {
- network_factory_.Bind(std::move(network_factory));
+ ReinitializeOnIOThread(
+ network::mojom::URLLoaderFactoryPtr(std::move(network_factory)));
+}
+
+void URLLoaderFactoryGetter::ReinitializeOnIOThread(
+ network::mojom::URLLoaderFactoryPtr network_factory) {
+ DCHECK(network_factory.is_bound());
+ network_factory_ = std::move(network_factory);
+ // Set a connection error handle so that connection errors on the pipes are
+ // noticed, but the class doesn't actually do anything when the error is
+ // observed - instead, a new pipe is created in GetURLLoaderFactory() as
+ // needed. This is to avoid incrementing the reference count of |this| in the
+ // callback, as that could result in increasing the reference count from 0 to
+ // 1 while there's a pending task to delete |this|. See
+ // https://crbug.com/870942 for more details.
+ network_factory_.set_connection_error_handler(base::DoNothing());
}
void URLLoaderFactoryGetter::HandleNetworkFactoryRequestOnUIThread(
diff --git a/chromium/content/browser/url_loader_factory_getter.h b/chromium/content/browser/url_loader_factory_getter.h
index 39bfbab5b7e..dc998f3e6ad 100644
--- a/chromium/content/browser/url_loader_factory_getter.h
+++ b/chromium/content/browser/url_loader_factory_getter.h
@@ -99,6 +99,10 @@ class URLLoaderFactoryGetter
void InitializeOnIOThread(
network::mojom::URLLoaderFactoryPtrInfo network_factory);
+ // Moves |network_factory| to |network_factory_| and sets up an error handler.
+ void ReinitializeOnIOThread(
+ network::mojom::URLLoaderFactoryPtr network_factory);
+
// Send |network_factory_request| to cached |StoragePartitionImpl|.
void HandleNetworkFactoryRequestOnUIThread(
network::mojom::URLLoaderFactoryRequest network_factory_request);
@@ -107,8 +111,9 @@ class URLLoaderFactoryGetter
// The pointer shouldn't be cached.
network::mojom::URLLoaderFactory* GetURLLoaderFactory();
- // Call |network_factory_.FlushForTesting()|. For test use only.
- void FlushNetworkInterfaceForTesting();
+ // Call |network_factory_.FlushForTesting()|. For test use only. When the
+ // flush is complete, |callback| will be called.
+ void FlushNetworkInterfaceForTesting(base::OnceClosure callback);
// Bound with appropriate URLLoaderFactories at HandleFactoryRequests().
network::mojom::URLLoaderFactoryRequest pending_network_factory_request_;
diff --git a/chromium/content/browser/utility_process_host.cc b/chromium/content/browser/utility_process_host.cc
index 9d7c9791bd9..da650c76a0a 100644
--- a/chromium/content/browser/utility_process_host.cc
+++ b/chromium/content/browser/utility_process_host.cc
@@ -30,6 +30,7 @@
#include "content/public/common/service_manager_connection.h"
#include "content/public/common/service_names.mojom.h"
#include "media/base/media_switches.h"
+#include "media/webrtc/webrtc_switches.h"
#include "services/network/public/cpp/network_switches.h"
#include "services/service_manager/embedder/switches.h"
#include "services/service_manager/public/cpp/interface_provider.h"
@@ -85,6 +86,12 @@ class UtilitySandboxedProcessLauncherDelegate
~UtilitySandboxedProcessLauncherDelegate() override {}
#if defined(OS_WIN)
+ bool DisableDefaultPolicy() override {
+ // Default policy is disabled for audio process to allow audio drivers
+ // to read device properties (https://crbug.com/883326).
+ return sandbox_type_ == service_manager::SANDBOX_TYPE_AUDIO;
+ }
+
bool ShouldLaunchElevated() override {
return sandbox_type_ ==
service_manager::SANDBOX_TYPE_NO_SANDBOX_AND_ELEVATED_PRIVILEGES;
@@ -104,7 +111,8 @@ class UtilitySandboxedProcessLauncherDelegate
#if BUILDFLAG(USE_ZYGOTE_HANDLE)
service_manager::ZygoteHandle GetZygote() override {
if (service_manager::IsUnsandboxedSandboxType(sandbox_type_) ||
- sandbox_type_ == service_manager::SANDBOX_TYPE_NETWORK) {
+ sandbox_type_ == service_manager::SANDBOX_TYPE_NETWORK ||
+ sandbox_type_ == service_manager::SANDBOX_TYPE_AUDIO) {
return nullptr;
}
return service_manager::GetGenericZygote();
@@ -313,6 +321,8 @@ bool UtilityProcessHost::StartProcess() {
switches::kFailAudioStreamCreation,
switches::kMuteAudio,
switches::kUseFileForFakeAudioCapture,
+ switches::kAecRefinedAdaptiveFilter,
+ switches::kAgcStartupMinVolume,
#if defined(OS_LINUX) || defined(OS_FREEBSD) || defined(OS_SOLARIS)
switches::kAlsaInputDevice,
switches::kAlsaOutputDevice,
diff --git a/chromium/content/browser/web_contents/web_contents_android.cc b/chromium/content/browser/web_contents/web_contents_android.cc
index 8cb3bf4b93e..b0d3fea4d0f 100644
--- a/chromium/content/browser/web_contents/web_contents_android.cc
+++ b/chromium/content/browser/web_contents/web_contents_android.cc
@@ -19,7 +19,8 @@
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/metrics/user_metrics.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
+#include "base/threading/scoped_blocking_call.h"
#include "content/browser/accessibility/browser_accessibility_android.h"
#include "content/browser/accessibility/browser_accessibility_manager_android.h"
#include "content/browser/android/java/gin_java_bridge_dispatcher_host.h"
@@ -142,7 +143,7 @@ void AXTreeSnapshotCallback(const ScopedJavaGlobalRef<jobject>& callback,
std::string CompressAndSaveBitmap(const std::string& dir,
const SkBitmap& bitmap) {
- base::AssertBlockingAllowed();
+ base::ScopedBlockingCall scoped_blocking_call(base::BlockingType::WILL_BLOCK);
std::vector<unsigned char> data;
if (!gfx::JPEGCodec::Encode(bitmap, 85, &data)) {
@@ -860,16 +861,6 @@ bool WebContentsAndroid::IsBeingDestroyed(JNIEnv* env,
return web_contents_->IsBeingDestroyed();
}
-int WebContentsAndroid::GetTopControlsShrinkBlinkHeightPixForTesting(
- JNIEnv* env,
- const JavaParamRef<jobject>& obj) {
- RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid();
- float scale = web_contents_->GetNativeView()->GetDipScale();
- return (rwhva && rwhva->DoBrowserControlsShrinkBlinkSize())
- ? rwhva->GetTopControlsHeight() * scale
- : 0;
-}
-
void WebContentsAndroid::SetDisplayCutoutSafeArea(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
diff --git a/chromium/content/browser/web_contents/web_contents_android.h b/chromium/content/browser/web_contents/web_contents_android.h
index d5094a6ad5c..6e55efc61f7 100644
--- a/chromium/content/browser/web_contents/web_contents_android.h
+++ b/chromium/content/browser/web_contents/web_contents_android.h
@@ -243,12 +243,6 @@ class CONTENT_EXPORT WebContentsAndroid
bool IsBeingDestroyed(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj);
- // Returns the amount of the top controls height if controls are in the state
- // of shrinking Blink's view size, otherwise 0.
- int GetTopControlsShrinkBlinkHeightPixForTesting(
- JNIEnv* env,
- const base::android::JavaParamRef<jobject>& obj);
-
void SetDisplayCutoutSafeArea(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
int top,
@@ -256,9 +250,9 @@ class CONTENT_EXPORT WebContentsAndroid
int bottom,
int right);
- private:
RenderWidgetHostViewAndroid* GetRenderWidgetHostViewAndroid();
+ private:
void OnFinishGetContentBitmap(const base::android::JavaRef<jobject>& obj,
const base::android::JavaRef<jobject>& callback,
const std::string& path,
diff --git a/chromium/content/browser/web_contents/web_contents_impl.cc b/chromium/content/browser/web_contents/web_contents_impl.cc
index 26384f823b5..499c8c0a2e8 100644
--- a/chromium/content/browser/web_contents/web_contents_impl.cc
+++ b/chromium/content/browser/web_contents/web_contents_impl.cc
@@ -35,6 +35,8 @@
#include "components/download/public/common/download_stats.h"
#include "components/rappor/public/rappor_utils.h"
#include "components/url_formatter/url_formatter.h"
+#include "content/browser/accessibility/accessibility_tree_formatter.h"
+#include "content/browser/accessibility/accessibility_tree_formatter_blink.h"
#include "content/browser/accessibility/browser_accessibility_state_impl.h"
#include "content/browser/bad_message.h"
#include "content/browser/browser_plugin/browser_plugin_embedder.h"
@@ -540,7 +542,7 @@ WebContentsImpl::WebContentsImpl(BrowserContext* browser_context)
force_disable_overscroll_content_(false),
last_dialog_suppressed_(false),
accessibility_mode_(
- BrowserAccessibilityStateImpl::GetInstance()->accessibility_mode()),
+ BrowserAccessibilityStateImpl::GetInstance()->GetAccessibilityMode()),
audio_stream_monitor_(this),
bluetooth_connected_device_count_(0),
media_device_group_id_salt_base_(
@@ -570,11 +572,8 @@ WebContentsImpl::WebContentsImpl(BrowserContext* browser_context)
#endif // !defined(OS_ANDROID)
#if defined(OS_ANDROID)
- if (base::FeatureList::IsEnabled(features::kDisplayCutoutAPI)) {
- display_cutout_host_impl_ = std::make_unique<DisplayCutoutHostImpl>(
- this, base::BindRepeating(&WebContentsImpl::NotifyViewportFitChanged,
- base::Unretained(this)));
- }
+ if (base::FeatureList::IsEnabled(features::kDisplayCutoutAPI))
+ display_cutout_host_impl_ = std::make_unique<DisplayCutoutHostImpl>(this);
#endif
registry_.AddInterface(base::BindRepeating(
@@ -682,6 +681,9 @@ WebContentsImpl::~WebContentsImpl() {
for (auto& observer : observers_)
observer.WebContentsDestroyed();
+ if (display_cutout_host_impl_)
+ display_cutout_host_impl_->WebContentsDestroyed();
+
for (auto& observer : observers_)
observer.ResetWebContents();
@@ -802,6 +804,8 @@ bool WebContentsImpl::OnMessageReceived(RenderViewHostImpl* render_view_host,
IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(WebContentsImpl, message, render_view_host)
IPC_MESSAGE_HANDLER(ViewHostMsg_DidFirstVisuallyNonEmptyPaint,
OnFirstVisuallyNonEmptyPaint)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_DidCommitAndDrawCompositorFrame,
+ OnCommitAndDrawCompositorFrame)
IPC_MESSAGE_HANDLER(ViewHostMsg_GoToEntryAtOffset, OnGoToEntryAtOffset)
IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateZoomLimits, OnUpdateZoomLimits)
IPC_MESSAGE_HANDLER(ViewHostMsg_PageScaleFactorChanged,
@@ -861,7 +865,6 @@ bool WebContentsImpl::OnMessageReceived(RenderFrameHostImpl* render_frame_host,
OnUnregisterProtocolHandler)
IPC_MESSAGE_HANDLER(FrameHostMsg_UpdatePageImportanceSignals,
OnUpdatePageImportanceSignals)
- IPC_MESSAGE_HANDLER(FrameHostMsg_Find_Reply, OnFindReply)
IPC_MESSAGE_HANDLER(FrameHostMsg_UpdateFaviconURL, OnUpdateFaviconURL)
#if BUILDFLAG(ENABLE_PLUGINS)
IPC_MESSAGE_HANDLER(FrameHostMsg_PepperInstanceCreated,
@@ -1117,10 +1120,10 @@ void WebContentsImpl::RequestAXTreeSnapshot(AXTreeSnapshotCallback callback,
// them into a single tree and call |callback| with that result, then
// delete |combiner|.
FrameTreeNode* root_node = frame_tree_.root();
- AXTreeSnapshotCombiner* combiner =
- new AXTreeSnapshotCombiner(std::move(callback));
+ auto combiner =
+ base::MakeRefCounted<AXTreeSnapshotCombiner>(std::move(callback));
- RecursiveRequestAXTreeSnapshotOnFrame(root_node, combiner, ax_mode);
+ RecursiveRequestAXTreeSnapshotOnFrame(root_node, combiner.get(), ax_mode);
}
void WebContentsImpl::RecursiveRequestAXTreeSnapshotOnFrame(
@@ -1493,6 +1496,8 @@ void WebContentsImpl::SetHasPictureInPictureVideo(
return;
has_picture_in_picture_video_ = has_picture_in_picture_video;
NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB);
+ for (auto& observer : observers_)
+ observer.MediaPictureInPictureChanged(has_picture_in_picture_video_);
}
bool WebContentsImpl::IsCrashed() const {
@@ -1660,6 +1665,10 @@ bool WebContentsImpl::HasRecentInteractiveInputEvent() const {
return delta <= kMaxInterval;
}
+void WebContentsImpl::SetIgnoreInputEvents(bool ignore_input_events) {
+ ignore_input_events_ = ignore_input_events;
+}
+
#if defined(OS_ANDROID)
void WebContentsImpl::SetMainFrameImportance(
ChildProcessImportance importance) {
@@ -2326,6 +2335,9 @@ void WebContentsImpl::ExitFullscreenMode(bool will_cause_resize) {
observer.DidToggleFullscreenModeForTab(IsFullscreenForCurrentTab(),
will_cause_resize);
}
+
+ if (display_cutout_host_impl_)
+ display_cutout_host_impl_->DidExitFullscreen();
}
void WebContentsImpl::FullscreenStateChanged(RenderFrameHost* rfh,
@@ -2390,6 +2402,9 @@ void WebContentsImpl::FullscreenStateChanged(RenderFrameHost* rfh,
for (auto& observer : observers_)
observer.DidAcquireFullscreen(max_depth_rfh);
+
+ if (display_cutout_host_impl_)
+ display_cutout_host_impl_->DidAcquireFullscreen(max_depth_rfh);
} else if (fullscreen_frame_tree_nodes_.size() == 0) {
current_fullscreen_frame_tree_node_id_ =
RenderFrameHost::kNoFrameTreeNodeId;
@@ -2661,8 +2676,8 @@ void WebContentsImpl::CreateNewWindow(
// FrameTreeNode id instead of the routing id of the Widget for the main
// frame. https://crbug.com/545684
DCHECK_NE(MSG_ROUTING_NONE, main_frame_widget_route_id);
- pending_contents_[std::make_pair(render_process_id,
- main_frame_widget_route_id)] =
+ pending_contents_[GlobalRoutingID(render_process_id,
+ main_frame_widget_route_id)] =
std::move(new_contents);
AddDestructionObserver(raw_new_contents);
}
@@ -2673,20 +2688,17 @@ void WebContentsImpl::CreateNewWindow(
params.target_url, raw_new_contents);
}
- if (opener) {
- for (auto& observer : observers_) {
- observer.DidOpenRequestedURL(raw_new_contents, opener, params.target_url,
- params.referrer, params.disposition,
- ui::PAGE_TRANSITION_LINK,
- false, // started_from_context_menu
- true); // renderer_initiated
- }
+ for (auto& observer : observers_) {
+ observer.DidOpenRequestedURL(raw_new_contents, opener, params.target_url,
+ params.referrer, params.disposition,
+ ui::PAGE_TRANSITION_LINK,
+ false, // started_from_context_menu
+ true); // renderer_initiated
}
// Any new WebContents opened while this WebContents is in fullscreen can be
// used to confuse the user, so drop fullscreen.
- if (IsFullscreenForCurrentTab())
- ExitFullscreen(true);
+ ForSecurityDropFullscreen();
if (params.opener_suppressed) {
// When the opener is suppressed, the original renderer cannot access the
@@ -2767,7 +2779,7 @@ void WebContentsImpl::CreateNewWidget(int32_t render_process_id,
widget_view->SetPopupType(popup_type);
}
// Save the created widget associated with the route so we can show it later.
- pending_widget_views_[std::make_pair(render_process_id, route_id)] =
+ pending_widget_views_[GlobalRoutingID(render_process_id, route_id)] =
widget_view;
}
@@ -2860,7 +2872,7 @@ void WebContentsImpl::ShowCreatedWidget(int process_id,
std::unique_ptr<WebContents> WebContentsImpl::GetCreatedWindow(
int process_id,
int main_frame_widget_route_id) {
- auto key = std::make_pair(process_id, main_frame_widget_route_id);
+ auto key = GlobalRoutingID(process_id, main_frame_widget_route_id);
auto iter = pending_contents_.find(key);
// Certain systems can block the creation of new windows. If we didn't succeed
@@ -2888,14 +2900,14 @@ std::unique_ptr<WebContents> WebContentsImpl::GetCreatedWindow(
RenderWidgetHostView* WebContentsImpl::GetCreatedWidget(int process_id,
int route_id) {
- auto iter = pending_widget_views_.find(std::make_pair(process_id, route_id));
+ auto iter = pending_widget_views_.find(GlobalRoutingID(process_id, route_id));
if (iter == pending_widget_views_.end()) {
DCHECK(false);
return nullptr;
}
RenderWidgetHostView* widget_host_view = iter->second;
- pending_widget_views_.erase(std::make_pair(process_id, route_id));
+ pending_widget_views_.erase(GlobalRoutingID(process_id, route_id));
RenderWidgetHost* widget_host = widget_host_view->GetRenderWidgetHost();
if (!widget_host->GetProcess()->IsInitializedAndNotDead()) {
@@ -2981,6 +2993,13 @@ void WebContentsImpl::AccessibilityLocationChangesReceived(
observer.AccessibilityLocationChangesReceived(details);
}
+base::string16 WebContentsImpl::DumpAccessibilityTree(bool internal) {
+ auto* ax_mgr = GetOrCreateRootBrowserAccessibilityManager();
+ DCHECK(ax_mgr);
+ return AccessibilityTreeFormatter::DumpAccessibilityTreeFromManager(ax_mgr,
+ internal);
+}
+
RenderFrameHost* WebContentsImpl::GetGuestByInstanceID(
RenderFrameHost* render_frame_host,
int browser_plugin_instance_id) {
@@ -3139,9 +3158,10 @@ void WebContentsImpl::SelectRange(const gfx::Point& base,
#if defined(OS_MACOSX)
void WebContentsImpl::DidChangeTextSelection(const base::string16& text,
- const gfx::Range& range) {
+ const gfx::Range& range,
+ size_t offset) {
for (auto& observer : observers_)
- observer.DidChangeTextSelection(text, range);
+ observer.DidChangeTextSelection(text, range, offset);
}
#endif
@@ -3228,10 +3248,10 @@ WebContents* WebContentsImpl::OpenURL(const OpenURLParams& params) {
if (new_contents && source_render_frame_host && new_contents != this) {
for (auto& observer : observers_) {
- observer.DidOpenRequestedURL(new_contents, source_render_frame_host,
- params.url, params.referrer,
- params.disposition, params.transition,
- params.started_from_context_menu, false);
+ observer.DidOpenRequestedURL(
+ new_contents, source_render_frame_host, params.url, params.referrer,
+ params.disposition, params.transition,
+ params.started_from_context_menu, params.is_renderer_initiated);
}
}
@@ -4015,6 +4035,9 @@ void WebContentsImpl::DidStartNavigation(NavigationHandle* navigation_handle) {
"navigation_handle", navigation_handle);
for (auto& observer : observers_)
observer.DidStartNavigation(navigation_handle);
+
+ if (display_cutout_host_impl_)
+ display_cutout_host_impl_->DidStartNavigation(navigation_handle);
}
void WebContentsImpl::DidRedirectNavigation(
@@ -4068,9 +4091,13 @@ void WebContentsImpl::ReadyToCommitNavigation(
if (navigation_handle->IsSameDocument())
return;
- controller_.ssl_manager()->DidStartResourceResponse(
- navigation_handle->GetURL(),
- net::IsCertStatusError(navigation_handle->GetSSLInfo().cert_status));
+ // SSLInfo is not needed on subframe navigations since the main-frame
+ // certificate is the only one that can be inspected (using the info
+ // bubble) without refreshing the page with DevTools open.
+ if (navigation_handle->IsInMainFrame())
+ controller_.ssl_manager()->DidStartResourceResponse(
+ navigation_handle->GetURL(),
+ net::IsCertStatusError(navigation_handle->GetSSLInfo().cert_status));
SetNotWaitingForResponse();
}
@@ -4082,6 +4109,9 @@ void WebContentsImpl::DidFinishNavigation(NavigationHandle* navigation_handle) {
for (auto& observer : observers_)
observer.DidFinishNavigation(navigation_handle);
+ if (display_cutout_host_impl_)
+ display_cutout_host_impl_->DidFinishNavigation(navigation_handle);
+
if (navigation_handle->HasCommitted()) {
BrowserAccessibilityManager* manager =
static_cast<RenderFrameHostImpl*>(
@@ -4338,8 +4368,7 @@ void WebContentsImpl::ViewSource(RenderFrameHostImpl* frame) {
// Any new WebContents opened while this WebContents is in fullscreen can be
// used to confuse the user, so drop fullscreen.
- if (IsFullscreenForCurrentTab())
- ExitFullscreen(true);
+ ForSecurityDropFullscreen();
// We intentionally don't share the SiteInstance with the original frame so
// that view source has a consistent process model and always ends up in a new
@@ -4399,9 +4428,11 @@ void WebContentsImpl::SubresourceResponseStarted(const GURL& url,
void WebContentsImpl::ResourceLoadComplete(
RenderFrameHost* render_frame_host,
+ const GlobalRequestID& request_id,
mojom::ResourceLoadInfoPtr resource_load_info) {
for (auto& observer : observers_) {
- observer.ResourceLoadComplete(render_frame_host, *resource_load_info);
+ observer.ResourceLoadComplete(render_frame_host, request_id,
+ *resource_load_info);
}
}
@@ -4561,22 +4592,6 @@ void WebContentsImpl::OnUpdatePageImportanceSignals(
page_importance_signals_ = signals;
}
-void WebContentsImpl::OnFindReply(RenderFrameHostImpl* source,
- int request_id,
- int number_of_matches,
- const gfx::Rect& selection_rect,
- int active_match_ordinal,
- bool final_update) {
- if (active_match_ordinal > 0)
- SetFocusedFrame(source->frame_tree_node(), source->GetSiteInstance());
-
- // Forward the find reply to the FindRequestManager, along with the
- // RenderFrameHost associated with the frame that the reply came from.
- GetOrCreateFindRequestManager()->OnFindReply(
- source, request_id, number_of_matches, selection_rect,
- active_match_ordinal, final_update);
-}
-
#if defined(OS_ANDROID)
void WebContentsImpl::OnOpenDateTimeDialog(
RenderViewHostImpl* source,
@@ -4753,6 +4768,12 @@ void WebContentsImpl::OnFirstVisuallyNonEmptyPaint(RenderViewHostImpl* source) {
}
}
+void WebContentsImpl::OnCommitAndDrawCompositorFrame(
+ RenderViewHostImpl* source) {
+ for (auto& observer : observers_)
+ observer.DidCommitAndDrawCompositorFrame();
+}
+
void WebContentsImpl::NotifyBeforeFormRepostWarningShow() {
for (auto& observer : observers_)
observer.BeforeFormRepostWarningShow();
@@ -4879,6 +4900,11 @@ void WebContentsImpl::NotifyViewSwapped(RenderViewHost* old_host,
view_->RenderViewHostChanged(old_host, new_host);
+ // If this is an inner WebContents that has swapped views, we need to reattach
+ // it to its outer WebContents.
+ if (node_.outer_web_contents())
+ ReattachToOuterWebContentsFrame();
+
// Ensure that the associated embedder gets cleared after a RenderViewHost
// gets swapped, so we don't reuse the same embedder next time a
// RenderViewHost is attached to this WebContents.
@@ -4974,6 +5000,9 @@ void WebContentsImpl::RenderFrameCreated(RenderFrameHost* render_frame_host) {
observer.RenderFrameCreated(render_frame_host);
UpdateAccessibilityModeOnFrame(render_frame_host);
+ if (display_cutout_host_impl_)
+ display_cutout_host_impl_->RenderFrameCreated(render_frame_host);
+
if (!render_frame_host->IsRenderFrameLive() || render_frame_host->GetParent())
return;
@@ -4994,6 +5023,9 @@ void WebContentsImpl::RenderFrameDeleted(RenderFrameHost* render_frame_host) {
pepper_playback_observer_->RenderFrameDeleted(render_frame_host);
#endif
+ if (display_cutout_host_impl_)
+ display_cutout_host_impl_->RenderFrameDeleted(render_frame_host);
+
// Remove any fullscreen state that the frame has stored.
FullscreenStateChanged(render_frame_host, false /* is_fullscreen */);
}
@@ -5031,8 +5063,7 @@ void WebContentsImpl::RunJavaScriptDialog(RenderFrameHost* render_frame_host,
// Running a dialog causes an exit to webpage-initiated fullscreen.
// http://crbug.com/728276
- if (IsFullscreenForCurrentTab())
- ExitFullscreen(true);
+ ForSecurityDropFullscreen();
auto callback =
base::BindOnce(&WebContentsImpl::OnDialogClosed, base::Unretained(this),
@@ -5101,8 +5132,7 @@ void WebContentsImpl::RunBeforeUnloadConfirm(
// Running a dialog causes an exit to webpage-initiated fullscreen.
// http://crbug.com/728276
- if (IsFullscreenForCurrentTab())
- ExitFullscreen(true);
+ ForSecurityDropFullscreen();
RenderFrameHostImpl* rfhi =
static_cast<RenderFrameHostImpl*>(render_frame_host);
@@ -5150,6 +5180,10 @@ void WebContentsImpl::RunBeforeUnloadConfirm(
void WebContentsImpl::RunFileChooser(RenderFrameHost* render_frame_host,
const FileChooserParams& params) {
+ // Any explicit focusing of another window while this WebContents is in
+ // fullscreen can be used to confuse the user, so drop fullscreen.
+ ForSecurityDropFullscreen();
+
if (delegate_)
delegate_->RunFileChooser(render_frame_host, params);
}
@@ -5684,6 +5718,15 @@ void WebContentsImpl::EnsureOpenerProxiesExist(RenderFrameHost* source_rfh) {
}
}
+void WebContentsImpl::ForSecurityDropFullscreen() {
+ WebContentsImpl* web_contents = this;
+ while (web_contents) {
+ if (web_contents->IsFullscreenForCurrentTab())
+ web_contents->ExitFullscreen(true);
+ web_contents = web_contents->GetOuterWebContents();
+ }
+}
+
void WebContentsImpl::SetAsFocusedWebContentsIfNecessary() {
// Only change focus if we are not currently focused.
WebContentsImpl* old_contents = GetFocusedWebContents();
@@ -5751,8 +5794,7 @@ void WebContentsImpl::SetFocusedFrame(FrameTreeNode* node,
void WebContentsImpl::DidCallFocus() {
// Any explicit focusing of another window while this WebContents is in
// fullscreen can be used to confuse the user, so drop fullscreen.
- if (IsFullscreenForCurrentTab())
- ExitFullscreen(true);
+ ForSecurityDropFullscreen();
}
RenderFrameHost* WebContentsImpl::GetFocusedFrameIncludingInnerWebContents() {
@@ -5848,6 +5890,17 @@ void WebContentsImpl::DidReceiveInputEvent(
SendUserGestureForResourceDispatchHost();
}
+bool WebContentsImpl::ShouldIgnoreInputEvents() {
+ WebContentsImpl* web_contents = this;
+ while (web_contents) {
+ if (web_contents->ignore_input_events_)
+ return true;
+ web_contents = web_contents->GetOuterWebContents();
+ }
+
+ return false;
+}
+
void WebContentsImpl::FocusOwningWebContents(
RenderWidgetHostImpl* render_widget_host) {
// The PDF plugin still runs as a BrowserPlugin and must go through the
@@ -5874,15 +5927,22 @@ void WebContentsImpl::OnIgnoredUIEvent() {
void WebContentsImpl::RendererUnresponsive(
RenderWidgetHostImpl* render_widget_host,
base::RepeatingClosure hang_monitor_restarter) {
- for (auto& observer : observers_)
- observer.OnRendererUnresponsive(render_widget_host->GetProcess());
-
if (ShouldIgnoreUnresponsiveRenderer())
return;
+ // Do not report hangs (to task manager, to hang renderer dialog, etc.) for
+ // invisible tabs (like extension background page, background tabs). See
+ // https://crbug.com/881812 for rationale and for choosing the visibility
+ // (rather than process priority) as the signal here.
+ if (GetVisibility() != Visibility::VISIBLE)
+ return;
+
if (!render_widget_host->renderer_initialized())
return;
+ for (auto& observer : observers_)
+ observer.OnRendererUnresponsive(render_widget_host->GetProcess());
+
if (delegate_)
delegate_->RendererUnresponsive(this, render_widget_host,
std::move(hang_monitor_restarter));
@@ -6105,12 +6165,12 @@ bool WebContentsImpl::GetAllowOtherViews() {
return view_->GetAllowOtherViews();
}
+#endif
+
bool WebContentsImpl::CompletedFirstVisuallyNonEmptyPaint() const {
return did_first_visually_non_empty_paint_;
}
-#endif
-
void WebContentsImpl::OnDidDownloadImage(
ImageDownloadCallback callback,
int id,
@@ -6458,6 +6518,20 @@ int WebContentsImpl::GetCurrentlyPlayingVideoCount() {
return currently_playing_video_count_;
}
+void WebContentsImpl::AudioContextPlaybackStarted(RenderFrameHost* host,
+ int context_id) {
+ WebContentsObserver::AudioContextId audio_context_id(host, context_id);
+ for (auto& observer : observers_)
+ observer.AudioContextPlaybackStarted(audio_context_id);
+}
+
+void WebContentsImpl::AudioContextPlaybackStopped(RenderFrameHost* host,
+ int context_id) {
+ WebContentsObserver::AudioContextId audio_context_id(host, context_id);
+ for (auto& observer : observers_)
+ observer.AudioContextPlaybackStopped(audio_context_id);
+}
+
void WebContentsImpl::UpdateWebContentsVisibility(Visibility visibility) {
// Occlusion is disabled when |features::kWebContentsOcclusion| is disabled
// (for power and speed impact assessment) or when
@@ -6532,11 +6606,6 @@ void WebContentsImpl::FocusedNodeTouched(bool editable) {
#endif
}
-void WebContentsImpl::DidReceiveCompositorFrame() {
- for (auto& observer : observers_)
- observer.DidReceiveCompositorFrame();
-}
-
void WebContentsImpl::ShowInsecureLocalhostWarningIfNeeded() {
bool allow_localhost = base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kAllowInsecureLocalhost);
diff --git a/chromium/content/browser/web_contents/web_contents_impl.h b/chromium/content/browser/web_contents/web_contents_impl.h
index d16a9912277..2687e87ea2d 100644
--- a/chromium/content/browser/web_contents/web_contents_impl.h
+++ b/chromium/content/browser/web_contents/web_contents_impl.h
@@ -41,6 +41,7 @@
#include "content/browser/wake_lock/wake_lock_context_host.h"
#include "content/common/content_export.h"
#include "content/public/browser/color_chooser.h"
+#include "content/public/browser/global_routing_id.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/web_contents.h"
@@ -176,10 +177,6 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
// TODO(creis): Remove this now that we can get to it via FrameTreeNode.
RenderFrameHostManager* GetRenderManagerForTesting();
- // Returns guest browser plugin object, or NULL if this WebContents is not a
- // guest.
- BrowserPluginGuest* GetBrowserPluginGuest() const;
-
// Sets a BrowserPluginGuest object for this WebContents. If this WebContents
// has a BrowserPluginGuest then that implies that it is being hosted by
// a BrowserPlugin object in an embedder renderer process.
@@ -229,9 +226,6 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
return screen_orientation_provider_.get();
}
- // Broadcasts the mode change to all frames.
- void SetAccessibilityMode(ui::AXMode mode);
-
// Adds the given accessibility mode to the current accessibility mode
// bitmap.
void AddAccessibilityMode(ui::AXMode mode);
@@ -366,6 +360,7 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
WebContents* outer_web_contents,
RenderFrameHost* outer_contents_frame) override;
WebContentsImpl* GetOuterWebContents() override;
+ WebContentsImpl* GetOutermostWebContents() override;
void DidChangeVisibleSecurityState() override;
void NotifyPreferencesChanged() override;
@@ -459,6 +454,8 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
bool IsShowingContextMenu() const override;
void SetShowingContextMenu(bool showing) override;
void PausePageScheduledTasks(bool paused) override;
+ BrowserPluginGuest* GetBrowserPluginGuest() const override;
+ bool CompletedFirstVisuallyNonEmptyPaint() const override;
#if defined(OS_ANDROID)
base::android::ScopedJavaLocalRef<jobject> GetJavaWebContents() override;
@@ -469,10 +466,10 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
#elif defined(OS_MACOSX)
void SetAllowOtherViews(bool allow) override;
bool GetAllowOtherViews() override;
- bool CompletedFirstVisuallyNonEmptyPaint() const override;
#endif
bool HasRecentInteractiveInputEvent() const override;
+ void SetIgnoreInputEvents(bool ignore_input_events) override;
// Implementation of PageNavigator.
WebContents* OpenURL(const OpenURLParams& params) override;
@@ -519,10 +516,13 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
WebContents* GetAsWebContents() override;
bool IsNeverVisible() override;
ui::AXMode GetAccessibilityMode() const override;
+ // Broadcasts the mode change to all frames.
+ void SetAccessibilityMode(ui::AXMode mode) override;
void AccessibilityEventReceived(
const AXEventNotificationDetails& details) override;
void AccessibilityLocationChangesReceived(
const std::vector<AXLocationChangeNotificationDetails>& details) override;
+ base::string16 DumpAccessibilityTree(bool internal) override;
RenderFrameHost* GetGuestByInstanceID(
RenderFrameHost* render_frame_host,
int browser_plugin_instance_id) override;
@@ -582,7 +582,16 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
net::CertStatus cert_status) override;
void ResourceLoadComplete(
RenderFrameHost* render_frame_host,
+ const GlobalRequestID& request_id,
mojom::ResourceLoadInfoPtr resource_load_information) override;
+
+ // Called when WebAudio starts or stops playing audible audio in an
+ // AudioContext.
+ void AudioContextPlaybackStarted(RenderFrameHost* host,
+ int context_id) override;
+ void AudioContextPlaybackStopped(RenderFrameHost* host,
+ int context_id) override;
+
// RenderViewHostDelegate ----------------------------------------------------
RenderViewHostDelegateView* GetDelegateView() override;
bool OnMessageReceived(RenderViewHostImpl* render_view_host,
@@ -610,6 +619,7 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
BrowserContext* browser_context) const override;
void DidReceiveInputEvent(RenderWidgetHostImpl* render_widget_host,
const blink::WebInputEvent::Type type) override;
+ bool ShouldIgnoreInputEvents() override;
void OnIgnoredUIEvent() override;
void Activate() override;
void UpdatePreferredSize(const gfx::Size& pref_size) override;
@@ -714,7 +724,8 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
void SelectRange(const gfx::Point& base, const gfx::Point& extent) override;
#if defined(OS_MACOSX)
void DidChangeTextSelection(const base::string16& text,
- const gfx::Range& range) override;
+ const gfx::Range& range,
+ size_t offset) override;
#endif
void MoveCaret(const gfx::Point& extent) override;
void AdjustSelectionByCharacterOffset(int start_adjust,
@@ -754,7 +765,6 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
bool IsWidgetForMainFrame(RenderWidgetHostImpl* render_widget_host) override;
bool AddDomainInfoToRapporSample(rappor::Sample* sample) override;
void FocusedNodeTouched(bool editable) override;
- void DidReceiveCompositorFrame() override;
bool IsShowingContextMenuOnPage() const override;
// RenderFrameHostManager::Delegate ------------------------------------------
@@ -925,6 +935,11 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
// |IsFullscreen| must return |true| when this method is called.
bool IsPictureInPictureAllowedForFullscreenVideo() const;
+ // The WebContents is trying to take some action that would cause user
+ // confusion if taken while in fullscreen. If this WebContents or any outer
+ // WebContents is in fullscreen, drop it.
+ void ForSecurityDropFullscreen();
+
// When inner or outer WebContents are present, become the focused
// WebContentsImpl. This will activate this content's main frame RenderWidget
// and indirectly all its subframe widgets. GetFocusedRenderWidgetHost will
@@ -968,6 +983,10 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
void SetDisplayCutoutSafeArea(gfx::Insets insets);
#endif
+ // Notify observers that the viewport fit value changed. This is called by
+ // |DisplayCutoutHostImpl|.
+ void NotifyViewportFitChanged(blink::mojom::ViewportFit value);
+
private:
friend class WebContentsObserver;
friend class WebContents; // To implement factory methods.
@@ -997,6 +1016,8 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
NotifyFullscreenAcquired_Navigate);
FRIEND_TEST_ALL_PREFIXES(WebContentsImplBrowserTest,
NotifyFullscreenAcquired_SameOrigin);
+ FRIEND_TEST_ALL_PREFIXES(WebContentsImplBrowserTest,
+ FullscreenAfterFrameSwap);
FRIEND_TEST_ALL_PREFIXES(FormStructureBrowserTest, HTMLFiles);
FRIEND_TEST_ALL_PREFIXES(NavigationControllerTest, HistoryNavigate);
FRIEND_TEST_ALL_PREFIXES(RenderFrameHostManagerTest, PageDoesBackAndReload);
@@ -1012,6 +1033,10 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
FRIEND_TEST_ALL_PREFIXES(WebContentsImplBrowserTest,
DialogsFromJavaScriptEndFullscreen);
FRIEND_TEST_ALL_PREFIXES(WebContentsImplBrowserTest,
+ DialogsFromJavaScriptEndFullscreenEvenInInnerWC);
+ FRIEND_TEST_ALL_PREFIXES(WebContentsImplBrowserTest,
+ FileChooserEndsFullscreen);
+ FRIEND_TEST_ALL_PREFIXES(WebContentsImplBrowserTest,
PopupsFromJavaScriptEndFullscreen);
FRIEND_TEST_ALL_PREFIXES(WebContentsImplBrowserTest,
FocusFromJavaScriptEndsFullscreen);
@@ -1174,12 +1199,6 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
const std::string& protocol,
const GURL& url,
bool user_gesture);
- void OnFindReply(RenderFrameHostImpl* source,
- int request_id,
- int number_of_matches,
- const gfx::Rect& selection_rect,
- int active_match_ordinal,
- bool final_update);
#if defined(OS_ANDROID)
void OnOpenDateTimeDialog(
RenderViewHostImpl* source,
@@ -1223,6 +1242,7 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
void OnUpdateFaviconURL(RenderFrameHostImpl* source,
const std::vector<FaviconURL>& candidates);
void OnFirstVisuallyNonEmptyPaint(RenderViewHostImpl* source);
+ void OnCommitAndDrawCompositorFrame(RenderViewHostImpl* source);
void OnShowValidationMessage(RenderViewHostImpl* source,
const gfx::Rect& anchor_in_root_view,
const base::string16& main_text,
@@ -1251,9 +1271,6 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
// focused WebContents.
bool ContainsOrIsFocusedWebContents();
- // Returns the root of the WebContents tree.
- WebContentsImpl* GetOutermostWebContents();
-
// Walks up the outer WebContents chain and focuses the FrameTreeNode where
// each inner WebContents is attached.
void FocusOuterAttachmentFrameChain();
@@ -1390,10 +1407,6 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
AXTreeSnapshotCombiner* combiner,
ui::AXMode ax_mode);
- // Notify observers that the viewport fit value changed. This is called by
- // |DisplayCutoutHostImpl|.
- void NotifyViewportFitChanged(blink::mojom::ViewportFit value);
-
// Data for core operation ---------------------------------------------------
// Delegate for notifying our owner about stuff. Not owned by us.
@@ -1412,13 +1425,11 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
// Tracks created WebContentsImpl objects that have not been shown yet. They
// are identified by the process ID and routing ID passed to CreateNewWindow.
- typedef std::pair<int, int> ProcessRoutingIdPair;
- std::map<ProcessRoutingIdPair, std::unique_ptr<WebContents>>
- pending_contents_;
+ std::map<GlobalRoutingID, std::unique_ptr<WebContents>> pending_contents_;
// This map holds widgets that were created on behalf of the renderer but
// haven't been shown yet.
- std::map<ProcessRoutingIdPair, RenderWidgetHostView*> pending_widget_views_;
+ std::map<GlobalRoutingID, RenderWidgetHostView*> pending_widget_views_;
std::map<WebContentsImpl*, std::unique_ptr<DestructionObserver>>
destruction_observers_;
@@ -1427,7 +1438,7 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
// This MUST be listed above frame_tree_ since at destruction time the
// latter might cause RenderViewHost's destructor to call us and we might use
// the observer list then.
- base::ObserverList<WebContentsObserver> observers_;
+ base::ObserverList<WebContentsObserver>::Unchecked observers_;
// Associated interface binding sets attached to this WebContents.
std::map<std::string, WebContentsBindingSet*> binding_sets_;
@@ -1547,6 +1558,9 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
// once.
bool notify_disconnection_;
+ // Set to true if we shouldn't send input events.
+ bool ignore_input_events_ = false;
+
// Pointer to the JavaScript dialog manager, lazily assigned. Used because the
// delegate of this WebContentsImpl is nulled before its destructor is called.
JavaScriptDialogManager* dialog_manager_;
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 4286d9a5c62..78857bccaea 100644
--- a/chromium/content/browser/web_contents/web_contents_impl_browsertest.cc
+++ b/chromium/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -57,6 +57,7 @@
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/controllable_http_response.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "services/network/public/cpp/features.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "url/gurl.h"
@@ -551,8 +552,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
NavigateToURL(shell(), kWebUIUrl);
- bool js_executed = content::ExecuteScript(shell(), kJSCodeForAppendingFrame);
- EXPECT_TRUE(js_executed);
+ EXPECT_TRUE(content::ExecuteScript(shell(), kJSCodeForAppendingFrame));
}
// Observer class to track the creation of RenderFrameHost objects. It is used
@@ -745,6 +745,7 @@ class ResourceLoadObserver : public WebContentsObserver {
// WebContentsObserver implementation:
void ResourceLoadComplete(
content::RenderFrameHost* render_frame_host,
+ const GlobalRequestID& request_id,
const mojom::ResourceLoadInfo& resource_load_info) override {
EXPECT_NE(nullptr, render_frame_host);
resource_load_infos_.push_back(resource_load_info.Clone());
@@ -1557,8 +1558,10 @@ class TestWCDelegateForDialogsAndFullscreen : public JavaScriptDialogManager,
void ExitFullscreenModeForTab(WebContents*) override {
is_fullscreen_ = false;
- if (waiting_for_ == kFullscreenExit)
+ if (waiting_for_ == kFullscreenExit) {
+ waiting_for_ = kNothing;
run_loop_->Quit();
+ }
}
bool IsFullscreenForTabOrPending(
@@ -1574,8 +1577,10 @@ class TestWCDelegateForDialogsAndFullscreen : public JavaScriptDialogManager,
bool* was_blocked) override {
popup_ = std::move(new_contents);
- if (waiting_for_ == kNewContents)
+ if (waiting_for_ == kNewContents) {
+ waiting_for_ = kNothing;
run_loop_->Quit();
+ }
}
// JavaScriptDialogManager
@@ -1590,8 +1595,10 @@ class TestWCDelegateForDialogsAndFullscreen : public JavaScriptDialogManager,
last_message_ = base::UTF16ToUTF8(message_text);
*did_suppress_message = true;
- if (waiting_for_ == kDialog)
+ if (waiting_for_ == kDialog) {
+ waiting_for_ = kNothing;
run_loop_->Quit();
+ }
}
void RunBeforeUnloadDialog(WebContents* web_contents,
@@ -1600,8 +1607,10 @@ class TestWCDelegateForDialogsAndFullscreen : public JavaScriptDialogManager,
DialogClosedCallback callback) override {
std::move(callback).Run(true, base::string16());
- if (waiting_for_ == kDialog)
+ if (waiting_for_ == kDialog) {
+ waiting_for_ = kNothing;
run_loop_->Quit();
+ }
}
bool HandleJavaScriptDialog(WebContents* web_contents,
@@ -1614,7 +1623,12 @@ class TestWCDelegateForDialogsAndFullscreen : public JavaScriptDialogManager,
bool reset_state) override {}
private:
- enum { kDialog, kNewContents, kFullscreenExit } waiting_for_;
+ enum {
+ kNothing,
+ kDialog,
+ kNewContents,
+ kFullscreenExit
+ } waiting_for_ = kNothing;
std::string last_message_;
@@ -2132,6 +2146,68 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
}
IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
+ DialogsFromJavaScriptEndFullscreenEvenInInnerWC) {
+ WebContentsImpl* top_contents =
+ static_cast<WebContentsImpl*>(shell()->web_contents());
+ TestWCDelegateForDialogsAndFullscreen top_test_delegate;
+ top_contents->SetDelegate(&top_test_delegate);
+
+ GURL url("about:blank");
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+
+ FrameTreeNode* root = top_contents->GetFrameTree()->root();
+ ASSERT_EQ(0U, root->child_count());
+
+ std::string script =
+ "var iframe = document.createElement('iframe');"
+ "document.body.appendChild(iframe);";
+ EXPECT_TRUE(content::ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+
+ ASSERT_EQ(1U, root->child_count());
+ RenderFrameHost* frame = root->child_at(0)->current_frame_host();
+ ASSERT_NE(nullptr, frame);
+
+ WebContentsImpl* inner_contents =
+ static_cast<WebContentsImpl*>(CreateAndAttachInnerContents(frame));
+ TestWCDelegateForDialogsAndFullscreen inner_test_delegate;
+ inner_contents->SetDelegate(&inner_test_delegate);
+
+ // A dialog from the inner WebContents should make the outer contents lose
+ // fullscreen.
+ top_contents->EnterFullscreenMode(url, blink::WebFullscreenOptions());
+ EXPECT_TRUE(top_contents->IsFullscreenForCurrentTab());
+ script = "alert('hi')";
+ inner_test_delegate.WillWaitForDialog();
+ EXPECT_TRUE(content::ExecuteScript(inner_contents, script));
+ inner_test_delegate.Wait();
+ EXPECT_FALSE(top_contents->IsFullscreenForCurrentTab());
+
+ inner_contents->SetDelegate(nullptr);
+ inner_contents->SetJavaScriptDialogManagerForTesting(nullptr);
+
+ top_contents->SetDelegate(nullptr);
+ top_contents->SetJavaScriptDialogManagerForTesting(nullptr);
+}
+
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, FileChooserEndsFullscreen) {
+ WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents());
+ TestWCDelegateForDialogsAndFullscreen test_delegate;
+ wc->SetDelegate(&test_delegate);
+
+ GURL url("about:blank");
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+
+ wc->EnterFullscreenMode(url, blink::WebFullscreenOptions());
+ EXPECT_TRUE(wc->IsFullscreenForCurrentTab());
+ wc->RunFileChooser(wc->GetMainFrame(), FileChooserParams());
+ EXPECT_FALSE(wc->IsFullscreenForCurrentTab());
+
+ wc->SetDelegate(nullptr);
+ wc->SetJavaScriptDialogManagerForTesting(nullptr);
+}
+
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
PopupsFromJavaScriptEndFullscreen) {
WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents());
TestWCDelegateForDialogsAndFullscreen test_delegate;
@@ -2367,7 +2443,12 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, UpdateLoadState) {
// Wait for the response to be ready, but never finish it.
EXPECT_TRUE(frame_pauser.WaitForResponse());
EXPECT_FALSE(frame_pauser.was_successful());
- waiter.Wait(net::LOAD_STATE_WAITING_FOR_DELEGATE, paused_host);
+ // Note: the pausing only works for the non-network service path because of
+ // http://crbug.com/791049.
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService))
+ waiter.Wait(net::LOAD_STATE_IDLE, base::string16());
+ else
+ waiter.Wait(net::LOAD_STATE_WAITING_FOR_DELEGATE, paused_host);
load_resource(a_frame, "/a_img");
a_response->WaitForRequest();
@@ -2390,10 +2471,12 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, UpdateLoadState) {
waiter.Wait(net::LOAD_STATE_READING_RESPONSE, a_host);
a_response->Done();
- // Now the only request in flight should be the delayed frame.
- waiter.Wait(net::LOAD_STATE_WAITING_FOR_DELEGATE, paused_host);
- frame_pauser.ResumeNavigation();
- waiter.Wait(net::LOAD_STATE_IDLE, base::string16());
+ if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ // Now the only request in flight should be the delayed frame.
+ waiter.Wait(net::LOAD_STATE_WAITING_FOR_DELEGATE, paused_host);
+ frame_pauser.ResumeNavigation();
+ waiter.Wait(net::LOAD_STATE_IDLE, base::string16());
+ }
}
IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, NotifyPreferencesChanged) {
@@ -2630,6 +2713,40 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, NotifyFullscreenAcquired) {
}
}
+// Regression test for https://crbug.com/855018.
+// RenderFrameHostImpls exit fullscreen as soon as they are swapped out.
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, FullscreenAfterFrameSwap) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+ WebContentsImpl* web_contents =
+ static_cast<WebContentsImpl*>(shell()->web_contents());
+
+ GURL url_a = embedded_test_server()->GetURL("a.com", "/title1.html");
+ GURL url_b = embedded_test_server()->GetURL("b.com", "/title1.html");
+
+ // 1) Navigate. There is initially no fullscreen frame.
+ EXPECT_TRUE(NavigateToURL(shell(), url_a));
+ RenderFrameHostImpl* main_frame =
+ static_cast<RenderFrameHostImpl*>(web_contents->GetMainFrame());
+ EXPECT_EQ(0u, web_contents->fullscreen_frame_tree_nodes_.size());
+
+ // 2) Make it fullscreen.
+ FullscreenWebContentsObserver observer(web_contents, main_frame);
+ EXPECT_TRUE(
+ ExecuteScript(main_frame, "document.body.webkitRequestFullscreen();"));
+ observer.Wait();
+ EXPECT_EQ(1u, web_contents->fullscreen_frame_tree_nodes_.size());
+
+ // 3) Navigate cross origin. Act as if the old frame was very slow delivering
+ // the swapout ack and stayed in pending deletion for a while. Even if the
+ // frame is still present, it must be removed from the list of frame in
+ // fullscreen immediately.
+ auto filter = base::MakeRefCounted<SwapoutACKMessageFilter>();
+ main_frame->GetProcess()->AddFilter(filter.get());
+ main_frame->DisableSwapOutTimerForTesting();
+ EXPECT_TRUE(NavigateToURL(shell(), url_b));
+ EXPECT_EQ(0u, web_contents->fullscreen_frame_tree_nodes_.size());
+}
+
IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
NotifyFullscreenAcquired_Navigate) {
ASSERT_TRUE(embedded_test_server()->Start());
@@ -2746,4 +2863,63 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
web_contents->current_fullscreen_frame_tree_node_id_);
}
+class MockDidOpenRequestedURLObserver : public WebContentsObserver {
+ public:
+ explicit MockDidOpenRequestedURLObserver(Shell* shell)
+ : WebContentsObserver(shell->web_contents()) {}
+
+ MOCK_METHOD8(DidOpenRequestedURL,
+ void(WebContents* new_contents,
+ RenderFrameHost* source_render_frame_host,
+ const GURL& url,
+ const Referrer& referrer,
+ WindowOpenDisposition disposition,
+ ui::PageTransition transition,
+ bool started_from_context_menu,
+ bool renderer_initiated));
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockDidOpenRequestedURLObserver);
+};
+
+// Test WebContentsObserver::DidOpenRequestedURL for ctrl-click-ed links.
+// This is a regression test for https://crbug.com/864736 (although it also
+// covers slightly more ground than just the |is_renderer_initiated| value).
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, CtrlClickSubframeLink) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ // Load a page with a subframe link.
+ GURL main_url(
+ embedded_test_server()->GetURL("/ctrl-click-subframe-link.html"));
+ NavigateToURL(shell(), main_url);
+
+ // Start intercepting the DidOpenRequestedURL callback.
+ MockDidOpenRequestedURLObserver mock_observer(shell());
+ WebContents* new_web_contents1 = nullptr;
+ RenderFrameHost* subframe = shell()->web_contents()->GetAllFrames()[1];
+ EXPECT_CALL(mock_observer,
+ DidOpenRequestedURL(
+ ::testing::_, // new_contents (captured via SaveArg below)
+ subframe, // source_render_frame_host
+ embedded_test_server()->GetURL("/title1.html"),
+ ::testing::Field(&Referrer::url, main_url),
+ WindowOpenDisposition::NEW_FOREGROUND_TAB,
+ ::testing::Truly([](ui::PageTransition arg) {
+ return ui::PageTransitionCoreTypeIs(
+ arg, ui::PAGE_TRANSITION_LINK);
+ }),
+ false, // started_from_context_menu
+ true)) // is_renderer_initiated
+ .WillOnce(testing::SaveArg<0>(&new_web_contents1));
+
+ // Simulate a ctrl click on the link and ask GMock to verify that the
+ // MockDidOpenRequestedURLObserver got called with the expected args.
+ WebContentsAddedObserver new_web_contents_observer;
+ EXPECT_TRUE(ExecuteScript(
+ shell(), "window.domAutomationController.send(ctrlClickLink());"));
+ WebContents* new_web_contents2 = new_web_contents_observer.GetWebContents();
+ EXPECT_TRUE(testing::Mock::VerifyAndClearExpectations(&mock_observer));
+ EXPECT_EQ(new_web_contents1, new_web_contents2);
+}
+
} // namespace content
diff --git a/chromium/content/browser/web_contents/web_contents_impl_unittest.cc b/chromium/content/browser/web_contents/web_contents_impl_unittest.cc
index c403c397331..aa74c714540 100644
--- a/chromium/content/browser/web_contents/web_contents_impl_unittest.cc
+++ b/chromium/content/browser/web_contents/web_contents_impl_unittest.cc
@@ -3415,6 +3415,9 @@ class TestOverlayWindow : public OverlayWindow {
void Close() override {}
void Show() override {}
void Hide() override {}
+ void SetPictureInPictureCustomControls(
+ const std::vector<blink::PictureInPictureControlInfo>& controls)
+ override {}
bool IsVisible() const override { return false; }
bool IsAlwaysOnTop() const override { return false; }
ui::Layer* GetLayer() override { return nullptr; }
diff --git a/chromium/content/browser/web_contents/web_contents_user_data_unittest.cc b/chromium/content/browser/web_contents/web_contents_user_data_unittest.cc
index 81b65023bd4..f967c37e3d0 100644
--- a/chromium/content/browser/web_contents/web_contents_user_data_unittest.cc
+++ b/chromium/content/browser/web_contents/web_contents_user_data_unittest.cc
@@ -33,9 +33,6 @@ class WebContentsAttachedClass2
friend class WebContentsUserData<WebContentsAttachedClass2>;
};
-DEFINE_WEB_CONTENTS_USER_DATA_KEY(WebContentsAttachedClass1);
-DEFINE_WEB_CONTENTS_USER_DATA_KEY(WebContentsAttachedClass2);
-
typedef RenderViewHostTestHarness WebContentsUserDataTest;
TEST_F(WebContentsUserDataTest, OneInstanceTwoAttachments) {
diff --git a/chromium/content/browser/web_contents/web_contents_view_android.cc b/chromium/content/browser/web_contents/web_contents_view_android.cc
index 8990bc7bf6c..fe977804cb8 100644
--- a/chromium/content/browser/web_contents/web_contents_view_android.cc
+++ b/chromium/content/browser/web_contents/web_contents_view_android.cc
@@ -107,11 +107,6 @@ void WebContentsViewAndroid::SetContentUiEventHandler(
content_ui_event_handler_ = std::move(handler);
}
-void WebContentsViewAndroid::SetSelectPopup(
- std::unique_ptr<SelectPopup> select_popup) {
- select_popup_ = std::move(select_popup);
-}
-
void WebContentsViewAndroid::SetOverscrollRefreshHandler(
std::unique_ptr<ui::OverscrollRefreshHandler> overscroll_refresh_handler) {
overscroll_refresh_handler_ = std::move(overscroll_refresh_handler);
@@ -323,6 +318,12 @@ void WebContentsViewAndroid::ShowContextMenu(
delegate_->ShowContextMenu(render_frame_host, params);
}
+SelectPopup* WebContentsViewAndroid::GetSelectPopup() {
+ if (!select_popup_)
+ select_popup_ = std::make_unique<SelectPopup>(web_contents_);
+ return select_popup_.get();
+}
+
void WebContentsViewAndroid::ShowPopupMenu(
RenderFrameHost* render_frame_host,
const gfx::Rect& bounds,
@@ -332,15 +333,12 @@ void WebContentsViewAndroid::ShowPopupMenu(
const std::vector<MenuItem>& items,
bool right_aligned,
bool allow_multiple_selection) {
- if (select_popup_) {
- select_popup_->ShowMenu(render_frame_host, bounds, items, selected_item,
- allow_multiple_selection, right_aligned);
- }
+ GetSelectPopup()->ShowMenu(render_frame_host, bounds, items, selected_item,
+ allow_multiple_selection, right_aligned);
}
void WebContentsViewAndroid::HidePopupMenu() {
- if (select_popup_)
- select_popup_->HideMenu();
+ GetSelectPopup()->HideMenu();
}
void WebContentsViewAndroid::StartDragging(
diff --git a/chromium/content/browser/web_contents/web_contents_view_android.h b/chromium/content/browser/web_contents/web_contents_view_android.h
index 088fedea3fa..53d1898347c 100644
--- a/chromium/content/browser/web_contents/web_contents_view_android.h
+++ b/chromium/content/browser/web_contents/web_contents_view_android.h
@@ -38,9 +38,6 @@ class WebContentsViewAndroid : public WebContentsView,
void SetContentUiEventHandler(std::unique_ptr<ContentUiEventHandler> handler);
- // Sets the object that show/hide popup view for <select> tag.
- void SetSelectPopup(std::unique_ptr<SelectPopup> select_popup);
-
void set_synchronous_compositor_client(SynchronousCompositorClient* client) {
synchronous_compositor_client_ = client;
}
@@ -142,6 +139,8 @@ class WebContentsViewAndroid : public WebContentsView,
void OnDragEnded();
void OnSystemDragEnded();
+ SelectPopup* GetSelectPopup();
+
// The WebContents whose contents we display.
WebContentsImpl* web_contents_;
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 713b17948ef..e471459007a 100644
--- a/chromium/content/browser/web_contents/web_contents_view_aura.cc
+++ b/chromium/content/browser/web_contents/web_contents_view_aura.cc
@@ -350,6 +350,26 @@ GlobalRoutingID GetRenderViewHostID(RenderViewHost* rvh) {
return GlobalRoutingID(rvh->GetProcess()->GetID(), rvh->GetRoutingID());
}
+// Returns the host window for |window|, or nullpr if it has no host window.
+aura::Window* GetHostWindow(aura::Window* window) {
+ aura::Window* host_window = window->GetProperty(aura::client::kHostWindowKey);
+ if (host_window)
+ return host_window;
+ return window->parent();
+}
+
+// Returns true iff the aura::client::kMirroringEnabledKey property is set for
+// |window| or its parent. That indicates that |window| is being displayed in
+// Alt-Tab view on ChromeOS.
+bool WindowIsMirrored(aura::Window* window) {
+ if (window->GetProperty(aura::client::kMirroringEnabledKey))
+ return true;
+
+ aura::Window* const host_window = GetHostWindow(window);
+ return host_window &&
+ host_window->GetProperty(aura::client::kMirroringEnabledKey);
+}
+
} // namespace
class WebContentsViewAura::WindowObserver
@@ -373,10 +393,7 @@ class WebContentsViewAura::WindowObserver
if (window != view_->window_.get())
return;
- aura::Window* host_window =
- window->GetProperty(aura::client::kHostWindowKey);
- if (!host_window)
- host_window = parent;
+ aura::Window* const host_window = GetHostWindow(window);
if (host_window_)
host_window_->RemoveObserver(this);
@@ -422,12 +439,8 @@ class WebContentsViewAura::WindowObserver
void OnWindowPropertyChanged(aura::Window* window,
const void* key,
intptr_t old) override {
- if (key != aura::client::kMirroringEnabledKey)
- return;
- if (window->GetProperty(aura::client::kMirroringEnabledKey))
- view_->web_contents_->IncrementCapturerCount(gfx::Size());
- else
- view_->web_contents_->DecrementCapturerCount();
+ if (key == aura::client::kMirroringEnabledKey)
+ view_->UpdateWebContentsVisibility();
}
// Overridden WindowTreeHostObserver:
@@ -467,7 +480,7 @@ WebContentsViewAura::WebContentsViewAura(WebContentsImpl* web_contents,
WebContentsViewDelegate* delegate)
: is_mus_browser_plugin_guest_(web_contents->GetBrowserPluginGuest() !=
nullptr &&
- !features::IsAshInBrowserProcess()),
+ features::IsUsingWindowService()),
web_contents_(web_contents),
delegate_(delegate),
current_drag_op_(blink::kWebDragOperationNone),
@@ -729,7 +742,7 @@ gfx::Rect WebContentsViewAura::GetViewBounds() const {
}
void WebContentsViewAura::CreateAuraWindow(aura::Window* context) {
- DCHECK(aura::Env::GetInstanceDontCreate());
+ DCHECK(aura::Env::HasInstance());
DCHECK(!window_);
window_ = std::make_unique<aura::Window>(this);
window_->set_owned_by_parent(false);
@@ -761,6 +774,23 @@ void WebContentsViewAura::CreateAuraWindow(aura::Window* context) {
window_observer_.reset(new WindowObserver(this));
}
+void WebContentsViewAura::UpdateWebContentsVisibility() {
+ web_contents_->UpdateWebContentsVisibility(GetVisibility());
+}
+
+Visibility WebContentsViewAura::GetVisibility() const {
+ if (window_->occlusion_state() == aura::Window::OcclusionState::VISIBLE ||
+ WindowIsMirrored(window_.get())) {
+ return Visibility::VISIBLE;
+ }
+
+ if (window_->occlusion_state() == aura::Window::OcclusionState::OCCLUDED)
+ return Visibility::OCCLUDED;
+
+ DCHECK_EQ(window_->occlusion_state(), aura::Window::OcclusionState::HIDDEN);
+ return Visibility::HIDDEN;
+}
+
////////////////////////////////////////////////////////////////////////////////
// WebContentsViewAura, WebContentsView implementation:
@@ -1100,12 +1130,7 @@ void WebContentsViewAura::OnWindowTargetVisibilityChanged(bool visible) {
void WebContentsViewAura::OnWindowOcclusionChanged(
aura::Window::OcclusionState occlusion_state) {
- web_contents_->UpdateWebContentsVisibility(
- occlusion_state == aura::Window::OcclusionState::VISIBLE
- ? content::Visibility::VISIBLE
- : (occlusion_state == aura::Window::OcclusionState::OCCLUDED
- ? content::Visibility::OCCLUDED
- : content::Visibility::HIDDEN));
+ UpdateWebContentsVisibility();
}
bool WebContentsViewAura::HasHitTestMask() const {
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 058f3e00d6f..212da86e253 100644
--- a/chromium/content/browser/web_contents/web_contents_view_aura.h
+++ b/chromium/content/browser/web_contents/web_contents_view_aura.h
@@ -12,12 +12,13 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
-#include "content/browser/loader/global_routing_id.h"
#include "content/browser/renderer_host/overscroll_controller_delegate.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"
#include "content/common/content_export.h"
+#include "content/public/browser/global_routing_id.h"
+#include "content/public/browser/visibility.h"
#include "ui/aura/client/drag_drop_delegate.h"
#include "ui/aura/window.h"
#include "ui/aura/window_delegate.h"
@@ -97,6 +98,12 @@ class CONTENT_EXPORT WebContentsViewAura
// Called from CreateView() to create |window_|.
void CreateAuraWindow(aura::Window* context);
+ // Computes the view's visibility updates the WebContents accordingly.
+ void UpdateWebContentsVisibility();
+
+ // Computes the view's visibility.
+ Visibility GetVisibility() const;
+
// Overridden from WebContentsView:
gfx::NativeView GetNativeView() const override;
gfx::NativeView GetContentNativeView() const override;
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 03d3de9320f..2982638ad0a 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
@@ -7,12 +7,14 @@
#include <memory>
#include "base/command_line.h"
+#include "base/macros.h"
#include "base/test/scoped_command_line.h"
#include "base/test/scoped_feature_list.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/common/content_features.h"
#include "content/public/test/test_renderer_host.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/aura/client/aura_constants.h"
#include "ui/aura/test/test_windows.h"
#include "ui/aura/window.h"
#include "ui/display/display_switches.h"
@@ -25,22 +27,39 @@ constexpr gfx::Rect kBounds = gfx::Rect(0, 0, 20, 20);
} // namespace
class WebContentsViewAuraTest : public RenderViewHostTestHarness {
- public:
+ protected:
WebContentsViewAuraTest() = default;
~WebContentsViewAuraTest() override = default;
void SetUp() override {
RenderViewHostTestHarness::SetUp();
root_window()->SetBounds(kBounds);
- web_contents()->GetNativeView()->SetBounds(kBounds);
- web_contents()->GetNativeView()->Show();
- root_window()->AddChild(web_contents()->GetNativeView());
+ GetNativeView()->SetBounds(kBounds);
+ GetNativeView()->Show();
+ root_window()->AddChild(GetNativeView());
+
+ occluding_window_.reset(aura::test::CreateTestWindowWithDelegateAndType(
+ nullptr, aura::client::WINDOW_TYPE_NORMAL, 0, kBounds, root_window(),
+ false));
+ }
+
+ void TearDown() override {
+ occluding_window_.reset();
+ RenderViewHostTestHarness::TearDown();
}
WebContentsViewAura* view() {
WebContentsImpl* contents = static_cast<WebContentsImpl*>(web_contents());
return static_cast<WebContentsViewAura*>(contents->GetView());
}
+
+ aura::Window* GetNativeView() { return web_contents()->GetNativeView(); }
+
+ // |occluding_window_| occludes |web_contents()| when it's shown.
+ std::unique_ptr<aura::Window> occluding_window_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(WebContentsViewAuraTest);
};
TEST_F(WebContentsViewAuraTest, EnableDisableOverscroll) {
@@ -63,17 +82,122 @@ TEST_F(WebContentsViewAuraTest, OccludeView) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(features::kWebContentsOcclusion);
- // |other_window| occludes |web_contents()| when it's shown.
- std::unique_ptr<aura::Window> other_window(
+ EXPECT_EQ(web_contents()->GetVisibility(), Visibility::VISIBLE);
+ occluding_window_->Show();
+ EXPECT_EQ(web_contents()->GetVisibility(), Visibility::OCCLUDED);
+ occluding_window_->Hide();
+ EXPECT_EQ(web_contents()->GetVisibility(), Visibility::VISIBLE);
+}
+
+TEST_F(WebContentsViewAuraTest, MirroringEnabledForHiddenView) {
+ EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
+ root_window()->Hide();
+ EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::HIDDEN);
+ GetNativeView()->SetProperty(aura::client::kMirroringEnabledKey, true);
+ EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
+ GetNativeView()->SetProperty(aura::client::kMirroringEnabledKey, false);
+ EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::HIDDEN);
+ root_window()->Show();
+ EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
+ GetNativeView()->SetProperty(aura::client::kMirroringEnabledKey, true);
+ EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
+ GetNativeView()->SetProperty(aura::client::kMirroringEnabledKey, false);
+ EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
+}
+
+TEST_F(WebContentsViewAuraTest, MirroringEnabledForOccludedView) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(features::kWebContentsOcclusion);
+
+ EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
+ occluding_window_->Show();
+ EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::OCCLUDED);
+ GetNativeView()->SetProperty(aura::client::kMirroringEnabledKey, true);
+ EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
+ GetNativeView()->SetProperty(aura::client::kMirroringEnabledKey, false);
+ EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::OCCLUDED);
+}
+
+TEST_F(WebContentsViewAuraTest, MirroringEnabledForHiddenViewParent) {
+ EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
+ root_window()->Hide();
+ EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::HIDDEN);
+ root_window()->SetProperty(aura::client::kMirroringEnabledKey, true);
+ EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
+ root_window()->SetProperty(aura::client::kMirroringEnabledKey, false);
+ EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::HIDDEN);
+ root_window()->Show();
+ EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
+ root_window()->SetProperty(aura::client::kMirroringEnabledKey, true);
+ EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
+ root_window()->SetProperty(aura::client::kMirroringEnabledKey, false);
+ EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
+}
+
+TEST_F(WebContentsViewAuraTest, MirroringEnabledForOccludedViewParent) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(features::kWebContentsOcclusion);
+
+ EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
+ occluding_window_->Show();
+ EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::OCCLUDED);
+ root_window()->SetProperty(aura::client::kMirroringEnabledKey, true);
+ EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
+ root_window()->SetProperty(aura::client::kMirroringEnabledKey, false);
+ EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::OCCLUDED);
+}
+
+TEST_F(WebContentsViewAuraTest, MirroringEnabledForHiddenViewHost) {
+ // Make root_window() the host of GetNativeView(), and introduce an
+ // |intermediate_window| in the hierarchy between root_window() and
+ // GetNativeView().
+ std::unique_ptr<aura::Window> intermediate_window(
aura::test::CreateTestWindowWithDelegateAndType(
nullptr, aura::client::WINDOW_TYPE_NORMAL, 0, kBounds, root_window(),
false));
+ GetNativeView()->SetProperty(aura::client::kHostWindowKey, root_window());
+ intermediate_window->AddChild(GetNativeView());
+ root_window()->StackChildAtBottom(intermediate_window.get());
+ intermediate_window->Show();
- EXPECT_EQ(web_contents()->GetVisibility(), Visibility::VISIBLE);
- other_window->Show();
- EXPECT_EQ(web_contents()->GetVisibility(), Visibility::OCCLUDED);
- other_window->Hide();
- EXPECT_EQ(web_contents()->GetVisibility(), Visibility::VISIBLE);
+ EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
+ root_window()->Hide();
+ EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::HIDDEN);
+ root_window()->SetProperty(aura::client::kMirroringEnabledKey, true);
+ EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
+ root_window()->SetProperty(aura::client::kMirroringEnabledKey, false);
+ EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::HIDDEN);
+ root_window()->Show();
+ EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
+ root_window()->SetProperty(aura::client::kMirroringEnabledKey, true);
+ EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
+ root_window()->SetProperty(aura::client::kMirroringEnabledKey, false);
+ EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
+}
+
+TEST_F(WebContentsViewAuraTest, MirroringEnabledForOccludedViewHost) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(features::kWebContentsOcclusion);
+
+ // Make root_window() the host of GetNativeView(), and introduce an
+ // |intermediate_window| in the hierarchy between root_window() and
+ // GetNativeView().
+ std::unique_ptr<aura::Window> intermediate_window(
+ aura::test::CreateTestWindowWithDelegateAndType(
+ nullptr, aura::client::WINDOW_TYPE_NORMAL, 0, kBounds, root_window(),
+ false));
+ GetNativeView()->SetProperty(aura::client::kHostWindowKey, root_window());
+ intermediate_window->AddChild(GetNativeView());
+ root_window()->StackChildAtBottom(intermediate_window.get());
+ intermediate_window->Show();
+
+ EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
+ occluding_window_->Show();
+ EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::OCCLUDED);
+ root_window()->SetProperty(aura::client::kMirroringEnabledKey, true);
+ EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
+ root_window()->SetProperty(aura::client::kMirroringEnabledKey, false);
+ EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::OCCLUDED);
}
} // 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 44c68ed25b6..12f6817499e 100644
--- a/chromium/content/browser/web_contents/web_contents_view_guest.cc
+++ b/chromium/content/browser/web_contents/web_contents_view_guest.cc
@@ -72,14 +72,14 @@ void WebContentsViewGuest::OnGuestAttached(WebContentsView* parent_view) {
// view hierarchy. We add this view as embedder's child here.
// This would go in WebContentsViewGuest::CreateView, but that is too early to
// access embedder_web_contents(). Therefore, we do it here.
- if (features::IsAshInBrowserProcess())
+ if (!features::IsUsingWindowService())
parent_view->GetNativeView()->AddChild(platform_view_->GetNativeView());
#endif // defined(USE_AURA)
}
void WebContentsViewGuest::OnGuestDetached(WebContentsView* old_parent_view) {
#if defined(USE_AURA)
- if (features::IsAshInBrowserProcess()) {
+ if (!features::IsUsingWindowService()) {
old_parent_view->GetNativeView()->RemoveChild(
platform_view_->GetNativeView());
}
diff --git a/chromium/content/browser/web_contents/web_contents_view_overscroll_animator_mac.h b/chromium/content/browser/web_contents/web_contents_view_overscroll_animator_mac.h
deleted file mode 100644
index 0603a9b99e3..00000000000
--- a/chromium/content/browser/web_contents/web_contents_view_overscroll_animator_mac.h
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_WEB_CONTENTS_WEB_CONTENTS_VIEW_OVERSCROLL_ANIMATOR_MAC_H_
-#define CONTENT_BROWSER_WEB_CONTENTS_WEB_CONTENTS_VIEW_OVERSCROLL_ANIMATOR_MAC_H_
-
-#import <Cocoa/Cocoa.h>
-
-namespace content {
-class WebContentsImpl;
-
-// The direction of the overscroll animations. Backwards means that the user
-// wants to navigate backwards in the navigation history. The opposite applies
-// to forwards.
-enum OverscrollAnimatorDirection {
- OVERSCROLL_ANIMATOR_DIRECTION_BACKWARDS,
- OVERSCROLL_ANIMATOR_DIRECTION_FORWARDS,
-};
-} // namespace content
-
-// NSViews that intend to manage the animation associated with an overscroll
-// must implement this protocol.
-@protocol WebContentsOverscrollAnimator
-// Some implementations require the WebContentsView to supply a snapshot of a
-// previous navigation state. This method determines whether the snapshot passed
-// to the overscroll animator is expected to be non-nil.
-- (BOOL)needsNavigationSnapshot;
-
-// Begin an overscroll animation. The method -needsNavigationSnapshot determines
-// whether |snapshot| can be nil.
-- (void)beginOverscrollInDirection:
- (content::OverscrollAnimatorDirection)direction
- navigationSnapshot:(NSImage*)snapshot;
-
-// Due to the nature of some of the overscroll animations, implementators of
-// this protocol must have control over the layout of the RenderWidgetHost's
-// NativeView. When there is no overscroll animation in progress, the
-// implementor must guarantee that the frame of the RenderWidgetHost's
-// NativeView in screen coordinates is the same as its own frame in screen
-// coordinates.
-// Due to the odd ownership cycles of the RenderWidgetHost's NativeView, it is
-// important that its presence in the NSView hierarchy is the only strong
-// reference, and that when it gets removed from the NSView hierarchy, it will
-// be dealloc'ed shortly thereafter.
-- (void)addRenderWidgetHostNativeView:(NSView*)view;
-
-// During an overscroll animation, |progress| ranges from 0 to 2, and indicates
-// how close the overscroll is to completing. If the overscroll ends with
-// |progress| >= 1, then the overscroll is considered completed.
-- (void)updateOverscrollProgress:(CGFloat)progress;
-
-// Animate the finish of the overscroll and perform a navigation. The navigation
-// may not happen synchronously, but is guaranteed to eventually occur.
-- (void)completeOverscroll:(content::WebContentsImpl*)webContents;
-
-// Animate the cancellation of the overscroll.
-- (void)cancelOverscroll;
-@end
-
-#endif // CONTENT_BROWSER_WEB_CONTENTS_WEB_CONTENTS_VIEW_OVERSCROLL_ANIMATOR_MAC_H_
diff --git a/chromium/content/browser/web_contents/web_contents_view_overscroll_animator_slider_mac.h b/chromium/content/browser/web_contents/web_contents_view_overscroll_animator_slider_mac.h
deleted file mode 100644
index 326c868b41c..00000000000
--- a/chromium/content/browser/web_contents/web_contents_view_overscroll_animator_slider_mac.h
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_WEB_CONTENTS_WEB_CONTENTS_VIEW_OVERSCROLL_ANIMATOR_SLIDER_MAC_H_
-#define CONTENT_BROWSER_WEB_CONTENTS_WEB_CONTENTS_VIEW_OVERSCROLL_ANIMATOR_SLIDER_MAC_H_
-
-#import <Cocoa/Cocoa.h>
-
-#include <memory>
-
-#include "base/mac/scoped_nsobject.h"
-#include "content/browser/web_contents/web_contents_view_overscroll_animator_mac.h"
-
-namespace overscroll_animator {
-class WebContentsPaintObserver;
-} // namespace overscroll_animator
-
-@interface OverscrollAnimatorSliderView
- : NSView<WebContentsOverscrollAnimator> {
- // This container view holds the RenderWidgetHost's NativeViews. Most of the
- // time, its frame in screen coordinates is the same as SliderView's frame in
- // screen coordinates. During an overscroll animation, it may temporarily be
- // relocated, but it will return to its original position after the overscroll
- // animation is finished.
- base::scoped_nsobject<NSView> middleView_;
-
- // This view is a sibling of middleView_, and is guaranteed to live below it.
- // Most of the time, it is hidden. During a backwards overscroll animation,
- // middleView_ is slid to the right, and bottomView_ peeks out from the
- // original position of middleView_.
- base::scoped_nsobject<NSImageView> bottomView_;
-
- // This view is a sibling of middleView_, and is guaranteed to live above it.
- // Most of the time, it is hidden. During a forwards overscroll animation,
- // topView_ is slid to the left from off screen, its final position exactly
- // covering middleView_.
- base::scoped_nsobject<NSImageView> topView_;
-
- // The direction of the current overscroll animation. This property has no
- // meaning when inOverscroll_ is false.
- content::OverscrollAnimatorDirection direction_;
-
- // Indicates that this view is completing or cancelling the overscroll. This
- // animation cannot be cancelled.
- BOOL animating_;
-
- // Reflects whether this view is in the process of handling an overscroll.
- BOOL inOverscroll_;
-
- // The most recent value passed to -updateOverscrollProgress:.
- CGFloat progress_;
-
- // An observer that reports the first non-empty paint of a WebContents. This
- // is used when completing an overscroll animation.
- std::unique_ptr<overscroll_animator::WebContentsPaintObserver> observer_;
-}
-@end
-
-#endif // CONTENT_BROWSER_WEB_CONTENTS_WEB_CONTENTS_VIEW_OVERSCROLL_ANIMATOR_SLIDER_MAC_H_
diff --git a/chromium/content/browser/web_contents/web_contents_view_overscroll_animator_slider_mac.mm b/chromium/content/browser/web_contents/web_contents_view_overscroll_animator_slider_mac.mm
deleted file mode 100644
index b614fb13dea..00000000000
--- a/chromium/content/browser/web_contents/web_contents_view_overscroll_animator_slider_mac.mm
+++ /dev/null
@@ -1,259 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import <QuartzCore/QuartzCore.h>
-
-#include "content/browser/web_contents/web_contents_view_overscroll_animator_slider_mac.h"
-
-#include "content/browser/web_contents/web_contents_impl.h"
-#include "content/public/browser/web_contents_observer.h"
-
-namespace {
-// The minimum possible progress of an overscroll animation.
-CGFloat kMinProgress = 0;
-// The maximum possible progress of an overscroll animation.
-CGFloat kMaxProgress = 2.0;
-// The maximum duration of the completion or cancellation animations. The
-// effective maximum is half of this value, since the longest animation is from
-// progress = 1.0 to progress = 2.0;
-CGFloat kMaxAnimationDuration = 0.2;
-} // namespace
-
-// OverscrollAnimatorSliderView Private Category -------------------------------
-
-@interface OverscrollAnimatorSliderView ()
-// Callback from WebContentsPaintObserver.
-- (void)webContentsFinishedNonEmptyPaint;
-
-// Resets overscroll animation state.
-- (void)reset;
-
-// Given a |progress| from 0 to 2, the expected frame origin of the -movingView.
-- (NSPoint)frameOriginWithProgress:(CGFloat)progress;
-
-// The NSView that is moving during the overscroll animation.
-- (NSView*)movingView;
-
-// The expected duration of an animation from progress_ to |progress|
-- (CGFloat)animationDurationForProgress:(CGFloat)progress;
-
-// NSView override. During an overscroll animation, the cursor may no longer
-// rest on the RenderWidgetHost's NativeView, which prevents wheel events from
-// reaching the NativeView. The overscroll animation is driven by wheel events
-// so they must be explicitly forwarded to the NativeView.
-- (void)scrollWheel:(NSEvent*)event;
-@end
-
-// Helper Class (ResizingView) -------------------------------------------------
-
-// This NSView subclass is intended to be the RenderWidgetHost's NativeView's
-// parent NSView. It is possible for the RenderWidgetHost's NativeView's size to
-// become out of sync with its parent NSView. The override of
-// -resizeSubviewsWithOldSize: ensures that the sizes will eventually become
-// consistent.
-// http://crbug.com/264207
-@interface ResizingView : NSView
-@end
-
-@implementation ResizingView
-- (void)resizeSubviewsWithOldSize:(NSSize)oldBoundsSize {
- for (NSView* subview in self.subviews)
- [subview setFrame:self.bounds];
-}
-@end
-
-// Helper Class (WebContentsPaintObserver) -------------------------------------
-
-namespace overscroll_animator {
-class WebContentsPaintObserver : public content::WebContentsObserver {
- public:
- WebContentsPaintObserver(content::WebContents* web_contents,
- OverscrollAnimatorSliderView* slider_view)
- : WebContentsObserver(web_contents), slider_view_(slider_view) {}
-
- void DidFirstVisuallyNonEmptyPaint() override {
- [slider_view_ webContentsFinishedNonEmptyPaint];
- }
-
- private:
- OverscrollAnimatorSliderView* slider_view_; // Weak reference.
-};
-} // namespace overscroll_animator
-
-// OverscrollAnimatorSliderView Implementation ---------------------------------
-
-@implementation OverscrollAnimatorSliderView
-
-- (instancetype)initWithFrame:(NSRect)frame {
- self = [super initWithFrame:frame];
- if (self) {
- bottomView_.reset([[NSImageView alloc] initWithFrame:self.bounds]);
- bottomView_.get().imageScaling = NSImageScaleNone;
- bottomView_.get().autoresizingMask =
- NSViewWidthSizable | NSViewHeightSizable;
- bottomView_.get().imageAlignment = NSImageAlignTop;
- [self addSubview:bottomView_];
- middleView_.reset([[ResizingView alloc] initWithFrame:self.bounds]);
- middleView_.get().autoresizingMask =
- NSViewWidthSizable | NSViewHeightSizable;
- [self addSubview:middleView_];
- topView_.reset([[NSImageView alloc] initWithFrame:self.bounds]);
- topView_.get().autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
- topView_.get().imageScaling = NSImageScaleNone;
- topView_.get().imageAlignment = NSImageAlignTop;
- [self addSubview:topView_];
-
- [self reset];
- }
- return self;
-}
-
-- (void)webContentsFinishedNonEmptyPaint {
- observer_.reset();
- [self reset];
-}
-
-- (void)reset {
- DCHECK(!animating_);
- inOverscroll_ = NO;
- progress_ = kMinProgress;
-
- [CATransaction begin];
- [CATransaction setDisableActions:YES];
- bottomView_.get().hidden = YES;
- middleView_.get().hidden = NO;
- topView_.get().hidden = YES;
-
- [bottomView_ setFrameOrigin:NSMakePoint(0, 0)];
- [middleView_ setFrameOrigin:NSMakePoint(0, 0)];
- [topView_ setFrameOrigin:NSMakePoint(0, 0)];
- [CATransaction commit];
-}
-
-- (NSPoint)frameOriginWithProgress:(CGFloat)progress {
- if (direction_ == content::OVERSCROLL_ANIMATOR_DIRECTION_BACKWARDS)
- return NSMakePoint(progress / kMaxProgress * self.bounds.size.width, 0);
- return NSMakePoint((1 - progress / kMaxProgress) * self.bounds.size.width, 0);
-}
-
-- (NSView*)movingView {
- if (direction_ == content::OVERSCROLL_ANIMATOR_DIRECTION_BACKWARDS)
- return middleView_;
- return topView_;
-}
-
-- (CGFloat)animationDurationForProgress:(CGFloat)progress {
- CGFloat progressPercentage =
- fabs(progress_ - progress) / (kMaxProgress - kMinProgress);
- return progressPercentage * kMaxAnimationDuration;
-}
-
-- (void)scrollWheel:(NSEvent*)event {
- NSView* latestRenderWidgetHostView = [[middleView_ subviews] lastObject];
- [latestRenderWidgetHostView scrollWheel:event];
-}
-
-// WebContentsOverscrollAnimator Implementation --------------------------------
-
-- (BOOL)needsNavigationSnapshot {
- return YES;
-}
-
-- (void)beginOverscrollInDirection:
- (content::OverscrollAnimatorDirection)direction
- navigationSnapshot:(NSImage*)snapshot {
- // TODO(erikchen): If snapshot is nil, need a placeholder.
- if (animating_ || inOverscroll_)
- return;
-
- inOverscroll_ = YES;
- direction_ = direction;
- if (direction_ == content::OVERSCROLL_ANIMATOR_DIRECTION_BACKWARDS) {
- // The middleView_ will slide to the right, revealing bottomView_.
- bottomView_.get().hidden = NO;
- [bottomView_ setImage:snapshot];
- } else {
- // The topView_ will slide in from the right, concealing middleView_.
- topView_.get().hidden = NO;
- [topView_ setFrameOrigin:NSMakePoint(self.bounds.size.width, 0)];
- [topView_ setImage:snapshot];
- }
-
- [self updateOverscrollProgress:kMinProgress];
-}
-
-- (void)addRenderWidgetHostNativeView:(NSView*)view {
- [middleView_ addSubview:view];
-}
-
-- (void)updateOverscrollProgress:(CGFloat)progress {
- if (animating_)
- return;
- DCHECK_LE(progress, kMaxProgress);
- DCHECK_GE(progress, kMinProgress);
- progress_ = progress;
- [[self movingView] setFrameOrigin:[self frameOriginWithProgress:progress]];
-}
-
-- (void)completeOverscroll:(content::WebContentsImpl*)webContents {
- if (animating_ || !inOverscroll_)
- return;
-
- animating_ = YES;
-
- NSView* view = [self movingView];
- [NSAnimationContext beginGrouping];
- [NSAnimationContext currentContext].duration =
- [self animationDurationForProgress:kMaxProgress];
- [[NSAnimationContext currentContext] setCompletionHandler:^{
- animating_ = NO;
-
- // Animation is complete. Now perform page load.
- if (direction_ == content::OVERSCROLL_ANIMATOR_DIRECTION_BACKWARDS)
- webContents->GetController().GoBack();
- else
- webContents->GetController().GoForward();
-
- // Reset the position of the middleView_, but wait for the page to paint
- // before showing it.
- middleView_.get().hidden = YES;
- [middleView_ setFrameOrigin:NSMakePoint(0, 0)];
- observer_.reset(
- new overscroll_animator::WebContentsPaintObserver(webContents, self));
- }];
-
- // Animate the moving view to its final position.
- [[view animator] setFrameOrigin:[self frameOriginWithProgress:kMaxProgress]];
-
- [NSAnimationContext endGrouping];
-}
-
-- (void)cancelOverscroll {
- if (animating_)
- return;
-
- if (!inOverscroll_) {
- [self reset];
- return;
- }
-
- animating_ = YES;
-
- NSView* view = [self movingView];
- [NSAnimationContext beginGrouping];
- [NSAnimationContext currentContext].duration =
- [self animationDurationForProgress:kMinProgress];
- [[NSAnimationContext currentContext] setCompletionHandler:^{
- // Animation is complete. Reset the state.
- animating_ = NO;
- [self reset];
- }];
-
- // Animate the moving view to its initial position.
- [[view animator] setFrameOrigin:[self frameOriginWithProgress:kMinProgress]];
-
- [NSAnimationContext endGrouping];
-}
-
-@end
diff --git a/chromium/content/browser/web_contents/web_drag_dest_mac.h b/chromium/content/browser/web_contents/web_drag_dest_mac.h
index c81c2a89ab8..6d6ae69232f 100644
--- a/chromium/content/browser/web_contents/web_drag_dest_mac.h
+++ b/chromium/content/browser/web_contents/web_drag_dest_mac.h
@@ -10,8 +10,8 @@
#include <memory>
#include "base/strings/string16.h"
-#include "content/browser/loader/global_routing_id.h"
#include "content/common/content_export.h"
+#include "content/public/browser/global_routing_id.h"
#include "content/public/common/drop_data.h"
#include "ui/gfx/geometry/point_f.h"
diff --git a/chromium/content/browser/web_contents/web_drag_source_mac.mm b/chromium/content/browser/web_contents/web_drag_source_mac.mm
index 4ef9fcdda1c..1ebcedb0875 100644
--- a/chromium/content/browser/web_contents/web_drag_source_mac.mm
+++ b/chromium/content/browser/web_contents/web_drag_source_mac.mm
@@ -16,7 +16,7 @@
#include "base/strings/string_util.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "base/threading/thread.h"
#include "base/threading/thread_restrictions.h"
#include "content/browser/download/drag_download_file.h"
@@ -145,8 +145,9 @@ void PromiseWriterHelper(const DropData& drop_data,
// 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());
+ std::string unescapedUrlString;
+ net::UnescapeBinaryURLComponent(dropData_->url.spec(),
+ &unescapedUrlString);
std::string escapedUrlString =
net::EscapeUrlEncodedData(unescapedUrlString, false);
url = [NSURL URLWithString:SysUTF8ToNSString(escapedUrlString)];
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 9e5ea4406c0..104dbe1498c 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
@@ -40,16 +40,17 @@ class DeferringURLLoaderThrottle final : public URLLoaderThrottle {
}
void WillRedirectRequest(
- const net::RedirectInfo& redirect_info,
- const network::ResourceResponseHead& response_head,
+ const net::RedirectInfo& /* redirect_info */,
+ const network::ResourceResponseHead& /* response_head */,
bool* defer,
- std::vector<std::string>* to_be_removed_headers) override {
+ std::vector<std::string>* /* to_be_removed_headers */,
+ net::HttpRequestHeaders* /* modified_headers */) override {
will_redirect_request_called_ = true;
*defer = true;
}
void WillProcessResponse(const GURL& response_url_,
- const network::ResourceResponseHead& response_head,
+ network::ResourceResponseHead* response_head,
bool* defer) override {
will_process_response_called_ = true;
*defer = true;
@@ -211,7 +212,7 @@ class SignedExchangeCertFetcherTest : public testing::Test {
base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
&mock_loader_factory_),
std::move(throttles_), url, request_initiator_, force_fetch,
- SignedExchangeVersion::kB1, std::move(callback),
+ SignedExchangeVersion::kB2, std::move(callback),
nullptr /* devtools_proxy */,
base::nullopt /* throttling_profile_id */);
}
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 1fd297d9512..c8e35ff3dee 100644
--- a/chromium/content/browser/web_package/signed_exchange_certificate_chain.cc
+++ b/chromium/content/browser/web_package/signed_exchange_certificate_chain.cc
@@ -17,12 +17,12 @@ namespace content {
namespace {
-// https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html#cert-chain-format
-std::unique_ptr<SignedExchangeCertificateChain> ParseB1(
+// https://wicg.github.io/webpackage/draft-yasskin-httpbis-origin-signed-exchanges-impl.html#cert-chain-format
+std::unique_ptr<SignedExchangeCertificateChain> ParseB2(
base::span<const uint8_t> message,
SignedExchangeDevToolsProxy* devtools_proxy) {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"),
- "SignedExchangeCertificateChain::ParseB1");
+ "SignedExchangeCertificateChain::ParseB2");
cbor::CBORReader::DecoderError error;
base::Optional<cbor::CBORValue> value =
@@ -94,9 +94,9 @@ std::unique_ptr<SignedExchangeCertificateChain> ParseB1(
auto ocsp_iter = cert_map.find(cbor::CBORValue(kOcspKey));
if (i == 1) {
- // Step 2. The first certificate’s ocsp value if any MUST be a complete,
+ // Step 2. The first certificate’s ocsp value MUST be a complete,
// DER-encoded OCSP response for that certificate (using the ASN.1 type
- // OCSPResponse defined in [RFC2560]). ... [spec text]
+ // OCSPResponse defined in [RFC6960]). ... [spec text]
if (ocsp_iter == cert_map.end() || !ocsp_iter->second.is_bytestring()) {
signed_exchange_utils::ReportErrorAndTraceEvent(
devtools_proxy,
@@ -119,13 +119,11 @@ std::unique_ptr<SignedExchangeCertificateChain> ParseB1(
return nullptr;
}
- // Step 3. Each certificate’s sct value MUST be a
+ // Step 3. Each certificate’s sct value if any MUST be a
// SignedCertificateTimestampList for that certificate as defined by Section
// 3.3 of [RFC6962]. [spec text]
//
// We use SCTs only of the main certificate.
- // TODO(crbug.com/815025): Update the spec text once
- // https://github.com/WICG/webpackage/issues/175 is resolved.
if (i == 1) {
auto sct_iter = cert_map.find(cbor::CBORValue(kSctKey));
if (sct_iter != cert_map.end()) {
@@ -162,8 +160,8 @@ SignedExchangeCertificateChain::Parse(
SignedExchangeVersion version,
base::span<const uint8_t> cert_response_body,
SignedExchangeDevToolsProxy* devtools_proxy) {
- DCHECK_EQ(version, SignedExchangeVersion::kB1);
- return ParseB1(cert_response_body, devtools_proxy);
+ DCHECK_EQ(version, SignedExchangeVersion::kB2);
+ return ParseB2(cert_response_body, devtools_proxy);
}
SignedExchangeCertificateChain::SignedExchangeCertificateChain(
diff --git a/chromium/content/browser/web_package/signed_exchange_certificate_chain_fuzzer.cc b/chromium/content/browser/web_package/signed_exchange_certificate_chain_fuzzer.cc
index 8d718db5f0a..e6dc41086f8 100644
--- a/chromium/content/browser/web_package/signed_exchange_certificate_chain_fuzzer.cc
+++ b/chromium/content/browser/web_package/signed_exchange_certificate_chain_fuzzer.cc
@@ -9,7 +9,7 @@
namespace content {
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- SignedExchangeCertificateChain::Parse(SignedExchangeVersion::kB1,
+ SignedExchangeCertificateChain::Parse(SignedExchangeVersion::kB2,
base::make_span(data, size), nullptr);
return 0;
}
diff --git a/chromium/content/browser/web_package/signed_exchange_certificate_chain_unittest.cc b/chromium/content/browser/web_package/signed_exchange_certificate_chain_unittest.cc
index 6389105c3a0..99149484e4c 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
@@ -27,13 +27,13 @@ cbor::CBORValue CBORByteString(base::StringPiece str) {
} // namespace
-TEST(SignedExchangeCertificateParseB1Test, Empty) {
+TEST(SignedExchangeCertificateParseB2Test, Empty) {
auto parsed = SignedExchangeCertificateChain::Parse(
- SignedExchangeVersion::kB1, base::span<const uint8_t>(), nullptr);
+ SignedExchangeVersion::kB2, base::span<const uint8_t>(), nullptr);
EXPECT_FALSE(parsed);
}
-TEST(SignedExchangeCertificateParseB1Test, EmptyChain) {
+TEST(SignedExchangeCertificateParseB2Test, EmptyChain) {
cbor::CBORValue::ArrayValue cbor_array;
cbor_array.push_back(cbor::CBORValue(u8"\U0001F4DC\u26D3"));
@@ -42,11 +42,11 @@ TEST(SignedExchangeCertificateParseB1Test, EmptyChain) {
ASSERT_TRUE(serialized.has_value());
auto parsed = SignedExchangeCertificateChain::Parse(
- SignedExchangeVersion::kB1, base::make_span(*serialized), nullptr);
+ SignedExchangeVersion::kB2, base::make_span(*serialized), nullptr);
EXPECT_FALSE(parsed);
}
-TEST(SignedExchangeCertificateParseB1Test, MissingCert) {
+TEST(SignedExchangeCertificateParseB2Test, MissingCert) {
cbor::CBORValue::MapValue cbor_map;
cbor_map[cbor::CBORValue("sct")] = CBORByteString("SCT");
cbor_map[cbor::CBORValue("ocsp")] = CBORByteString("OCSP");
@@ -60,11 +60,11 @@ TEST(SignedExchangeCertificateParseB1Test, MissingCert) {
ASSERT_TRUE(serialized.has_value());
auto parsed = SignedExchangeCertificateChain::Parse(
- SignedExchangeVersion::kB1, base::make_span(*serialized), nullptr);
+ SignedExchangeVersion::kB2, base::make_span(*serialized), nullptr);
EXPECT_FALSE(parsed);
}
-TEST(SignedExchangeCertificateParseB1Test, OneCert) {
+TEST(SignedExchangeCertificateParseB2Test, OneCert) {
net::CertificateList certs;
ASSERT_TRUE(
net::LoadCertificateFiles({"subjectAltName_sanity_check.pem"}, &certs));
@@ -86,7 +86,7 @@ TEST(SignedExchangeCertificateParseB1Test, OneCert) {
ASSERT_TRUE(serialized.has_value());
auto parsed = SignedExchangeCertificateChain::Parse(
- SignedExchangeVersion::kB1, base::make_span(*serialized), nullptr);
+ SignedExchangeVersion::kB2, base::make_span(*serialized), nullptr);
ASSERT_TRUE(parsed);
EXPECT_EQ(cert_der, net::x509_util::CryptoBufferAsStringPiece(
parsed->cert()->cert_buffer()));
@@ -95,7 +95,7 @@ TEST(SignedExchangeCertificateParseB1Test, OneCert) {
EXPECT_EQ(parsed->sct(), base::make_optional<std::string>("SCT"));
}
-TEST(SignedExchangeCertificateParseB1Test, MissingOCSPInFirstCert) {
+TEST(SignedExchangeCertificateParseB2Test, MissingOCSPInFirstCert) {
net::CertificateList certs;
ASSERT_TRUE(
net::LoadCertificateFiles({"subjectAltName_sanity_check.pem"}, &certs));
@@ -116,11 +116,11 @@ TEST(SignedExchangeCertificateParseB1Test, MissingOCSPInFirstCert) {
ASSERT_TRUE(serialized.has_value());
auto parsed = SignedExchangeCertificateChain::Parse(
- SignedExchangeVersion::kB1, base::make_span(*serialized), nullptr);
+ SignedExchangeVersion::kB2, base::make_span(*serialized), nullptr);
EXPECT_FALSE(parsed);
}
-TEST(SignedExchangeCertificateParseB1Test, TwoCerts) {
+TEST(SignedExchangeCertificateParseB2Test, TwoCerts) {
net::CertificateList certs;
ASSERT_TRUE(net::LoadCertificateFiles(
{"subjectAltName_sanity_check.pem", "root_ca_cert.pem"}, &certs));
@@ -148,7 +148,7 @@ TEST(SignedExchangeCertificateParseB1Test, TwoCerts) {
ASSERT_TRUE(serialized.has_value());
auto parsed = SignedExchangeCertificateChain::Parse(
- SignedExchangeVersion::kB1, base::make_span(*serialized), nullptr);
+ SignedExchangeVersion::kB2, base::make_span(*serialized), nullptr);
ASSERT_TRUE(parsed);
EXPECT_EQ(cert1_der, net::x509_util::CryptoBufferAsStringPiece(
parsed->cert()->cert_buffer()));
@@ -159,7 +159,7 @@ TEST(SignedExchangeCertificateParseB1Test, TwoCerts) {
EXPECT_EQ(parsed->sct(), base::make_optional<std::string>("SCT"));
}
-TEST(SignedExchangeCertificateParseB1Test, HavingOCSPInSecondCert) {
+TEST(SignedExchangeCertificateParseB2Test, HavingOCSPInSecondCert) {
net::CertificateList certs;
ASSERT_TRUE(net::LoadCertificateFiles(
{"subjectAltName_sanity_check.pem", "root_ca_cert.pem"}, &certs));
@@ -188,11 +188,11 @@ TEST(SignedExchangeCertificateParseB1Test, HavingOCSPInSecondCert) {
ASSERT_TRUE(serialized.has_value());
auto parsed = SignedExchangeCertificateChain::Parse(
- SignedExchangeVersion::kB1, base::make_span(*serialized), nullptr);
+ SignedExchangeVersion::kB2, base::make_span(*serialized), nullptr);
EXPECT_FALSE(parsed);
}
-TEST(SignedExchangeCertificateParseB1Test, ParseGoldenFile) {
+TEST(SignedExchangeCertificateParseB2Test, ParseGoldenFile) {
base::FilePath path;
base::PathService::Get(content::DIR_TEST_DATA, &path);
path =
@@ -201,7 +201,7 @@ TEST(SignedExchangeCertificateParseB1Test, ParseGoldenFile) {
ASSERT_TRUE(base::ReadFileToString(path, &contents));
auto parsed = SignedExchangeCertificateChain::Parse(
- SignedExchangeVersion::kB1, base::as_bytes(base::make_span(contents)),
+ SignedExchangeVersion::kB2, base::as_bytes(base::make_span(contents)),
nullptr);
ASSERT_TRUE(parsed);
}
diff --git a/chromium/content/browser/web_package/signed_exchange_consts.h b/chromium/content/browser/web_package/signed_exchange_consts.h
index 6e8bd5210ae..4f18d332992 100644
--- a/chromium/content/browser/web_package/signed_exchange_consts.h
+++ b/chromium/content/browser/web_package/signed_exchange_consts.h
@@ -8,9 +8,9 @@
namespace content {
constexpr char kAcceptHeaderSignedExchangeSuffix[] =
- ",application/signed-exchange;v=b1";
+ ",application/signed-exchange;v=b2";
-enum class SignedExchangeVersion { kB1 };
+enum class SignedExchangeVersion { kB2 };
// Field names defined in the application/signed-exchange content type:
// https://wicg.github.io/webpackage/draft-yasskin-httpbis-origin-signed-exchanges-impl.html#application-signed-exchange
diff --git a/chromium/content/browser/web_package/signed_exchange_envelope.cc b/chromium/content/browser/web_package/signed_exchange_envelope.cc
index b42ccc07872..96f2750eadc 100644
--- a/chromium/content/browser/web_package/signed_exchange_envelope.cc
+++ b/chromium/content/browser/web_package/signed_exchange_envelope.cc
@@ -15,6 +15,7 @@
#include "components/cbor/cbor_reader.h"
#include "content/browser/web_package/signed_exchange_consts.h"
#include "content/browser/web_package/signed_exchange_utils.h"
+#include "net/http/http_response_headers.h"
#include "net/http/http_util.h"
#include "url/origin.h"
@@ -83,30 +84,6 @@ bool ParseRequestMap(const cbor::CBORValue& value,
const cbor::CBORValue::MapValue& request_map = value.GetMap();
- auto url_iter = request_map.find(
- cbor::CBORValue(kUrlKey, cbor::CBORValue::Type::BYTE_STRING));
- if (url_iter == request_map.end() || !url_iter->second.is_bytestring()) {
- signed_exchange_utils::ReportErrorAndTraceEvent(
- devtools_proxy, ":url is not found or not a bytestring.");
- return false;
- }
- out->set_request_url(GURL(url_iter->second.GetBytestringAsString()));
- if (!out->request_url().is_valid()) {
- signed_exchange_utils::ReportErrorAndTraceEvent(devtools_proxy,
- ":url is not a valid URL.");
- return false;
- }
- if (out->request_url().has_ref()) {
- signed_exchange_utils::ReportErrorAndTraceEvent(
- devtools_proxy, ":url can't have a fragment.");
- return false;
- }
- if (!out->request_url().SchemeIs("https")) {
- signed_exchange_utils::ReportErrorAndTraceEvent(
- devtools_proxy, ":url scheme must be 'https'.");
- return false;
- }
-
auto method_iter = request_map.find(
cbor::CBORValue(kMethodKey, cbor::CBORValue::Type::BYTE_STRING));
if (method_iter == request_map.end() ||
@@ -137,7 +114,15 @@ bool ParseRequestMap(const cbor::CBORValue& value,
return false;
}
base::StringPiece name_str = it.first.GetBytestringAsString();
- if (name_str == kUrlKey || name_str == kMethodKey)
+
+ if (name_str == kUrlKey) {
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy,
+ ":url key in request map is obsolete in this version of the format.");
+ return false;
+ }
+
+ if (name_str == kMethodKey)
continue;
// TODO(kouhei): Add spec ref here once
@@ -195,6 +180,20 @@ bool ParseResponseMap(const cbor::CBORValue& value,
devtools_proxy, "Failed to parse status code to integer.");
return false;
}
+ // https://wicg.github.io/webpackage/loading.html#parsing-b1
+ // Step 26. If parsedExchange’s response's status is a redirect status or the
+ // signed exchange version of parsedExchange’s response is not
+ // undefined, return a failure. [spec text]
+ // TODO(crbug.com/803774): Reject if inner response is a signed exchange.
+ if (net::HttpResponseHeaders::IsRedirectResponseCode(response_code)) {
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy,
+ base::StringPrintf(
+ "Exchange's response status must not be a redirect status. "
+ "status: %d",
+ response_code));
+ return false;
+ }
out->set_response_code(static_cast<net::HttpStatusCode>(response_code));
for (const auto& it : response_map) {
@@ -257,11 +256,15 @@ bool ParseResponseMap(const cbor::CBORValue& value,
// static
base::Optional<SignedExchangeEnvelope> SignedExchangeEnvelope::Parse(
+ const GURL& fallback_url,
base::StringPiece signature_header_field,
base::span<const uint8_t> cbor_header,
SignedExchangeDevToolsProxy* devtools_proxy) {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"),
"SignedExchangeEnvelope::Parse");
+
+ const GURL& request_url = fallback_url;
+
cbor::CBORReader::DecoderError error;
base::Optional<cbor::CBORValue> value =
cbor::CBORReader::Read(cbor_header, &error);
@@ -293,6 +296,8 @@ base::Optional<SignedExchangeEnvelope> SignedExchangeEnvelope::Parse(
}
SignedExchangeEnvelope ret;
+ ret.set_cbor_header(cbor_header);
+ ret.set_request_url(request_url);
if (!ParseRequestMap(top_level_array[0], &ret, devtools_proxy)) {
signed_exchange_utils::ReportErrorAndTraceEvent(
@@ -321,7 +326,6 @@ base::Optional<SignedExchangeEnvelope> SignedExchangeEnvelope::Parse(
// If the signature’s “validity-url” parameter is not same-origin with
// exchange’s effective request URI (Section 5.5 of [RFC7230]), return
// “invalid” [spec text]
- const GURL request_url = ret.request_url();
const GURL validity_url = ret.signature().validity_url;
if (!url::IsSameOriginWith(request_url, validity_url)) {
signed_exchange_utils::ReportErrorAndTraceEvent(
@@ -371,4 +375,8 @@ SignedExchangeEnvelope::BuildHttpResponseHeaders() const {
net::HttpUtil::AssembleRawHeaders(header_str.c_str(), header_str.size()));
}
+void SignedExchangeEnvelope::set_cbor_header(base::span<const uint8_t> data) {
+ cbor_header_ = std::vector<uint8_t>(data.begin(), data.end());
+}
+
} // 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 7d865308062..6903b8eb536 100644
--- a/chromium/content/browser/web_package/signed_exchange_envelope.h
+++ b/chromium/content/browser/web_package/signed_exchange_envelope.h
@@ -30,12 +30,13 @@ class CONTENT_EXPORT SignedExchangeEnvelope {
public:
using HeaderMap = std::map<std::string, std::string>;
- // Parse headers from the application/signed-exchange;v=b0 format.
+ // Parse headers from the application/signed-exchange;v=b2 format.
// https://wicg.github.io/webpackage/draft-yasskin-httpbis-origin-signed-exchanges-impl.html#application-signed-exchange
//
// This also performs the step 1, 3 and 4 of "Cross-origin trust" validation.
// https://wicg.github.io/webpackage/draft-yasskin-httpbis-origin-signed-exchanges-impl.html#cross-origin-trust
static base::Optional<SignedExchangeEnvelope> Parse(
+ const GURL& fallback_url,
base::StringPiece signature_header_field,
base::span<const uint8_t> cbor_header,
SignedExchangeDevToolsProxy* devtools_proxy);
@@ -50,6 +51,11 @@ class CONTENT_EXPORT SignedExchangeEnvelope {
bool AddResponseHeader(base::StringPiece name, base::StringPiece value);
scoped_refptr<net::HttpResponseHeaders> BuildHttpResponseHeaders() const;
+ const base::span<const uint8_t> cbor_header() const {
+ return base::make_span(cbor_header_);
+ }
+ void set_cbor_header(base::span<const uint8_t> data);
+
const GURL& request_url() const { return request_url_; };
void set_request_url(GURL url) { request_url_ = std::move(url); }
@@ -72,6 +78,8 @@ class CONTENT_EXPORT SignedExchangeEnvelope {
}
private:
+ std::vector<uint8_t> cbor_header_;
+
GURL request_url_;
std::string request_method_;
diff --git a/chromium/content/browser/web_package/signed_exchange_envelope_unittest.cc b/chromium/content/browser/web_package/signed_exchange_envelope_unittest.cc
index 021d7fef021..919019bdfdf 100644
--- a/chromium/content/browser/web_package/signed_exchange_envelope_unittest.cc
+++ b/chromium/content/browser/web_package/signed_exchange_envelope_unittest.cc
@@ -34,6 +34,7 @@ cbor::CBORValue CBORByteString(const char* str) {
}
base::Optional<SignedExchangeEnvelope> GenerateHeaderAndParse(
+ const GURL& fallback_url,
base::StringPiece signature,
const std::map<const char*, const char*>& request_map,
const std::map<const char*, const char*>& response_map) {
@@ -50,7 +51,8 @@ base::Optional<SignedExchangeEnvelope> GenerateHeaderAndParse(
auto serialized = cbor::CBORWriter::Write(cbor::CBORValue(std::move(array)));
return SignedExchangeEnvelope::Parse(
- signature, base::make_span(serialized->data(), serialized->size()),
+ fallback_url, signature,
+ base::make_span(serialized->data(), serialized->size()),
nullptr /* devtools_proxy */);
}
@@ -66,25 +68,38 @@ TEST(SignedExchangeEnvelopeTest, ParseGoldenFile) {
ASSERT_TRUE(base::ReadFileToString(test_sxg_path, &contents));
auto* contents_bytes = reinterpret_cast<const uint8_t*>(contents.data());
- ASSERT_GT(contents.size(), SignedExchangePrologue::kEncodedPrologueInBytes);
- base::Optional<SignedExchangePrologue> prologue =
- SignedExchangePrologue::Parse(
- base::make_span(contents_bytes,
- SignedExchangePrologue::kEncodedPrologueInBytes),
+ ASSERT_GT(contents.size(),
+ signed_exchange_prologue::BeforeFallbackUrl::kEncodedSizeInBytes);
+ signed_exchange_prologue::BeforeFallbackUrl prologue_a =
+ signed_exchange_prologue::BeforeFallbackUrl::Parse(
+ base::make_span(
+ contents_bytes,
+ signed_exchange_prologue::BeforeFallbackUrl::kEncodedSizeInBytes),
nullptr /* devtools_proxy */);
- ASSERT_TRUE(prologue.has_value());
- ASSERT_GT(contents.size(), SignedExchangePrologue::kEncodedPrologueInBytes +
- prologue->ComputeFollowingSectionsLength());
-
+ ASSERT_GT(contents.size(),
+ signed_exchange_prologue::BeforeFallbackUrl::kEncodedSizeInBytes +
+ prologue_a.ComputeFallbackUrlAndAfterLength());
+ signed_exchange_prologue::FallbackUrlAndAfter prologue_b =
+ signed_exchange_prologue::FallbackUrlAndAfter::Parse(
+ base::make_span(contents_bytes +
+ signed_exchange_prologue::BeforeFallbackUrl::
+ kEncodedSizeInBytes,
+ prologue_a.ComputeFallbackUrlAndAfterLength()),
+ prologue_a, nullptr /* devtools_proxy */);
+
+ size_t signature_header_field_offset =
+ signed_exchange_prologue::BeforeFallbackUrl::kEncodedSizeInBytes +
+ prologue_a.ComputeFallbackUrlAndAfterLength();
base::StringPiece signature_header_field(
- contents.data() + SignedExchangePrologue::kEncodedPrologueInBytes,
- prologue->signature_header_field_length());
+ contents.data() + signature_header_field_offset,
+ prologue_b.signature_header_field_length());
const auto cbor_bytes = base::make_span<const uint8_t>(
- contents_bytes + SignedExchangePrologue::kEncodedPrologueInBytes +
- prologue->signature_header_field_length(),
- prologue->cbor_header_length());
+ contents_bytes + signature_header_field_offset +
+ prologue_b.signature_header_field_length(),
+ prologue_b.cbor_header_length());
const base::Optional<SignedExchangeEnvelope> envelope =
- SignedExchangeEnvelope::Parse(signature_header_field, cbor_bytes,
+ SignedExchangeEnvelope::Parse(prologue_b.fallback_url(),
+ signature_header_field, cbor_bytes,
nullptr /* devtools_proxy */);
ASSERT_TRUE(envelope.has_value());
EXPECT_EQ(envelope->request_url(), GURL("https://test.example.org/test/"));
@@ -92,14 +107,14 @@ TEST(SignedExchangeEnvelopeTest, ParseGoldenFile) {
EXPECT_EQ(envelope->response_code(), static_cast<net::HttpStatusCode>(200u));
EXPECT_EQ(envelope->response_headers().size(), 3u);
EXPECT_EQ(envelope->response_headers().find("content-encoding")->second,
- "mi-sha256-draft2");
+ "mi-sha256-03");
}
TEST(SignedExchangeEnvelopeTest, ValidHeader) {
auto header = GenerateHeaderAndParse(
- kSignatureString,
+ GURL("https://test.example.org/test/"), kSignatureString,
{
- {kUrlKey, "https://test.example.org/test/"}, {kMethodKey, "GET"},
+ {kMethodKey, "GET"},
},
{{kStatusKey, "200"}, {"content-type", "text/html"}});
ASSERT_TRUE(header.has_value());
@@ -110,58 +125,61 @@ TEST(SignedExchangeEnvelopeTest, ValidHeader) {
}
TEST(SignedExchangeEnvelopeTest, UnsafeMethod) {
- auto header = GenerateHeaderAndParse(
- kSignatureString,
- {
- {kUrlKey, "https://test.example.org/test/"}, {kMethodKey, "POST"},
- },
- {
- {kStatusKey, "200"},
- });
+ auto header = GenerateHeaderAndParse(GURL("https://test.example.org/test/"),
+ kSignatureString,
+ {
+ {kMethodKey, "POST"},
+ },
+ {
+ {kStatusKey, "200"},
+ });
ASSERT_FALSE(header.has_value());
}
-TEST(SignedExchangeEnvelopeTest, InvalidURL) {
- auto header = GenerateHeaderAndParse(
- kSignatureString,
- {
- {kUrlKey, "https:://test.example.org/test/"}, {kMethodKey, "GET"},
- },
- {
- {kStatusKey, "200"},
- });
+TEST(SignedExchangeEnvelopeTest, RelativeURL) {
+ auto header = GenerateHeaderAndParse(GURL("test/"), kSignatureString,
+ {
+ {kMethodKey, "GET"},
+ },
+ {
+ {kStatusKey, "200"},
+ });
ASSERT_FALSE(header.has_value());
}
-TEST(SignedExchangeEnvelopeTest, URLWithFragment) {
- auto header = GenerateHeaderAndParse(
- kSignatureString,
- {
- {kUrlKey, "https://test.example.org/test/#foo"}, {kMethodKey, "GET"},
- },
- {
- {kStatusKey, "200"},
- });
+TEST(SignedExchangeEnvelopeTest, HttpURLShouldFail) {
+ auto header = GenerateHeaderAndParse(GURL("http://test.example.org/test/"),
+ kSignatureString,
+ {
+ {kMethodKey, "GET"},
+ },
+ {
+ {kStatusKey, "200"},
+ });
ASSERT_FALSE(header.has_value());
}
-TEST(SignedExchangeEnvelopeTest, RelativeURL) {
- auto header =
- GenerateHeaderAndParse(kSignatureString,
- {
- {kUrlKey, "test/"}, {kMethodKey, "GET"},
- },
- {
- {kStatusKey, "200"},
- });
+TEST(SignedExchangeEnvelopeTest, RedirectStatusShouldFail) {
+ auto header = GenerateHeaderAndParse(GURL("https://test.example.org/test/"),
+ kSignatureString, {{kMethodKey, "GET"}},
+ {{kStatusKey, "302"}});
ASSERT_FALSE(header.has_value());
}
-TEST(SignedExchangeEnvelopeTest, HttpURLShouldFail) {
+TEST(SignedExchangeEnvelopeTest, Status300ShouldSucceed) {
+ auto header = GenerateHeaderAndParse(
+ GURL("https://test.example.org/test/"), kSignatureString,
+ {{kMethodKey, "GET"}},
+ {{kStatusKey, "300"}}); // 300 is not a redirect status.
+ ASSERT_TRUE(header.has_value());
+ EXPECT_EQ(header->response_code(), static_cast<net::HttpStatusCode>(300u));
+}
+
+TEST(SignedExchangeEnvelopeTest, StatefulRequestHeader) {
auto header = GenerateHeaderAndParse(
- kSignatureString,
+ GURL("https://test.example.org/test/"), kSignatureString,
{
- {kUrlKey, "http://test.example.org/test/"}, {kMethodKey, "GET"},
+ {kMethodKey, "GET"}, {"authorization", "Basic Zm9vOmJhcg=="},
},
{
{kStatusKey, "200"},
@@ -169,25 +187,11 @@ TEST(SignedExchangeEnvelopeTest, HttpURLShouldFail) {
ASSERT_FALSE(header.has_value());
}
-TEST(SignedExchangeEnvelopeTest, StatefulRequestHeader) {
- auto header =
- GenerateHeaderAndParse(kSignatureString,
- {
- {kUrlKey, "https://test.example.org/test/"},
- {kMethodKey, "GET"},
- {"authorization", "Basic Zm9vOmJhcg=="},
- },
- {
- {kStatusKey, "200"},
- });
- ASSERT_FALSE(header.has_value());
-}
-
TEST(SignedExchangeEnvelopeTest, StatefulResponseHeader) {
auto header = GenerateHeaderAndParse(
- kSignatureString,
+ GURL("https://test.example.org/test/"), kSignatureString,
{
- {kUrlKey, "https://test.example.org/test/"}, {kMethodKey, "GET"},
+ {kMethodKey, "GET"},
},
{
{kStatusKey, "200"}, {"set-cookie", "foo=bar"},
@@ -196,22 +200,20 @@ TEST(SignedExchangeEnvelopeTest, StatefulResponseHeader) {
}
TEST(SignedExchangeEnvelopeTest, UppercaseRequestMap) {
- auto header =
- GenerateHeaderAndParse(kSignatureString,
- {{kUrlKey, "https://test.example.org/test/"},
- {kMethodKey, "GET"},
- {"Accept-Language", "en-us"}},
- {
- {kStatusKey, "200"},
- });
+ auto header = GenerateHeaderAndParse(
+ GURL("https://test.example.org/test/"), kSignatureString,
+ {{kMethodKey, "GET"}, {"Accept-Language", "en-us"}},
+ {
+ {kStatusKey, "200"},
+ });
ASSERT_FALSE(header.has_value());
}
TEST(SignedExchangeEnvelopeTest, UppercaseResponseMap) {
auto header = GenerateHeaderAndParse(
- kSignatureString,
+ GURL("https://test.example.org/test/"), kSignatureString,
{
- {kUrlKey, "https://test.example.org/test/"}, {kMethodKey, "GET"},
+ {kMethodKey, "GET"},
},
{{kStatusKey, "200"}, {"Content-Length", "123"}});
ASSERT_FALSE(header.has_value());
@@ -219,9 +221,9 @@ TEST(SignedExchangeEnvelopeTest, UppercaseResponseMap) {
TEST(SignedExchangeEnvelopeTest, InvalidValidityURLHeader) {
auto header = GenerateHeaderAndParse(
- kSignatureString,
+ GURL("https://test2.example.org/test/"), kSignatureString,
{
- {kUrlKey, "https://test2.example.org/test/"}, {kMethodKey, "GET"},
+ {kMethodKey, "GET"},
},
{{kStatusKey, "200"}, {"content-type", "text/html"}});
ASSERT_FALSE(header.has_value());
diff --git a/chromium/content/browser/web_package/signed_exchange_handler.cc b/chromium/content/browser/web_package/signed_exchange_handler.cc
index b068987cc1f..a2c5fb82f99 100644
--- a/chromium/content/browser/web_package/signed_exchange_handler.cc
+++ b/chromium/content/browser/web_package/signed_exchange_handler.cc
@@ -7,7 +7,10 @@
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
+#include "content/browser/frame_host/frame_tree_node.h"
+#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/loader/merkle_integrity_source_stream.h"
+#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/web_package/signed_exchange_cert_fetcher_factory.h"
#include "content/browser/web_package/signed_exchange_certificate_chain.h"
#include "content/browser/web_package/signed_exchange_devtools_proxy.h"
@@ -17,39 +20,34 @@
#include "content/browser/web_package/signed_exchange_utils.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_features.h"
#include "content/public/common/url_loader_throttle.h"
+#include "mojo/public/cpp/bindings/callback_helpers.h"
#include "mojo/public/cpp/system/string_data_pipe_producer.h"
#include "net/base/io_buffer.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/cert/asn1_util.h"
#include "net/cert/cert_status_flags.h"
-#include "net/cert/cert_verifier.h"
-#include "net/cert/ct_policy_enforcer.h"
-#include "net/cert/ct_verifier.h"
#include "net/cert/x509_certificate.h"
#include "net/cert/x509_util.h"
#include "net/filter/source_stream.h"
-#include "net/http/transport_security_state.h"
-#include "net/ssl/ssl_config.h"
-#include "net/ssl/ssl_config_service.h"
#include "net/ssl/ssl_info.h"
-#include "net/url_request/url_request_context.h"
-#include "net/url_request/url_request_context_getter.h"
#include "services/network/public/cpp/features.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/mojom/network_context.mojom.h"
namespace content {
namespace {
-constexpr char kMiHeader[] = "MI-Draft2";
+constexpr char kDigestHeader[] = "Digest";
-net::CertVerifier* g_cert_verifier_for_testing = nullptr;
+network::mojom::NetworkContext* g_network_context_for_testing = nullptr;
base::Optional<base::Time> g_verification_time_for_testing;
@@ -59,12 +57,58 @@ base::Time GetVerificationTime() {
return base::Time::Now();
}
+bool IsSupportedSignedExchangeVersion(
+ const base::Optional<SignedExchangeVersion>& version) {
+ return version == SignedExchangeVersion::kB2;
+}
+
+using VerifyCallback = base::OnceCallback<void(int32_t,
+ const net::CertVerifyResult&,
+ const net::ct::CTVerifyResult&)>;
+
+void OnVerifyCertUI(VerifyCallback callback,
+ int32_t error_code,
+ const net::CertVerifyResult& cv_result,
+ const net::ct::CTVerifyResult& ct_result) {
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(std::move(callback), error_code, cv_result, ct_result));
+}
+
+void VerifyCert(const scoped_refptr<net::X509Certificate>& certificate,
+ const GURL& url,
+ const std::string& ocsp_result,
+ const std::string& sct_list,
+ base::RepeatingCallback<int(void)> frame_tree_node_id_getter,
+ VerifyCallback callback) {
+ VerifyCallback wrapped_callback = mojo::WrapCallbackWithDefaultInvokeIfNotRun(
+ base::BindOnce(OnVerifyCertUI, std::move(callback)), net::ERR_FAILED,
+ net::CertVerifyResult(), net::ct::CTVerifyResult());
+
+ network::mojom::NetworkContext* network_context =
+ g_network_context_for_testing;
+ if (!network_context) {
+ auto* frame =
+ FrameTreeNode::GloballyFindByID(frame_tree_node_id_getter.Run());
+ if (!frame)
+ return;
+
+ network_context = frame->current_frame_host()
+ ->GetProcess()
+ ->GetStoragePartition()
+ ->GetNetworkContext();
+ }
+
+ network_context->VerifyCertForSignedExchange(
+ certificate, url, ocsp_result, sct_list, std::move(wrapped_callback));
+}
+
} // namespace
// static
-void SignedExchangeHandler::SetCertVerifierForTesting(
- net::CertVerifier* cert_verifier) {
- g_cert_verifier_for_testing = cert_verifier;
+void SignedExchangeHandler::SetNetworkContextForTesting(
+ network::mojom::NetworkContext* network_context) {
+ g_network_context_for_testing = network_context;
}
// static
@@ -79,17 +123,14 @@ SignedExchangeHandler::SignedExchangeHandler(
ExchangeHeadersCallback headers_callback,
std::unique_ptr<SignedExchangeCertFetcherFactory> cert_fetcher_factory,
int load_flags,
- scoped_refptr<net::URLRequestContextGetter> request_context_getter,
- std::unique_ptr<SignedExchangeDevToolsProxy> devtools_proxy)
+ std::unique_ptr<SignedExchangeDevToolsProxy> devtools_proxy,
+ base::RepeatingCallback<int(void)> frame_tree_node_id_getter)
: headers_callback_(std::move(headers_callback)),
source_(std::move(body)),
cert_fetcher_factory_(std::move(cert_fetcher_factory)),
load_flags_(load_flags),
- request_context_getter_(std::move(request_context_getter)),
- net_log_(net::NetLogWithSource::Make(
- request_context_getter_->GetURLRequestContext()->net_log(),
- net::NetLogSourceType::CERT_VERIFIER_JOB)),
devtools_proxy_(std::move(devtools_proxy)),
+ frame_tree_node_id_getter_(frame_tree_node_id_getter),
weak_factory_(this) {
DCHECK(signed_exchange_utils::IsSignedExchangeHandlingEnabled());
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"),
@@ -97,23 +138,20 @@ SignedExchangeHandler::SignedExchangeHandler(
if (!SignedExchangeSignatureHeaderField::GetVersionParamFromContentType(
content_type, &version_) ||
- version_ != SignedExchangeVersion::kB1) {
- base::SequencedTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(&SignedExchangeHandler::RunErrorCallback,
- weak_factory_.GetWeakPtr(),
- net::ERR_INVALID_SIGNED_EXCHANGE));
+ !IsSupportedSignedExchangeVersion(version_)) {
signed_exchange_utils::ReportErrorAndTraceEvent(
devtools_proxy_.get(),
base::StringPrintf("Unsupported version of the content type. Currentry "
"content type must be "
- "\"application/signed-exchange;v=b1\". But the "
+ "\"application/signed-exchange;v=b2\". But the "
"response content type was \"%s\"",
content_type.c_str()));
- return;
+ // Proceed to extract and redirect to the fallback URL.
}
// Triggering the read (asynchronously) for the prologue bytes.
- SetupBuffers(SignedExchangePrologue::kEncodedPrologueInBytes);
+ SetupBuffers(
+ signed_exchange_prologue::BeforeFallbackUrl::kEncodedSizeInBytes);
base::SequencedTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&SignedExchangeHandler::DoHeaderLoop,
weak_factory_.GetWeakPtr()));
@@ -124,6 +162,10 @@ SignedExchangeHandler::~SignedExchangeHandler() = default;
SignedExchangeHandler::SignedExchangeHandler()
: load_flags_(net::LOAD_NORMAL), weak_factory_(this) {}
+const GURL& SignedExchangeHandler::GetFallbackUrl() const {
+ return prologue_fallback_url_and_after_.fallback_url();
+}
+
void SignedExchangeHandler::SetupBuffers(size_t size) {
header_buf_ = base::MakeRefCounted<net::IOBuffer>(size);
header_read_buf_ =
@@ -131,7 +173,9 @@ void SignedExchangeHandler::SetupBuffers(size_t size) {
}
void SignedExchangeHandler::DoHeaderLoop() {
- DCHECK(state_ == State::kReadingPrologue || state_ == State::kReadingHeaders);
+ DCHECK(state_ == State::kReadingPrologueBeforeFallbackUrl ||
+ state_ == State::kReadingPrologueFallbackUrlAndAfter ||
+ state_ == State::kReadingHeaders);
int rv = source_->Read(
header_read_buf_.get(), header_read_buf_->BytesRemaining(),
base::BindRepeating(&SignedExchangeHandler::DidReadHeader,
@@ -141,7 +185,9 @@ void SignedExchangeHandler::DoHeaderLoop() {
}
void SignedExchangeHandler::DidReadHeader(bool completed_syncly, int result) {
- DCHECK(state_ == State::kReadingPrologue || state_ == State::kReadingHeaders);
+ DCHECK(state_ == State::kReadingPrologueBeforeFallbackUrl ||
+ state_ == State::kReadingPrologueFallbackUrlAndAfter ||
+ state_ == State::kReadingHeaders);
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"),
"SignedExchangeHandler::DidReadHeader");
@@ -164,8 +210,14 @@ void SignedExchangeHandler::DidReadHeader(bool completed_syncly, int result) {
header_read_buf_->DidConsume(result);
if (header_read_buf_->BytesRemaining() == 0) {
switch (state_) {
- case State::kReadingPrologue:
- if (!ParsePrologue()) {
+ case State::kReadingPrologueBeforeFallbackUrl:
+ if (!ParsePrologueBeforeFallbackUrl()) {
+ RunErrorCallback(net::ERR_INVALID_SIGNED_EXCHANGE);
+ return;
+ }
+ break;
+ case State::kReadingPrologueFallbackUrlAndAfter:
+ if (!ParsePrologueFallbackUrlAndAfter()) {
RunErrorCallback(net::ERR_INVALID_SIGNED_EXCHANGE);
return;
}
@@ -186,7 +238,9 @@ void SignedExchangeHandler::DidReadHeader(bool completed_syncly, int result) {
return;
// Trigger the next read.
- DCHECK(state_ == State::kReadingPrologue || state_ == State::kReadingHeaders);
+ DCHECK(state_ == State::kReadingPrologueBeforeFallbackUrl ||
+ state_ == State::kReadingPrologueFallbackUrlAndAfter ||
+ state_ == State::kReadingHeaders);
if (completed_syncly) {
base::SequencedTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&SignedExchangeHandler::DoHeaderLoop,
@@ -196,18 +250,49 @@ void SignedExchangeHandler::DidReadHeader(bool completed_syncly, int result) {
}
}
-bool SignedExchangeHandler::ParsePrologue() {
- DCHECK_EQ(state_, State::kReadingPrologue);
+bool SignedExchangeHandler::ParsePrologueBeforeFallbackUrl() {
+ DCHECK_EQ(state_, State::kReadingPrologueBeforeFallbackUrl);
+
+ prologue_before_fallback_url_ =
+ signed_exchange_prologue::BeforeFallbackUrl::Parse(
+ base::make_span(
+ reinterpret_cast<uint8_t*>(header_buf_->data()),
+ signed_exchange_prologue::BeforeFallbackUrl::kEncodedSizeInBytes),
+ devtools_proxy_.get());
+
+ // Note: We will proceed even if |!prologue_before_fallback_url_.is_valid()|
+ // to attempt reading `fallbackUrl`.
+
+ // Set up a new buffer for reading
+ // |signed_exchange_prologue::FallbackUrlAndAfter|.
+ SetupBuffers(
+ prologue_before_fallback_url_.ComputeFallbackUrlAndAfterLength());
+ state_ = State::kReadingPrologueFallbackUrlAndAfter;
+ return true;
+}
+
+bool SignedExchangeHandler::ParsePrologueFallbackUrlAndAfter() {
+ DCHECK_EQ(state_, State::kReadingPrologueFallbackUrlAndAfter);
+
+ prologue_fallback_url_and_after_ =
+ signed_exchange_prologue::FallbackUrlAndAfter::Parse(
+ base::make_span(
+ reinterpret_cast<uint8_t*>(header_buf_->data()),
+ prologue_before_fallback_url_.ComputeFallbackUrlAndAfterLength()),
+ prologue_before_fallback_url_, devtools_proxy_.get());
+ if (!prologue_fallback_url_and_after_.is_valid()) {
+ return false;
+ }
- prologue_ = SignedExchangePrologue::Parse(
- base::make_span(reinterpret_cast<uint8_t*>(header_buf_->data()),
- SignedExchangePrologue::kEncodedPrologueInBytes),
- devtools_proxy_.get());
- if (!prologue_)
+ // If the signed exchange version from content-type is unsupported, abort
+ // parsing and redirect to the fallback URL.
+ if (!IsSupportedSignedExchangeVersion(version_))
return false;
- // Set up a new buffer for Signature + CBOR-encoded header reading.
- SetupBuffers(prologue_->ComputeFollowingSectionsLength());
+ // Set up a new buffer for reading the Signature header field and CBOR-encoded
+ // headers.
+ SetupBuffers(
+ prologue_fallback_url_and_after_.ComputeFollowingSectionsLength());
state_ = State::kReadingHeaders;
return true;
}
@@ -218,13 +303,15 @@ bool SignedExchangeHandler::ParseHeadersAndFetchCertificate() {
DCHECK_EQ(state_, State::kReadingHeaders);
base::StringPiece data(header_buf_->data(), header_read_buf_->size());
- base::StringPiece signature_header_field =
- data.substr(0, prologue_->signature_header_field_length());
- base::span<const uint8_t> cbor_header = base::as_bytes(
- base::make_span(data.substr(prologue_->signature_header_field_length(),
- prologue_->cbor_header_length())));
- envelope_ = SignedExchangeEnvelope::Parse(signature_header_field, cbor_header,
- devtools_proxy_.get());
+ base::StringPiece signature_header_field = data.substr(
+ 0, prologue_fallback_url_and_after_.signature_header_field_length());
+ base::span<const uint8_t> cbor_header =
+ base::as_bytes(base::make_span(data.substr(
+ prologue_fallback_url_and_after_.signature_header_field_length(),
+ prologue_fallback_url_and_after_.cbor_header_length())));
+ envelope_ =
+ SignedExchangeEnvelope::Parse(GetFallbackUrl(), signature_header_field,
+ cbor_header, devtools_proxy_.get());
header_read_buf_ = nullptr;
header_buf_ = nullptr;
if (!envelope_) {
@@ -264,8 +351,8 @@ void SignedExchangeHandler::RunErrorCallback(net::Error error) {
nullptr);
}
std::move(headers_callback_)
- .Run(error, GURL(), std::string(), network::ResourceResponseHead(),
- nullptr);
+ .Run(error, GetFallbackUrl(), std::string(),
+ network::ResourceResponseHead(), nullptr);
state_ = State::kHeadersCallbackCalled;
}
@@ -301,37 +388,25 @@ void SignedExchangeHandler::OnCertReceived(
return;
}
- // TODO(https://crbug.com/849935): The code below reaching into
- // URLRequestContext will not work with Network service.
- DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
- net::URLRequestContext* request_context =
- request_context_getter_->GetURLRequestContext();
- if (!request_context) {
- signed_exchange_utils::ReportErrorAndTraceEvent(
- devtools_proxy_.get(), "No request context available.");
- RunErrorCallback(net::ERR_CONTEXT_SHUT_DOWN);
- return;
- }
+ auto certificate = unverified_cert_chain_->cert();
+ auto url = envelope_->request_url();
+
+ // https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html#cross-origin-trust
+ // Step 6.4 Validate that valid SCTs from trusted logs are available from any
+ // of:
+ // - The SignedCertificateTimestampList in main-certificate’s sct property
+ // (Section 3.3),
+ const std::string& sct_list_from_cert_cbor = unverified_cert_chain_->sct();
+ // - An OCSP extension in the OCSP response in main-certificate’s ocsp
+ // property, or
+ const std::string& stapled_ocsp_response = unverified_cert_chain_->ocsp();
- net::SSLConfig config;
- request_context->ssl_config_service()->GetSSLConfig(&config);
-
- net::CertVerifier* cert_verifier = g_cert_verifier_for_testing
- ? g_cert_verifier_for_testing
- : request_context->cert_verifier();
- int result = cert_verifier->Verify(
- net::CertVerifier::RequestParams(
- unverified_cert_chain_->cert(), envelope_->request_url().host(),
- config.GetCertVerifyFlags(), unverified_cert_chain_->ocsp(),
- net::CertificateList()),
- net::SSLConfigService::GetCRLSet().get(), &cert_verify_result_,
- base::BindRepeating(&SignedExchangeHandler::OnCertVerifyComplete,
- base::Unretained(this)),
- &cert_verifier_request_, net_log_);
- // TODO(https://crbug.com/803774): Avoid these recursive patterns by using
- // explicit state machines (eg: DoLoop() in //net).
- if (result != net::ERR_IO_PENDING)
- OnCertVerifyComplete(result);
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&VerifyCert, certificate, url, stapled_ocsp_response,
+ sct_list_from_cert_cbor, frame_tree_node_id_getter_,
+ base::BindOnce(&SignedExchangeHandler::OnVerifyCert,
+ weak_factory_.GetWeakPtr())));
}
bool SignedExchangeHandler::CheckCertExtension(
@@ -364,109 +439,34 @@ bool SignedExchangeHandler::CheckOCSPStatus(
return true;
}
-// TODO(https://crbug.com/815025, https://crbug.com/849935): This is temporary
-// code until we have Network Service friendly CT verification.
-int SignedExchangeHandler::VerifyCT(net::ct::CTVerifyResult* ct_verify_result) {
- // This function will not work with Network Service.
- DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
-
- net::URLRequestContext* request_context =
- request_context_getter_->GetURLRequestContext();
- if (!request_context)
- return net::ERR_CONTEXT_SHUT_DOWN;
-
- // https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html#cross-origin-trust
- // Step 6.4 Validate that valid SCTs from trusted logs are available from any
- // of:
- // - The SignedCertificateTimestampList in main-certificate’s sct property
- // (Section 3.3),
- const std::string& sct_list_from_cert_cbor = unverified_cert_chain_->sct();
- // - An OCSP extension in the OCSP response in main-certificate’s ocsp
- // property, or
- const std::string& stapled_ocsp_response = unverified_cert_chain_->ocsp();
- // - An X.509 extension in the certificate in main-certificate’s cert
- // property,
- net::X509Certificate* verified_cert = cert_verify_result_.verified_cert.get();
- // as described by Section 3.3 of [RFC6962]. [spec text]
- request_context->cert_transparency_verifier()->Verify(
- envelope_->request_url().host(), verified_cert, stapled_ocsp_response,
- sct_list_from_cert_cbor, &ct_verify_result->scts, net_log_);
-
- net::ct::SCTList verified_scts = net::ct::SCTsMatchingStatus(
- ct_verify_result->scts, net::ct::SCT_STATUS_OK);
-
- ct_verify_result->policy_compliance =
- request_context->ct_policy_enforcer()->CheckCompliance(
- verified_cert, verified_scts, net_log_);
-
- // TODO(https://crbug.com/803774): We should determine whether EV & SXG
- // should be a thing (due to the online/offline signing difference)
- if (cert_verify_result_.cert_status & net::CERT_STATUS_IS_EV &&
- ct_verify_result->policy_compliance !=
- net::ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS &&
- ct_verify_result->policy_compliance !=
- net::ct::CTPolicyCompliance::CT_POLICY_BUILD_NOT_TIMELY) {
- cert_verify_result_.cert_status |= net::CERT_STATUS_CT_COMPLIANCE_FAILED;
- cert_verify_result_.cert_status &= ~net::CERT_STATUS_IS_EV;
- }
-
- net::TransportSecurityState::CTRequirementsStatus ct_requirement_status =
- request_context->transport_security_state()->CheckCTRequirements(
- net::HostPortPair::FromURL(envelope_->request_url()),
- cert_verify_result_.is_issued_by_known_root,
- cert_verify_result_.public_key_hashes, verified_cert,
- unverified_cert_chain_->cert().get(), ct_verify_result->scts,
- net::TransportSecurityState::ENABLE_EXPECT_CT_REPORTS,
- ct_verify_result->policy_compliance);
-
- switch (ct_requirement_status) {
- case net::TransportSecurityState::CT_REQUIREMENTS_NOT_MET:
- return net::ERR_CERTIFICATE_TRANSPARENCY_REQUIRED;
- case net::TransportSecurityState::CT_REQUIREMENTS_MET:
- ct_verify_result->policy_compliance_required = true;
- break;
- case net::TransportSecurityState::CT_NOT_REQUIRED:
- // CT is not required if the certificate does not chain to a publicly
- // trusted root certificate.
- if (!cert_verify_result_.is_issued_by_known_root) {
- ct_verify_result->policy_compliance_required = false;
- break;
- }
- // For old certificates (issued before 2018-05-01), CheckCTRequirements()
- // may return CT_NOT_REQUIRED, so we check the compliance status here.
- // TODO(https://crbug.com/851778): Remove this condition once we require
- // signing certificates to have CanSignHttpExchanges extension, because
- // such certificates should be naturally after 2018-05-01.
- if (ct_verify_result->policy_compliance ==
- net::ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS ||
- ct_verify_result->policy_compliance ==
- net::ct::CTPolicyCompliance::CT_POLICY_BUILD_NOT_TIMELY) {
- ct_verify_result->policy_compliance_required = true;
- break;
- }
- // Require CT compliance, by overriding CT_NOT_REQUIRED and treat it as
- // ERR_CERTIFICATE_TRANSPARENCY_REQUIRED.
- return net::ERR_CERTIFICATE_TRANSPARENCY_REQUIRED;
- }
- return net::OK;
-}
-
-void SignedExchangeHandler::OnCertVerifyComplete(int result) {
+void SignedExchangeHandler::OnVerifyCert(
+ int32_t error_code,
+ const net::CertVerifyResult& cv_result,
+ const net::ct::CTVerifyResult& ct_result) {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"),
"SignedExchangeHandler::OnCertVerifyComplete");
- if (result != net::OK) {
+ if (error_code != net::OK) {
+ std::string error_message;
+ if (error_code == net::ERR_CERTIFICATE_TRANSPARENCY_REQUIRED) {
+ error_message = base::StringPrintf(
+ "CT verification failed. result: %s, policy compliance: %d",
+ net::ErrorToShortString(error_code).c_str(),
+ ct_result.policy_compliance);
+ } else {
+ error_message =
+ base::StringPrintf("Certificate verification error: %s",
+ net::ErrorToShortString(error_code).c_str());
+ }
signed_exchange_utils::ReportErrorAndTraceEvent(
- devtools_proxy_.get(),
- base::StringPrintf("Certificate verification error: %s",
- net::ErrorToShortString(result).c_str()),
+ devtools_proxy_.get(), error_message,
std::make_pair(0 /* signature_index */,
SignedExchangeError::Field::kSignatureCertUrl));
RunErrorCallback(net::ERR_INVALID_SIGNED_EXCHANGE);
return;
}
- if (!CheckCertExtension(cert_verify_result_.verified_cert.get())) {
+ if (!CheckCertExtension(cv_result.verified_cert.get())) {
signed_exchange_utils::ReportErrorAndTraceEvent(
devtools_proxy_.get(),
"Certificate must have CanSignHttpExchangesDraft extension. To ignore "
@@ -478,28 +478,13 @@ void SignedExchangeHandler::OnCertVerifyComplete(int result) {
return;
}
- if (!CheckOCSPStatus(cert_verify_result_.ocsp_result)) {
+ if (!CheckOCSPStatus(cv_result.ocsp_result)) {
signed_exchange_utils::ReportErrorAndTraceEvent(
devtools_proxy_.get(),
base::StringPrintf(
"OCSP check failed. response status: %d, revocation status: %d",
- cert_verify_result_.ocsp_result.response_status,
- cert_verify_result_.ocsp_result.revocation_status),
- std::make_pair(0 /* signature_index */,
- SignedExchangeError::Field::kSignatureCertUrl));
- RunErrorCallback(net::ERR_INVALID_SIGNED_EXCHANGE);
- return;
- }
-
- net::ct::CTVerifyResult ct_verify_result;
- int ct_result = VerifyCT(&ct_verify_result);
- if (ct_result != net::OK) {
- signed_exchange_utils::ReportErrorAndTraceEvent(
- devtools_proxy_.get(),
- base::StringPrintf(
- "CT verification failed. result: %s, policy compliance: %d",
- net::ErrorToShortString(ct_result).c_str(),
- ct_verify_result.policy_compliance),
+ cv_result.ocsp_result.response_status,
+ cv_result.ocsp_result.revocation_status),
std::make_pair(0 /* signature_index */,
SignedExchangeError::Field::kSignatureCertUrl));
RunErrorCallback(net::ERR_INVALID_SIGNED_EXCHANGE);
@@ -520,29 +505,28 @@ void SignedExchangeHandler::OnCertVerifyComplete(int result) {
response_head.load_timing.send_end = now;
response_head.load_timing.receive_headers_end = now;
- std::string mi_header_value;
- if (!response_head.headers->EnumerateHeader(nullptr, kMiHeader,
- &mi_header_value)) {
+ std::string digest_header_value;
+ if (!response_head.headers->EnumerateHeader(nullptr, kDigestHeader,
+ &digest_header_value)) {
signed_exchange_utils::ReportErrorAndTraceEvent(
- devtools_proxy_.get(), "Signed exchange has no MI-Draft2: header");
+ devtools_proxy_.get(), "Signed exchange has no Digest: header");
RunErrorCallback(net::ERR_INVALID_SIGNED_EXCHANGE);
return;
}
auto mi_stream = std::make_unique<MerkleIntegritySourceStream>(
- mi_header_value, std::move(source_));
+ digest_header_value, std::move(source_));
net::SSLInfo ssl_info;
- ssl_info.cert = cert_verify_result_.verified_cert;
+ ssl_info.cert = cv_result.verified_cert;
ssl_info.unverified_cert = unverified_cert_chain_->cert();
- ssl_info.cert_status = cert_verify_result_.cert_status;
- ssl_info.is_issued_by_known_root =
- cert_verify_result_.is_issued_by_known_root;
- ssl_info.public_key_hashes = cert_verify_result_.public_key_hashes;
- ssl_info.ocsp_result = cert_verify_result_.ocsp_result;
+ ssl_info.cert_status = cv_result.cert_status;
+ ssl_info.is_issued_by_known_root = cv_result.is_issued_by_known_root;
+ ssl_info.public_key_hashes = cv_result.public_key_hashes;
+ ssl_info.ocsp_result = cv_result.ocsp_result;
ssl_info.is_fatal_cert_error =
net::IsCertStatusError(ssl_info.cert_status) &&
!net::IsCertStatusMinorError(ssl_info.cert_status);
- ssl_info.UpdateCertificateTransparencyInfo(ct_verify_result);
+ ssl_info.UpdateCertificateTransparencyInfo(ct_result);
if (devtools_proxy_) {
devtools_proxy_->OnSignedExchangeReceived(
diff --git a/chromium/content/browser/web_package/signed_exchange_handler.h b/chromium/content/browser/web_package/signed_exchange_handler.h
index b2ded77ac04..122ac720be3 100644
--- a/chromium/content/browser/web_package/signed_exchange_handler.h
+++ b/chromium/content/browser/web_package/signed_exchange_handler.h
@@ -24,16 +24,17 @@
#include "url/origin.h"
namespace net {
-class CertVerifier;
class CertVerifyResult;
class DrainableIOBuffer;
class SourceStream;
-class URLRequestContextGetter;
struct OCSPVerifyResult;
} // namespace net
namespace network {
struct ResourceResponseHead;
+namespace mojom {
+class NetworkContext;
+}
} // namespace network
namespace content {
@@ -43,12 +44,16 @@ class SignedExchangeCertFetcherFactory;
class SignedExchangeCertificateChain;
class SignedExchangeDevToolsProxy;
-// IMPORTANT: Currenly SignedExchangeHandler partially implements the verifying
-// logic.
-// TODO(https://crbug.com/803774): Implement verifying logic.
+// SignedExchangeHandler reads "application/signed-exchange" format from a
+// net::SourceStream, parse and verify the signed exchange, and report
+// the result asynchronously via SignedExchangeHandler::ExchangeHeadersCallback.
+//
+// Note that verifying a signed exchange requires an associated certificate
+// chain. SignedExchangeHandler creates a SignedExchangeCertFetcher to
+// fetch the certificate chain over network, and verify it with the
+// net::CertVerifier.
class CONTENT_EXPORT SignedExchangeHandler {
public:
- // TODO(https://crbug.com/803774): Add verification status here.
using ExchangeHeadersCallback = base::OnceCallback<void(
net::Error error,
const GURL& request_url,
@@ -56,9 +61,8 @@ class CONTENT_EXPORT SignedExchangeHandler {
const network::ResourceResponseHead&,
std::unique_ptr<net::SourceStream> payload_stream)>;
- // TODO(https://crbug.com/817187): Find a more sophisticated way to use a
- // MockCertVerifier in browser tests instead of using the static method.
- static void SetCertVerifierForTesting(net::CertVerifier* cert_verifier);
+ static void SetNetworkContextForTesting(
+ network::mojom::NetworkContext* network_context);
static void SetVerificationTimeForTesting(
base::Optional<base::Time> verification_time_for_testing);
@@ -73,8 +77,8 @@ class CONTENT_EXPORT SignedExchangeHandler {
ExchangeHeadersCallback headers_callback,
std::unique_ptr<SignedExchangeCertFetcherFactory> cert_fetcher_factory,
int load_flags,
- scoped_refptr<net::URLRequestContextGetter> request_context_getter,
- std::unique_ptr<SignedExchangeDevToolsProxy> devtools_proxy);
+ std::unique_ptr<SignedExchangeDevToolsProxy> devtools_proxy,
+ base::RepeatingCallback<int(void)> frame_tree_node_id_getter);
~SignedExchangeHandler();
protected:
@@ -82,57 +86,57 @@ class CONTENT_EXPORT SignedExchangeHandler {
private:
enum class State {
- kReadingPrologue,
+ kReadingPrologueBeforeFallbackUrl,
+ kReadingPrologueFallbackUrlAndAfter,
kReadingHeaders,
kFetchingCertificate,
kHeadersCallbackCalled,
};
+ const GURL& GetFallbackUrl() const;
+
void SetupBuffers(size_t size);
void DoHeaderLoop();
void DidReadHeader(bool completed_syncly, int result);
- bool ParsePrologue();
+ bool ParsePrologueBeforeFallbackUrl();
+ bool ParsePrologueFallbackUrlAndAfter();
bool ParseHeadersAndFetchCertificate();
void RunErrorCallback(net::Error);
void OnCertReceived(
std::unique_ptr<SignedExchangeCertificateChain> cert_chain);
- void OnCertVerifyComplete(int result);
bool CheckCertExtension(const net::X509Certificate* verified_cert);
bool CheckOCSPStatus(const net::OCSPVerifyResult& ocsp_result);
- int VerifyCT(net::ct::CTVerifyResult* ct_verify_result);
+
+ void OnVerifyCert(int32_t error_code,
+ const net::CertVerifyResult& cv_result,
+ const net::ct::CTVerifyResult& ct_result);
ExchangeHeadersCallback headers_callback_;
base::Optional<SignedExchangeVersion> version_;
std::unique_ptr<net::SourceStream> source_;
- State state_ = State::kReadingPrologue;
+ State state_ = State::kReadingPrologueBeforeFallbackUrl;
// Buffer used for prologue and envelope reading.
scoped_refptr<net::IOBuffer> header_buf_;
// Wrapper around |header_buf_| to progressively read fixed-size data.
scoped_refptr<net::DrainableIOBuffer> header_read_buf_;
- base::Optional<SignedExchangePrologue> prologue_;
+
+ signed_exchange_prologue::BeforeFallbackUrl prologue_before_fallback_url_;
+ signed_exchange_prologue::FallbackUrlAndAfter
+ prologue_fallback_url_and_after_;
base::Optional<SignedExchangeEnvelope> envelope_;
std::unique_ptr<SignedExchangeCertFetcherFactory> cert_fetcher_factory_;
std::unique_ptr<SignedExchangeCertFetcher> cert_fetcher_;
const int load_flags_;
- scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
-
std::unique_ptr<SignedExchangeCertificateChain> unverified_cert_chain_;
- // CertVerifyResult must be freed after the Request has been destructed.
- // So |cert_verify_result_| must be written before |cert_verifier_request_|.
- net::CertVerifyResult cert_verify_result_;
- std::unique_ptr<net::CertVerifier::Request> cert_verifier_request_;
-
- // TODO(https://crbug.com/767450): figure out what we should do for NetLog
- // with Network Service.
- net::NetLogWithSource net_log_;
-
std::unique_ptr<SignedExchangeDevToolsProxy> devtools_proxy_;
+ base::RepeatingCallback<int(void)> frame_tree_node_id_getter_;
+
base::WeakPtrFactory<SignedExchangeHandler> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(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 54a648fc03b..43578473a64 100644
--- a/chromium/content/browser/web_package/signed_exchange_handler_unittest.cc
+++ b/chromium/content/browser/web_package/signed_exchange_handler_unittest.cc
@@ -12,11 +12,11 @@
#include "base/files/file_util.h"
#include "base/path_service.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
#include "content/browser/web_package/signed_exchange_cert_fetcher_factory.h"
#include "content/browser/web_package/signed_exchange_devtools_proxy.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_paths.h"
+#include "content/public/test/test_browser_thread_bundle.h"
#include "net/base/io_buffer.h"
#include "net/base/load_flags.h"
#include "net/base/test_completion_callback.h"
@@ -28,6 +28,7 @@
#include "net/test/cert_test_util.h"
#include "net/test/test_data_directory.h"
#include "net/url_request/url_request_test_util.h"
+#include "services/network/network_context.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -45,10 +46,17 @@ namespace {
const uint64_t kSignatureHeaderDate = 1520834000;
const int kOutputBufferSize = 4096;
+constexpr char kTestSxgInnerURL[] = "https://test.example.org/test/";
+
// "wildcard_example.org.public.pem.cbor" has these dummy data in "ocsp" and
// "sct" fields.
constexpr base::StringPiece kDummyOCSPDer = "OCSP";
-constexpr base::StringPiece kDummySCTList = "SCT";
+constexpr char kDummySCTBytes[] = {
+ 0x00, 0x05, // Length of the sct list
+ 0x00, 0x03, 'S', 'C', 'T' // List entry: length and body
+};
+constexpr base::StringPiece kDummySCTList(kDummySCTBytes,
+ sizeof(kDummySCTBytes));
std::string GetTestFileContents(base::StringPiece name) {
base::FilePath path;
@@ -105,20 +113,19 @@ class GMockCertVerifier : public net::CertVerifier {
public:
// net::CompletionOnceCallback is move-only, which GMock does not support.
int Verify(const net::CertVerifier::RequestParams& params,
- net::CRLSet* crl_set,
net::CertVerifyResult* verify_result,
net::CompletionOnceCallback callback,
std::unique_ptr<net::CertVerifier::Request>* out_req,
const net::NetLogWithSource& net_log) override {
- return VerifyImpl(params, crl_set, verify_result, out_req, net_log);
+ return VerifyImpl(params, verify_result, out_req, net_log);
}
- MOCK_METHOD5(VerifyImpl,
+ MOCK_METHOD4(VerifyImpl,
int(const net::CertVerifier::RequestParams& params,
- net::CRLSet* crl_set,
net::CertVerifyResult* verify_result,
std::unique_ptr<net::CertVerifier::Request>* out_req,
const net::NetLogWithSource& net_log));
+ MOCK_METHOD1(SetConfig, void(const net::CertVerifier::Config& config));
};
class MockCTVerifier : public net::CTVerifier {
@@ -158,7 +165,7 @@ class SignedExchangeHandlerTest
url::Origin::Create(GURL("https://sxg.example.com/test.sxg"))) {}
virtual std::string ContentType() {
- return "application/signed-exchange;v=b1";
+ return "application/signed-exchange;v=b2";
}
void SetUp() override {
@@ -183,14 +190,15 @@ class SignedExchangeHandlerTest
}
void TearDown() override {
- SignedExchangeHandler::SetCertVerifierForTesting(nullptr);
+ SignedExchangeHandler::SetNetworkContextForTesting(nullptr);
+ network::NetworkContext::SetCertVerifierForTesting(nullptr);
SignedExchangeHandler::SetVerificationTimeForTesting(
base::Optional<base::Time>());
}
void SetCertVerifier(std::unique_ptr<net::CertVerifier> cert_verifier) {
cert_verifier_ = std::move(cert_verifier);
- SignedExchangeHandler::SetCertVerifierForTesting(cert_verifier_.get());
+ network::NetworkContext::SetCertVerifierForTesting(cert_verifier_.get());
}
// Reads from |stream| until an error occurs or the EOF is reached.
@@ -228,6 +236,7 @@ class SignedExchangeHandlerTest
bool read_header() const { return read_header_; }
net::Error error() const { return error_; }
+ const GURL& inner_url() const { return inner_url_; }
const network::ResourceResponseHead& resource_response() const {
return resource_response_;
}
@@ -245,53 +254,61 @@ class SignedExchangeHandlerTest
void CreateSignedExchangeHandler(
std::unique_ptr<net::TestURLRequestContext> context) {
- request_context_getter_ = new net::TestURLRequestContextGetter(
- scoped_task_environment_.GetMainThreadTaskRunner(), std::move(context));
+ url_request_context_ = std::move(context);
+ network_context_ = std::make_unique<network::NetworkContext>(
+ nullptr, mojo::MakeRequest(&network_context_ptr_),
+ url_request_context_.get());
+ SignedExchangeHandler::SetNetworkContextForTesting(network_context_.get());
handler_ = std::make_unique<SignedExchangeHandler>(
ContentType(), std::move(source_stream_),
base::BindOnce(&SignedExchangeHandlerTest::OnHeaderFound,
base::Unretained(this)),
std::move(cert_fetcher_factory_), net::LOAD_NORMAL,
- request_context_getter_, nullptr /* devtools_proxy */);
+ nullptr /* devtools_proxy */, base::RepeatingCallback<int(void)>());
}
void WaitForHeader() {
while (!read_header()) {
while (source_->awaiting_completion())
source_->CompleteNextRead();
- scoped_task_environment_.RunUntilIdle();
+ browser_thread_bundle_.RunUntilIdle();
}
}
protected:
MockSignedExchangeCertFetcherFactory* mock_cert_fetcher_factory_;
std::unique_ptr<net::CertVerifier> cert_verifier_;
+ std::unique_ptr<MockCTVerifier> mock_ct_verifier_;
std::unique_ptr<MockCTPolicyEnforcer> mock_ct_policy_enforcer_;
net::MockSourceStream* source_;
std::unique_ptr<SignedExchangeHandler> handler_;
private:
void OnHeaderFound(net::Error error,
- const GURL&,
+ const GURL& url,
const std::string&,
const network::ResourceResponseHead& resource_response,
std::unique_ptr<net::SourceStream> payload_stream) {
read_header_ = true;
error_ = error;
+ inner_url_ = url;
resource_response_ = resource_response;
payload_stream_ = std::move(payload_stream);
}
base::test::ScopedFeatureList feature_list_;
- base::test::ScopedTaskEnvironment scoped_task_environment_;
- scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_;
+ content::TestBrowserThreadBundle browser_thread_bundle_;
+ 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<net::MockSourceStream> source_stream_;
std::unique_ptr<MockSignedExchangeCertFetcherFactory> cert_fetcher_factory_;
bool read_header_ = false;
net::Error error_;
+ GURL inner_url_;
network::ResourceResponseHead resource_response_;
std::unique_ptr<net::SourceStream> payload_stream_;
};
@@ -304,6 +321,7 @@ TEST_P(SignedExchangeHandlerTest, Empty) {
ASSERT_TRUE(read_header());
EXPECT_EQ(net::ERR_INVALID_SIGNED_EXCHANGE, error());
+ EXPECT_TRUE(inner_url().is_empty());
}
TEST_P(SignedExchangeHandlerTest, Simple) {
@@ -334,6 +352,7 @@ TEST_P(SignedExchangeHandlerTest, Simple) {
ASSERT_TRUE(read_header());
EXPECT_EQ(net::OK, error());
+ EXPECT_EQ(kTestSxgInnerURL, inner_url());
EXPECT_EQ(200, resource_response().headers->response_code());
EXPECT_EQ("text/html", resource_response().mime_type);
EXPECT_EQ("utf-8", resource_response().charset);
@@ -394,7 +413,7 @@ TEST_P(SignedExchangeHandlerTest, MimeType) {
}
TEST_P(SignedExchangeHandlerTest, HeaderParseError) {
- const uint8_t data[] = {'s', 'x', 'g', '1', '-', 'b', '1', '\0',
+ const uint8_t data[] = {'s', 'x', 'g', '1', '-', 'b', '2', '\0',
0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00};
source_->AddReadResult(reinterpret_cast<const char*>(data), sizeof(data),
net::OK, GetParam());
@@ -403,6 +422,7 @@ TEST_P(SignedExchangeHandlerTest, HeaderParseError) {
ASSERT_TRUE(read_header());
EXPECT_EQ(net::ERR_INVALID_SIGNED_EXCHANGE, error());
+ EXPECT_TRUE(inner_url().is_empty());
}
TEST_P(SignedExchangeHandlerTest, TruncatedInHeader) {
@@ -416,6 +436,7 @@ TEST_P(SignedExchangeHandlerTest, TruncatedInHeader) {
ASSERT_TRUE(read_header());
EXPECT_EQ(net::ERR_INVALID_SIGNED_EXCHANGE, error());
+ EXPECT_TRUE(inner_url().is_empty());
}
TEST_P(SignedExchangeHandlerTest, CertWithoutExtensionShouldBeRejected) {
@@ -446,6 +467,7 @@ TEST_P(SignedExchangeHandlerTest, CertWithoutExtensionShouldBeRejected) {
ASSERT_TRUE(read_header());
EXPECT_EQ(net::ERR_INVALID_SIGNED_EXCHANGE, error());
+ EXPECT_EQ(kTestSxgInnerURL, inner_url());
// Drain the MockSourceStream, otherwise its destructer causes DCHECK failure.
ReadStream(source_, nullptr);
}
@@ -513,6 +535,7 @@ TEST_P(SignedExchangeHandlerTest, CertSha256Mismatch) {
ASSERT_TRUE(read_header());
EXPECT_EQ(net::ERR_INVALID_SIGNED_EXCHANGE, error());
+ EXPECT_EQ(kTestSxgInnerURL, inner_url());
// Drain the MockSourceStream, otherwise its destructer causes DCHECK failure.
ReadStream(source_, nullptr);
}
@@ -547,6 +570,7 @@ TEST_P(SignedExchangeHandlerTest, VerifyCertFailure) {
ASSERT_TRUE(read_header());
EXPECT_EQ(net::ERR_INVALID_SIGNED_EXCHANGE, error());
+ EXPECT_EQ("https://test.example.com/test/", inner_url());
// Drain the MockSourceStream, otherwise its destructer causes DCHECK failure.
ReadStream(source_, nullptr);
}
@@ -578,6 +602,7 @@ TEST_P(SignedExchangeHandlerTest, OCSPNotChecked) {
ASSERT_TRUE(read_header());
EXPECT_EQ(net::ERR_INVALID_SIGNED_EXCHANGE, error());
+ EXPECT_EQ(kTestSxgInnerURL, inner_url());
// Drain the MockSourceStream, otherwise its destructer causes DCHECK failure.
ReadStream(source_, nullptr);
}
@@ -609,6 +634,7 @@ TEST_P(SignedExchangeHandlerTest, OCSPNotProvided) {
ASSERT_TRUE(read_header());
EXPECT_EQ(net::ERR_INVALID_SIGNED_EXCHANGE, error());
+ EXPECT_EQ(kTestSxgInnerURL, inner_url());
// Drain the MockSourceStream, otherwise its destructer causes DCHECK failure.
ReadStream(source_, nullptr);
}
@@ -641,6 +667,7 @@ TEST_P(SignedExchangeHandlerTest, OCSPInvalid) {
ASSERT_TRUE(read_header());
EXPECT_EQ(net::ERR_INVALID_SIGNED_EXCHANGE, error());
+ EXPECT_EQ(kTestSxgInnerURL, inner_url());
// Drain the MockSourceStream, otherwise its destructer causes DCHECK failure.
ReadStream(source_, nullptr);
}
@@ -674,6 +701,7 @@ TEST_P(SignedExchangeHandlerTest, OCSPRevoked) {
ASSERT_TRUE(read_header());
EXPECT_EQ(net::ERR_INVALID_SIGNED_EXCHANGE, error());
+ EXPECT_EQ(kTestSxgInnerURL, inner_url());
// Drain the MockSourceStream, otherwise its destructer causes DCHECK failure.
ReadStream(source_, nullptr);
}
@@ -704,10 +732,9 @@ TEST_P(SignedExchangeHandlerTest, CertVerifierParams) {
CertEqualsIncludingChain(original_cert)),
Property(&net::CertVerifier::RequestParams::hostname,
"test.example.org")),
- _ /* crl_set */, _ /* verify_result */, _ /* out_req */,
- _ /* net_log */
+ _ /* verify_result */, _ /* out_req */, _ /* net_log */
))
- .WillOnce(DoAll(SetArgPointee<2>(fake_result), Return(net::OK)));
+ .WillOnce(DoAll(SetArgPointee<1>(fake_result), Return(net::OK)));
SetCertVerifier(std::move(gmock_cert_verifier));
std::string contents = GetTestFileContents("test.example.org_test.sxg");
@@ -760,6 +787,7 @@ TEST_P(SignedExchangeHandlerTest, NotEnoughSCTsFromPubliclyTrustedCert) {
ASSERT_TRUE(read_header());
EXPECT_EQ(net::ERR_INVALID_SIGNED_EXCHANGE, error());
+ EXPECT_EQ(kTestSxgInnerURL, inner_url());
// Drain the MockSourceStream, otherwise its destructer causes DCHECK failure.
ReadStream(source_, nullptr);
}
@@ -884,9 +912,8 @@ TEST_P(SignedExchangeHandlerTest, CTVerifierParams) {
.WillOnce(
Return(net::ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS));
- std::unique_ptr<MockCTVerifier> ct_verifier =
- std::make_unique<MockCTVerifier>();
- EXPECT_CALL(*ct_verifier,
+ mock_ct_verifier_ = std::make_unique<MockCTVerifier>();
+ EXPECT_CALL(*mock_ct_verifier_,
Verify(base::StringPiece("test.example.org"),
CertEqualsIncludingChain(original_cert), kDummyOCSPDer,
kDummySCTList, _ /* output_scts */, _ /* net_log */))
@@ -896,7 +923,8 @@ TEST_P(SignedExchangeHandlerTest, CTVerifierParams) {
true /* delay_initialization */);
test_url_request_context->set_ct_policy_enforcer(
mock_ct_policy_enforcer_.get());
- test_url_request_context->set_cert_transparency_verifier(ct_verifier.get());
+ test_url_request_context->set_cert_transparency_verifier(
+ mock_ct_verifier_.get());
test_url_request_context->Init();
// Make the MockCertVerifier treat the certificate
diff --git a/chromium/content/browser/web_package/signed_exchange_loader.cc b/chromium/content/browser/web_package/signed_exchange_loader.cc
index 9ede996006a..d03dd7f2947 100644
--- a/chromium/content/browser/web_package/signed_exchange_loader.cc
+++ b/chromium/content/browser/web_package/signed_exchange_loader.cc
@@ -20,7 +20,6 @@
#include "net/base/net_errors.h"
#include "net/cert/cert_status_flags.h"
#include "net/http/http_util.h"
-#include "net/url_request/url_request_context_getter.h"
#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"
@@ -30,11 +29,22 @@ namespace content {
namespace {
-net::RedirectInfo CreateRedirectInfo(const GURL& new_url) {
+net::RedirectInfo CreateRedirectInfo(const GURL& new_url,
+ const GURL& outer_request_url) {
net::RedirectInfo redirect_info;
- redirect_info.new_url = new_url;
+ if (outer_request_url.has_ref()) {
+ // Propagate ref fragment from the outer request URL.
+ url::Replacements<char> replacements;
+ base::StringPiece ref = outer_request_url.ref_piece();
+ replacements.SetRef(ref.data(), url::Component(0, ref.length()));
+ redirect_info.new_url = new_url.ReplaceComponents(replacements);
+ } else {
+ redirect_info.new_url = new_url;
+ }
redirect_info.new_method = "GET";
- redirect_info.status_code = 302;
+ // https://wicg.github.io/webpackage/loading.html#mp-http-fetch
+ // Step 3. Set actualResponse's status to 303. [spec text]
+ redirect_info.status_code = 303;
redirect_info.new_site_for_cookies = redirect_info.new_url;
return redirect_info;
}
@@ -57,7 +67,7 @@ class SignedExchangeLoader::ResponseTimingInfo {
network::ResourceResponseHead CreateRedirectResponseHead() const {
network::ResourceResponseHead response_head;
response_head.encoded_data_length = 0;
- std::string buf(base::StringPrintf("HTTP/1.1 %d %s\r\n", 302, "Found"));
+ std::string buf(base::StringPrintf("HTTP/1.1 %d %s\r\n", 303, "See Other"));
response_head.headers = new net::HttpResponseHeaders(
net::HttpUtil::AssembleRawHeaders(buf.c_str(), buf.size()));
response_head.encoded_data_length = 0;
@@ -87,12 +97,14 @@ SignedExchangeLoader::SignedExchangeLoader(
url::Origin request_initiator,
uint32_t url_loader_options,
int load_flags,
+ bool should_redirect_on_failure,
const base::Optional<base::UnguessableToken>& throttling_profile_id,
std::unique_ptr<SignedExchangeDevToolsProxy> devtools_proxy,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
URLLoaderThrottlesGetter url_loader_throttles_getter,
- scoped_refptr<net::URLRequestContextGetter> request_context_getter)
- : outer_response_timing_info_(
+ base::RepeatingCallback<int(void)> frame_tree_node_id_getter)
+ : outer_request_url_(outer_request_url),
+ outer_response_timing_info_(
std::make_unique<ResponseTimingInfo>(outer_response)),
outer_response_(outer_response),
forwarding_client_(std::move(forwarding_client)),
@@ -100,13 +112,15 @@ SignedExchangeLoader::SignedExchangeLoader(
request_initiator_(request_initiator),
url_loader_options_(url_loader_options),
load_flags_(load_flags),
+ should_redirect_on_failure_(should_redirect_on_failure),
throttling_profile_id_(throttling_profile_id),
devtools_proxy_(std::move(devtools_proxy)),
url_loader_factory_(std::move(url_loader_factory)),
url_loader_throttles_getter_(std::move(url_loader_throttles_getter)),
- request_context_getter_(std::move(request_context_getter)),
+ frame_tree_node_id_getter_(frame_tree_node_id_getter),
weak_factory_(this) {
DCHECK(signed_exchange_utils::IsSignedExchangeHandlingEnabled());
+ DCHECK(outer_request_url_.is_valid());
// https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html#privacy-considerations
// This can be difficult to determine when the exchange is being loaded from
@@ -129,25 +143,6 @@ SignedExchangeLoader::SignedExchangeLoader(
return;
}
- // TODO(https://crbug.com/849935): Remove this once we have Network Service
- // friendly cert, OCSP, and CT verification.
- if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
- devtools_proxy_->ReportError(
- "Currently, signed exchange does not work when "
- "chrome://flags/#network-service is enabled. "
- "See http://crbug.com/849935 for details.",
- base::nullopt /* error_field */);
- // Calls OnSignedExchangeReceived() to show the outer response in DevTool's
- // Network panel and the error message in the Preview panel.
- devtools_proxy_->OnSignedExchangeReceived(base::nullopt /* header */,
- nullptr /* certificate */,
- nullptr /* ssl_info */);
- // This will asynchronously delete |this|.
- forwarding_client_->OnComplete(
- network::URLLoaderCompletionStatus(net::ERR_INVALID_SIGNED_EXCHANGE));
- return;
- }
-
// Can't use HttpResponseHeaders::GetMimeType() because SignedExchangeHandler
// checks "v=" parameter.
outer_response.headers->EnumerateHeader(nullptr, "content-type",
@@ -228,8 +223,8 @@ void SignedExchangeLoader::OnStartLoadingResponseBody(
content_type_, std::make_unique<DataPipeToSourceStream>(std::move(body)),
base::BindOnce(&SignedExchangeLoader::OnHTTPExchangeFound,
weak_factory_.GetWeakPtr()),
- std::move(cert_fetcher_factory), load_flags_,
- std::move(request_context_getter_), std::move(devtools_proxy_));
+ std::move(cert_fetcher_factory), load_flags_, std::move(devtools_proxy_),
+ frame_tree_node_id_getter_);
}
void SignedExchangeLoader::OnComplete(
@@ -243,9 +238,6 @@ void SignedExchangeLoader::FollowRedirect(
}
void SignedExchangeLoader::ProceedWithResponse() {
- // TODO(https://crbug.com/791049): Remove this when NetworkService is
- // enabled by default.
- DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
DCHECK(body_data_pipe_adapter_);
DCHECK(pending_body_consumer_.is_valid());
@@ -280,15 +272,28 @@ void SignedExchangeLoader::OnHTTPExchangeFound(
const network::ResourceResponseHead& resource_response,
std::unique_ptr<net::SourceStream> payload_stream) {
if (error) {
- // This will eventually delete |this|.
- forwarding_client_->OnComplete(network::URLLoaderCompletionStatus(error));
+ if (error != net::ERR_INVALID_SIGNED_EXCHANGE ||
+ !should_redirect_on_failure_ || !request_url.is_valid()) {
+ // Let the request fail.
+ // This will eventually delete |this|.
+ forwarding_client_->OnComplete(network::URLLoaderCompletionStatus(error));
+ return;
+ }
+ // Make a fallback redirect to |request_url|.
+ DCHECK(!has_redirected_to_fallback_url_);
+ has_redirected_to_fallback_url_ = true;
+ DCHECK(outer_response_timing_info_);
+ forwarding_client_->OnReceiveRedirect(
+ CreateRedirectInfo(request_url, outer_request_url_),
+ std::move(outer_response_timing_info_)->CreateRedirectResponseHead());
+ forwarding_client_.reset();
return;
}
// TODO(https://crbug.com/803774): Handle no-GET request_method as a error.
DCHECK(outer_response_timing_info_);
forwarding_client_->OnReceiveRedirect(
- CreateRedirectInfo(request_url),
+ CreateRedirectInfo(request_url, outer_request_url_),
std::move(outer_response_timing_info_)->CreateRedirectResponseHead());
forwarding_client_.reset();
diff --git a/chromium/content/browser/web_package/signed_exchange_loader.h b/chromium/content/browser/web_package/signed_exchange_loader.h
index 2ab0d3a1d66..47cdeccf490 100644
--- a/chromium/content/browser/web_package/signed_exchange_loader.h
+++ b/chromium/content/browser/web_package/signed_exchange_loader.h
@@ -19,7 +19,6 @@
namespace net {
class SourceStream;
-class URLRequestContextGetter;
} // namespace net
namespace network {
@@ -45,6 +44,8 @@ class SignedExchangeLoader final : public network::mojom::URLLoaderClient,
using URLLoaderThrottlesGetter = base::RepeatingCallback<
std::vector<std::unique_ptr<content::URLLoaderThrottle>>()>;
+ // If |should_redirect_on_failure| is true, verification failure causes a
+ // redirect to the fallback URL.
SignedExchangeLoader(
const GURL& outer_request_url,
const network::ResourceResponseHead& outer_response,
@@ -53,13 +54,18 @@ class SignedExchangeLoader final : public network::mojom::URLLoaderClient,
url::Origin request_initiator,
uint32_t url_loader_options,
int load_flags,
+ bool should_redirect_on_failure,
const base::Optional<base::UnguessableToken>& throttling_profile_id,
std::unique_ptr<SignedExchangeDevToolsProxy> devtools_proxy,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
URLLoaderThrottlesGetter url_loader_throttles_getter,
- scoped_refptr<net::URLRequestContextGetter> request_context_getter);
+ base::RepeatingCallback<int(void)> frame_tree_node_id_getter);
~SignedExchangeLoader() override;
+ bool HasRedirectedToFallbackURL() const {
+ return has_redirected_to_fallback_url_;
+ }
+
// network::mojom::URLLoaderClient implementation
// Only OnStartLoadingResponseBody() and OnComplete() are called.
void OnReceiveResponse(
@@ -107,6 +113,8 @@ class SignedExchangeLoader final : public network::mojom::URLLoaderClient,
void FinishReadingBody(int result);
+ const GURL outer_request_url_;
+
// This timing info is used to create a dummy redirect response.
std::unique_ptr<const ResponseTimingInfo> outer_response_timing_info_;
@@ -137,11 +145,13 @@ class SignedExchangeLoader final : public network::mojom::URLLoaderClient,
url::Origin request_initiator_;
const uint32_t url_loader_options_;
const int load_flags_;
+ const bool should_redirect_on_failure_;
+ bool has_redirected_to_fallback_url_ = false;
const base::Optional<base::UnguessableToken> throttling_profile_id_;
std::unique_ptr<SignedExchangeDevToolsProxy> devtools_proxy_;
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
URLLoaderThrottlesGetter url_loader_throttles_getter_;
- scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
+ base::RepeatingCallback<int(void)> frame_tree_node_id_getter_;
base::Optional<net::SSLInfo> ssl_info_;
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 c28252bf4df..abf10c2ed0a 100644
--- a/chromium/content/browser/web_package/signed_exchange_prefetch_handler.cc
+++ b/chromium/content/browser/web_package/signed_exchange_prefetch_handler.cc
@@ -51,12 +51,13 @@ SignedExchangePrefetchHandler::SignedExchangePrefetchHandler(
signed_exchange_loader_ = std::make_unique<SignedExchangeLoader>(
outer_request_url, response, std::move(client), std::move(endpoints),
std::move(request_initiator), network::mojom::kURLLoadOptionNone,
- load_flags, throttling_profile_id,
+ load_flags, false /* should_redirect_to_fallback */,
+ throttling_profile_id,
std::make_unique<SignedExchangeDevToolsProxy>(
- outer_request_url, response, std::move(frame_tree_node_id_getter),
+ outer_request_url, response, frame_tree_node_id_getter,
base::nullopt /* devtools_navigation_token */, report_raw_headers),
std::move(url_loader_factory), loader_throttles_getter,
- request_context_getter);
+ frame_tree_node_id_getter);
}
SignedExchangePrefetchHandler::~SignedExchangePrefetchHandler() = default;
diff --git a/chromium/content/browser/web_package/signed_exchange_prologue.cc b/chromium/content/browser/web_package/signed_exchange_prologue.cc
index 8f45dc93d90..c298b0b6261 100644
--- a/chromium/content/browser/web_package/signed_exchange_prologue.cc
+++ b/chromium/content/browser/web_package/signed_exchange_prologue.cc
@@ -4,6 +4,7 @@
#include "content/browser/web_package/signed_exchange_prologue.h"
+#include "base/strings/string_piece.h"
#include "base/strings/stringprintf.h"
#include "base/trace_event/trace_event.h"
#include "content/browser/web_package/signed_exchange_utils.h"
@@ -12,72 +13,170 @@ namespace content {
namespace {
-constexpr char kSignedExchangeMagic[] = "sxg1-b1";
+constexpr char kSignedExchangeMagic[] = "sxg1-b2";
+
+// size of `fallbackUrlLength` field in number of bytes.
+constexpr size_t kFallbackUrlLengthFieldSizeInBytes = 2;
+// size of `sigLength` field in number of bytes.
+constexpr size_t kSigLengthFieldLengthInBytes = 3;
+// size of `headerLength` field in number of bytes.
+constexpr size_t kHeaderLengthFieldLengthInBytes = 3;
+
constexpr size_t kMaximumSignatureHeaderFieldLength = 16 * 1024;
constexpr size_t kMaximumCBORHeaderLength = 512 * 1024;
} // namespace
-constexpr size_t SignedExchangePrologue::kEncodedLengthInBytes;
-size_t SignedExchangePrologue::kEncodedPrologueInBytes =
- sizeof(kSignedExchangeMagic) +
- SignedExchangePrologue::kEncodedLengthInBytes * 2;
+namespace signed_exchange_prologue {
-// static
-size_t SignedExchangePrologue::ParseEncodedLength(
- base::span<const uint8_t> input) {
- DCHECK_EQ(input.size(), SignedExchangePrologue::kEncodedLengthInBytes);
+constexpr size_t BeforeFallbackUrl::kEncodedSizeInBytes =
+ sizeof(kSignedExchangeMagic) + kFallbackUrlLengthFieldSizeInBytes;
+
+size_t Parse2BytesEncodedLength(base::span<const uint8_t> input) {
+ DCHECK_EQ(input.size(), 2u);
+ return static_cast<size_t>(input[0]) << 8 | static_cast<size_t>(input[1]);
+}
+
+size_t Parse3BytesEncodedLength(base::span<const uint8_t> input) {
+ DCHECK_EQ(input.size(), 3u);
return static_cast<size_t>(input[0]) << 16 |
static_cast<size_t>(input[1]) << 8 | static_cast<size_t>(input[2]);
}
// static
-base::Optional<SignedExchangePrologue> SignedExchangePrologue::Parse(
+BeforeFallbackUrl BeforeFallbackUrl::Parse(
base::span<const uint8_t> input,
SignedExchangeDevToolsProxy* devtools_proxy) {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"),
- "SignedExchangePrologue::Parse");
+ "signed_exchange_prologue::BeforeFallbackUrl::Parse");
- CHECK_EQ(input.size(), kEncodedPrologueInBytes);
+ CHECK_EQ(input.size(), kEncodedSizeInBytes);
const auto magic_string = input.subspan(0, sizeof(kSignedExchangeMagic));
- const auto encoded_signature_header_field_length =
- input.subspan(sizeof(kSignedExchangeMagic), kEncodedLengthInBytes);
- const auto encoded_cbor_header_length =
- input.subspan(sizeof(kSignedExchangeMagic) + kEncodedLengthInBytes,
- kEncodedLengthInBytes);
+ const auto encoded_fallback_url_length_field = input.subspan(
+ sizeof(kSignedExchangeMagic), kFallbackUrlLengthFieldSizeInBytes);
+ bool is_valid = true;
if (memcmp(magic_string.data(), kSignedExchangeMagic,
sizeof(kSignedExchangeMagic)) != 0) {
signed_exchange_utils::ReportErrorAndTraceEvent(devtools_proxy,
"Wrong magic string");
- return base::nullopt;
+ is_valid = false;
+ }
+
+ size_t fallback_url_length =
+ Parse2BytesEncodedLength(encoded_fallback_url_length_field);
+ return BeforeFallbackUrl(is_valid, fallback_url_length);
+}
+
+size_t BeforeFallbackUrl::ComputeFallbackUrlAndAfterLength() const {
+ return fallback_url_length_ + kSigLengthFieldLengthInBytes +
+ kHeaderLengthFieldLengthInBytes;
+}
+
+// static
+FallbackUrlAndAfter FallbackUrlAndAfter::ParseFailedButFallbackUrlAvailable(
+ GURL fallback_url) {
+ return FallbackUrlAndAfter(/*is_valid=*/false, std::move(fallback_url),
+ /*signature_header_field_length=*/0,
+ /*cbor_header_length=*/0);
+}
+
+// static
+FallbackUrlAndAfter FallbackUrlAndAfter::Parse(
+ base::span<const uint8_t> input,
+ const BeforeFallbackUrl& before_fallback_url,
+ SignedExchangeDevToolsProxy* devtools_proxy) {
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"),
+ "signed_exchange_prologue::FallbackUrlAndAfter::Parse");
+
+ if (input.size() < before_fallback_url.fallback_url_length()) {
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy,
+ "End of stream reached before reading the entire `fallbackUrl`.");
+ return FallbackUrlAndAfter();
+ }
+
+ base::StringPiece fallback_url_str(
+ reinterpret_cast<const char*>(input.data()),
+ before_fallback_url.fallback_url_length());
+ GURL fallback_url(fallback_url_str);
+
+ if (!fallback_url.is_valid()) {
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy, "Failed to parse `fallbackUrl`.");
+ return FallbackUrlAndAfter();
}
+ if (!fallback_url.SchemeIs(url::kHttpsScheme)) {
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy, "`fallbackUrl` in non-https scheme.");
+ return FallbackUrlAndAfter();
+ }
+ if (fallback_url.has_ref()) {
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy, ":url can't have a fragment.");
+ return FallbackUrlAndAfter();
+ }
+
+ // Note: For the code path after this comment, if parsing failed but
+ // the `fallbackUrl` parse had succeed, the return value can still be
+ // used for fallback redirect.
+
+ if (!before_fallback_url.is_valid())
+ return ParseFailedButFallbackUrlAvailable(fallback_url);
+
+ if (input.size() < before_fallback_url.ComputeFallbackUrlAndAfterLength()) {
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy,
+ "End of stream reached before reading `sigLength` and `headerLength` "
+ "fields.");
+ return ParseFailedButFallbackUrlAvailable(fallback_url);
+ }
+
+ const auto encoded_signature_header_field_length = input.subspan(
+ before_fallback_url.fallback_url_length(), kSigLengthFieldLengthInBytes);
+ const auto encoded_cbor_header_length = input.subspan(
+ before_fallback_url.fallback_url_length() + kSigLengthFieldLengthInBytes,
+ kHeaderLengthFieldLengthInBytes);
size_t signature_header_field_length =
- ParseEncodedLength(encoded_signature_header_field_length);
- size_t cbor_header_length = ParseEncodedLength(encoded_cbor_header_length);
+ Parse3BytesEncodedLength(encoded_signature_header_field_length);
+ size_t cbor_header_length =
+ Parse3BytesEncodedLength(encoded_cbor_header_length);
if (signature_header_field_length > kMaximumSignatureHeaderFieldLength) {
signed_exchange_utils::ReportErrorAndTraceEvent(
devtools_proxy,
base::StringPrintf("Signature header field too long: %zu",
signature_header_field_length));
- return base::nullopt;
+ return ParseFailedButFallbackUrlAvailable(fallback_url);
}
if (cbor_header_length > kMaximumCBORHeaderLength) {
signed_exchange_utils::ReportErrorAndTraceEvent(
devtools_proxy,
base::StringPrintf("CBOR header too long: %zu", cbor_header_length));
- return base::nullopt;
+ return ParseFailedButFallbackUrlAvailable(fallback_url);
}
- return SignedExchangePrologue(signature_header_field_length,
- cbor_header_length);
+ return FallbackUrlAndAfter(true, fallback_url, signature_header_field_length,
+ cbor_header_length);
}
-size_t SignedExchangePrologue::ComputeFollowingSectionsLength() const {
+size_t FallbackUrlAndAfter::signature_header_field_length() const {
+ DCHECK(is_valid());
+ return signature_header_field_length_;
+}
+
+size_t FallbackUrlAndAfter::cbor_header_length() const {
+ DCHECK(is_valid());
+ return cbor_header_length_;
+}
+
+size_t FallbackUrlAndAfter::ComputeFollowingSectionsLength() const {
+ DCHECK(is_valid());
return signature_header_field_length_ + cbor_header_length_;
}
+} // namespace signed_exchange_prologue
+
} // namespace content
diff --git a/chromium/content/browser/web_package/signed_exchange_prologue.h b/chromium/content/browser/web_package/signed_exchange_prologue.h
index 2106d417e42..1414e718cb1 100644
--- a/chromium/content/browser/web_package/signed_exchange_prologue.h
+++ b/chromium/content/browser/web_package/signed_exchange_prologue.h
@@ -11,64 +11,129 @@
#include "base/gtest_prod_util.h"
#include "base/optional.h"
#include "content/common/content_export.h"
+#include "url/gurl.h"
namespace content {
class SignedExchangeDevToolsProxy;
-// SignedExchangePrologue maps to the first bytes of
-// the "application/signed-exchange" format.
-// SignedExchangePrologue derives the lengths of the variable-length sections
-// following the prologue bytes.
-class CONTENT_EXPORT SignedExchangePrologue {
+// signed_exchange_prologue namespace contains parsers for the first bytes of
+// the "application/signed-exchange" format, preceding the cbor-encoded
+// response header.
+namespace signed_exchange_prologue {
+
+// Parse 2-byte encoded length of the variable-length field in the signed
+// exchange. Note: |input| must be pointing to a valid memory address that has
+// at least 2 bytes.
+CONTENT_EXPORT size_t Parse2BytesEncodedLength(base::span<const uint8_t> input);
+
+// Parse 3-byte encoded length of the variable-length field in the signed
+// exchange. Note: |input| must be pointing to a valid memory address that has
+// at least 3 bytes.
+CONTENT_EXPORT size_t Parse3BytesEncodedLength(base::span<const uint8_t> input);
+
+// BeforeFallbackUrl holds the decoded data from the first
+// |BeforeFallbackUrl::kEncodedSizeInBytes| bytes of the
+// "application/signed-exchange" format.
+class CONTENT_EXPORT BeforeFallbackUrl {
public:
- // Parse encoded length of the variable-length field in the signed exchange.
- // Note: |input| must be pointing to a valid memory address that has at least
- // |kEncodedLengthInBytes|.
- static size_t ParseEncodedLength(base::span<const uint8_t> input);
-
- // Size of the prologue bytes of the "application/signed-exchange" format
- // which maps to this class.
- static size_t kEncodedPrologueInBytes;
-
- // Parses the first bytes of the "application/signed-exchange" format.
- // |input| must be a valid span with length of kEncodedPrologueInBytes.
- // If success, returns the result. Otherwise, returns nullopt and
- // reports the error to |devtools_proxy|.
- static base::Optional<SignedExchangePrologue> Parse(
- base::span<const uint8_t> input,
- SignedExchangeDevToolsProxy* devtools_proxy);
-
- SignedExchangePrologue(size_t signature_header_field_length,
- size_t cbor_header_length)
- : signature_header_field_length_(signature_header_field_length),
- cbor_header_length_(cbor_header_length) {}
- SignedExchangePrologue(const SignedExchangePrologue&) = default;
- ~SignedExchangePrologue() = default;
+ // Size of the BeforeFallbackUrl part of "application/signed-exchange"
+ // prologue.
+ static const size_t kEncodedSizeInBytes;
+
+ BeforeFallbackUrl() = default;
+ BeforeFallbackUrl(bool is_valid, size_t fallback_url_length)
+ : is_valid_(is_valid), fallback_url_length_(fallback_url_length) {}
+ BeforeFallbackUrl(const BeforeFallbackUrl&) = default;
+ ~BeforeFallbackUrl() = default;
+
+ // Parses the first |kEncodedSizeInBytes| bytes of the
+ // "application/signed-exchange" format.
+ // |input| must be a valid span with length of |kEncodedSizeInBytes|.
+ // If success, returns a |is_valid()| result.
+ // Otherwise, returns a |!is_valid()| result and report the error to
+ // |devtools_proxy|.
+ static BeforeFallbackUrl Parse(base::span<const uint8_t> input,
+ SignedExchangeDevToolsProxy* devtools_proxy);
+
+ size_t ComputeFallbackUrlAndAfterLength() const;
+
+ // |is_valid()| returns false if magic string was invalid.
+ bool is_valid() const { return is_valid_; }
- size_t signature_header_field_length() const {
- return signature_header_field_length_;
- }
- size_t cbor_header_length() const { return cbor_header_length_; }
+ size_t fallback_url_length() const { return fallback_url_length_; }
+
+ private:
+ bool is_valid_ = false;
+
+ // Corresponds to `fallbackUrlLength` in the spec text.
+ // Encoded length of the Signature header field's value.
+ // https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html#application-signed-exchange
+ size_t fallback_url_length_ = 0;
+};
+
+class CONTENT_EXPORT FallbackUrlAndAfter {
+ public:
+ FallbackUrlAndAfter() = default;
+ FallbackUrlAndAfter(const FallbackUrlAndAfter&) = default;
+ ~FallbackUrlAndAfter() = default;
+
+ // Parses the bytes of the "application/signed-exchange" format,
+ // proceeding the BeforeFallbackUrl bytes.
+ // |input| must be a valid span with length of
+ // |before_fallback_url.ComputeFallbackUrlAndAfterLength()|.
+ // If success, returns a |is_valid()| result.
+ // Otherwise, returns a |!is_valid()| result and report the error to
+ // |devtools_proxy|.
+ static FallbackUrlAndAfter Parse(base::span<const uint8_t> input,
+ const BeforeFallbackUrl& before_fallback_url,
+ SignedExchangeDevToolsProxy* devtools_proxy);
+
+ bool is_valid() const { return is_valid_; }
+
+ // Note: fallback_url() may still be called even if |!is_valid()|,
+ // for trigering fallback redirect.
+ const GURL& fallback_url() const { return fallback_url_; }
+
+ size_t signature_header_field_length() const;
+ size_t cbor_header_length() const;
size_t ComputeFollowingSectionsLength() const;
private:
- FRIEND_TEST_ALL_PREFIXES(SignedExchangePrologueTest, ParseEncodedLength);
+ static FallbackUrlAndAfter ParseFailedButFallbackUrlAvailable(
+ GURL fallback_url);
+
+ FallbackUrlAndAfter(bool is_valid,
+ GURL fallback_url,
+ size_t signature_header_field_length,
+ size_t cbor_header_length)
+ : is_valid_(is_valid),
+ fallback_url_(std::move(fallback_url)),
+ signature_header_field_length_(signature_header_field_length),
+ cbor_header_length_(cbor_header_length) {}
+
+ bool is_valid_ = false;
- static constexpr size_t kEncodedLengthInBytes = 3;
+ // Corresponds to `fallbackUrl` in the spec text.
+ // The URL to redirect navigation to when the signed exchange processing steps
+ // has failed.
+ // https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html#application-signed-exchange
+ GURL fallback_url_;
// Corresponds to `sigLength` in the spec text.
// Encoded length of the Signature header field's value.
// https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html#application-signed-exchange
- size_t signature_header_field_length_;
+ size_t signature_header_field_length_ = 0;
// Corresponds to `headerLength` in the spec text.
// Length of the CBOR representation of the request and response headers.
// https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html#application-signed-exchange
- size_t cbor_header_length_;
+ size_t cbor_header_length_ = 0;
};
+} // namespace signed_exchange_prologue
+
} // namespace content
#endif // CONTENT_BROWSER_WEB_PACKAGE_SIGNED_EXCHANGE_PROLOGUE_H_
diff --git a/chromium/content/browser/web_package/signed_exchange_prologue_unittest.cc b/chromium/content/browser/web_package/signed_exchange_prologue_unittest.cc
index befb942e039..03febaea9d9 100644
--- a/chromium/content/browser/web_package/signed_exchange_prologue_unittest.cc
+++ b/chromium/content/browser/web_package/signed_exchange_prologue_unittest.cc
@@ -7,10 +7,26 @@
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
+namespace signed_exchange_prologue {
-TEST(SignedExchangePrologueTest, ParseEncodedLength) {
+TEST(SignedExchangePrologueTest, Parse2BytesEncodedLength) {
constexpr struct {
- uint8_t bytes[SignedExchangePrologue::kEncodedLengthInBytes];
+ uint8_t bytes[2];
+ size_t expected;
+ } kTestCases[] = {
+ {{0x00, 0x01}, 1u}, {{0xab, 0xcd}, 43981u},
+ };
+
+ int test_element_index = 0;
+ for (const auto& test_case : kTestCases) {
+ SCOPED_TRACE(testing::Message() << "testing case " << test_element_index++);
+ EXPECT_EQ(Parse2BytesEncodedLength(test_case.bytes), test_case.expected);
+ }
+}
+
+TEST(SignedExchangePrologueTest, Parse3BytesEncodedLength) {
+ constexpr struct {
+ uint8_t bytes[3];
size_t expected;
} kTestCases[] = {
{{0x00, 0x00, 0x01}, 1u}, {{0x01, 0xe2, 0x40}, 123456u},
@@ -19,45 +35,109 @@ TEST(SignedExchangePrologueTest, ParseEncodedLength) {
int test_element_index = 0;
for (const auto& test_case : kTestCases) {
SCOPED_TRACE(testing::Message() << "testing case " << test_element_index++);
- EXPECT_EQ(SignedExchangePrologue::ParseEncodedLength(test_case.bytes),
- test_case.expected);
+ EXPECT_EQ(Parse3BytesEncodedLength(test_case.bytes), test_case.expected);
}
}
-TEST(SignedExchangePrologueTest, Simple) {
- uint8_t bytes[] = {'s', 'x', 'g', '1', '-', 'b', '1',
- '\0', 0x00, 0x12, 0x34, 0x00, 0x23, 0x45};
+TEST(SignedExchangePrologueTest, BeforeFallbackUrl_Success) {
+ uint8_t bytes[] = {'s', 'x', 'g', '1', '-', 'b', '2', '\0', 0x12, 0x34};
+
+ BeforeFallbackUrl before_fallback_url = BeforeFallbackUrl::Parse(
+ base::make_span(bytes), nullptr /* devtools_proxy */);
+ EXPECT_TRUE(before_fallback_url.is_valid());
+ EXPECT_EQ(0x1234u, before_fallback_url.fallback_url_length());
+}
+
+TEST(SignedExchangePrologueTest, BeforeFallbackUrl_WrongMagic) {
+ uint8_t bytes[] = {'s', 'x', 'g', '!', '-', 'b', '2', '\0', 0x12, 0x34};
- auto prologue = SignedExchangePrologue::Parse(base::make_span(bytes),
- nullptr /* devtools_proxy */);
- EXPECT_TRUE(prologue);
- EXPECT_EQ(0x1234u, prologue->signature_header_field_length());
- EXPECT_EQ(0x2345u, prologue->cbor_header_length());
- EXPECT_EQ(0x3579u, prologue->ComputeFollowingSectionsLength());
+ BeforeFallbackUrl before_fallback_url = BeforeFallbackUrl::Parse(
+ base::make_span(bytes), nullptr /* devtools_proxy */);
+ EXPECT_FALSE(before_fallback_url.is_valid());
+ EXPECT_EQ(0x1234u, before_fallback_url.fallback_url_length());
}
-TEST(SignedExchangePrologueTest, WrongMagic) {
- uint8_t bytes[] = {'s', 'x', 'g', '!', '-', 'b', '1',
- '\0', 0x00, 0x12, 0x34, 0x00, 0x23, 0x45};
+TEST(SignedExchangePrologueTest, FallbackUrlAndAfter_Success) {
+ uint8_t bytes[] = {'h', 't', 't', 'p', 's', ':', '/', '/', 'e',
+ 'x', 'a', 'm', 'p', 'l', 'e', '.', 'c', 'o',
+ 'm', '/', 0x00, 0x12, 0x34, 0x00, 0x23, 0x45};
+
+ BeforeFallbackUrl before_fallback_url(true,
+ sizeof("https://example.com/") - 1);
+ EXPECT_TRUE(before_fallback_url.is_valid());
- EXPECT_FALSE(SignedExchangePrologue::Parse(base::make_span(bytes),
- nullptr /* devtools_proxy */));
+ FallbackUrlAndAfter fallback_url_and_after =
+ FallbackUrlAndAfter::Parse(base::make_span(bytes), before_fallback_url,
+ nullptr /* devtools_proxy */);
+
+ EXPECT_TRUE(fallback_url_and_after.is_valid());
+ EXPECT_EQ("https://example.com/",
+ fallback_url_and_after.fallback_url().spec());
+ EXPECT_EQ(0x1234u, fallback_url_and_after.signature_header_field_length());
+ EXPECT_EQ(0x2345u, fallback_url_and_after.cbor_header_length());
}
-TEST(SignedExchangePrologueTest, LongSignatureHeaderField) {
- uint8_t bytes[] = {'s', 'x', 'g', '1', '-', 'b', '1',
- '\0', 0xff, 0x12, 0x34, 0x00, 0x23, 0x45};
+TEST(SignedExchangePrologueTest, FallbackUrlAndAfter_NonHttpsUrl) {
+ uint8_t bytes[] = {'h', 't', 't', 'p', ':', '/', '/', 'e', 'x',
+ 'a', 'm', 'p', 'l', 'e', '.', 'c', 'o', 'm',
+ '/', 0x00, 0x12, 0x34, 0x00, 0x23, 0x45};
+
+ BeforeFallbackUrl before_fallback_url(true,
+ sizeof("http://example.com/") - 1);
+ FallbackUrlAndAfter fallback_url_and_after =
+ FallbackUrlAndAfter::Parse(base::make_span(bytes), before_fallback_url,
+ nullptr /* devtools_proxy */);
- EXPECT_FALSE(SignedExchangePrologue::Parse(base::make_span(bytes),
- nullptr /* devtools_proxy */));
+ EXPECT_FALSE(fallback_url_and_after.is_valid());
+ EXPECT_FALSE(fallback_url_and_after.fallback_url().is_valid());
}
-TEST(SignedExchangePrologueTest, LongCBORHeader) {
- uint8_t bytes[] = {'s', 'x', 'g', '1', '-', 'b', '1',
- '\0', 0x00, 0x12, 0x34, 0xff, 0x23, 0x45};
+TEST(SignedExchangePrologueTest, FallbackUrlAndAfter_UrlWithFragment) {
+ uint8_t bytes[] = {'h', 't', 't', 'p', 's', ':', '/', '/', 'e', 'x',
+ 'a', 'm', 'p', 'l', 'e', '.', 'c', 'o', 'm', '/',
+ '#', 'f', 'o', 'o', 0x00, 0x12, 0x34, 0x00, 0x23, 0x45};
+
+ BeforeFallbackUrl before_fallback_url(true,
+ sizeof("https://example.com/#foo") - 1);
+ FallbackUrlAndAfter fallback_url_and_after =
+ FallbackUrlAndAfter::Parse(base::make_span(bytes), before_fallback_url,
+ nullptr /* devtools_proxy */);
+
+ EXPECT_FALSE(fallback_url_and_after.is_valid());
+ EXPECT_FALSE(fallback_url_and_after.fallback_url().is_valid());
+}
+
+TEST(SignedExchangePrologueTest, FallbackUrlAndAfter_LongSignatureHeader) {
+ uint8_t bytes[] = {'h', 't', 't', 'p', 's', ':', '/', '/', 'e',
+ 'x', 'a', 'm', 'p', 'l', 'e', '.', 'c', 'o',
+ 'm', '/', 0xff, 0x12, 0x34, 0x00, 0x23, 0x45};
+
+ BeforeFallbackUrl before_fallback_url(true,
+ sizeof("https://example.com/") - 1);
+ FallbackUrlAndAfter fallback_url_and_after =
+ FallbackUrlAndAfter::Parse(base::make_span(bytes), before_fallback_url,
+ nullptr /* devtools_proxy */);
+
+ EXPECT_FALSE(fallback_url_and_after.is_valid());
+ EXPECT_EQ("https://example.com/",
+ fallback_url_and_after.fallback_url().spec());
+}
+
+TEST(SignedExchangePrologueTest, FallbackUrlAndAfter_LongCBORHeader) {
+ uint8_t bytes[] = {'h', 't', 't', 'p', 's', ':', '/', '/', 'e',
+ 'x', 'a', 'm', 'p', 'l', 'e', '.', 'c', 'o',
+ 'm', '/', 0x00, 0x12, 0x34, 0xff, 0x23, 0x45};
+
+ BeforeFallbackUrl before_fallback_url(true,
+ sizeof("https://example.com/") - 1);
+ FallbackUrlAndAfter fallback_url_and_after =
+ FallbackUrlAndAfter::Parse(base::make_span(bytes), before_fallback_url,
+ nullptr /* devtools_proxy */);
- EXPECT_FALSE(SignedExchangePrologue::Parse(base::make_span(bytes),
- nullptr /* devtools_proxy */));
+ EXPECT_FALSE(fallback_url_and_after.is_valid());
+ EXPECT_EQ("https://example.com/",
+ fallback_url_and_after.fallback_url().spec());
}
+} // namespace signed_exchange_prologue
} // namespace content
diff --git a/chromium/content/browser/web_package/signed_exchange_request_handler.cc b/chromium/content/browser/web_package/signed_exchange_request_handler.cc
index e5d33126395..97e0b1e0765 100644
--- a/chromium/content/browser/web_package/signed_exchange_request_handler.cc
+++ b/chromium/content/browser/web_package/signed_exchange_request_handler.cc
@@ -15,7 +15,6 @@
#include "content/public/common/content_features.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "net/http/http_response_headers.h"
-#include "net/url_request/url_request_context_getter.h"
#include "services/network/public/cpp/resource_response.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/mojom/url_loader.mojom.h"
@@ -39,8 +38,7 @@ SignedExchangeRequestHandler::SignedExchangeRequestHandler(
bool report_raw_headers,
int load_flags,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
- URLLoaderThrottlesGetter url_loader_throttles_getter,
- scoped_refptr<net::URLRequestContextGetter> request_context_getter)
+ URLLoaderThrottlesGetter url_loader_throttles_getter)
: request_initiator_(std::move(request_initiator)),
url_(url),
url_loader_options_(url_loader_options),
@@ -51,7 +49,6 @@ SignedExchangeRequestHandler::SignedExchangeRequestHandler(
load_flags_(load_flags),
url_loader_factory_(url_loader_factory),
url_loader_throttles_getter_(std::move(url_loader_throttles_getter)),
- request_context_getter_(std::move(request_context_getter)),
weak_factory_(this) {
DCHECK(signed_exchange_utils::IsSignedExchangeHandlingEnabled());
}
@@ -59,17 +56,19 @@ SignedExchangeRequestHandler::SignedExchangeRequestHandler(
SignedExchangeRequestHandler::~SignedExchangeRequestHandler() = default;
void SignedExchangeRequestHandler::MaybeCreateLoader(
- const network::ResourceRequest& resource_request,
+ const network::ResourceRequest& /* tentative_resource_request */,
ResourceContext* resource_context,
- LoaderCallback callback) {
- // TODO(https://crbug.com/803774): Ask WebPackageFetchManager to get the
- // ongoing matching SignedExchangeHandler which was created by a
- // WebPackagePrefetcher.
-
+ LoaderCallback callback,
+ FallbackCallback fallback_callback) {
if (!signed_exchange_loader_) {
std::move(callback).Run({});
return;
}
+ if (signed_exchange_loader_->HasRedirectedToFallbackURL()) {
+ signed_exchange_loader_ = nullptr;
+ std::move(callback).Run({});
+ return;
+ }
std::move(callback).Run(
base::BindOnce(&SignedExchangeRequestHandler::StartResponse,
@@ -81,6 +80,7 @@ bool SignedExchangeRequestHandler::MaybeCreateLoaderForResponse(
network::mojom::URLLoaderPtr* loader,
network::mojom::URLLoaderClientRequest* client_request,
ThrottlingURLLoader* url_loader) {
+ DCHECK(!signed_exchange_loader_);
if (!signed_exchange_utils::ShouldHandleAsSignedHTTPExchange(
request_initiator_.GetURL(), response)) {
return false;
@@ -89,23 +89,26 @@ bool SignedExchangeRequestHandler::MaybeCreateLoaderForResponse(
network::mojom::URLLoaderClientPtr client;
*client_request = mojo::MakeRequest(&client);
- // TODO(https://crbug.com/803774): Consider creating a new ThrottlingURLLoader
- // or reusing the existing ThrottlingURLLoader by reattaching URLLoaderClient,
- // to support SafeBrowsing checking of the content of the WebPackage.
+ // This lets the SignedExchangeLoader directly returns an artificial redirect
+ // to the downstream client without going through ThrottlingURLLoader, which
+ // means some checks like SafeBrowsing may not see the redirect. Given that
+ // the redirected request will be checked when it's restarted we suppose
+ // this is fine.
signed_exchange_loader_ = std::make_unique<SignedExchangeLoader>(
url_, response, std::move(client), url_loader->Unbind(),
- std::move(request_initiator_), url_loader_options_, load_flags_,
- throttling_profile_id_,
+ request_initiator_, url_loader_options_, load_flags_,
+ true /* should_redirect_to_fallback */, throttling_profile_id_,
std::make_unique<SignedExchangeDevToolsProxy>(
url_, response,
base::BindRepeating([](int id) { return id; }, frame_tree_node_id_),
- std::move(devtools_navigation_token_), report_raw_headers_),
- std::move(url_loader_factory_), std::move(url_loader_throttles_getter_),
- std::move(request_context_getter_));
+ devtools_navigation_token_, report_raw_headers_),
+ url_loader_factory_, url_loader_throttles_getter_,
+ base::BindRepeating([](int id) { return id; }, frame_tree_node_id_));
return true;
}
void SignedExchangeRequestHandler::StartResponse(
+ const network::ResourceRequest& resource_request,
network::mojom::URLLoaderRequest request,
network::mojom::URLLoaderClientPtr client) {
signed_exchange_loader_->ConnectToClient(std::move(client));
diff --git a/chromium/content/browser/web_package/signed_exchange_request_handler.h b/chromium/content/browser/web_package/signed_exchange_request_handler.h
index 02fbd7af3d5..b0037c69d84 100644
--- a/chromium/content/browser/web_package/signed_exchange_request_handler.h
+++ b/chromium/content/browser/web_package/signed_exchange_request_handler.h
@@ -12,10 +12,6 @@
#include "content/public/common/resource_type.h"
#include "url/origin.h"
-namespace net {
-class URLRequestContextGetter;
-} // namespace net
-
namespace network {
class SharedURLLoaderFactory;
} // namespace network
@@ -42,14 +38,15 @@ class SignedExchangeRequestHandler final : public NavigationLoaderInterceptor {
bool report_raw_headers,
int load_flags,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
- URLLoaderThrottlesGetter url_loader_throttles_getter,
- scoped_refptr<net::URLRequestContextGetter> request_context_getter);
+ URLLoaderThrottlesGetter url_loader_throttles_getter);
~SignedExchangeRequestHandler() override;
// NavigationLoaderInterceptor implementation
- void MaybeCreateLoader(const network::ResourceRequest& resource_request,
- ResourceContext* resource_context,
- LoaderCallback callback) override;
+ void MaybeCreateLoader(
+ const network::ResourceRequest& tentative_resource_request,
+ ResourceContext* resource_context,
+ LoaderCallback callback,
+ FallbackCallback fallback_callback) override;
bool MaybeCreateLoaderForResponse(
const network::ResourceResponseHead& response,
network::mojom::URLLoaderPtr* loader,
@@ -57,7 +54,8 @@ class SignedExchangeRequestHandler final : public NavigationLoaderInterceptor {
ThrottlingURLLoader* url_loader) override;
private:
- void StartResponse(network::mojom::URLLoaderRequest request,
+ void StartResponse(const network::ResourceRequest& resource_request,
+ network::mojom::URLLoaderRequest request,
network::mojom::URLLoaderClientPtr client);
// Valid after MaybeCreateLoaderForResponse intercepts the request and until
@@ -75,7 +73,6 @@ class SignedExchangeRequestHandler final : public NavigationLoaderInterceptor {
const int load_flags_;
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
URLLoaderThrottlesGetter url_loader_throttles_getter_;
- scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
base::WeakPtrFactory<SignedExchangeRequestHandler> weak_factory_;
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 a2251cab8ce..03a54596795 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
@@ -21,8 +21,8 @@
#include "content/public/common/content_paths.h"
#include "content/public/common/page_type.h"
#include "content/public/test/browser_test_utils.h"
-#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
+#include "content/public/test/content_cert_verifier_browser_test.h"
#include "content/public/test/test_navigation_throttle.h"
#include "content/public/test/url_loader_interceptor.h"
#include "content/shell/browser/shell.h"
@@ -44,38 +44,31 @@ namespace {
const uint64_t kSignatureHeaderDate = 1520834000; // 2018-03-12T05:53:20Z
-class NavigationFailureObserver : public WebContentsObserver {
+class RedirectObserver : public WebContentsObserver {
public:
- explicit NavigationFailureObserver(WebContents* web_contents)
+ explicit RedirectObserver(WebContents* web_contents)
: WebContentsObserver(web_contents) {}
- ~NavigationFailureObserver() override = default;
-
- void DidStartNavigation(NavigationHandle* handle) override {
- auto throttle = std::make_unique<TestNavigationThrottle>(handle);
- throttle->SetCallback(
- TestNavigationThrottle::WILL_FAIL_REQUEST,
- base::BindRepeating(&NavigationFailureObserver::OnWillFailRequestCalled,
- base::Unretained(this)));
- handle->RegisterThrottleForTesting(
- std::unique_ptr<TestNavigationThrottle>(std::move(throttle)));
+ ~RedirectObserver() override = default;
+
+ void DidRedirectNavigation(NavigationHandle* handle) override {
+ const net::HttpResponseHeaders* response = handle->GetResponseHeaders();
+ if (response)
+ response_code_ = response->response_code();
}
- bool did_fail() const { return did_fail_; }
+ const base::Optional<int>& response_code() const { return response_code_; }
private:
- void OnWillFailRequestCalled() { did_fail_ = true; }
-
- bool did_fail_ = false;
+ base::Optional<int> response_code_;
- DISALLOW_COPY_AND_ASSIGN(NavigationFailureObserver);
+ DISALLOW_COPY_AND_ASSIGN(RedirectObserver);
};
} // namespace
-class SignedExchangeRequestHandlerBrowserTest : public ContentBrowserTest {
+class SignedExchangeRequestHandlerBrowserTest : public CertVerifierBrowserTest {
public:
- SignedExchangeRequestHandlerBrowserTest()
- : mock_cert_verifier_(std::make_unique<net::MockCertVerifier>()) {
+ SignedExchangeRequestHandlerBrowserTest() {
// This installs "root_ca_cert.pem" from which our test certificates are
// created. (Needed for the tests that use real certificate, i.e.
// RealCertVerifier)
@@ -83,25 +76,22 @@ class SignedExchangeRequestHandlerBrowserTest : public ContentBrowserTest {
}
void SetUp() override {
- SignedExchangeHandler::SetCertVerifierForTesting(mock_cert_verifier_.get());
SignedExchangeHandler::SetVerificationTimeForTesting(
base::Time::UnixEpoch() +
base::TimeDelta::FromSeconds(kSignatureHeaderDate));
SetUpFeatures();
- ContentBrowserTest::SetUp();
+ CertVerifierBrowserTest::SetUp();
}
void TearDownOnMainThread() override {
interceptor_.reset();
- SignedExchangeHandler::SetCertVerifierForTesting(nullptr);
SignedExchangeHandler::SetVerificationTimeForTesting(
base::Optional<base::Time>());
}
protected:
virtual void SetUpFeatures() {
- feature_list_.InitWithFeatures({features::kSignedHTTPExchange},
- {network::features::kNetworkService});
+ feature_list_.InitWithFeatures({features::kSignedHTTPExchange}, {});
}
static scoped_refptr<net::X509Certificate> LoadCertificate(
@@ -132,12 +122,10 @@ class SignedExchangeRequestHandlerBrowserTest : public ContentBrowserTest {
}
base::test::ScopedFeatureList feature_list_;
- std::unique_ptr<net::MockCertVerifier> mock_cert_verifier_;
private:
static void InstallMockInterceptors(const GURL& url,
const std::string& data_path) {
- DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
base::FilePath root_path;
CHECK(base::PathService::Get(base::DIR_SOURCE_ROOT, &root_path));
net::URLRequestFilter::GetInstance()->AddUrlInterceptor(
@@ -146,7 +134,6 @@ class SignedExchangeRequestHandlerBrowserTest : public ContentBrowserTest {
}
bool OnInterceptCallback(URLLoaderInterceptor::RequestParams* params) {
- DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService));
const auto it = interceptor_data_path_map_.find(params->url_request.url);
if (it == interceptor_data_path_map_.end())
return false;
@@ -160,15 +147,6 @@ class SignedExchangeRequestHandlerBrowserTest : public ContentBrowserTest {
DISALLOW_COPY_AND_ASSIGN(SignedExchangeRequestHandlerBrowserTest);
};
-class SignedExchangeRequestHandlerWithNetworkServiceBrowserTest
- : public SignedExchangeRequestHandlerBrowserTest {
- void SetUpFeatures() override {
- feature_list_.InitWithFeatures(
- {features::kSignedHTTPExchange, network::features::kNetworkService},
- {});
- }
-};
-
IN_PROC_BROWSER_TEST_F(SignedExchangeRequestHandlerBrowserTest, Simple) {
InstallUrlInterceptor(
GURL("https://cert.example.org/cert.msg"),
@@ -183,7 +161,7 @@ IN_PROC_BROWSER_TEST_F(SignedExchangeRequestHandlerBrowserTest, Simple) {
dummy_result.cert_status = net::OK;
dummy_result.ocsp_result.response_status = net::OCSPVerifyResult::PROVIDED;
dummy_result.ocsp_result.revocation_status = net::OCSPRevocationStatus::GOOD;
- mock_cert_verifier_->AddResultForCertAndHost(
+ mock_cert_verifier()->AddResultForCertAndHost(
original_cert, "test.example.org", dummy_result, net::OK);
embedded_test_server()->RegisterRequestMonitor(
@@ -191,7 +169,7 @@ IN_PROC_BROWSER_TEST_F(SignedExchangeRequestHandlerBrowserTest, Simple) {
if (request.relative_url == "/sxg/test.example.org_test.sxg") {
const auto& accept_value = request.headers.find("accept")->second;
EXPECT_THAT(accept_value,
- ::testing::HasSubstr("application/signed-exchange;v=b1"));
+ ::testing::HasSubstr("application/signed-exchange;v=b2"));
}
}));
embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
@@ -199,8 +177,11 @@ IN_PROC_BROWSER_TEST_F(SignedExchangeRequestHandlerBrowserTest, Simple) {
GURL url = embedded_test_server()->GetURL("/sxg/test.example.org_test.sxg");
base::string16 title = base::ASCIIToUTF16("https://test.example.org/test/");
TitleWatcher title_watcher(shell()->web_contents(), title);
+ RedirectObserver redirect_observer(shell()->web_contents());
+
NavigateToURL(shell(), url);
EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
+ EXPECT_EQ(303, redirect_observer.response_code());
NavigationEntry* entry =
shell()->web_contents()->GetController().GetVisibleEntry();
@@ -226,6 +207,8 @@ IN_PROC_BROWSER_TEST_F(SignedExchangeRequestHandlerBrowserTest,
InstallUrlInterceptor(
GURL("https://cert.example.org/cert.msg"),
"content/test/data/sxg/test.example.org.public.pem.cbor");
+ InstallUrlInterceptor(GURL("https://test.example.org/test/"),
+ "content/test/data/sxg/fallback.html");
// Make the MockCertVerifier treat the certificate
// "prime256v1-sha256.public.pem" as valid for "test.example.org".
@@ -236,7 +219,7 @@ IN_PROC_BROWSER_TEST_F(SignedExchangeRequestHandlerBrowserTest,
dummy_result.cert_status = net::OK;
dummy_result.ocsp_result.response_status = net::OCSPVerifyResult::PROVIDED;
dummy_result.ocsp_result.revocation_status = net::OCSPRevocationStatus::GOOD;
- mock_cert_verifier_->AddResultForCertAndHost(
+ mock_cert_verifier()->AddResultForCertAndHost(
original_cert, "test.example.org", dummy_result, net::OK);
embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
@@ -244,76 +227,79 @@ IN_PROC_BROWSER_TEST_F(SignedExchangeRequestHandlerBrowserTest,
GURL url = embedded_test_server()->GetURL(
"/sxg/test.example.org_test_invalid_content_type.sxg");
- NavigationFailureObserver failure_observer(shell()->web_contents());
+ base::string16 title = base::ASCIIToUTF16("Fallback URL response");
+ TitleWatcher title_watcher(shell()->web_contents(), title);
+ RedirectObserver redirect_observer(shell()->web_contents());
NavigateToURL(shell(), url);
- EXPECT_TRUE(failure_observer.did_fail());
- NavigationEntry* entry =
- shell()->web_contents()->GetController().GetVisibleEntry();
- EXPECT_EQ(PAGE_TYPE_ERROR, entry->GetPageType());
+ EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
+ EXPECT_EQ(303, redirect_observer.response_code());
}
-IN_PROC_BROWSER_TEST_F(SignedExchangeRequestHandlerBrowserTest, CertNotFound) {
- InstallUrlInterceptor(GURL("https://cert.example.org/cert.msg"),
- "content/test/data/sxg/404.msg");
+IN_PROC_BROWSER_TEST_F(SignedExchangeRequestHandlerBrowserTest,
+ RedirectBrokenSignedExchanges) {
+ InstallUrlInterceptor(GURL("https://test.example.org/test/"),
+ "content/test/data/sxg/fallback.html");
embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
ASSERT_TRUE(embedded_test_server()->Start());
- GURL url = embedded_test_server()->GetURL("/sxg/test.example.org_test.sxg");
- NavigationFailureObserver failure_observer(shell()->web_contents());
- NavigateToURL(shell(), url);
- EXPECT_TRUE(failure_observer.did_fail());
- NavigationEntry* entry =
- shell()->web_contents()->GetController().GetVisibleEntry();
- EXPECT_EQ(PAGE_TYPE_ERROR, entry->GetPageType());
-}
+ constexpr const char* kBrokenExchanges[] = {
+ "/sxg/test.example.org_test_invalid_magic_string.sxg",
+ "/sxg/test.example.org_test_invalid_cbor_header.sxg",
+ };
-IN_PROC_BROWSER_TEST_F(
- SignedExchangeRequestHandlerWithNetworkServiceBrowserTest,
- NetworkServiceEnabled) {
- InstallUrlInterceptor(
- GURL("https://test.example.org/cert.msg"),
- "content/test/data/sxg/test.example.org.public.pem.cbor");
+ for (const auto* broken_exchange : kBrokenExchanges) {
+ SCOPED_TRACE(testing::Message()
+ << "testing broken exchange: " << broken_exchange);
- // Make the MockCertVerifier treat the certificate
- // "prime256v1-sha256.public.pem" as valid for "test.example.org".
- scoped_refptr<net::X509Certificate> original_cert =
- LoadCertificate("prime256v1-sha256.public.pem");
- net::CertVerifyResult dummy_result;
- dummy_result.verified_cert = original_cert;
- dummy_result.cert_status = net::OK;
- dummy_result.ocsp_result.response_status = net::OCSPVerifyResult::PROVIDED;
- dummy_result.ocsp_result.revocation_status = net::OCSPRevocationStatus::GOOD;
- mock_cert_verifier_->AddResultForCertAndHost(
- original_cert, "test.example.org", dummy_result, net::OK);
+ GURL url = embedded_test_server()->GetURL(broken_exchange);
+
+ base::string16 title = base::ASCIIToUTF16("Fallback URL response");
+ TitleWatcher title_watcher(shell()->web_contents(), title);
+ NavigateToURL(shell(), url);
+ EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
+ }
+}
+
+IN_PROC_BROWSER_TEST_F(SignedExchangeRequestHandlerBrowserTest, CertNotFound) {
+ InstallUrlInterceptor(GURL("https://cert.example.org/cert.msg"),
+ "content/test/data/sxg/404.msg");
+ InstallUrlInterceptor(GURL("https://test.example.org/test/"),
+ "content/test/data/sxg/fallback.html");
embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
ASSERT_TRUE(embedded_test_server()->Start());
GURL url = embedded_test_server()->GetURL("/sxg/test.example.org_test.sxg");
- NavigationFailureObserver failure_observer(shell()->web_contents());
+ base::string16 title = base::ASCIIToUTF16("Fallback URL response");
+ TitleWatcher title_watcher(shell()->web_contents(), title);
NavigateToURL(shell(), url);
- EXPECT_TRUE(failure_observer.did_fail());
- NavigationEntry* entry =
- shell()->web_contents()->GetController().GetVisibleEntry();
- EXPECT_EQ(PAGE_TYPE_ERROR, entry->GetPageType());
+ EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
}
-IN_PROC_BROWSER_TEST_F(SignedExchangeRequestHandlerBrowserTest,
- RealCertVerifier) {
+class SignedExchangeRequestHandlerRealCertVerifierBrowserTest
+ : public SignedExchangeRequestHandlerBrowserTest {
+ public:
+ SignedExchangeRequestHandlerRealCertVerifierBrowserTest() {
+ // Use "real" CertVerifier.
+ disable_mock_cert_verifier();
+ }
+};
+
+IN_PROC_BROWSER_TEST_F(SignedExchangeRequestHandlerRealCertVerifierBrowserTest,
+ Basic) {
InstallUrlInterceptor(
GURL("https://cert.example.org/cert.msg"),
"content/test/data/sxg/test.example.org.public.pem.cbor");
-
- // Use "real" CertVerifier.
- SignedExchangeHandler::SetCertVerifierForTesting(nullptr);
+ InstallUrlInterceptor(GURL("https://test.example.org/test/"),
+ "content/test/data/sxg/fallback.html");
embedded_test_server()->RegisterRequestMonitor(
base::BindRepeating([](const net::test_server::HttpRequest& request) {
if (request.relative_url == "/sxg/test.example.org_test.sxg") {
const auto& accept_value = request.headers.find("accept")->second;
EXPECT_THAT(accept_value,
- ::testing::HasSubstr("application/signed-exchange;v=b1"));
+ ::testing::HasSubstr("application/signed-exchange;v=b2"));
}
}));
embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
@@ -330,18 +316,17 @@ IN_PROC_BROWSER_TEST_F(SignedExchangeRequestHandlerBrowserTest,
"*OCSP*");
shell()->web_contents()->SetDelegate(&console_observer);
- NavigationFailureObserver failure_observer(shell()->web_contents());
+ base::string16 title = base::ASCIIToUTF16("Fallback URL response");
+ TitleWatcher title_watcher(shell()->web_contents(), title);
NavigateToURL(shell(), url);
- EXPECT_TRUE(failure_observer.did_fail());
- NavigationEntry* entry =
- shell()->web_contents()->GetController().GetVisibleEntry();
- EXPECT_EQ(PAGE_TYPE_ERROR, entry->GetPageType());
+ EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
// Verify that it failed at the OCSP check step.
// TODO(https://crbug.com/803774): Find a better way than matching against the
// error message. We can probably make DevToolsProxy derive some context from
// StoragePartition so that we can record and extract the detailed error
// status for testing via that.
+ console_observer.Wait();
EXPECT_TRUE(base::StartsWith(console_observer.message(), "OCSP check failed.",
base::CompareCase::SENSITIVE));
}
diff --git a/chromium/content/browser/web_package/signed_exchange_signature_header_field.cc b/chromium/content/browser/web_package/signed_exchange_signature_header_field.cc
index b7bcef2acae..f6e3cfdeb81 100644
--- a/chromium/content/browser/web_package/signed_exchange_signature_header_field.cc
+++ b/chromium/content/browser/web_package/signed_exchange_signature_header_field.cc
@@ -294,8 +294,8 @@ bool SignedExchangeSignatureHeaderField::GetVersionParamFromContentType(
if (it == parameterised_identifier.params.end()) {
*version_param = base::nullopt;
} else {
- if (it->second == "b1")
- *version_param = SignedExchangeVersion::kB1;
+ if (it->second == "b2")
+ *version_param = SignedExchangeVersion::kB2;
else
return false;
}
diff --git a/chromium/content/browser/web_package/signed_exchange_signature_header_field_unittest.cc b/chromium/content/browser/web_package/signed_exchange_signature_header_field_unittest.cc
index d47655171a9..e34fd133926 100644
--- a/chromium/content/browser/web_package/signed_exchange_signature_header_field_unittest.cc
+++ b/chromium/content/browser/web_package/signed_exchange_signature_header_field_unittest.cc
@@ -300,34 +300,34 @@ TEST_F(SignedExchangeSignatureHeaderFieldTest, VersionParam_EmptyString) {
}
TEST_F(SignedExchangeSignatureHeaderFieldTest, VersionParam_Simple) {
- const char content_type[] = "application/signed-exchange;v=b1";
+ const char content_type[] = "application/signed-exchange;v=b2";
base::Optional<SignedExchangeVersion> version;
EXPECT_TRUE(
SignedExchangeSignatureHeaderField::GetVersionParamFromContentType(
content_type, &version));
ASSERT_TRUE(version);
- EXPECT_EQ(*version, SignedExchangeVersion::kB1);
+ EXPECT_EQ(*version, SignedExchangeVersion::kB2);
}
TEST_F(SignedExchangeSignatureHeaderFieldTest, VersionParam_SimpleWithSpace) {
- const char content_type[] = "application/signed-exchange; v=b1";
+ const char content_type[] = "application/signed-exchange; v=b2";
base::Optional<SignedExchangeVersion> version;
EXPECT_TRUE(
SignedExchangeSignatureHeaderField::GetVersionParamFromContentType(
content_type, &version));
ASSERT_TRUE(version);
- EXPECT_EQ(*version, SignedExchangeVersion::kB1);
+ EXPECT_EQ(*version, SignedExchangeVersion::kB2);
}
TEST_F(SignedExchangeSignatureHeaderFieldTest,
VersionParam_SimpleWithDoublequotes) {
- const char content_type[] = "application/signed-exchange;v=\"b1\"";
+ const char content_type[] = "application/signed-exchange;v=\"b2\"";
base::Optional<SignedExchangeVersion> version;
EXPECT_TRUE(
SignedExchangeSignatureHeaderField::GetVersionParamFromContentType(
content_type, &version));
ASSERT_TRUE(version);
- EXPECT_EQ(*version, SignedExchangeVersion::kB1);
+ EXPECT_EQ(*version, SignedExchangeVersion::kB2);
}
} // namespace content
diff --git a/chromium/content/browser/web_package/signed_exchange_signature_verifier.cc b/chromium/content/browser/web_package/signed_exchange_signature_verifier.cc
index e29e5c8cf49..f19306b6f9a 100644
--- a/chromium/content/browser/web_package/signed_exchange_signature_verifier.cc
+++ b/chromium/content/browser/web_package/signed_exchange_signature_verifier.cc
@@ -4,6 +4,7 @@
#include "content/browser/web_package/signed_exchange_signature_verifier.h"
+#include "base/big_endian.h"
#include "base/containers/span.h"
#include "base/format_macros.h"
#include "base/strings/string_number_conversions.h"
@@ -30,20 +31,20 @@ namespace content {
namespace {
// https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html#signature-validity
-// Step 7. "Let message be the concatenation of the following byte strings."
+// Step 5. "Let message be the concatenation of the following byte strings."
constexpr uint8_t kMessageHeader[] =
- // 7.1. "A string that consists of octet 32 (0x20) repeated 64 times."
+ // 5.1. "A string that consists of octet 32 (0x20) repeated 64 times."
// [spec text]
"\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"
"\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"
"\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"
"\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"
- // 7.2. "A context string: the ASCII encoding of "HTTP Exchange 1"." ...
+ // 5.2. "A context string: the ASCII encoding of "HTTP Exchange 1"." ...
// "but implementations of drafts MUST NOT use it and MUST use another
// draft-specific string beginning with "HTTP Exchange 1 " instead."
// [spec text]
- // 7.3. "A single 0 byte which serves as a separator." [spec text]
- "HTTP Exchange 1 b1";
+ // 5.3. "A single 0 byte which serves as a separator." [spec text]
+ "HTTP Exchange 1 b2";
base::Optional<cbor::CBORValue> GenerateCanonicalRequestCBOR(
const SignedExchangeEnvelope& envelope) {
@@ -94,56 +95,6 @@ base::Optional<cbor::CBORValue> GenerateCanonicalExchangeHeadersCBOR(
return cbor::CBORValue(array);
}
-// Generate a CBOR map value as specified in
-// https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html#signature-validity
-// Step 7.4.
-base::Optional<cbor::CBORValue> GenerateSignedMessageCBOR(
- const SignedExchangeEnvelope& envelope) {
- auto headers_val = GenerateCanonicalExchangeHeadersCBOR(envelope);
- if (!headers_val)
- return base::nullopt;
-
- // 7.4. "The bytes of the canonical CBOR serialization (Section 3.4) of
- // a CBOR map mapping:" [spec text]
- cbor::CBORValue::MapValue map;
- // 7.4.1. "If cert-sha256 is set: The text string "cert-sha256" to the byte
- // string value of cert-sha256." [spec text]
- if (envelope.signature().cert_sha256.has_value()) {
- map.insert_or_assign(
- cbor::CBORValue(kCertSha256Key),
- cbor::CBORValue(
- base::StringPiece(reinterpret_cast<const char*>(
- envelope.signature().cert_sha256->data),
- sizeof(envelope.signature().cert_sha256->data)),
- cbor::CBORValue::Type::BYTE_STRING));
- }
- // 7.4.2. "The text string "validity-url" to the byte string value of
- // validity-url." [spec text]
- map.insert_or_assign(cbor::CBORValue(kValidityUrlKey),
- cbor::CBORValue(envelope.signature().validity_url.spec(),
- cbor::CBORValue::Type::BYTE_STRING));
- // 7.4.3. "The text string "date" to the integer value of date." [spec text]
- if (!base::IsValueInRangeForNumericType<int64_t>(envelope.signature().date))
- return base::nullopt;
-
- map.insert_or_assign(
- cbor::CBORValue(kDateKey),
- cbor::CBORValue(base::checked_cast<int64_t>(envelope.signature().date)));
- // 7.4.4. "The text string "expires" to the integer value of expires."
- // [spec text]
- if (!base::IsValueInRangeForNumericType<int64_t>(
- envelope.signature().expires))
- return base::nullopt;
-
- map.insert_or_assign(cbor::CBORValue(kExpiresKey),
- cbor::CBORValue(base::checked_cast<int64_t>(
- envelope.signature().expires)));
- // 7.4.5. "The text string "headers" to the CBOR representation
- // (Section 3.2) of exchange's headers." [spec text]
- map.insert_or_assign(cbor::CBORValue(kHeadersKey), std::move(*headers_val));
- return cbor::CBORValue(map);
-}
-
base::Optional<crypto::SignatureVerifier::SignatureAlgorithm>
GetSignatureAlgorithm(scoped_refptr<net::X509Certificate> cert,
SignedExchangeDevToolsProxy* devtools_proxy) {
@@ -217,40 +168,62 @@ std::string HexDump(const std::vector<uint8_t>& msg) {
return output;
}
+void AppendToBuf8BytesBigEndian(std::vector<uint8_t>* buf, uint64_t n) {
+ char encoded[8];
+ base::WriteBigEndian(encoded, n);
+ buf->insert(buf->end(), std::begin(encoded), std::end(encoded));
+}
+
base::Optional<std::vector<uint8_t>> GenerateSignedMessage(
const SignedExchangeEnvelope& envelope) {
TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("loading"),
"GenerateSignedMessage");
- // GenerateSignedMessageCBOR corresponds to Step 7.4.
- base::Optional<cbor::CBORValue> cbor_val =
- GenerateSignedMessageCBOR(envelope);
- if (!cbor_val) {
- TRACE_EVENT_END1(TRACE_DISABLED_BY_DEFAULT("loading"),
- "GenerateSignedMessage", "error",
- "GenerateSignedMessageCBOR failed.");
- return base::nullopt;
- }
-
- base::Optional<std::vector<uint8_t>> cbor_message =
- cbor::CBORWriter::Write(*cbor_val);
- if (!cbor_message) {
- TRACE_EVENT_END1(TRACE_DISABLED_BY_DEFAULT("loading"),
- "GenerateSignedMessage", "error",
- "CBORWriter::Write failed.");
- return base::nullopt;
- }
+ const auto signature = envelope.signature();
// https://wicg.github.io/webpackage/draft-yasskin-httpbis-origin-signed-exchanges-impl.html#signature-validity
- // Step 7. "Let message be the concatenation of the following byte strings."
+ // Step 5. "Let message be the concatenation of the following byte strings."
std::vector<uint8_t> message;
- // see kMessageHeader for Steps 7.1 to 7.3.
- message.reserve(arraysize(kMessageHeader) + cbor_message->size());
+ // see kMessageHeader for Steps 5.1 to 5.3.
message.insert(message.end(), std::begin(kMessageHeader),
std::end(kMessageHeader));
- // 7.4. "The bytes of the canonical CBOR serialization (Section 3.4) of
- // a CBOR map mapping:" [spec text]
- message.insert(message.end(), cbor_message->begin(), cbor_message->end());
+
+ // Step 5.4. "If cert-sha256 is set, a byte holding the value 32 followed by
+ // the 32 bytes of the value of cert-sha256. Otherwise a 0 byte." [spec text]
+ // Note: cert-sha256 must be set for application/signed-exchange envelope
+ // format.
+ message.push_back(32);
+ const auto& cert_sha256 = envelope.signature().cert_sha256.value();
+ message.insert(message.end(), std::begin(cert_sha256.data),
+ std::end(cert_sha256.data));
+
+ // Step 5.5. "The 8-byte big-endian encoding of the length in bytes of
+ // validity-url, followed by the bytes of validity-url." [spec text]
+ const auto& validity_url_spec = signature.validity_url.spec();
+ AppendToBuf8BytesBigEndian(&message, validity_url_spec.size());
+ message.insert(message.end(), std::begin(validity_url_spec),
+ std::end(validity_url_spec));
+
+ // Step 5.6. "The 8-byte big-endian encoding of date." [spec text]
+ AppendToBuf8BytesBigEndian(&message, signature.date);
+
+ // Step 5.7. "The 8-byte big-endian encoding of expires." [spec text]
+ AppendToBuf8BytesBigEndian(&message, signature.expires);
+
+ // Step 5.8. "The 8-byte big-endian encoding of the length in bytes of
+ // requestUrl, followed by the bytes of requestUrl." [spec text]
+ const auto& request_url_spec = envelope.request_url().spec();
+
+ AppendToBuf8BytesBigEndian(&message, request_url_spec.size());
+ message.insert(message.end(), std::begin(request_url_spec),
+ std::end(request_url_spec));
+
+ // Step 5.9. "The 8-byte big-endian encoding of the length in bytes of
+ // headers, followed by the bytes of headers." [spec text]
+ AppendToBuf8BytesBigEndian(&message, envelope.cbor_header().size());
+ message.insert(message.end(), envelope.cbor_header().begin(),
+ envelope.cbor_header().end());
+
TRACE_EVENT_END1(TRACE_DISABLED_BY_DEFAULT("loading"),
"GenerateSignedMessage", "dump", HexDump(message));
return message;
@@ -260,7 +233,7 @@ base::Time TimeFromSignedExchangeUnixTime(uint64_t t) {
return base::Time::UnixEpoch() + base::TimeDelta::FromSeconds(t);
}
-// Implements steps 5-6 of
+// Implements steps 3-4 of
// https://wicg.github.io/webpackage/draft-yasskin-httpbis-origin-signed-exchanges-impl.html#signature-validity
bool VerifyTimestamps(const SignedExchangeEnvelope& envelope,
const base::Time& verification_time) {
@@ -269,12 +242,12 @@ bool VerifyTimestamps(const SignedExchangeEnvelope& envelope,
base::Time creation_time =
TimeFromSignedExchangeUnixTime(envelope.signature().date);
- // 5. "If expires is more than 7 days (604800 seconds) after date, return
+ // 3. "If expires is more than 7 days (604800 seconds) after date, return
// "invalid"." [spec text]
if ((expires_time - creation_time).InSeconds() > 604800)
return false;
- // 6. "If the current time is before date or after expires, return
+ // 4. "If the current time is before date or after expires, return
// "invalid"."
if (verification_time < creation_time || expires_time < verification_time)
return false;
@@ -347,10 +320,11 @@ SignedExchangeSignatureVerifier::Result SignedExchangeSignatureVerifier::Verify(
}
if (!base::EqualsCaseInsensitiveASCII(envelope.signature().integrity,
- "mi-draft2")) {
+ "digest/mi-sha256-03")) {
signed_exchange_utils::ReportErrorAndTraceEvent(
devtools_proxy,
- "The current implemention only supports \"mi\" integrity scheme.");
+ "The current implemention only supports \"digest/mi-sha256-03\" "
+ "integrity scheme.");
return Result::kErrInvalidSignatureIntegrity;
}
return Result::kSuccess;
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 9dbab4e6422..25a6ab70296 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
@@ -20,7 +20,7 @@ TEST(SignedExchangeSignatureVerifier, EncodeCanonicalExchangeHeaders) {
envelope.set_request_url(GURL("https://example.com/index.html"));
envelope.set_response_code(net::HTTP_OK);
envelope.AddResponseHeader("content-type", "text/html; charset=utf-8");
- envelope.AddResponseHeader("content-encoding", "mi-sha256-draft2");
+ envelope.AddResponseHeader("content-encoding", "mi-sha256-03");
base::Optional<std::vector<uint8_t>> encoded =
SignedExchangeSignatureVerifier::EncodeCanonicalExchangeHeaders(envelope);
@@ -51,9 +51,9 @@ TEST(SignedExchangeSignatureVerifier, EncodeCanonicalExchangeHeaders) {
0x50, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x65, 0x6e,
0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, // bytes "content-encoding"
- 0x50, 0x6d, 0x69, 0x2d, 0x73, 0x68, 0x61, 0x32, 0x35, 0x36, 0x2d,
- 0x64, 0x72, 0x61, 0x66, 0x74, 0x32
- // bytes "mi-sha256-draft2"
+ 0x4c, 0x6d, 0x69, 0x2d, 0x73, 0x68, 0x61, 0x32, 0x35, 0x36, 0x2d,
+ 0x30, 0x33
+ // bytes "mi-sha256-03"
// clang-format on
};
EXPECT_THAT(*encoded,
@@ -65,9 +65,25 @@ const uint64_t kSignatureHeaderExpires = 1517895941;
// See content/testdata/sxg/README on how to generate these data.
// clang-format off
-constexpr char kSignatureHeaderRSA[] = R"(label; sig=*yYFb09i7VXuqsGBxc3RuJzGL4XMD9bZ20kXWSv1JObEf7KIG0MznSE1nu1fE+7DrgWQxH7FQfSWjyseOAvxsBOfkptmCCi/Ffklz3N1UU8LfwfaLWj80oBqDeofiIYwevSSpsaRKBYie7KjiVOjslFLOGe82MmHyF2utFRKY/i6UAHgMrg2FGfbwBaJsxEgtpPcN8/QnFKgt1la+JjwvYbMHpJhHTedDqx9GCxJOzbJjKRL1E2tIBvhDfK2m3eJv/nqvgWkK3MOd/Xp4FkndciS3eNyZZjwvJ6IL/3x4e0AZ36KvglpS092ZftiE4lKQWnHmVeDRmEHW6qOyv1Q3+w==*; validity-url="https://example.com/resource.validity.msg"; integrity="mi-draft2"; cert-url="https://example.com/cert.msg"; cert-sha256=*tJGJP8ej7KCEW8VnVK3bKwpBza/oLrtWA75z5ZPptuc=*; date=1517892341; expires=1517895941)";
-constexpr char kSignatureHeaderECDSAP256[] = R"(label; sig=*MEQCIA0w6auOuWGT6//MO/h43/xkXBchJUOp53GU5dmA8U+/AiAe0FggCblVxzosT2Ow9rrC2Q8zO0DZPLSNbcu29xYP6g==*; validity-url="https://example.com/resource.validity.msg"; integrity="mi-draft2"; cert-url="https://example.com/cert.msg"; cert-sha256=*KX+BYLSMgDOON8Ju65RoId39Qvajxa12HO+WnD4HpS0=*; date=1517892341; expires=1517895941)";
-constexpr char kSignatureHeaderECDSAP384[] = R"(label; sig=*MGYCMQC/P8m0ZnPrIMlI3I412MixcK9cQSirIECUNR7pOIlTiLaH95L72KXqq2aL+lxxKIICMQDU3s/BhoWtR61eKG9SqgGHd0ZtUJVY24xaJ2yHiYWxZU/QhOr5ZArSj3x1khivpRg=*; validity-url="https://example.com/resource.validity.msg"; integrity="mi-draft2"; cert-url="https://example.com/cert.msg"; cert-sha256=*8X8y8nj8vDJHSSa0cxn+TCu+8zGpIJfbdzAnd5cW+jA=*; date=1517892341; expires=1517895941)";
+constexpr char kSignatureHeaderRSA[] = R"(label; sig=*DDeXzJshGnPT+ei1rS1KmZx+QLwwLTbNKDVSmTb2HjGfgPngv+C+uMbjZiliOmGe0b514JcAlYAM57t0kZY2FPd9JdqwYPIiAWEwxByfV2iXBbsGZNWGtS/AAq1SaPwIMfrzdLXAFbKbtTRhS7B5LHCo/6hEIXu0TJJFbv5fKaLgTTLF0AK5dV0/En0uz+bnVARuBIH/ez2gPEFc6KbGnTTp8LYcCe/YjlHQy/Oac28ACBtn70rP1TerWEaYBwMMDckJ2gfsVyLqMcFtJqV0uGLT6Atb2wBSUZlZDTEZf228362r+EHLrADAuhz4bdSMKFsFgWyceOriDyHhc0PSwQ==*; validity-url="https://example.com/resource.validity.msg"; integrity="digest/mi-sha256-03"; cert-url="https://example.com/cert.msg"; cert-sha256=*tJGJP8ej7KCEW8VnVK3bKwpBza/oLrtWA75z5ZPptuc=*; date=1517892341; expires=1517895941)";
+constexpr char kSignatureHeaderECDSAP256[] = R"(label; sig=*MEUCIQC7tM/B6YxVgrJmgfFawtwBKPev2vFCh7amR+JTDBMgTQIga9LkS51vteYr8NWPTCSZRy10lcLaFNN9m1G3OBS9lBs=*; validity-url="https://example.com/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 uint8_t kCborHeadersECDSAP256[] = {
+ 0x82, 0xa1, 0x47, 0x3a, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x43, 0x47,
+ 0x45, 0x54, 0xa4, 0x46, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x58, 0x39,
+ 0x6d, 0x69, 0x2d, 0x73, 0x68, 0x61, 0x32, 0x35, 0x36, 0x2d, 0x30, 0x33,
+ 0x3d, 0x77, 0x6d, 0x70, 0x34, 0x64, 0x52, 0x4d, 0x59, 0x67, 0x78, 0x50,
+ 0x33, 0x74, 0x53, 0x4d, 0x43, 0x77, 0x56, 0x2f, 0x49, 0x30, 0x43, 0x57,
+ 0x4f, 0x43, 0x69, 0x48, 0x5a, 0x70, 0x41, 0x69, 0x68, 0x4b, 0x5a, 0x6b,
+ 0x31, 0x39, 0x62, 0x73, 0x4e, 0x39, 0x52, 0x49, 0x3d, 0x47, 0x3a, 0x73,
+ 0x74, 0x61, 0x74, 0x75, 0x73, 0x43, 0x32, 0x30, 0x30, 0x4c, 0x63, 0x6f,
+ 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x58, 0x18,
+ 0x74, 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3b, 0x20, 0x63,
+ 0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3d, 0x75, 0x74, 0x66, 0x2d, 0x38,
+ 0x50, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x65, 0x6e, 0x63,
+ 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x4c, 0x6d, 0x69, 0x2d, 0x73, 0x68, 0x61,
+ 0x32, 0x35, 0x36, 0x2d, 0x30, 0x33
+};
+constexpr char kSignatureHeaderECDSAP384[] = R"(label; sig=*MGUCMQDm3+Mf3ymTQOF2EUFk+NDIpOIqbFCboYsPD9YOV9rpayKTmAXzUD7Hxtp+XP/8mQECMEfTRcJmvL9QMAMKuDIzQqy/ib8MPeJHap9kQVQT1OdROaYj4EISngkJeT5om9/YlA==*; validity-url="https://example.com/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)";
// clang-format on
// |expires| (1518497142) is more than 7 days (604800 seconds) after |date|
@@ -255,10 +271,9 @@ TEST_F(SignedExchangeSignatureVerifierTest, VerifyRSA) {
envelope.set_request_url(GURL("https://test.example.org/test/"));
envelope.set_response_code(net::HTTP_OK);
envelope.AddResponseHeader("content-type", "text/html; charset=utf-8");
- envelope.AddResponseHeader("content-encoding", "mi-sha256-draft2");
+ envelope.AddResponseHeader("content-encoding", "mi-sha256-03");
envelope.AddResponseHeader(
- "mi-draft2",
- "mi-sha256-draft2=wmp4dRMYgxP3tSMCwV_I0CWOCiHZpAihKZk19bsN9RI");
+ "digest", "mi-sha256-03=wmp4dRMYgxP3tSMCwV/I0CWOCiHZpAihKZk19bsN9RI=");
envelope.SetSignatureForTesting((*signature)[0]);
EXPECT_EQ(SignedExchangeSignatureVerifier::Result::kErrUnsupportedCertType,
@@ -284,10 +299,10 @@ TEST_F(SignedExchangeSignatureVerifierTest, VerifyECDSAP256) {
envelope.set_request_url(GURL("https://test.example.org/test/"));
envelope.set_response_code(net::HTTP_OK);
envelope.AddResponseHeader("content-type", "text/html; charset=utf-8");
- envelope.AddResponseHeader("content-encoding", "mi-sha256-draft2");
+ envelope.AddResponseHeader("content-encoding", "mi-sha256-03");
envelope.AddResponseHeader(
- "mi-draft2",
- "mi-sha256-draft2=wmp4dRMYgxP3tSMCwV_I0CWOCiHZpAihKZk19bsN9RI");
+ "digest", "mi-sha256-03=wmp4dRMYgxP3tSMCwV/I0CWOCiHZpAihKZk19bsN9RI=");
+ envelope.set_cbor_header(base::make_span(kCborHeadersECDSAP256));
envelope.SetSignatureForTesting((*signature)[0]);
@@ -311,10 +326,9 @@ TEST_F(SignedExchangeSignatureVerifierTest, VerifyECDSAP384) {
envelope.set_request_url(GURL("https://test.example.org/test/"));
envelope.set_response_code(net::HTTP_OK);
envelope.AddResponseHeader("content-type", "text/html; charset=utf-8");
- envelope.AddResponseHeader("content-encoding", "mi-sha256-draft2");
+ envelope.AddResponseHeader("content-encoding", "mi-sha256-03");
envelope.AddResponseHeader(
- "mi-draft2",
- "mi-sha256-draft2=wmp4dRMYgxP3tSMCwV_I0CWOCiHZpAihKZk19bsN9RIG");
+ "digest", "mi-sha256-03=wmp4dRMYgxP3tSMCwV/I0CWOCiHZpAihKZk19bsN9RIG=");
envelope.SetSignatureForTesting((*signature)[0]);
diff --git a/chromium/content/browser/webauth/authenticator_impl.cc b/chromium/content/browser/webauth/authenticator_impl.cc
index 80b95998948..b2ffb181123 100644
--- a/chromium/content/browser/webauth/authenticator_impl.cc
+++ b/chromium/content/browser/webauth/authenticator_impl.cc
@@ -18,6 +18,7 @@
#include "content/browser/bad_message.h"
#include "content/browser/webauth/authenticator_type_converters.h"
#include "content/public/browser/authenticator_request_client_delegate.h"
+#include "content/public/browser/browser_context.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_frame_host.h"
@@ -30,6 +31,7 @@
#include "content/public/common/service_manager_connection.h"
#include "crypto/sha2.h"
#include "device/base/features.h"
+#include "device/bluetooth/bluetooth_adapter_factory.h"
#include "device/fido/authenticator_selection_criteria.h"
#include "device/fido/ctap_get_assertion_request.h"
#include "device/fido/ctap_make_credential_request.h"
@@ -218,8 +220,7 @@ device::CtapGetAssertionRequest CreateCtapGetAssertionRequest(
if (!options->cable_authentication_data.empty()) {
request_parameter.SetCableExtension(
- mojo::ConvertTo<
- std::vector<device::FidoCableDiscovery::CableDiscoveryData>>(
+ mojo::ConvertTo<std::vector<device::CableDiscoveryData>>(
options->cable_authentication_data));
}
return request_parameter;
@@ -280,7 +281,7 @@ CreateMakeCredentialResponse(
blink::mojom::GetAssertionAuthenticatorResponsePtr CreateGetAssertionResponse(
const std::string& client_data_json,
device::AuthenticatorGetAssertionResponse response_data,
- bool echo_appid_extension) {
+ base::Optional<bool> echo_appid_extension) {
auto response = blink::mojom::GetAssertionAuthenticatorResponse::New();
auto common_info = blink::mojom::CommonCredentialInfo::New();
common_info->client_data_json.assign(client_data_json.begin(),
@@ -291,7 +292,10 @@ blink::mojom::GetAssertionAuthenticatorResponsePtr CreateGetAssertionResponse(
response->authenticator_data =
response_data.auth_data().SerializeToByteArray();
response->signature = response_data.signature();
- response->echo_appid_extension = echo_appid_extension;
+ if (echo_appid_extension) {
+ response->echo_appid_extension = true;
+ response->appid_extension = *echo_appid_extension;
+ }
response_data.user_entity()
? response->user_handle.emplace(response_data.user_entity()->user_id())
: response->user_handle.emplace();
@@ -307,6 +311,32 @@ std::string Base64UrlEncode(const base::span<const uint8_t> input) {
return ret;
}
+base::flat_set<device::FidoTransportProtocol> GetTransportsEnabledByFlags() {
+ base::flat_set<device::FidoTransportProtocol> transports;
+ transports.insert(device::FidoTransportProtocol::kUsbHumanInterfaceDevice);
+ transports.insert(device::FidoTransportProtocol::kInternal);
+
+ // TODO(crbug.com/885165): We should not directly access the BLE stack here.
+ // It is used by //device/fido, so its availability should be checked there.
+ if (!device::BluetoothAdapterFactory::Get().IsLowEnergySupported())
+ return transports;
+
+ if (base::FeatureList::IsEnabled(features::kWebAuthBle)) {
+ transports.insert(device::FidoTransportProtocol::kBluetoothLowEnergy);
+ }
+
+#if defined(OS_WIN)
+ if (base::FeatureList::IsEnabled(features::kWebAuthCable) &&
+ base::FeatureList::IsEnabled(features::kWebAuthCableWin)) {
+#else
+ if (base::FeatureList::IsEnabled(features::kWebAuthCable)) {
+#endif // defined(OS_WIN)
+ transports.insert(
+ device::FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy);
+ }
+ return transports;
+}
+
} // namespace
AuthenticatorImpl::AuthenticatorImpl(RenderFrameHost* render_frame_host)
@@ -320,21 +350,12 @@ AuthenticatorImpl::AuthenticatorImpl(RenderFrameHost* render_frame_host,
: WebContentsObserver(WebContents::FromRenderFrameHost(render_frame_host)),
render_frame_host_(render_frame_host),
connector_(connector),
+ transports_(GetTransportsEnabledByFlags()),
timer_(std::move(timer)),
binding_(this),
weak_factory_(this) {
DCHECK(render_frame_host_);
DCHECK(timer_);
-
- protocols_.insert(device::FidoTransportProtocol::kUsbHumanInterfaceDevice);
- if (base::FeatureList::IsEnabled(features::kWebAuthBle)) {
- protocols_.insert(device::FidoTransportProtocol::kBluetoothLowEnergy);
- }
-
- if (base::FeatureList::IsEnabled(features::kWebAuthCable)) {
- protocols_.insert(
- device::FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy);
- }
}
AuthenticatorImpl::~AuthenticatorImpl() {
@@ -354,6 +375,13 @@ void AuthenticatorImpl::Bind(blink::mojom::AuthenticatorRequest request) {
binding_.Bind(std::move(request));
}
+void AuthenticatorImpl::UpdateRequestDelegate() {
+ DCHECK(!request_delegate_);
+ request_delegate_ =
+ GetContentClient()->browser()->GetWebAuthenticationRequestDelegate(
+ render_frame_host_);
+}
+
bool AuthenticatorImpl::IsFocused() const {
return render_frame_host_->IsCurrent() && request_delegate_->IsFocused();
}
@@ -362,38 +390,16 @@ bool AuthenticatorImpl::IsFocused() const {
std::string AuthenticatorImpl::SerializeCollectedClientDataToJson(
const std::string& type,
const url::Origin& origin,
- base::span<const uint8_t> challenge,
- base::Optional<base::span<const uint8_t>> token_binding) {
+ base::span<const uint8_t> challenge) {
static constexpr char kTypeKey[] = "type";
static constexpr char kChallengeKey[] = "challenge";
static constexpr char kOriginKey[] = "origin";
- static constexpr char kTokenBindingKey[] = "tokenBinding";
base::DictionaryValue client_data;
client_data.SetKey(kTypeKey, base::Value(type));
client_data.SetKey(kChallengeKey, base::Value(Base64UrlEncode(challenge)));
client_data.SetKey(kOriginKey, base::Value(origin.Serialize()));
- if (token_binding) {
- base::DictionaryValue token_binding_dict;
- static constexpr char kTokenBindingStatusKey[] = "status";
- static constexpr char kTokenBindingIdKey[] = "id";
- static constexpr char kTokenBindingSupportedStatus[] = "supported";
- static constexpr char kTokenBindingPresentStatus[] = "present";
-
- if (token_binding->empty()) {
- token_binding_dict.SetKey(kTokenBindingStatusKey,
- base::Value(kTokenBindingSupportedStatus));
- } else {
- token_binding_dict.SetKey(kTokenBindingStatusKey,
- base::Value(kTokenBindingPresentStatus));
- token_binding_dict.SetKey(kTokenBindingIdKey,
- base::Value(Base64UrlEncode(*token_binding)));
- }
-
- client_data.SetKey(kTokenBindingKey, std::move(token_binding_dict));
- }
-
if (base::RandDouble() < 0.2) {
// An extra key is sometimes added to ensure that RPs do not make
// unreasonably specific assumptions about the clientData JSON. This is
@@ -419,10 +425,7 @@ void AuthenticatorImpl::MakeCredential(
return;
}
- DCHECK(!request_delegate_);
- request_delegate_ =
- GetContentClient()->browser()->GetWebAuthenticationRequestDelegate(
- render_frame_host_);
+ UpdateRequestDelegate();
if (!request_delegate_) {
InvokeCallbackAndCleanup(std::move(callback),
blink::mojom::AuthenticatorStatus::PENDING_REQUEST,
@@ -460,11 +463,10 @@ void AuthenticatorImpl::MakeCredential(
DCHECK(make_credential_response_callback_.is_null());
make_credential_response_callback_ = std::move(callback);
- request_delegate_->DidStartRequest();
timer_->Start(
FROM_HERE, options->adjusted_timeout,
- base::Bind(&AuthenticatorImpl::OnTimeout, base::Unretained(this)));
+ base::BindOnce(&AuthenticatorImpl::OnTimeout, base::Unretained(this)));
if (!connector_)
connector_ = ServiceManagerConnection::GetForProcess()->GetConnector();
@@ -472,8 +474,7 @@ void AuthenticatorImpl::MakeCredential(
// TODO(kpaulhamus): Fetch and add the Token Binding ID public key used to
// communicate with the origin.
client_data_json_ = SerializeCollectedClientDataToJson(
- client_data::kCreateType, caller_origin, std::move(options->challenge),
- base::nullopt);
+ client_data::kCreateType, caller_origin, std::move(options->challenge));
const bool individual_attestation =
options->attestation ==
@@ -482,11 +483,6 @@ void AuthenticatorImpl::MakeCredential(
attestation_preference_ = options->attestation;
- // Communication using Cable protocol is only supported for GetAssertion
- // request on CTAP2 devices.
- protocols_.erase(
- device::FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy);
-
auto authenticator_selection_criteria =
options->authenticator_selection
? mojo::ConvertTo<device::AuthenticatorSelectionCriteria>(
@@ -494,15 +490,27 @@ void AuthenticatorImpl::MakeCredential(
: device::AuthenticatorSelectionCriteria();
request_ = std::make_unique<device::MakeCredentialRequestHandler>(
- connector_, protocols_,
+ connector_, transports_,
CreateCtapMakeCredentialRequest(
ConstructClientDataHash(client_data_json_), options,
individual_attestation),
std::move(authenticator_selection_criteria),
base::BindOnce(&AuthenticatorImpl::OnRegisterResponse,
- weak_factory_.GetWeakPtr()),
- base::BindOnce(&AuthenticatorImpl::MaybeCreatePlatformAuthenticator,
- base::Unretained(this)));
+ weak_factory_.GetWeakPtr()));
+
+ request_delegate_->RegisterActionCallbacks(
+ base::BindOnce(&AuthenticatorImpl::Cancel,
+ weak_factory_.GetWeakPtr()) /* cancel_callback */,
+ base::BindRepeating(
+ &device::FidoRequestHandlerBase::StartAuthenticatorRequest,
+ request_->GetWeakPtr()) /* request_callback */,
+ base::BindRepeating(
+ &device::FidoRequestHandlerBase::PowerOnBluetoothAdapter,
+ request_->GetWeakPtr()) /* bluetooth_adapter_power_on_callback */);
+ request_->set_observer(request_delegate_.get());
+
+ request_->SetPlatformAuthenticatorOrMarkUnavailable(
+ CreatePlatformAuthenticatorIfAvailable());
}
// mojom:Authenticator
@@ -515,10 +523,7 @@ void AuthenticatorImpl::GetAssertion(
return;
}
- DCHECK(!request_delegate_);
- request_delegate_ =
- GetContentClient()->browser()->GetWebAuthenticationRequestDelegate(
- render_frame_host_);
+ UpdateRequestDelegate();
if (!request_delegate_) {
InvokeCallbackAndCleanup(std::move(callback),
blink::mojom::AuthenticatorStatus::PENDING_REQUEST,
@@ -546,28 +551,22 @@ void AuthenticatorImpl::GetAssertion(
return;
}
- base::Optional<std::array<uint8_t, crypto::kSHA256Length>>
- alternative_application_parameter;
if (options->appid) {
- auto appid_hash = ProcessAppIdExtension(*options->appid, caller_origin);
- if (!appid_hash) {
+ alternative_application_parameter_ =
+ ProcessAppIdExtension(*options->appid, caller_origin);
+ if (!alternative_application_parameter_) {
std::move(callback).Run(blink::mojom::AuthenticatorStatus::INVALID_DOMAIN,
nullptr);
return;
}
-
- alternative_application_parameter = std::move(appid_hash);
- // TODO(agl): needs a test once a suitable, mock U2F device exists.
- echo_appid_extension_ = true;
}
DCHECK(get_assertion_response_callback_.is_null());
get_assertion_response_callback_ = std::move(callback);
- request_delegate_->DidStartRequest();
timer_->Start(
FROM_HERE, options->adjusted_timeout,
- base::Bind(&AuthenticatorImpl::OnTimeout, base::Unretained(this)));
+ base::BindOnce(&AuthenticatorImpl::OnTimeout, base::Unretained(this)));
if (!connector_)
connector_ = ServiceManagerConnection::GetForProcess()->GetConnector();
@@ -576,27 +575,58 @@ void AuthenticatorImpl::GetAssertion(
// TODO(kpaulhamus): Fetch and add the Token Binding ID public key used to
// communicate with the origin.
client_data_json_ = SerializeCollectedClientDataToJson(
- client_data::kGetType, caller_origin, std::move(options->challenge),
- base::nullopt);
+ client_data::kGetType, caller_origin, std::move(options->challenge));
+
+ auto ctap_request = CreateCtapGetAssertionRequest(
+ ConstructClientDataHash(client_data_json_), std::move(options),
+ alternative_application_parameter_);
+ auto opt_platform_authenticator_info =
+ CreatePlatformAuthenticatorIfAvailableAndCheckIfCredentialExists(
+ ctap_request);
request_ = std::make_unique<device::GetAssertionRequestHandler>(
- connector_, protocols_,
- CreateCtapGetAssertionRequest(
- ConstructClientDataHash(client_data_json_), std::move(options),
- std::move(alternative_application_parameter)),
+ connector_, transports_, std::move(ctap_request),
base::BindOnce(&AuthenticatorImpl::OnSignResponse,
- weak_factory_.GetWeakPtr()),
- base::BindOnce(&AuthenticatorImpl::MaybeCreatePlatformAuthenticator,
- base::Unretained(this)));
+ weak_factory_.GetWeakPtr()));
+
+ request_delegate_->RegisterActionCallbacks(
+ base::BindOnce(&AuthenticatorImpl::Cancel,
+ weak_factory_.GetWeakPtr()) /* cancel_callback */,
+ base::BindRepeating(
+ &device::FidoRequestHandlerBase::StartAuthenticatorRequest,
+ request_->GetWeakPtr()) /* request_callback */,
+ base::BindRepeating(
+ &device::FidoRequestHandlerBase::PowerOnBluetoothAdapter,
+ request_->GetWeakPtr()) /* bluetooth_adapter_power_on_callback */);
+ request_->set_observer(request_delegate_.get());
+
+ request_->SetPlatformAuthenticatorOrMarkUnavailable(
+ std::move(opt_platform_authenticator_info));
}
void AuthenticatorImpl::IsUserVerifyingPlatformAuthenticatorAvailable(
IsUserVerifyingPlatformAuthenticatorAvailableCallback callback) {
- bool result = false;
+ const bool result = IsUserVerifyingPlatformAuthenticatorAvailableImpl();
+ base::SequencedTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(std::move(callback), result));
+}
+
+bool AuthenticatorImpl::IsUserVerifyingPlatformAuthenticatorAvailableImpl() {
#if defined(OS_MACOSX)
- result = device::fido::mac::TouchIdAuthenticator::IsAvailable();
+ // Touch ID is disabled, regardless of hardware support, if the embedder
+ // doesn't support it or if this is an Incognito session. N.B.
+ // request_delegate_ may be nullptr at this point.
+ if (!GetContentClient()
+ ->browser()
+ ->IsWebAuthenticationTouchIdAuthenticatorSupported() ||
+ browser_context()->IsOffTheRecord()) {
+ return false;
+ }
+
+ return device::fido::mac::TouchIdAuthenticator::IsAvailable();
+#else
+ return false;
#endif
- std::move(callback).Run(result);
}
void AuthenticatorImpl::DidFinishNavigation(
@@ -619,7 +649,8 @@ void AuthenticatorImpl::DidFinishNavigation(
// Callback to handle the async registration response from a U2fDevice.
void AuthenticatorImpl::OnRegisterResponse(
device::FidoReturnCode status_code,
- base::Optional<device::AuthenticatorMakeCredentialResponse> response_data) {
+ base::Optional<device::AuthenticatorMakeCredentialResponse> response_data,
+ device::FidoTransportProtocol transport_used) {
if (!request_) {
// Either the callback was called immediately and |request_| has not yet
// been assigned (this is a bug), or a navigation caused the request to be
@@ -632,6 +663,10 @@ void AuthenticatorImpl::OnRegisterResponse(
// Duplicate registration: the new credential would be created on an
// authenticator that already contains one of the credentials in
// |exclude_credentials|.
+ DCHECK(request_delegate_);
+ request_delegate_->DidFailWithInterestingReason(
+ AuthenticatorRequestClientDelegate::InterestingFailureReason::
+ kKeyAlreadyRegistered);
InvokeCallbackAndCleanup(
std::move(make_credential_response_callback_),
blink::mojom::AuthenticatorStatus::CREDENTIAL_EXCLUDED, nullptr,
@@ -645,10 +680,18 @@ void AuthenticatorImpl::OnRegisterResponse(
Focus::kDoCheck);
return;
case device::FidoReturnCode::kUserConsentButCredentialNotRecognized:
+ // TODO(crbug/876109): This isn't strictly unreachable.
NOTREACHED();
return;
+ case device::FidoReturnCode::kUserConsentDenied:
+ InvokeCallbackAndCleanup(
+ std::move(make_credential_response_callback_),
+ blink::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR, nullptr,
+ Focus::kDoCheck);
+ return;
case device::FidoReturnCode::kSuccess:
DCHECK(response_data.has_value());
+ request_delegate_->UpdateLastTransportUsed(transport_used);
if (attestation_preference_ !=
blink::mojom::AttestationConveyancePreference::NONE) {
@@ -660,7 +703,10 @@ void AuthenticatorImpl::OnRegisterResponse(
return;
}
- response_data->EraseAttestationStatement();
+ if (!response_data->IsSelfAttestation()) {
+ response_data->EraseAttestationStatement();
+ }
+
InvokeCallbackAndCleanup(
std::move(make_credential_response_callback_),
blink::mojom::AuthenticatorStatus::SUCCESS,
@@ -722,7 +768,8 @@ void AuthenticatorImpl::OnRegisterResponseAttestationDecided(
void AuthenticatorImpl::OnSignResponse(
device::FidoReturnCode status_code,
- base::Optional<device::AuthenticatorGetAssertionResponse> response_data) {
+ base::Optional<device::AuthenticatorGetAssertionResponse> response_data,
+ device::FidoTransportProtocol transport_used) {
if (!request_) {
// Either the callback was called immediately and |request_| has not yet
// been assigned (this is a bug), or a navigation caused the request to be
@@ -733,6 +780,10 @@ void AuthenticatorImpl::OnSignResponse(
switch (status_code) {
case device::FidoReturnCode::kUserConsentButCredentialNotRecognized:
// No authenticators contained the credential.
+ DCHECK(request_delegate_);
+ request_delegate_->DidFailWithInterestingReason(
+ AuthenticatorRequestClientDelegate::InterestingFailureReason::
+ kKeyNotRegistered);
InvokeCallbackAndCleanup(
std::move(get_assertion_response_callback_),
blink::mojom::AuthenticatorStatus::CREDENTIAL_NOT_RECOGNIZED,
@@ -745,24 +796,35 @@ void AuthenticatorImpl::OnSignResponse(
blink::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR, nullptr);
return;
case device::FidoReturnCode::kUserConsentButCredentialExcluded:
+ // TODO(crbug/876109): This isn't strictly unreachable.
NOTREACHED();
return;
+ case device::FidoReturnCode::kUserConsentDenied:
+ InvokeCallbackAndCleanup(
+ std::move(get_assertion_response_callback_),
+ blink::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR, nullptr);
+ return;
case device::FidoReturnCode::kSuccess:
DCHECK(response_data.has_value());
+ request_delegate_->UpdateLastTransportUsed(transport_used);
+
+ base::Optional<bool> echo_appid_extension;
+ if (alternative_application_parameter_) {
+ echo_appid_extension = (response_data->GetRpIdHash() ==
+ *alternative_application_parameter_);
+ }
InvokeCallbackAndCleanup(
std::move(get_assertion_response_callback_),
blink::mojom::AuthenticatorStatus::SUCCESS,
CreateGetAssertionResponse(std::move(client_data_json_),
std::move(*response_data),
- echo_appid_extension_));
+ echo_appid_extension));
return;
}
NOTREACHED();
}
-void AuthenticatorImpl::OnTimeout() {
- // TODO(crbug.com/814418): Add layout tests to verify timeouts are
- // indistinguishable from NOT_ALLOWED_ERROR cases.
+void AuthenticatorImpl::FailWithNotAllowedErrorAndCleanup() {
DCHECK(make_credential_response_callback_ ||
get_assertion_response_callback_);
if (make_credential_response_callback_) {
@@ -777,6 +839,24 @@ void AuthenticatorImpl::OnTimeout() {
}
}
+void AuthenticatorImpl::OnTimeout() {
+ DCHECK(request_delegate_);
+ request_delegate_->DidFailWithInterestingReason(
+ AuthenticatorRequestClientDelegate::InterestingFailureReason::kTimeout);
+
+ // TODO(crbug.com/814418): Add layout tests to verify timeouts are
+ // indistinguishable from NOT_ALLOWED_ERROR cases.
+ FailWithNotAllowedErrorAndCleanup();
+}
+
+void AuthenticatorImpl::Cancel() {
+ // If response callback is invoked already, then ignore cancel request.
+ if (!make_credential_response_callback_ && !get_assertion_response_callback_)
+ return;
+
+ FailWithNotAllowedErrorAndCleanup();
+}
+
void AuthenticatorImpl::InvokeCallbackAndCleanup(
MakeCredentialCallback callback,
blink::mojom::AuthenticatorStatus status,
@@ -807,21 +887,65 @@ void AuthenticatorImpl::Cleanup() {
make_credential_response_callback_.Reset();
get_assertion_response_callback_.Reset();
client_data_json_.clear();
- echo_appid_extension_ = false;
+ alternative_application_parameter_.reset();
+}
+
+BrowserContext* AuthenticatorImpl::browser_context() const {
+ return content::WebContents::FromRenderFrameHost(render_frame_host_)
+ ->GetBrowserContext();
}
-std::unique_ptr<device::FidoAuthenticator>
-AuthenticatorImpl::MaybeCreatePlatformAuthenticator() {
#if defined(OS_MACOSX)
+namespace {
+std::unique_ptr<device::fido::mac::TouchIdAuthenticator>
+CreateTouchIdAuthenticatorIfAvailable(
+ const AuthenticatorRequestClientDelegate* request_delegate) {
+ // Not all embedders may provide an authenticator config.
auto opt_authenticator_config =
- request_delegate_->GetTouchIdAuthenticatorConfig();
- if (opt_authenticator_config) {
- return device::fido::mac::TouchIdAuthenticator::CreateIfAvailable(
- std::move(opt_authenticator_config->keychain_access_group),
- std::move(opt_authenticator_config->metadata_secret));
- }
-#endif // defined(OS_MACOSX)
- return nullptr;
+ request_delegate->GetTouchIdAuthenticatorConfig();
+ if (!opt_authenticator_config) {
+ return nullptr;
+ }
+ return device::fido::mac::TouchIdAuthenticator::CreateIfAvailable(
+ std::move(opt_authenticator_config->keychain_access_group),
+ std::move(opt_authenticator_config->metadata_secret));
+}
+} // namespace
+#endif
+
+base::Optional<device::PlatformAuthenticatorInfo>
+AuthenticatorImpl::CreatePlatformAuthenticatorIfAvailable() {
+ // Incognito mode disables platform authenticators, so check for availability
+ // first.
+ if (!IsUserVerifyingPlatformAuthenticatorAvailableImpl()) {
+ return base::nullopt;
+ }
+#if defined(OS_MACOSX)
+ return device::PlatformAuthenticatorInfo(
+ CreateTouchIdAuthenticatorIfAvailable(request_delegate_.get()), false);
+#else
+ return base::nullopt;
+#endif
+}
+
+base::Optional<device::PlatformAuthenticatorInfo> AuthenticatorImpl::
+ CreatePlatformAuthenticatorIfAvailableAndCheckIfCredentialExists(
+ const device::CtapGetAssertionRequest& request) {
+ // Incognito mode disables platform authenticators, so check for availability
+ // first.
+ if (!IsUserVerifyingPlatformAuthenticatorAvailableImpl()) {
+ return base::nullopt;
+ }
+#if defined(OS_MACOSX)
+ std::unique_ptr<device::fido::mac::TouchIdAuthenticator> authenticator =
+ CreateTouchIdAuthenticatorIfAvailable(request_delegate_.get());
+ const bool has_credential =
+ authenticator->HasCredentialForGetAssertionRequest(request);
+ return device::PlatformAuthenticatorInfo(std::move(authenticator),
+ has_credential);
+#else
+ return base::nullopt;
+#endif
}
} // namespace content
diff --git a/chromium/content/browser/webauth/authenticator_impl.h b/chromium/content/browser/webauth/authenticator_impl.h
index 538b06b559c..df8cdf26eb4 100644
--- a/chromium/content/browser/webauth/authenticator_impl.h
+++ b/chromium/content/browser/webauth/authenticator_impl.h
@@ -16,12 +16,13 @@
#include "base/optional.h"
#include "content/common/content_export.h"
#include "content/public/browser/web_contents_observer.h"
+#include "crypto/sha2.h"
#include "device/fido/authenticator_get_assertion_response.h"
#include "device/fido/authenticator_make_credential_response.h"
#include "device/fido/fido_constants.h"
#include "device/fido/fido_transport_protocol.h"
#include "mojo/public/cpp/bindings/binding.h"
-#include "third_party/blink/public/platform/modules/webauth/authenticator.mojom.h"
+#include "third_party/blink/public/platform/modules/webauthn/authenticator.mojom.h"
#include "url/origin.h"
namespace base {
@@ -30,7 +31,8 @@ class OneShotTimer;
namespace device {
-class FidoAuthenticator;
+struct PlatformAuthenticatorInfo;
+class CtapGetAssertionRequest;
class FidoRequestHandlerBase;
enum class FidoReturnCode : uint8_t;
@@ -48,6 +50,7 @@ class Origin;
namespace content {
class AuthenticatorRequestClientDelegate;
+class BrowserContext;
class RenderFrameHost;
namespace client_data {
@@ -79,6 +82,16 @@ class CONTENT_EXPORT AuthenticatorImpl : public blink::mojom::Authenticator,
// to a new active document.
void Bind(blink::mojom::AuthenticatorRequest request);
+ base::flat_set<device::FidoTransportProtocol> enabled_transports_for_testing()
+ const {
+ return transports_;
+ }
+
+ protected:
+ virtual void UpdateRequestDelegate();
+
+ std::unique_ptr<AuthenticatorRequestClientDelegate> request_delegate_;
+
private:
friend class AuthenticatorImplTest;
@@ -96,8 +109,7 @@ class CONTENT_EXPORT AuthenticatorImpl : public blink::mojom::Authenticator,
static std::string SerializeCollectedClientDataToJson(
const std::string& type,
const url::Origin& origin,
- base::span<const uint8_t> challenge,
- base::Optional<base::span<const uint8_t>> token_binding);
+ base::span<const uint8_t> challenge);
// mojom:Authenticator
void MakeCredential(
@@ -108,14 +120,17 @@ class CONTENT_EXPORT AuthenticatorImpl : public blink::mojom::Authenticator,
void IsUserVerifyingPlatformAuthenticatorAvailable(
IsUserVerifyingPlatformAuthenticatorAvailableCallback callback) override;
+ // Synchronous implementation of IsUserVerfyingPlatformAuthenticatorAvailable.
+ bool IsUserVerifyingPlatformAuthenticatorAvailableImpl();
+
// WebContentsObserver:
void DidFinishNavigation(NavigationHandle* navigation_handle) override;
// Callback to handle the async response from a U2fDevice.
void OnRegisterResponse(
device::FidoReturnCode status_code,
- base::Optional<device::AuthenticatorMakeCredentialResponse>
- response_data);
+ base::Optional<device::AuthenticatorMakeCredentialResponse> response_data,
+ device::FidoTransportProtocol transport_used);
// Callback to complete the registration process once a decision about
// whether or not to return attestation data has been made.
@@ -126,10 +141,15 @@ class CONTENT_EXPORT AuthenticatorImpl : public blink::mojom::Authenticator,
// Callback to handle the async response from a U2fDevice.
void OnSignResponse(
device::FidoReturnCode status_code,
- base::Optional<device::AuthenticatorGetAssertionResponse> response_data);
+ base::Optional<device::AuthenticatorGetAssertionResponse> response_data,
+ device::FidoTransportProtocol transport_used);
+
+ void FailWithNotAllowedErrorAndCleanup();
// Runs when timer expires and cancels all issued requests to a U2fDevice.
void OnTimeout();
+ // Runs when the user cancels WebAuthN request via UI dialog.
+ void Cancel();
void InvokeCallbackAndCleanup(
MakeCredentialCallback callback,
@@ -142,26 +162,30 @@ class CONTENT_EXPORT AuthenticatorImpl : public blink::mojom::Authenticator,
blink::mojom::GetAssertionAuthenticatorResponsePtr response);
void Cleanup();
- std::unique_ptr<device::FidoAuthenticator> MaybeCreatePlatformAuthenticator();
+ base::Optional<device::PlatformAuthenticatorInfo>
+ CreatePlatformAuthenticatorIfAvailable();
+ base::Optional<device::PlatformAuthenticatorInfo>
+ CreatePlatformAuthenticatorIfAvailableAndCheckIfCredentialExists(
+ const device::CtapGetAssertionRequest& request);
+
+ BrowserContext* browser_context() const;
RenderFrameHost* const render_frame_host_;
service_manager::Connector* connector_ = nullptr;
- base::flat_set<device::FidoTransportProtocol> protocols_;
+ const base::flat_set<device::FidoTransportProtocol> transports_;
std::unique_ptr<device::FidoRequestHandlerBase> request_;
- std::unique_ptr<AuthenticatorRequestClientDelegate> request_delegate_;
MakeCredentialCallback make_credential_response_callback_;
GetAssertionCallback get_assertion_response_callback_;
std::string client_data_json_;
blink::mojom::AttestationConveyancePreference attestation_preference_;
std::string relying_party_id_;
std::unique_ptr<base::OneShotTimer> timer_;
-
- // Whether or not a GetAssertion call should return a PublicKeyCredential
- // instance whose getClientExtensionResults() method yields a
- // AuthenticationExtensions dictionary that contains the `appid: true`
- // extension output.
- bool echo_appid_extension_ = false;
+ // If the "appid" extension is in use then this is the SHA-256 hash of a U2F
+ // AppID. This is used to detect when an assertion request was successfully
+ // retried with this value.
+ base::Optional<std::array<uint8_t, crypto::kSHA256Length>>
+ alternative_application_parameter_;
// Owns pipes to this Authenticator from |render_frame_host_|.
mojo::Binding<blink::mojom::Authenticator> binding_;
diff --git a/chromium/content/browser/webauth/authenticator_impl_unittest.cc b/chromium/content/browser/webauth/authenticator_impl_unittest.cc
index 4dc815e0ebe..fdb9b181f0e 100644
--- a/chromium/content/browser/webauth/authenticator_impl_unittest.cc
+++ b/chromium/content/browser/webauth/authenticator_impl_unittest.cc
@@ -18,6 +18,7 @@
#include "base/test/test_mock_time_task_runner.h"
#include "base/time/tick_clock.h"
#include "base/time/time.h"
+#include "build/build_config.h"
#include "components/cbor/cbor_reader.h"
#include "components/cbor/cbor_values.h"
#include "content/public/browser/authenticator_request_client_delegate.h"
@@ -26,7 +27,13 @@
#include "content/public/test/test_service_manager_context.h"
#include "content/test/test_render_frame_host.h"
#include "device/base/features.h"
-#include "device/fido/fake_hid_impl_for_testing.h"
+#include "device/bluetooth/bluetooth_adapter_factory.h"
+#include "device/bluetooth/test/mock_bluetooth_adapter.h"
+#include "device/fido/attested_credential_data.h"
+#include "device/fido/authenticator_data.h"
+#include "device/fido/fake_fido_discovery.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 "mojo/public/cpp/bindings/binding.h"
@@ -34,6 +41,10 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#if defined(OS_MACOSX)
+#include "device/fido/mac/scoped_touch_id_test_environment.h"
+#endif
+
namespace content {
using ::testing::_;
@@ -58,11 +69,17 @@ using blink::mojom::PublicKeyCredentialRpEntityPtr;
using blink::mojom::PublicKeyCredentialType;
using blink::mojom::PublicKeyCredentialUserEntity;
using blink::mojom::PublicKeyCredentialUserEntityPtr;
+using blink::mojom::AuthenticatorTransport;
using cbor::CBORValue;
using cbor::CBORReader;
namespace {
+using InterestingFailureReason =
+ ::content::AuthenticatorRequestClientDelegate::InterestingFailureReason;
+using FailureReasonCallbackReceiver =
+ ::device::test::TestCallbackReceiver<InterestingFailureReason>;
+
typedef struct {
const char* origin;
// Either a relying party ID or a U2F AppID.
@@ -193,6 +210,7 @@ constexpr OriginClaimedAuthorityPair kInvalidRelyingPartyTestCases[] = {
{"https://com", "https://www.gstatic.com/securitykey/origins.json"},
};
+using TestIsUvpaaCallback = device::test::ValueCallbackReceiver<bool>;
using TestMakeCredentialCallback = device::test::StatusAndValueCallbackReceiver<
AuthenticatorStatus,
MakeCredentialAuthenticatorResponsePtr>;
@@ -249,6 +267,8 @@ std::vector<PublicKeyCredentialDescriptorPtr> GetTestAllowCredentials() {
credential->type = PublicKeyCredentialType::PUBLIC_KEY;
std::vector<uint8_t> id(32, 0x0A);
credential->id = id;
+ credential->transports.push_back(AuthenticatorTransport::USB);
+ credential->transports.push_back(AuthenticatorTransport::BLE);
descriptors.push_back(std::move(credential));
return descriptors;
}
@@ -348,15 +368,7 @@ class AuthenticatorImplTest : public content::RenderViewHostTestHarness {
std::string GetTestClientDataJSON(std::string type) {
return AuthenticatorImpl::SerializeCollectedClientDataToJson(
- std::move(type), GetTestOrigin(), GetTestChallengeBytes(),
- base::nullopt);
- }
-
- std::string GetTokenBindingTestClientDataJSON(
- base::Optional<base::span<const uint8_t>> token_binding) {
- return AuthenticatorImpl::SerializeCollectedClientDataToJson(
- client_data::kGetType, GetTestOrigin(), GetTestChallengeBytes(),
- token_binding);
+ std::move(type), GetTestOrigin(), GetTestChallengeBytes());
}
AuthenticatorStatus TryAuthenticationWithAppId(const std::string& origin,
@@ -378,7 +390,13 @@ class AuthenticatorImplTest : public content::RenderViewHostTestHarness {
}
bool SupportsTransportProtocol(::device::FidoTransportProtocol protocol) {
- return base::ContainsKey(authenticator_impl_->protocols_, protocol);
+ return base::ContainsKey(
+ authenticator_impl_->enabled_transports_for_testing(), protocol);
+ }
+
+ void EnableFeature(const base::Feature& feature) {
+ scoped_feature_list_.emplace();
+ scoped_feature_list_->InitAndEnableFeature(feature);
}
protected:
@@ -386,6 +404,7 @@ class AuthenticatorImplTest : public content::RenderViewHostTestHarness {
service_manager::mojom::ConnectorRequest request_;
std::unique_ptr<service_manager::Connector> connector_;
std::unique_ptr<device::FakeHidManager> fake_hid_manager_;
+ base::Optional<base::test::ScopedFeatureList> scoped_feature_list_;
};
// Verify behavior for various combinations of origins and RP IDs.
@@ -592,34 +611,6 @@ TEST_F(AuthenticatorImplTest, TestSerializedSignClientData) {
GetTestClientDataJSON(client_data::kGetType));
}
-TEST_F(AuthenticatorImplTest, TestTokenBindingClientData) {
- const std::vector<
- std::pair<base::Optional<std::vector<uint8_t>>, const char*>>
- kTestCases = {
- std::make_pair(base::nullopt, ""),
- std::make_pair(std::vector<uint8_t>{},
- R"({"tokenBinding":{"status":"supported"}})"),
- std::make_pair(
- std::vector<uint8_t>{1, 2, 3, 4},
- R"({"tokenBinding":{"status":"present","id":"AQIDBA"}})"),
- };
-
- for (const auto& test : kTestCases) {
- const auto& token_binding = test.first;
- const std::string expected_json_subset = test.second;
- SCOPED_TRACE(expected_json_subset);
- const std::string client_data =
- GetTokenBindingTestClientDataJSON(token_binding);
-
- if (!expected_json_subset.empty()) {
- CheckJSONIsSubsetOfJSON(expected_json_subset, client_data);
- } else {
- EXPECT_TRUE(client_data.find("tokenBinding") == std::string::npos)
- << client_data;
- }
- }
-}
-
TEST_F(AuthenticatorImplTest, TestMakeCredentialTimeout) {
SimulateNavigation(GURL(kTestOrigin1));
PublicKeyCredentialCreationOptionsPtr options =
@@ -710,26 +701,71 @@ TEST_F(AuthenticatorImplTest, AppIdExtensionValues) {
// Verify that a credential registered with U2F can be used via webauthn.
TEST_F(AuthenticatorImplTest, AppIdExtension) {
SimulateNavigation(GURL(kTestOrigin1));
- PublicKeyCredentialRequestOptionsPtr options =
- GetTestPublicKeyCredentialRequestOptions();
- TestGetAssertionCallback callback_receiver;
auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
base::Time::Now(), base::TimeTicks::Now());
auto authenticator = ConstructAuthenticatorWithTimer(task_runner);
- device::test::ScopedVirtualFidoDevice virtual_device;
- // Inject a registration for the URL (which is a U2F AppID).
- ASSERT_TRUE(virtual_device.mutable_state()->InjectRegistration(
- options->allow_credentials[0]->id, kTestOrigin1));
+ {
+ // First, test that the appid extension isn't echoed at all when not
+ // requested.
+ PublicKeyCredentialRequestOptionsPtr options =
+ GetTestPublicKeyCredentialRequestOptions();
+ device::test::ScopedVirtualFidoDevice virtual_device;
+ ASSERT_TRUE(virtual_device.mutable_state()->InjectRegistration(
+ options->allow_credentials[0]->id, kTestRelyingPartyId));
- // Set the same URL as the appid parameter.
- options->appid = kTestOrigin1;
+ TestGetAssertionCallback callback_receiver;
+ authenticator->GetAssertion(std::move(options),
+ callback_receiver.callback());
+ callback_receiver.WaitForCallback();
+ ASSERT_EQ(AuthenticatorStatus::SUCCESS, callback_receiver.status());
- authenticator->GetAssertion(std::move(options), callback_receiver.callback());
+ EXPECT_EQ(false, callback_receiver.value()->echo_appid_extension);
+ }
- // Trigger timer.
- callback_receiver.WaitForCallback();
- EXPECT_EQ(AuthenticatorStatus::SUCCESS, callback_receiver.status());
+ {
+ // Second, test that the appid extension is echoed, but is false, when appid
+ // is requested but not used.
+ PublicKeyCredentialRequestOptionsPtr options =
+ GetTestPublicKeyCredentialRequestOptions();
+ device::test::ScopedVirtualFidoDevice virtual_device;
+ ASSERT_TRUE(virtual_device.mutable_state()->InjectRegistration(
+ options->allow_credentials[0]->id, kTestRelyingPartyId));
+
+ // This AppID won't be used because the RP ID will be tried (successfully)
+ // first.
+ 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(false, callback_receiver.value()->appid_extension);
+ }
+
+ {
+ // Lastly, when used, the appid extension result should be "true".
+ 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(
+ 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);
+ }
}
TEST_F(AuthenticatorImplTest, TestGetAssertionTimeout) {
@@ -768,6 +804,7 @@ TEST_F(AuthenticatorImplTest, OversizedCredentialId) {
auto credential = PublicKeyCredentialDescriptor::New();
credential->type = PublicKeyCredentialType::PUBLIC_KEY;
credential->id.resize(size);
+ credential->transports.push_back(AuthenticatorTransport::USB);
const bool should_be_valid = size < 256;
if (should_be_valid) {
@@ -791,78 +828,61 @@ TEST_F(AuthenticatorImplTest, OversizedCredentialId) {
}
}
-TEST_F(AuthenticatorImplTest, TestCableDiscoveryEnabledWithSwitch) {
- TestServiceManagerContext service_manager_context;
- base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitWithFeatures(
- std::vector<base::Feature>{features::kWebAuthCable},
- std::vector<base::Feature>{});
-
- SimulateNavigation(GURL(kTestOrigin1));
- PublicKeyCredentialRequestOptionsPtr options =
- GetTestPublicKeyCredentialRequestOptions();
- TestGetAssertionCallback callback_receiver;
-
- auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
- base::Time::Now(), base::TimeTicks::Now());
- auto authenticator = ConstructAuthenticatorWithTimer(task_runner);
- authenticator->GetAssertion(std::move(options), callback_receiver.callback());
-
- // Trigger timer.
- base::RunLoop().RunUntilIdle();
- task_runner->FastForwardBy(base::TimeDelta::FromMinutes(1));
- callback_receiver.WaitForCallback();
-
- EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());
- EXPECT_TRUE(SupportsTransportProtocol(
+TEST_F(AuthenticatorImplTest, TestCableDiscoveryByDefault) {
+ auto authenticator = ConnectToAuthenticator();
+// On Windows caBLE should be disabled by default regardless of version.
+#if defined(OS_WIN)
+ EXPECT_FALSE(SupportsTransportProtocol(
device::FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy));
+// Otherwise, it should be enabled by default if BLE is supported.
+#else
+ EXPECT_EQ(
+ device::BluetoothAdapterFactory::Get().IsLowEnergySupported(),
+ SupportsTransportProtocol(
+ device::FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy));
+#endif
}
-TEST_F(AuthenticatorImplTest, TestCableDiscoveryDisabledForMakeCredential) {
- base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitAndEnableFeature(features::kWebAuthCable);
-
- SimulateNavigation(GURL(kTestOrigin1));
- PublicKeyCredentialCreationOptionsPtr options =
- GetTestPublicKeyCredentialCreationOptions();
- TestMakeCredentialCallback callback_receiver;
-
- auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
- base::Time::Now(), base::TimeTicks::Now());
- auto authenticator = ConstructAuthenticatorWithTimer(task_runner);
- authenticator->MakeCredential(std::move(options),
- callback_receiver.callback());
+TEST_F(AuthenticatorImplTest, TestCableDiscoveryDisabledWithFlag) {
+ scoped_feature_list_.emplace();
+ scoped_feature_list_->InitAndDisableFeature(features::kWebAuthCable);
- // Trigger timer.
- base::RunLoop().RunUntilIdle();
- task_runner->FastForwardBy(base::TimeDelta::FromMinutes(1));
- callback_receiver.WaitForCallback();
-
- EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());
+ auto authenticator = ConnectToAuthenticator();
EXPECT_FALSE(SupportsTransportProtocol(
device::FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy));
}
-TEST_F(AuthenticatorImplTest, TestCableDiscoveryDisabledWithoutSwitch) {
- SimulateNavigation(GURL(kTestOrigin1));
- PublicKeyCredentialRequestOptionsPtr options =
- GetTestPublicKeyCredentialRequestOptions();
- TestGetAssertionCallback callback_receiver;
+#if defined(OS_WIN)
+TEST_F(AuthenticatorImplTest, TestCableDiscoveryEnabledWithWinFlag) {
+ EnableFeature(features::kWebAuthCableWin);
- auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
- base::Time::Now(), base::TimeTicks::Now());
- auto authenticator = ConstructAuthenticatorWithTimer(task_runner);
- authenticator->GetAssertion(std::move(options), callback_receiver.callback());
+ auto authenticator = ConnectToAuthenticator();
- // Trigger timer.
- base::RunLoop().RunUntilIdle();
- task_runner->FastForwardBy(base::TimeDelta::FromMinutes(1));
- callback_receiver.WaitForCallback();
+ // Should be enabled if the new Windows BLE stack is.
+ EXPECT_EQ(
+ device::BluetoothAdapterFactory::Get().IsLowEnergySupported(),
+ SupportsTransportProtocol(
+ device::FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy));
+}
- EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());
- EXPECT_FALSE(SupportsTransportProtocol(
- device::FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy));
+// Tests that caBLE is not supported when features::kWebAuthCable is disabled,
+// regardless of the state of features::kWebAuthCableWin.
+TEST_F(AuthenticatorImplTest, TestCableDiscoveryDisabledWithoutFlagWin) {
+ for (bool enable_win_flag : {false, true}) {
+ std::vector<base::Feature> enabled_features;
+ std::vector<base::Feature> disabled_features = {features::kWebAuthCable};
+ enable_win_flag ? enabled_features.push_back(features::kWebAuthCableWin)
+ : disabled_features.push_back(features::kWebAuthCableWin);
+
+ scoped_feature_list_.emplace();
+ scoped_feature_list_->InitWithFeatures(enabled_features, disabled_features);
+
+ auto authenticator = ConnectToAuthenticator();
+ EXPECT_FALSE(SupportsTransportProtocol(
+ device::FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy));
+ }
}
+#endif
TEST_F(AuthenticatorImplTest, TestGetAssertionU2fDeviceBackwardsCompatibility) {
SimulateNavigation(GURL(kTestOrigin1));
@@ -886,6 +906,15 @@ TEST_F(AuthenticatorImplTest, TestGetAssertionU2fDeviceBackwardsCompatibility) {
}
TEST_F(AuthenticatorImplTest, GetAssertionWithEmptyAllowCredentials) {
+ auto mock_adapter =
+ base::MakeRefCounted<::testing::NiceMock<device::MockBluetoothAdapter>>();
+ EXPECT_CALL(*mock_adapter, IsPresent())
+ .WillRepeatedly(::testing::Return(true));
+ device::BluetoothAdapterFactory::SetAdapterForTesting(mock_adapter);
+ auto bluetooth_adapter_factory_overrides =
+ device::BluetoothAdapterFactory::Get().InitGlobalValuesForTesting();
+ bluetooth_adapter_factory_overrides->SetLESupported(true);
+
SimulateNavigation(GURL(kTestOrigin1));
PublicKeyCredentialRequestOptionsPtr options =
GetTestPublicKeyCredentialRequestOptions();
@@ -1069,23 +1098,36 @@ enum class AttestationConsent {
DENIED,
};
+enum class AttestationType {
+ ANY,
+ NONE,
+ U2F,
+ SELF,
+};
+
class TestAuthenticatorRequestDelegate
: public AuthenticatorRequestClientDelegate {
public:
- TestAuthenticatorRequestDelegate(RenderFrameHost* render_frame_host,
- base::OnceClosure did_start_request_callback,
- IndividualAttestation individual_attestation,
- AttestationConsent attestation_consent,
- bool is_focused)
- : did_start_request_callback_(std::move(did_start_request_callback)),
+ TestAuthenticatorRequestDelegate(
+ RenderFrameHost* render_frame_host,
+ base::OnceClosure action_callbacks_registered_callback,
+ IndividualAttestation individual_attestation,
+ AttestationConsent attestation_consent,
+ bool is_focused)
+ : action_callbacks_registered_callback_(
+ std::move(action_callbacks_registered_callback)),
individual_attestation_(individual_attestation),
attestation_consent_(attestation_consent),
is_focused_(is_focused) {}
~TestAuthenticatorRequestDelegate() override {}
- void DidStartRequest() override {
- ASSERT_TRUE(did_start_request_callback_) << "DidStartRequest called twice.";
- std::move(did_start_request_callback_).Run();
+ void RegisterActionCallbacks(
+ base::OnceClosure cancel_callback,
+ device::FidoRequestHandlerBase::RequestCallback request_callback,
+ base::RepeatingClosure bluetooth_adapter_power_on_callback) override {
+ ASSERT_TRUE(action_callbacks_registered_callback_)
+ << "RegisterActionCallbacks called twice.";
+ std::move(action_callbacks_registered_callback_).Run();
}
bool ShouldPermitIndividualAttestation(
@@ -1102,7 +1144,7 @@ class TestAuthenticatorRequestDelegate
bool IsFocused() override { return is_focused_; }
- base::OnceClosure did_start_request_callback_;
+ base::OnceClosure action_callbacks_registered_callback_;
const IndividualAttestation individual_attestation_;
const AttestationConsent attestation_consent_;
const bool is_focused_;
@@ -1120,14 +1162,23 @@ class TestAuthenticatorContentBrowserClient : public ContentBrowserClient {
return nullptr;
return std::make_unique<TestAuthenticatorRequestDelegate>(
render_frame_host,
- request_started_callback ? std::move(request_started_callback)
- : base::DoNothing(),
+ action_callbacks_registered_callback
+ ? std::move(action_callbacks_registered_callback)
+ : base::DoNothing(),
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 request_started_callback;
+ base::OnceClosure action_callbacks_registered_callback;
IndividualAttestation individual_attestation =
IndividualAttestation::NOT_REQUESTED;
@@ -1151,7 +1202,7 @@ class AuthenticatorContentBrowserClientTest : public AuthenticatorImplTest {
IndividualAttestation individual_attestation;
AttestationConsent attestation_consent;
AuthenticatorStatus expected_status;
- const char* expected_attestation_format;
+ AttestationType expected_attestation;
const char* expected_certificate_substring;
};
@@ -1197,7 +1248,7 @@ class AuthenticatorContentBrowserClientTest : public AuthenticatorImplTest {
ASSERT_EQ(test.expected_status, callback_receiver.status());
if (test.expected_status != AuthenticatorStatus::SUCCESS) {
- ASSERT_STREQ("", test.expected_attestation_format);
+ ASSERT_EQ(AttestationType::ANY, test.expected_attestation);
continue;
}
@@ -1206,11 +1257,56 @@ class AuthenticatorContentBrowserClientTest : public AuthenticatorImplTest {
ASSERT_TRUE(attestation_value);
ASSERT_TRUE(attestation_value->is_map());
const auto& attestation = attestation_value->GetMap();
- ExpectMapHasKeyWithStringValue(attestation, "fmt",
- test.expected_attestation_format);
- if (strlen(test.expected_certificate_substring) > 0) {
- ExpectCertificateContainingSubstring(
- attestation, test.expected_certificate_substring);
+
+ switch (test.expected_attestation) {
+ case AttestationType::ANY:
+ ASSERT_STREQ("", test.expected_certificate_substring);
+ break;
+
+ case AttestationType::NONE:
+ ASSERT_STREQ("", test.expected_certificate_substring);
+ ExpectMapHasKeyWithStringValue(attestation, "fmt", "none");
+ break;
+
+ case AttestationType::U2F:
+ ExpectMapHasKeyWithStringValue(attestation, "fmt", "fido-u2f");
+ if (strlen(test.expected_certificate_substring) > 0) {
+ ExpectCertificateContainingSubstring(
+ attestation, test.expected_certificate_substring);
+ }
+ break;
+
+ case AttestationType::SELF:
+ ASSERT_STREQ("", test.expected_certificate_substring);
+ ExpectMapHasKeyWithStringValue(attestation, "fmt", "packed");
+
+ // A self-attestation should not include an X.509 chain nor ECDAA key.
+ const auto attestation_statement_it =
+ attestation.find(CBORValue("attStmt"));
+ ASSERT_TRUE(attestation_statement_it != attestation.end());
+ ASSERT_TRUE(attestation_statement_it->second.is_map());
+ const auto& attestation_statement =
+ attestation_statement_it->second.GetMap();
+
+ ASSERT_TRUE(attestation_statement.find(CBORValue("x5c")) ==
+ attestation_statement.end());
+ ASSERT_TRUE(attestation_statement.find(CBORValue("ecdaaKeyId")) ==
+ attestation_statement.end());
+
+ // The AAGUID should be all zero.
+ const auto auth_data_it = attestation.find(CBORValue("authData"));
+ ASSERT_TRUE(auth_data_it != attestation.end());
+ ASSERT_TRUE(auth_data_it->second.is_bytestring());
+ const std::vector<uint8_t>& auth_data =
+ auth_data_it->second.GetBytestring();
+ base::Optional<device::AuthenticatorData> parsed_auth_data =
+ device::AuthenticatorData::DecodeAuthenticatorData(auth_data);
+ ASSERT_TRUE(parsed_auth_data);
+ const base::Optional<device::AttestedCredentialData>& cred_data(
+ parsed_auth_data->attested_data());
+ ASSERT_TRUE(cred_data);
+ EXPECT_TRUE(cred_data->IsAaguidZero());
+ break;
}
}
}
@@ -1287,72 +1383,78 @@ TEST_F(AuthenticatorContentBrowserClientTest, AttestationBehaviour) {
{
AttestationConveyancePreference::NONE,
IndividualAttestation::NOT_REQUESTED, AttestationConsent::DENIED,
- AuthenticatorStatus::SUCCESS, "none", "",
+ AuthenticatorStatus::SUCCESS, AttestationType::NONE, "",
},
{
AttestationConveyancePreference::NONE,
IndividualAttestation::REQUESTED, AttestationConsent::DENIED,
- AuthenticatorStatus::SUCCESS, "none", "",
+ AuthenticatorStatus::SUCCESS, AttestationType::NONE, "",
},
{
AttestationConveyancePreference::INDIRECT,
IndividualAttestation::NOT_REQUESTED, AttestationConsent::DENIED,
- AuthenticatorStatus::NOT_ALLOWED_ERROR, "", "",
+ AuthenticatorStatus::NOT_ALLOWED_ERROR, AttestationType::ANY, "",
},
{
AttestationConveyancePreference::INDIRECT,
IndividualAttestation::REQUESTED, AttestationConsent::DENIED,
- AuthenticatorStatus::NOT_ALLOWED_ERROR, "", "",
+ AuthenticatorStatus::NOT_ALLOWED_ERROR, AttestationType::ANY, "",
},
{
AttestationConveyancePreference::INDIRECT,
IndividualAttestation::NOT_REQUESTED, AttestationConsent::GRANTED,
- AuthenticatorStatus::SUCCESS, "fido-u2f", kStandardCommonName,
+ AuthenticatorStatus::SUCCESS, AttestationType::U2F,
+ kStandardCommonName,
},
{
AttestationConveyancePreference::INDIRECT,
IndividualAttestation::REQUESTED, AttestationConsent::GRANTED,
- AuthenticatorStatus::SUCCESS, "fido-u2f", kStandardCommonName,
+ AuthenticatorStatus::SUCCESS, AttestationType::U2F,
+ kStandardCommonName,
},
{
AttestationConveyancePreference::DIRECT,
IndividualAttestation::NOT_REQUESTED, AttestationConsent::DENIED,
- AuthenticatorStatus::NOT_ALLOWED_ERROR, "", "",
+ AuthenticatorStatus::NOT_ALLOWED_ERROR, AttestationType::ANY, "",
},
{
AttestationConveyancePreference::DIRECT,
IndividualAttestation::REQUESTED, AttestationConsent::DENIED,
- AuthenticatorStatus::NOT_ALLOWED_ERROR, "", "",
+ AuthenticatorStatus::NOT_ALLOWED_ERROR, AttestationType::ANY, "",
},
{
AttestationConveyancePreference::DIRECT,
IndividualAttestation::NOT_REQUESTED, AttestationConsent::GRANTED,
- AuthenticatorStatus::SUCCESS, "fido-u2f", kStandardCommonName,
+ AuthenticatorStatus::SUCCESS, AttestationType::U2F,
+ kStandardCommonName,
},
{
AttestationConveyancePreference::DIRECT,
IndividualAttestation::REQUESTED, AttestationConsent::GRANTED,
- AuthenticatorStatus::SUCCESS, "fido-u2f", kStandardCommonName,
+ AuthenticatorStatus::SUCCESS, AttestationType::U2F,
+ kStandardCommonName,
},
{
AttestationConveyancePreference::ENTERPRISE,
IndividualAttestation::NOT_REQUESTED, AttestationConsent::DENIED,
- AuthenticatorStatus::NOT_ALLOWED_ERROR, "", "",
+ AuthenticatorStatus::NOT_ALLOWED_ERROR, AttestationType::ANY, "",
},
{
AttestationConveyancePreference::ENTERPRISE,
IndividualAttestation::REQUESTED, AttestationConsent::DENIED,
- AuthenticatorStatus::NOT_ALLOWED_ERROR, "", "",
+ AuthenticatorStatus::NOT_ALLOWED_ERROR, AttestationType::ANY, "",
},
{
AttestationConveyancePreference::ENTERPRISE,
IndividualAttestation::NOT_REQUESTED, AttestationConsent::GRANTED,
- AuthenticatorStatus::SUCCESS, "fido-u2f", kStandardCommonName,
+ AuthenticatorStatus::SUCCESS, AttestationType::U2F,
+ kStandardCommonName,
},
{
AttestationConveyancePreference::ENTERPRISE,
IndividualAttestation::REQUESTED, AttestationConsent::GRANTED,
- AuthenticatorStatus::SUCCESS, "fido-u2f", kIndividualCommonName,
+ AuthenticatorStatus::SUCCESS, AttestationType::U2F,
+ kIndividualCommonName,
},
};
@@ -1375,7 +1477,7 @@ TEST_F(AuthenticatorContentBrowserClientTest,
{
AttestationConveyancePreference::ENTERPRISE,
IndividualAttestation::NOT_REQUESTED, AttestationConsent::DENIED,
- AuthenticatorStatus::NOT_ALLOWED_ERROR, "", "",
+ AuthenticatorStatus::NOT_ALLOWED_ERROR, AttestationType::ANY, "",
},
{
AttestationConveyancePreference::DIRECT,
@@ -1384,7 +1486,7 @@ TEST_F(AuthenticatorContentBrowserClientTest,
// If individual attestation was not requested then the attestation
// certificate will be removed, even if consent is given, because
// the consent isn't to be tracked.
- "none", "",
+ AttestationType::NONE, "",
},
{
AttestationConveyancePreference::ENTERPRISE,
@@ -1393,13 +1495,13 @@ TEST_F(AuthenticatorContentBrowserClientTest,
// If individual attestation was not requested then the attestation
// certificate will be removed, even if consent is given, because
// the consent isn't to be tracked.
- "none", "",
+ AttestationType::NONE, "",
},
{
AttestationConveyancePreference::ENTERPRISE,
IndividualAttestation::REQUESTED, AttestationConsent::GRANTED,
- AuthenticatorStatus::SUCCESS, "fido-u2f", kCommonName,
+ AuthenticatorStatus::SUCCESS, AttestationType::U2F, kCommonName,
},
};
@@ -1411,6 +1513,59 @@ TEST_F(AuthenticatorContentBrowserClientTest,
RunTestCases(kTests);
}
+TEST_F(AuthenticatorContentBrowserClientTest, Ctap2SelfAttestation) {
+ virtual_device_.SetSupportedProtocol(device::ProtocolVersion::kCtap);
+ virtual_device_.mutable_state()->self_attestation = true;
+ NavigateAndCommit(GURL("https://example.com"));
+
+ const std::vector<TestCase> kTests = {
+ {
+ // If no attestation is requested, we'll return the self attestation
+ // rather than erasing it.
+ AttestationConveyancePreference::NONE,
+ IndividualAttestation::NOT_REQUESTED, AttestationConsent::DENIED,
+ AuthenticatorStatus::SUCCESS, AttestationType::SELF, "",
+ },
+ {
+ // If attestation is requested, but denied, we'll still fail the
+ // request.
+ AttestationConveyancePreference::DIRECT,
+ IndividualAttestation::NOT_REQUESTED, AttestationConsent::DENIED,
+ AuthenticatorStatus::NOT_ALLOWED_ERROR, AttestationType::ANY, "",
+ },
+ {
+ // If attestation is requested and granted, the self attestation
+ // will be returned.
+ AttestationConveyancePreference::DIRECT,
+ IndividualAttestation::NOT_REQUESTED, AttestationConsent::GRANTED,
+ AuthenticatorStatus::SUCCESS, AttestationType::SELF, "",
+ },
+ };
+
+ RunTestCases(kTests);
+}
+
+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;
+ NavigateAndCommit(GURL("https://example.com"));
+
+ const std::vector<TestCase> kTests = {
+ {
+ // Since the virtual device is configured to set a non-zero AAGUID
+ // the self-attestation should still be replaced with a "none"
+ // attestation.
+ AttestationConveyancePreference::NONE,
+ IndividualAttestation::NOT_REQUESTED, AttestationConsent::DENIED,
+ AuthenticatorStatus::SUCCESS, AttestationType::NONE, "",
+ },
+ };
+
+ RunTestCases(kTests);
+}
+
TEST_F(AuthenticatorContentBrowserClientTest,
MakeCredentialRequestStartedCallback) {
TestServiceManagerContext smc;
@@ -1421,7 +1576,8 @@ TEST_F(AuthenticatorContentBrowserClientTest,
GetTestPublicKeyCredentialCreationOptions();
TestRequestStartedCallback request_started;
- test_client_.request_started_callback = request_started.callback();
+ test_client_.action_callbacks_registered_callback =
+ request_started.callback();
authenticator->MakeCredential(std::move(options), base::DoNothing());
request_started.WaitForCallback();
}
@@ -1436,7 +1592,8 @@ TEST_F(AuthenticatorContentBrowserClientTest,
GetTestPublicKeyCredentialRequestOptions();
TestRequestStartedCallback request_started;
- test_client_.request_started_callback = request_started.callback();
+ test_client_.action_callbacks_registered_callback =
+ request_started.callback();
authenticator->GetAssertion(std::move(options), base::DoNothing());
request_started.WaitForCallback();
}
@@ -1457,7 +1614,8 @@ TEST_F(AuthenticatorContentBrowserClientTest, Unfocused) {
TestMakeCredentialCallback cb;
TestRequestStartedCallback request_started;
- test_client_.request_started_callback = request_started.callback();
+ test_client_.action_callbacks_registered_callback =
+ request_started.callback();
authenticator->MakeCredential(std::move(options), cb.callback());
cb.WaitForCallback();
@@ -1475,13 +1633,16 @@ TEST_F(AuthenticatorContentBrowserClientTest, Unfocused) {
auto credential = PublicKeyCredentialDescriptor::New();
credential->type = PublicKeyCredentialType::PUBLIC_KEY;
credential->id.resize(16);
+ credential->transports = {AuthenticatorTransport::USB};
+
ASSERT_TRUE(virtual_device_.mutable_state()->InjectRegistration(
credential->id, kTestRelyingPartyId));
options->allow_credentials.emplace_back(std::move(credential));
TestGetAssertionCallback cb;
TestRequestStartedCallback request_started;
- test_client_.request_started_callback = request_started.callback();
+ test_client_.action_callbacks_registered_callback =
+ request_started.callback();
authenticator->GetAssertion(std::move(options), cb.callback());
cb.WaitForCallback();
@@ -1519,4 +1680,333 @@ TEST_F(AuthenticatorContentBrowserClientTest,
}
}
+#if defined(OS_MACOSX)
+TEST_F(AuthenticatorContentBrowserClientTest,
+ IsUVPAAFalseIfEmbedderDoesNotSupportTouchId) {
+ if (__builtin_available(macOS 10.12.2, *)) {
+ // Touch ID is hardware-supported, and flag-enabled, but not enabled by the
+ // embedder.
+ EnableFeature(device::kWebAuthTouchId);
+ 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, IsUVPAAFalseIfFeatureFlagOff) {
+ if (__builtin_available(macOS 10.12.2, *)) {
+ // Touch ID is hardware-supported and embedder-enabled, but the flag is off.
+ 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_FALSE(cb.value());
+ }
+}
+
+TEST_F(AuthenticatorContentBrowserClientTest, IsUVPAATrueIfTouchIdAvailable) {
+ if (__builtin_available(macOS 10.12.2, *)) {
+ // Touch ID is available.
+ EnableFeature(device::kWebAuthTouchId);
+ 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_MACOSX)
+TEST_F(AuthenticatorContentBrowserClientTest, IsUVPAAFalse) {
+ // No platform authenticator on non-macOS platforms.
+ NavigateAndCommit(GURL(kTestOrigin1));
+ AuthenticatorPtr authenticator = ConnectToAuthenticator();
+
+ TestIsUvpaaCallback cb;
+ authenticator->IsUserVerifyingPlatformAuthenticatorAvailable(cb.callback());
+ cb.WaitForCallback();
+ EXPECT_FALSE(cb.value());
+}
+#endif // !defined(OS_MACOSX)
+
+class MockAuthenticatorRequestDelegateObserver
+ : public TestAuthenticatorRequestDelegate {
+ public:
+ using InterestingFailureReasonCallback =
+ base::OnceCallback<void(InterestingFailureReason)>;
+
+ MockAuthenticatorRequestDelegateObserver(
+ InterestingFailureReasonCallback failure_reasons_callback =
+ base::DoNothing())
+ : TestAuthenticatorRequestDelegate(
+ nullptr /* render_frame_host */,
+ base::DoNothing() /* did_start_request_callback */,
+ IndividualAttestation::NOT_REQUESTED,
+ AttestationConsent::DENIED,
+ true /* is_focused */),
+ failure_reasons_callback_(std::move(failure_reasons_callback)) {}
+ ~MockAuthenticatorRequestDelegateObserver() override = default;
+
+ void DidFailWithInterestingReason(InterestingFailureReason reason) override {
+ ASSERT_TRUE(failure_reasons_callback_);
+ std::move(failure_reasons_callback_).Run(reason);
+ }
+
+ MOCK_METHOD1(
+ OnTransportAvailabilityEnumerated,
+ void(device::FidoRequestHandlerBase::TransportAvailabilityInfo data));
+ MOCK_METHOD1(EmbedderControlsAuthenticatorDispatch,
+ bool(const device::FidoAuthenticator&));
+ MOCK_METHOD1(FidoAuthenticatorAdded, void(const device::FidoAuthenticator&));
+ MOCK_METHOD1(FidoAuthenticatorRemoved, void(base::StringPiece));
+
+ private:
+ InterestingFailureReasonCallback failure_reasons_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockAuthenticatorRequestDelegateObserver);
+};
+
+// Fake test construct that shares all other behavior with AuthenticatorImpl
+// except that:
+// - FakeAuthenticatorImpl does not trigger UI activity.
+// - MockAuthenticatorRequestDelegateObserver is injected to
+// |request_delegate_|
+// instead of ChromeAuthenticatorRequestDelegate.
+class FakeAuthenticatorImpl : public AuthenticatorImpl {
+ public:
+ explicit FakeAuthenticatorImpl(
+ RenderFrameHost* render_frame_host,
+ service_manager::Connector* connector,
+ std::unique_ptr<base::OneShotTimer> timer,
+ std::unique_ptr<MockAuthenticatorRequestDelegateObserver> mock_delegate)
+ : AuthenticatorImpl(render_frame_host, connector, std::move(timer)),
+ mock_delegate_(std::move(mock_delegate)) {}
+ ~FakeAuthenticatorImpl() override = default;
+
+ void UpdateRequestDelegate() override {
+ DCHECK(mock_delegate_);
+ request_delegate_ = std::move(mock_delegate_);
+ }
+
+ private:
+ friend class AuthenticatorImplRequestDelegateTest;
+
+ std::unique_ptr<MockAuthenticatorRequestDelegateObserver> mock_delegate_;
+};
+
+class AuthenticatorImplRequestDelegateTest : public AuthenticatorImplTest {
+ public:
+ AuthenticatorImplRequestDelegateTest() {}
+ ~AuthenticatorImplRequestDelegateTest() override {}
+
+ void TearDown() override {
+ // The |RenderFrameHost| must outlive |AuthenticatorImpl|.
+ authenticator_impl_.reset();
+ content::RenderViewHostTestHarness::TearDown();
+ }
+
+ AuthenticatorPtr ConnectToFakeAuthenticator(
+ std::unique_ptr<MockAuthenticatorRequestDelegateObserver> delegate,
+ service_manager::Connector* connector,
+ std::unique_ptr<base::OneShotTimer> timer) {
+ authenticator_impl_.reset(new FakeAuthenticatorImpl(
+ main_rfh(), connector, std::move(timer), std::move(delegate)));
+ AuthenticatorPtr authenticator;
+ authenticator_impl_->Bind(mojo::MakeRequest(&authenticator));
+ return authenticator;
+ }
+
+ AuthenticatorPtr ConstructFakeAuthenticatorWithTimer(
+ std::unique_ptr<MockAuthenticatorRequestDelegateObserver> delegate,
+ scoped_refptr<base::TestMockTimeTaskRunner> task_runner) {
+ connector_ = service_manager::Connector::Create(&request_);
+ fake_hid_manager_ = std::make_unique<device::FakeHidManager>();
+ service_manager::Connector::TestApi test_api(connector_.get());
+ test_api.OverrideBinderForTesting(
+ service_manager::Identity(device::mojom::kServiceName),
+ device::mojom::HidManager::Name_,
+ base::Bind(&device::FakeHidManager::AddBinding,
+ base::Unretained(fake_hid_manager_.get())));
+
+ // Set up a timer for testing.
+ auto timer =
+ std::make_unique<base::OneShotTimer>(task_runner->GetMockTickClock());
+ timer->SetTaskRunner(task_runner);
+ return ConnectToFakeAuthenticator(std::move(delegate), connector_.get(),
+ std::move(timer));
+ }
+
+ protected:
+ std::unique_ptr<FakeAuthenticatorImpl> authenticator_impl_;
+};
+
+TEST_F(AuthenticatorImplRequestDelegateTest,
+ TestRequestDelegateObservesFidoRequestHandler) {
+ EnableFeature(features::kWebAuthBle);
+ auto mock_adapter =
+ base::MakeRefCounted<::testing::NiceMock<device::MockBluetoothAdapter>>();
+ EXPECT_CALL(*mock_adapter, IsPresent())
+ .WillRepeatedly(::testing::Return(true));
+ device::BluetoothAdapterFactory::SetAdapterForTesting(mock_adapter);
+ auto bluetooth_adapter_factory_overrides =
+ device::BluetoothAdapterFactory::Get().InitGlobalValuesForTesting();
+ bluetooth_adapter_factory_overrides->SetLESupported(true);
+
+ device::test::ScopedFakeFidoDiscoveryFactory discovery_factory;
+ auto* fake_ble_discovery = discovery_factory.ForgeNextBleDiscovery();
+
+ SimulateNavigation(GURL(kTestOrigin1));
+ PublicKeyCredentialRequestOptionsPtr options =
+ GetTestPublicKeyCredentialRequestOptions();
+ TestGetAssertionCallback callback_receiver;
+ auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
+ base::Time::Now(), base::TimeTicks::Now());
+
+ auto mock_delegate =
+ std::make_unique<MockAuthenticatorRequestDelegateObserver>();
+ auto* const mock_delegate_ptr = mock_delegate.get();
+ auto authenticator = ConstructFakeAuthenticatorWithTimer(
+ std::move(mock_delegate), task_runner);
+
+ auto mock_ble_device = device::MockFidoDevice::MakeCtap();
+ mock_ble_device->StubGetId();
+ mock_ble_device->SetDeviceTransport(
+ device::FidoTransportProtocol::kBluetoothLowEnergy);
+ const auto device_id = mock_ble_device->GetId();
+
+ EXPECT_CALL(*mock_delegate_ptr, OnTransportAvailabilityEnumerated(_));
+ EXPECT_CALL(*mock_delegate_ptr, EmbedderControlsAuthenticatorDispatch(_))
+ .WillOnce(testing::Return(true));
+
+ base::RunLoop ble_device_found_done;
+ EXPECT_CALL(*mock_delegate_ptr, FidoAuthenticatorAdded(_))
+ .WillOnce(testing::InvokeWithoutArgs(
+ [&ble_device_found_done]() { ble_device_found_done.Quit(); }));
+
+ base::RunLoop ble_device_lost_done;
+ EXPECT_CALL(*mock_delegate_ptr, FidoAuthenticatorRemoved(_))
+ .WillOnce(testing::InvokeWithoutArgs(
+ [&ble_device_lost_done]() { ble_device_lost_done.Quit(); }));
+
+ authenticator->GetAssertion(std::move(options), callback_receiver.callback());
+ fake_ble_discovery->WaitForCallToStartAndSimulateSuccess();
+ fake_ble_discovery->AddDevice(std::move(mock_ble_device));
+ ble_device_found_done.Run();
+
+ fake_ble_discovery->RemoveDevice(device_id);
+ ble_device_lost_done.Run();
+ base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(AuthenticatorImplRequestDelegateTest, FailureReasonForTimeout) {
+ SimulateNavigation(GURL(kTestOrigin1));
+
+ FailureReasonCallbackReceiver failure_reason_receiver;
+ auto mock_delegate = std::make_unique<
+ ::testing::NiceMock<MockAuthenticatorRequestDelegateObserver>>(
+ failure_reason_receiver.callback());
+ auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
+ base::Time::Now(), base::TimeTicks::Now());
+ auto authenticator = ConstructFakeAuthenticatorWithTimer(
+ std::move(mock_delegate), task_runner);
+
+ TestGetAssertionCallback callback_receiver;
+ authenticator->GetAssertion(GetTestPublicKeyCredentialRequestOptions(),
+ callback_receiver.callback());
+
+ base::RunLoop().RunUntilIdle();
+ task_runner->FastForwardBy(base::TimeDelta::FromMinutes(1));
+
+ callback_receiver.WaitForCallback();
+ EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());
+
+ ASSERT_TRUE(failure_reason_receiver.was_called());
+ EXPECT_EQ(content::AuthenticatorRequestClientDelegate::
+ InterestingFailureReason::kTimeout,
+ std::get<0>(*failure_reason_receiver.result()));
+}
+
+TEST_F(AuthenticatorImplRequestDelegateTest,
+ FailureReasonForDuplicateRegistration) {
+ device::test::ScopedVirtualFidoDevice scoped_virtual_device;
+ SimulateNavigation(GURL(kTestOrigin1));
+
+ FailureReasonCallbackReceiver failure_reason_receiver;
+ auto mock_delegate = std::make_unique<
+ ::testing::NiceMock<MockAuthenticatorRequestDelegateObserver>>(
+ failure_reason_receiver.callback());
+ auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
+ base::Time::Now(), base::TimeTicks::Now());
+ auto authenticator = ConstructFakeAuthenticatorWithTimer(
+ std::move(mock_delegate), task_runner);
+
+ PublicKeyCredentialCreationOptionsPtr options =
+ GetTestPublicKeyCredentialCreationOptions();
+ options->exclude_credentials = GetTestAllowCredentials();
+ ASSERT_TRUE(scoped_virtual_device.mutable_state()->InjectRegistration(
+ options->exclude_credentials[0]->id, kTestRelyingPartyId));
+
+ TestMakeCredentialCallback callback_receiver;
+ authenticator->MakeCredential(std::move(options),
+ callback_receiver.callback());
+
+ callback_receiver.WaitForCallback();
+ EXPECT_EQ(AuthenticatorStatus::CREDENTIAL_EXCLUDED,
+ callback_receiver.status());
+
+ ASSERT_TRUE(failure_reason_receiver.was_called());
+ EXPECT_EQ(content::AuthenticatorRequestClientDelegate::
+ InterestingFailureReason::kKeyAlreadyRegistered,
+ std::get<0>(*failure_reason_receiver.result()));
+}
+
+TEST_F(AuthenticatorImplRequestDelegateTest,
+ FailureReasonForMissingRegistration) {
+ device::test::ScopedVirtualFidoDevice scoped_virtual_device;
+ SimulateNavigation(GURL(kTestOrigin1));
+
+ FailureReasonCallbackReceiver failure_reason_receiver;
+ auto mock_delegate = std::make_unique<
+ ::testing::NiceMock<MockAuthenticatorRequestDelegateObserver>>(
+ failure_reason_receiver.callback());
+ auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
+ base::Time::Now(), base::TimeTicks::Now());
+ auto authenticator = ConstructFakeAuthenticatorWithTimer(
+ std::move(mock_delegate), task_runner);
+
+ TestGetAssertionCallback callback_receiver;
+ authenticator->GetAssertion(GetTestPublicKeyCredentialRequestOptions(),
+ callback_receiver.callback());
+
+ callback_receiver.WaitForCallback();
+ EXPECT_EQ(AuthenticatorStatus::CREDENTIAL_NOT_RECOGNIZED,
+ callback_receiver.status());
+
+ ASSERT_TRUE(failure_reason_receiver.was_called());
+ EXPECT_EQ(content::AuthenticatorRequestClientDelegate::
+ InterestingFailureReason::kKeyNotRegistered,
+ std::get<0>(*failure_reason_receiver.result()));
+}
+
} // namespace content
diff --git a/chromium/content/browser/webauth/authenticator_type_converters.cc b/chromium/content/browser/webauth/authenticator_type_converters.cc
index 28985e8756f..b916b86a15c 100644
--- a/chromium/content/browser/webauth/authenticator_type_converters.cc
+++ b/chromium/content/browser/webauth/authenticator_type_converters.cc
@@ -5,7 +5,9 @@
#include "content/browser/webauth/authenticator_type_converters.h"
#include <algorithm>
+#include <utility>
+#include "base/containers/flat_set.h"
#include "device/fido/fido_constants.h"
#include "device/fido/fido_parsing_utils.h"
@@ -33,6 +35,10 @@ TypeConverter<::device::FidoTransportProtocol, AuthenticatorTransport>::Convert(
return ::device::FidoTransportProtocol::kNearFieldCommunication;
case AuthenticatorTransport::BLE:
return ::device::FidoTransportProtocol::kBluetoothLowEnergy;
+ case AuthenticatorTransport::CABLE:
+ return ::device::FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy;
+ case AuthenticatorTransport::INTERNAL:
+ return ::device::FidoTransportProtocol::kInternal;
}
NOTREACHED();
return ::device::FidoTransportProtocol::kUsbHumanInterfaceDevice;
@@ -78,8 +84,14 @@ TypeConverter<std::vector<::device::PublicKeyCredentialDescriptor>,
credential_descriptors.reserve(input.size());
for (const auto& credential : input) {
+ base::flat_set<::device::FidoTransportProtocol> protocols;
+ for (const auto& protocol : credential->transports) {
+ protocols.emplace(ConvertTo<::device::FidoTransportProtocol>(protocol));
+ }
+
credential_descriptors.emplace_back(::device::PublicKeyCredentialDescriptor(
- ConvertTo<::device::CredentialType>(credential->type), credential->id));
+ ConvertTo<::device::CredentialType>(credential->type), credential->id,
+ std::move(protocols)));
}
return credential_descriptors;
}
@@ -162,30 +174,30 @@ TypeConverter<::device::PublicKeyCredentialUserEntity,
}
// static
-std::vector<::device::FidoCableDiscovery::CableDiscoveryData>
-TypeConverter<std::vector<::device::FidoCableDiscovery::CableDiscoveryData>,
+std::vector<::device::CableDiscoveryData>
+TypeConverter<std::vector<::device::CableDiscoveryData>,
std::vector<CableAuthenticationPtr>>::
Convert(const std::vector<CableAuthenticationPtr>& input) {
- std::vector<::device::FidoCableDiscovery::CableDiscoveryData> discovery_data;
+ std::vector<::device::CableDiscoveryData> discovery_data;
discovery_data.reserve(input.size());
for (const auto& data : input) {
- ::device::FidoCableDiscovery::EidArray client_eid;
+ ::device::EidArray client_eid;
DCHECK_EQ(client_eid.size(), data->client_eid.size());
std::copy(data->client_eid.begin(), data->client_eid.end(),
client_eid.begin());
- ::device::FidoCableDiscovery::EidArray authenticator_eid;
+ ::device::EidArray authenticator_eid;
DCHECK_EQ(authenticator_eid.size(), data->authenticator_eid.size());
std::copy(data->authenticator_eid.begin(), data->authenticator_eid.end(),
authenticator_eid.begin());
- ::device::FidoCableDiscovery::SessionPreKeyArray session_pre_key;
+ ::device::SessionPreKeyArray session_pre_key;
DCHECK_EQ(session_pre_key.size(), data->session_pre_key.size());
std::copy(data->session_pre_key.begin(), data->session_pre_key.end(),
session_pre_key.begin());
- discovery_data.push_back(::device::FidoCableDiscovery::CableDiscoveryData{
+ discovery_data.push_back(::device::CableDiscoveryData{
data->version, client_eid, authenticator_eid, session_pre_key});
}
diff --git a/chromium/content/browser/webauth/authenticator_type_converters.h b/chromium/content/browser/webauth/authenticator_type_converters.h
index cc4a53db728..90fd80fb7c6 100644
--- a/chromium/content/browser/webauth/authenticator_type_converters.h
+++ b/chromium/content/browser/webauth/authenticator_type_converters.h
@@ -8,14 +8,14 @@
#include <vector>
#include "device/fido/authenticator_selection_criteria.h"
-#include "device/fido/fido_cable_discovery.h"
+#include "device/fido/cable/cable_discovery_data.h"
#include "device/fido/fido_transport_protocol.h"
#include "device/fido/public_key_credential_descriptor.h"
#include "device/fido/public_key_credential_params.h"
#include "device/fido/public_key_credential_rp_entity.h"
#include "device/fido/public_key_credential_user_entity.h"
#include "mojo/public/cpp/bindings/type_converter.h"
-#include "third_party/blink/public/platform/modules/webauth/authenticator.mojom.h"
+#include "third_party/blink/public/platform/modules/webauthn/authenticator.mojom.h"
// TODO(hongjunchoi): Remove type converters and instead expose mojo interface
// directly from device/fido service.
@@ -91,10 +91,9 @@ struct TypeConverter<::device::PublicKeyCredentialUserEntity,
};
template <>
-struct TypeConverter<
- std::vector<::device::FidoCableDiscovery::CableDiscoveryData>,
- std::vector<::blink::mojom::CableAuthenticationPtr>> {
- static std::vector<::device::FidoCableDiscovery::CableDiscoveryData> Convert(
+struct TypeConverter<std::vector<::device::CableDiscoveryData>,
+ std::vector<::blink::mojom::CableAuthenticationPtr>> {
+ static std::vector<::device::CableDiscoveryData> Convert(
const std::vector<::blink::mojom::CableAuthenticationPtr>& input);
};
diff --git a/chromium/content/browser/webauth/scoped_virtual_authenticator_environment.h b/chromium/content/browser/webauth/scoped_virtual_authenticator_environment.h
index 378de2ff2db..0c0bf6f47b9 100644
--- a/chromium/content/browser/webauth/scoped_virtual_authenticator_environment.h
+++ b/chromium/content/browser/webauth/scoped_virtual_authenticator_environment.h
@@ -15,7 +15,7 @@
#include "content/common/content_export.h"
#include "device/fido/fido_discovery.h"
#include "mojo/public/cpp/bindings/binding_set.h"
-#include "third_party/blink/public/platform/modules/webauth/virtual_authenticator.mojom.h"
+#include "third_party/blink/public/platform/modules/webauthn/virtual_authenticator.mojom.h"
namespace content {
diff --git a/chromium/content/browser/webauth/virtual_authenticator.cc b/chromium/content/browser/webauth/virtual_authenticator.cc
index b93637c3189..4fbc6ae976e 100644
--- a/chromium/content/browser/webauth/virtual_authenticator.cc
+++ b/chromium/content/browser/webauth/virtual_authenticator.cc
@@ -7,6 +7,7 @@
#include <utility>
#include <vector>
+#include "base/containers/span.h"
#include "base/guid.h"
#include "crypto/ec_private_key.h"
#include "device/fido/virtual_u2f_device.h"
@@ -64,7 +65,9 @@ void VirtualAuthenticator::AddRegistration(
::device::VirtualFidoDevice::RegistrationData(
crypto::ECPrivateKey::CreateFromPrivateKeyInfo(
registration->private_key),
- registration->application_parameter, registration->counter));
+ base::make_span<device::kRpIdHashLength>(
+ registration->application_parameter),
+ registration->counter));
std::move(callback).Run(success);
}
diff --git a/chromium/content/browser/webauth/virtual_authenticator.h b/chromium/content/browser/webauth/virtual_authenticator.h
index d048250f30b..fe8ecc1719f 100644
--- a/chromium/content/browser/webauth/virtual_authenticator.h
+++ b/chromium/content/browser/webauth/virtual_authenticator.h
@@ -14,7 +14,7 @@
#include "device/fido/fido_transport_protocol.h"
#include "device/fido/virtual_fido_device.h"
#include "mojo/public/cpp/bindings/binding_set.h"
-#include "third_party/blink/public/platform/modules/webauth/virtual_authenticator.mojom.h"
+#include "third_party/blink/public/platform/modules/webauthn/virtual_authenticator.mojom.h"
namespace content {
diff --git a/chromium/content/browser/webauth/webauth_browsertest.cc b/chromium/content/browser/webauth/webauth_browsertest.cc
index 3943e65820e..57bc30c924b 100644
--- a/chromium/content/browser/webauth/webauth_browsertest.cc
+++ b/chromium/content/browser/webauth/webauth_browsertest.cc
@@ -32,8 +32,8 @@
#include "content/test/did_commit_provisional_load_interceptor.h"
#include "device/base/features.h"
#include "device/fido/fake_fido_discovery.h"
-#include "device/fido/fake_hid_impl_for_testing.h"
#include "device/fido/fido_test_data.h"
+#include "device/fido/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"
@@ -42,7 +42,7 @@
#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/platform/modules/webauth/authenticator.mojom.h"
+#include "third_party/blink/public/platform/modules/webauthn/authenticator.mojom.h"
namespace content {
diff --git a/chromium/content/browser/webrtc/webrtc_audio_browsertest.cc b/chromium/content/browser/webrtc/webrtc_audio_browsertest.cc
index d0679ee756a..308f749f75d 100644
--- a/chromium/content/browser/webrtc/webrtc_audio_browsertest.cc
+++ b/chromium/content/browser/webrtc/webrtc_audio_browsertest.cc
@@ -16,12 +16,10 @@
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/test_utils.h"
#include "media/base/media_switches.h"
+#include "media/webrtc/webrtc_switches.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
-#include "testing/gtest/include/gtest/gtest-param-test.h"
-
-#if defined(OS_WIN)
#include "services/service_manager/sandbox/features.h"
-#endif
+#include "testing/gtest/include/gtest/gtest-param-test.h"
namespace content {
@@ -37,6 +35,9 @@ enum class AudioServiceFeatures {
#if defined(OS_WIN)
kSandboxed,
#endif
+#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
+ kSandboxedWithAudioServiceAPM
+#endif
};
} // namespace
@@ -77,6 +78,13 @@ class WebRtcAudioBrowserTest
{});
break;
#endif
+#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
+ case AudioServiceFeatures::kSandboxedWithAudioServiceAPM:
+ audio_service_oop_features.push_back(
+ service_manager::features::kAudioServiceSandbox);
+ audio_service_oop_features.push_back(
+ features::kWebRtcApmInAudioService);
+#endif
}
}
~WebRtcAudioBrowserTest() override {}
@@ -172,17 +180,21 @@ IN_PROC_BROWSER_TEST_P(WebRtcAudioBrowserTest,
// removed after launch.
#if defined(OS_LINUX) || defined(OS_MACOSX)
// Supported platforms.
-INSTANTIATE_TEST_CASE_P(,
- WebRtcAudioBrowserTest,
- ::testing::Values(AudioServiceFeatures::kDisabled,
- AudioServiceFeatures::kOutOfProcess));
+INSTANTIATE_TEST_CASE_P(
+ ,
+ WebRtcAudioBrowserTest,
+ ::testing::Values(AudioServiceFeatures::kDisabled,
+ AudioServiceFeatures::kOutOfProcess,
+ AudioServiceFeatures::kSandboxedWithAudioServiceAPM));
#elif defined(OS_WIN)
// On Windows, also run in sandboxed mode.
-INSTANTIATE_TEST_CASE_P(,
- WebRtcAudioBrowserTest,
- ::testing::Values(AudioServiceFeatures::kDisabled,
- AudioServiceFeatures::kOutOfProcess,
- AudioServiceFeatures::kSandboxed));
+INSTANTIATE_TEST_CASE_P(
+ ,
+ WebRtcAudioBrowserTest,
+ ::testing::Values(AudioServiceFeatures::kDisabled,
+ AudioServiceFeatures::kOutOfProcess,
+ AudioServiceFeatures::kSandboxed,
+ AudioServiceFeatures::kSandboxedWithAudioServiceAPM));
#elif defined(OS_ANDROID) && defined(ADDRESS_SANITIZER)
// Renderer crashes under Android ASAN: https://crbug.com/408496.
#else
diff --git a/chromium/content/browser/webrtc/webrtc_audio_debug_recordings_browsertest.cc b/chromium/content/browser/webrtc/webrtc_audio_debug_recordings_browsertest.cc
index 965c78d992f..65b3adef54f 100644
--- a/chromium/content/browser/webrtc/webrtc_audio_debug_recordings_browsertest.cc
+++ b/chromium/content/browser/webrtc/webrtc_audio_debug_recordings_browsertest.cc
@@ -34,19 +34,6 @@ const int kWaveHeaderSizeBytes = 44;
const base::FilePath::CharType kBaseFilename[] =
FILE_PATH_LITERAL("audio_debug");
-// Get the ID for the render process host when there should only be one.
-bool GetRenderProcessHostId(base::ProcessId* id) {
- content::RenderProcessHost::iterator it(
- content::RenderProcessHost::AllHostsIterator());
- *id = it.GetCurrentValue()->GetProcess().Pid();
- EXPECT_NE(base::kNullProcessId, *id);
- if (*id == base::kNullProcessId)
- return false;
- it.Advance();
- EXPECT_TRUE(it.IsAtEnd());
- return it.IsAtEnd();
-}
-
// Get the expected AEC dump file name. The name will be
// <temporary path>.<render process id>.aec_dump.<consumer id>, for example
// "/tmp/.com.google.Chrome.Z6UC3P.12345.aec_dump.1".
@@ -104,10 +91,11 @@ class WebRtcAudioDebugRecordingsBrowserTest
~WebRtcAudioDebugRecordingsBrowserTest() override {}
};
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) || defined(OS_LINUX)
// Renderer crashes under Android ASAN: https://crbug.com/408496.
// Renderer crashes under Android: https://crbug.com/820934.
// Failures on Android M. https://crbug.com/535728.
+// Flaky on Linux: https://crbug.com/871182
#define MAYBE_CallWithAudioDebugRecordings DISABLED_CallWithAudioDebugRecordings
#else
#define MAYBE_CallWithAudioDebugRecordings CallWithAudioDebugRecordings
@@ -182,8 +170,8 @@ IN_PROC_BROWSER_TEST_F(WebRtcAudioDebugRecordingsBrowserTest,
}
// Verify that the expected AEC dump file exists and contains some data.
- base::ProcessId render_process_id = base::kNullProcessId;
- EXPECT_TRUE(GetRenderProcessHostId(&render_process_id));
+ base::ProcessId render_process_id =
+ shell()->web_contents()->GetMainFrame()->GetProcess()->GetProcess().Pid();
base::FilePath file_path =
GetExpectedAecDumpFileName(base_file_path, render_process_id);
EXPECT_TRUE(base::PathExists(file_path));
@@ -252,19 +240,15 @@ IN_PROC_BROWSER_TEST_F(WebRtcAudioDebugRecordingsBrowserTest,
base::ThreadRestrictions::SetIOAllowed(prev_io_allowed);
}
-#if defined(OS_ANDROID)
+// Same test as CallWithAudioDebugRecordings, but does two parallel calls.
+// TODO(crbug.com/874378): Fix an re-enable test.
+// List of issues filed before this test was disabled for all platforms:
// Renderer crashes under Android ASAN: https://crbug.com/408496.
// Renderer crashes under Android: https://crbug.com/820934.
// Failures on Android M. https://crbug.com/535728.
-#define MAYBE_TwoCallsWithAudioDebugRecordings \
- DISABLED_TwoCallsWithAudioDebugRecordings
-#else
-#define MAYBE_TwoCallsWithAudioDebugRecordings TwoCallsWithAudioDebugRecordings
-#endif
-
-// Same test as CallWithAudioDebugRecordings, but does two parallel calls.
+// Flaky on Linux: https://crbug.com/871182
IN_PROC_BROWSER_TEST_F(WebRtcAudioDebugRecordingsBrowserTest,
- MAYBE_TwoCallsWithAudioDebugRecordings) {
+ DISABLED_TwoCallsWithAudioDebugRecordings) {
if (!HasAudioOutputDevices()) {
LOG(INFO) << "Missing output devices: skipping test...";
return;
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 7b67681f34c..e68b81bb58a 100644
--- a/chromium/content/browser/webrtc/webrtc_capture_from_element_browsertest.cc
+++ b/chromium/content/browser/webrtc/webrtc_capture_from_element_browsertest.cc
@@ -7,6 +7,7 @@
#include "build/build_config.h"
#include "content/browser/webrtc/webrtc_content_browsertest_base.h"
#include "content/public/common/content_switches.h"
+#include "content/public/test/browser_test_utils.h"
#include "content/shell/common/shell_switches.h"
#include "media/base/media_switches.h"
#include "media/base/test_data_util.h"
@@ -108,8 +109,17 @@ IN_PROC_BROWSER_TEST_F(WebRtcCaptureFromElementBrowserTest,
MakeTypicalCall("testCanvasCapture(drawWebGL);", kCanvasCaptureTestHtmlFile);
}
+#if defined(OS_WIN)
+// https://crbug.com/869723
+// Flaky on Windows 10 with Viz (i.e. in viz_content_browsertests).
+#define MAYBE_VerifyCanvasCaptureOffscreenCanvasFrames \
+ DISABLED_VerifyCanvasCaptureOffscreenCanvasFrames
+#else
+#define MAYBE_VerifyCanvasCaptureOffscreenCanvasFrames \
+ VerifyCanvasCaptureOffscreenCanvasFrames
+#endif
IN_PROC_BROWSER_TEST_F(WebRtcCaptureFromElementBrowserTest,
- VerifyCanvasCaptureOffscreenCanvasFrames) {
+ MAYBE_VerifyCanvasCaptureOffscreenCanvasFrames) {
MakeTypicalCall("testCanvasCapture(drawOffscreenCanvas);",
kCanvasCaptureTestHtmlFile);
}
@@ -132,13 +142,10 @@ IN_PROC_BROWSER_TEST_P(WebRtcCaptureFromElementBrowserTest,
}
#endif
- MakeTypicalCall(
- base::StringPrintf("testCaptureFromMediaElement(\"%s\", %d, %d, %d);",
- GetParam().filename.c_str(),
- GetParam().has_video,
- GetParam().has_audio,
- GetParam().use_audio_tag),
- kVideoAudioHtmlFile);
+ MakeTypicalCall(JsReplace("testCaptureFromMediaElement($1, $2, $3, $4)",
+ GetParam().filename, GetParam().has_video,
+ GetParam().has_audio, GetParam().use_audio_tag),
+ kVideoAudioHtmlFile);
}
IN_PROC_BROWSER_TEST_F(WebRtcCaptureFromElementBrowserTest,
diff --git a/chromium/content/browser/webrtc/webrtc_internals.h b/chromium/content/browser/webrtc/webrtc_internals.h
index b8b0c6097c1..b2d75ad012a 100644
--- a/chromium/content/browser/webrtc/webrtc_internals.h
+++ b/chromium/content/browser/webrtc/webrtc_internals.h
@@ -187,7 +187,7 @@ class CONTENT_EXPORT WebRTCInternals : public RenderProcessHostObserver,
int lid,
size_t* index = nullptr);
- base::ObserverList<WebRTCInternalsUIObserver> observers_;
+ base::ObserverList<WebRTCInternalsUIObserver>::Unchecked observers_;
// |peer_connection_data_| is a list containing all the PeerConnection
// updates.
diff --git a/chromium/content/browser/webrtc/webrtc_video_capture_service_browsertest.cc b/chromium/content/browser/webrtc/webrtc_video_capture_service_browsertest.cc
index f632cd62a5f..032f909449b 100644
--- a/chromium/content/browser/webrtc/webrtc_video_capture_service_browsertest.cc
+++ b/chromium/content/browser/webrtc/webrtc_video_capture_service_browsertest.cc
@@ -6,7 +6,6 @@
#include "base/run_loop.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
-#include "components/viz/common/gl_helper.h"
#include "components/viz/common/gpu/context_provider.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_features.h"
@@ -46,7 +45,7 @@ namespace {
class InvokeClosureOnDelete
: public video_capture::mojom::ScopedAccessPermission {
public:
- InvokeClosureOnDelete(base::OnceClosure closure)
+ explicit InvokeClosureOnDelete(base::OnceClosure closure)
: closure_(std::move(closure)) {}
~InvokeClosureOnDelete() override { std::move(closure_).Run(); }
@@ -98,14 +97,12 @@ class TextureDeviceExerciser : public VirtualDeviceExerciser {
CHECK(context_provider_);
gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
CHECK(gl);
- auto gl_helper = std::make_unique<viz::GLHelper>(
- context_provider_->ContextGL(), context_provider_->ContextSupport());
const uint8_t kDarkFrameByteValue = 0;
const uint8_t kLightFrameByteValue = 200;
- CreateDummyRgbFrame(gl, gl_helper.get(), kDarkFrameByteValue,
+ CreateDummyRgbFrame(gl, kDarkFrameByteValue,
&dummy_frame_0_mailbox_holder_);
- CreateDummyRgbFrame(gl, gl_helper.get(), kLightFrameByteValue,
+ CreateDummyRgbFrame(gl, kLightFrameByteValue,
&dummy_frame_1_mailbox_holder_);
}
@@ -169,7 +166,6 @@ class TextureDeviceExerciser : public VirtualDeviceExerciser {
private:
void CreateDummyRgbFrame(gpu::gles2::GLES2Interface* gl,
- viz::GLHelper* gl_helper,
uint8_t value_for_all_rgb_bytes,
std::vector<gpu::MailboxHolder>* target) {
const int32_t kBytesPerRGBPixel = 3;
@@ -187,16 +183,25 @@ class TextureDeviceExerciser : public VirtualDeviceExerciser {
target->push_back(gpu::MailboxHolder());
continue;
}
- auto texture_id = gl_helper->CreateTexture();
- auto mailbox_holder =
- gl_helper->ProduceMailboxHolderFromTexture(texture_id);
+ GLuint texture_id = 0;
+ gl->GenTextures(1, &texture_id);
gl->BindTexture(GL_TEXTURE_2D, texture_id);
+ gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RGB, kDummyFrameDimensions.width(),
kDummyFrameDimensions.height(), 0, GL_RGB,
GL_UNSIGNED_BYTE, dummy_frame_data.get());
gl->BindTexture(GL_TEXTURE_2D, 0);
- target->push_back(std::move(mailbox_holder));
+
+ gpu::Mailbox mailbox;
+ gl->ProduceTextureDirectCHROMIUM(texture_id, mailbox.name);
+ gpu::SyncToken sync_token;
+ gl->GenSyncTokenCHROMIUM(sync_token.GetData());
+
+ target->push_back(gpu::MailboxHolder(mailbox, sync_token, GL_TEXTURE_2D));
}
gl->ShallowFlushCHROMIUM();
CHECK_EQ(gl->GetError(), static_cast<GLenum>(GL_NO_ERROR));
diff --git a/chromium/content/browser/webui/content_web_ui_controller_factory.cc b/chromium/content/browser/webui/content_web_ui_controller_factory.cc
index 5fd3c07d4ef..23651bbbbe8 100644
--- a/chromium/content/browser/webui/content_web_ui_controller_factory.cc
+++ b/chromium/content/browser/webui/content_web_ui_controller_factory.cc
@@ -5,7 +5,6 @@
#include "content/browser/webui/content_web_ui_controller_factory.h"
#include "build/build_config.h"
-#include "content/browser/accessibility/accessibility_ui.h"
#include "content/browser/appcache/appcache_internals_ui.h"
#include "content/browser/gpu/gpu_internals_ui.h"
#include "content/browser/histograms_internals_ui.h"
@@ -38,7 +37,6 @@ WebUI::TypeID ContentWebUIControllerFactory::GetWebUIType(
url.host_piece() == kChromeUIIndexedDBInternalsHost ||
url.host_piece() == kChromeUIMediaInternalsHost ||
url.host_piece() == kChromeUIServiceWorkerInternalsHost ||
- url.host_piece() == kChromeUIAccessibilityHost ||
url.host_piece() == kChromeUIAppCacheInternalsHost ||
url.host_piece() == kChromeUINetworkErrorsListingHost ||
url.host_piece() == kChromeUIProcessInternalsHost) {
@@ -74,8 +72,6 @@ ContentWebUIControllerFactory::CreateWebUIControllerForURL(
return std::make_unique<IndexedDBInternalsUI>(web_ui);
if (url.host_piece() == kChromeUIMediaInternalsHost)
return std::make_unique<MediaInternalsUI>(web_ui);
- if (url.host_piece() == kChromeUIAccessibilityHost)
- return std::make_unique<AccessibilityUI>(web_ui);
if (url.host_piece() == kChromeUIServiceWorkerInternalsHost)
return std::make_unique<ServiceWorkerInternalsUI>(web_ui);
if (url.host_piece() == kChromeUINetworkErrorsListingHost)
diff --git a/chromium/content/browser/webui/url_data_manager.cc b/chromium/content/browser/webui/url_data_manager.cc
index ce87d5984c0..fca1d4aa616 100644
--- a/chromium/content/browser/webui/url_data_manager.cc
+++ b/chromium/content/browser/webui/url_data_manager.cc
@@ -6,6 +6,7 @@
#include <stddef.h>
+#include <utility>
#include <vector>
#include "base/bind.h"
@@ -128,9 +129,10 @@ void URLDataManager::DeleteDataSource(const URLDataSourceImpl* data_source) {
// static
void URLDataManager::AddDataSource(BrowserContext* browser_context,
- URLDataSource* source) {
- GetFromBrowserContext(browser_context)->
- AddDataSource(new URLDataSourceImpl(source->GetSource(), source));
+ std::unique_ptr<URLDataSource> source) {
+ std::string name = source->GetSource();
+ GetFromBrowserContext(browser_context)
+ ->AddDataSource(new URLDataSourceImpl(name, std::move(source)));
}
// static
diff --git a/chromium/content/browser/webui/url_data_manager.h b/chromium/content/browser/webui/url_data_manager.h
index 5ceb74d411f..95cff69e1b4 100644
--- a/chromium/content/browser/webui/url_data_manager.h
+++ b/chromium/content/browser/webui/url_data_manager.h
@@ -57,7 +57,7 @@ class CONTENT_EXPORT URLDataManager : public base::SupportsUserData::Data {
// |URLDataManager|. Creates a URLDataSourceImpl to wrap the given
// source.
static void AddDataSource(BrowserContext* browser_context,
- URLDataSource* source);
+ std::unique_ptr<URLDataSource> source);
// Adds a WebUI data source to |browser_context|'s |URLDataManager|.
static void AddWebUIDataSource(BrowserContext* browser_context,
diff --git a/chromium/content/browser/webui/url_data_manager_backend.cc b/chromium/content/browser/webui/url_data_manager_backend.cc
index 80f12df9d42..9a2cb49cf5a 100644
--- a/chromium/content/browser/webui/url_data_manager_backend.cc
+++ b/chromium/content/browser/webui/url_data_manager_backend.cc
@@ -8,12 +8,9 @@
#include <utility>
#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/compiler_specific.h"
-#include "base/debug/alias.h"
-#include "base/lazy_instance.h"
#include "base/location.h"
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
#include "base/memory/ref_counted_memory.h"
#include "base/single_thread_task_runner.h"
@@ -21,7 +18,7 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
-#include "base/task_scheduler/post_task.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/blob_storage/chrome_blob_storage_context.h"
@@ -267,13 +264,24 @@ std::unique_ptr<net::SourceStream> URLRequestChromeJob::SetUpSourceStream() {
void URLRequestChromeJob::MimeTypeAvailable(const std::string& mime_type) {
mime_type_ = mime_type;
- NotifyHeadersComplete();
}
void URLRequestChromeJob::DataAvailable(base::RefCountedMemory* bytes) {
TRACE_EVENT_ASYNC_END0("browser", "DataManager:Request", this);
DCHECK(!data_);
+ if (bytes)
+ set_expected_content_size(bytes->size());
+
+ // We notify headers are complete unusually late for these jobs, because we
+ // need to have |bytes| first to report an accurate expected content size.
+ // Otherwise, we cannot support <video> streaming.
+ NotifyHeadersComplete();
+
+ // The job can be cancelled after sending the headers.
+ if (is_done())
+ return;
+
// All further requests will be satisfied from the passed-in data.
data_ = bytes;
if (!bytes)
@@ -416,9 +424,8 @@ class ChromeProtocolHandler
URLDataManagerBackend::URLDataManagerBackend()
: next_request_id_(0), weak_factory_(this) {
URLDataSource* shared_source = new SharedResourcesDataSource();
- URLDataSourceImpl* source_impl =
- new URLDataSourceImpl(shared_source->GetSource(), shared_source);
- AddDataSource(source_impl);
+ AddDataSource(new URLDataSourceImpl(shared_source->GetSource(),
+ base::WrapUnique(shared_source)));
}
URLDataManagerBackend::~URLDataManagerBackend() = default;
@@ -500,7 +507,6 @@ bool URLDataManagerBackend::StartRequest(const net::URLRequest* request,
if (mime_type == "text/html")
job->SetSource(source);
- // Also notifies that the headers are complete.
job->MimeTypeAvailable(mime_type);
// Look up additional request info to pass down.
@@ -589,8 +595,8 @@ scoped_refptr<net::HttpResponseHeaders> URLDataManagerBackend::GetHeaders(
// Set the headers so that requests serviced by ChromeURLDataManager return a
// status code of 200. Without this they return a 0, which makes the status
// indistiguishable from other error types. Instant relies on getting a 200.
- scoped_refptr<net::HttpResponseHeaders> headers(
- new net::HttpResponseHeaders("HTTP/1.1 200 OK"));
+ auto headers =
+ base::MakeRefCounted<net::HttpResponseHeaders>("HTTP/1.1 200 OK");
if (!source_impl)
return headers;
diff --git a/chromium/content/browser/webui/url_data_source_impl.cc b/chromium/content/browser/webui/url_data_source_impl.cc
index 47c2ae68868..1a38e0b9c1d 100644
--- a/chromium/content/browser/webui/url_data_source_impl.cc
+++ b/chromium/content/browser/webui/url_data_source_impl.cc
@@ -16,8 +16,8 @@
namespace content {
URLDataSourceImpl::URLDataSourceImpl(const std::string& source_name,
- URLDataSource* source)
- : source_name_(source_name), backend_(nullptr), source_(source) {}
+ std::unique_ptr<URLDataSource> source)
+ : source_name_(source_name), source_(std::move(source)) {}
URLDataSourceImpl::~URLDataSourceImpl() {
}
diff --git a/chromium/content/browser/webui/url_data_source_impl.h b/chromium/content/browser/webui/url_data_source_impl.h
index 62cbd439883..56f0aea4546 100644
--- a/chromium/content/browser/webui/url_data_source_impl.h
+++ b/chromium/content/browser/webui/url_data_source_impl.h
@@ -52,10 +52,9 @@ struct DeleteURLDataSource {
class URLDataSourceImpl : public base::RefCountedThreadSafe<
URLDataSourceImpl, DeleteURLDataSource> {
public:
- // See source_name_ below for docs on that parameter. Takes ownership of
- // |source|.
+ // See |source_name_| below for docs on that parameter.
URLDataSourceImpl(const std::string& source_name,
- URLDataSource* source);
+ std::unique_ptr<URLDataSource> source);
// Report that a request has resulted in the data |bytes|.
// If the request can't be satisfied, pass NULL for |bytes| to indicate
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 5dad37af6f2..46f56be78db 100644
--- a/chromium/content/browser/webui/web_ui_data_source_impl.cc
+++ b/chromium/content/browser/webui/web_ui_data_source_impl.cc
@@ -8,6 +8,8 @@
#include <stdint.h>
#include <string>
+#include <utility>
+#include <vector>
#include "base/bind.h"
#include "base/logging.h"
@@ -105,7 +107,8 @@ class WebUIDataSourceImpl::InternalDataSource : public URLDataSource {
};
WebUIDataSourceImpl::WebUIDataSourceImpl(const std::string& source_name)
- : URLDataSourceImpl(source_name, new InternalDataSource(this)),
+ : URLDataSourceImpl(source_name,
+ std::make_unique<InternalDataSource>(this)),
source_name_(source_name),
default_resource_(-1),
add_csp_(true),
diff --git a/chromium/content/browser/webui/web_ui_mojo_browsertest.cc b/chromium/content/browser/webui/web_ui_mojo_browsertest.cc
index d8ab9ec2be1..3f4031598fa 100644
--- a/chromium/content/browser/webui/web_ui_mojo_browsertest.cc
+++ b/chromium/content/browser/webui/web_ui_mojo_browsertest.cc
@@ -45,7 +45,7 @@ namespace {
bool g_got_message = false;
base::FilePath GetFilePathForJSResource(const std::string& path) {
- base::ThreadRestrictions::ScopedAllowIO allow_io_from_test_callbacks;
+ base::ScopedAllowBlockingForTesting allow_blocking;
std::string binding_path = "gen/" + path;
#if defined(OS_WIN)
@@ -60,7 +60,7 @@ base::FilePath GetFilePathForJSResource(const std::string& path) {
// up the generated file from disk and returns it.
bool GetResource(const std::string& id,
const WebUIDataSource::GotDataCallback& callback) {
- base::ThreadRestrictions::ScopedAllowIO allow_io_from_test_callbacks;
+ base::ScopedAllowBlockingForTesting allow_blocking;
std::string contents;
if (base::EndsWith(id, ".mojom.js", base::CompareCase::SENSITIVE)) {
@@ -274,7 +274,7 @@ bool IsGeneratedResourceAvailable(const std::string& resource_path) {
// files. If the bindings file doesn't exist assume we're on such a bot and
// pass.
// TODO(sky): remove this conditional when isolates support copying from gen.
- base::ThreadRestrictions::ScopedAllowIO allow_io_for_file_existence_check;
+ base::ScopedAllowBlockingForTesting allow_blocking;
const base::FilePath test_file_path(GetFilePathForJSResource(resource_path));
if (base::PathExists(test_file_path))
return true;
diff --git a/chromium/content/browser/webui/web_ui_url_loader_factory.cc b/chromium/content/browser/webui/web_ui_url_loader_factory.cc
index 653e22e0ee5..a0e39809838 100644
--- a/chromium/content/browser/webui/web_ui_url_loader_factory.cc
+++ b/chromium/content/browser/webui/web_ui_url_loader_factory.cc
@@ -13,7 +13,7 @@
#include "base/memory/ref_counted_memory.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_piece.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "content/browser/bad_message.h"
#include "content/browser/blob_storage/blob_internals_url_loader.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
diff --git a/chromium/content/browser/zoom_browsertest.cc b/chromium/content/browser/zoom_browsertest.cc
index 6c653819f2c..7d776641853 100644
--- a/chromium/content/browser/zoom_browsertest.cc
+++ b/chromium/content/browser/zoom_browsertest.cc
@@ -95,13 +95,12 @@ double GetMainframeWindowBorder(const ToRenderFrameHost& adapter) {
}
double GetMainFrameZoomFactor(const ToRenderFrameHost& adapter, double border) {
- const char kGetMainFrameZoomLevel[] =
- "window.domAutomationController.send("
- "(window.outerWidth - %f)/window.innerWidth"
- ");";
double zoom_factor;
EXPECT_TRUE(ExecuteScriptAndExtractDouble(
- adapter, base::StringPrintf(kGetMainFrameZoomLevel, border),
+ adapter,
+ JsReplace("window.domAutomationController.send("
+ " (window.outerWidth - $1) / window.innerWidth);",
+ border),
&zoom_factor));
return zoom_factor;
}
diff --git a/chromium/content/child/BUILD.gn b/chromium/content/child/BUILD.gn
index 1f8971c0eb0..018a0053ef9 100644
--- a/chromium/content/child/BUILD.gn
+++ b/chromium/content/child/BUILD.gn
@@ -55,6 +55,8 @@ target(link_target_type, "child") {
"dwrite_font_proxy/dwrite_localized_strings_win.h",
"dwrite_font_proxy/font_fallback_win.cc",
"dwrite_font_proxy/font_fallback_win.h",
+ "field_trial.cc",
+ "field_trial.h",
"font_warmup_win.cc",
"font_warmup_win.h",
"image_decoder.cc",
diff --git a/chromium/content/child/blink_platform_impl.cc b/chromium/content/child/blink_platform_impl.cc
index 49c0dcb3182..50fedfa4c46 100644
--- a/chromium/content/child/blink_platform_impl.cc
+++ b/chromium/content/child/blink_platform_impl.cc
@@ -107,6 +107,8 @@ static int ToMessageID(WebLocalizedString::Name name) {
return IDS_AX_MEDIA_ENTER_FULL_SCREEN_BUTTON;
case WebLocalizedString::kAXMediaExitFullscreenButton:
return IDS_AX_MEDIA_EXIT_FULL_SCREEN_BUTTON;
+ case WebLocalizedString::kAXMediaDisplayCutoutFullscreenButton:
+ return IDS_AX_MEDIA_DISPLAY_CUT_OUT_FULL_SCREEN_BUTTON;
case WebLocalizedString::kAXMediaEnterPictureInPictureButton:
return IDS_AX_MEDIA_ENTER_PICTURE_IN_PICTURE_BUTTON;
case WebLocalizedString::kAXMediaExitPictureInPictureButton:
@@ -147,6 +149,8 @@ static int ToMessageID(WebLocalizedString::Name name) {
return IDS_AX_MEDIA_ENTER_FULL_SCREEN_BUTTON_HELP;
case WebLocalizedString::kAXMediaExitFullscreenButtonHelp:
return IDS_AX_MEDIA_EXIT_FULL_SCREEN_BUTTON_HELP;
+ case WebLocalizedString::kAXMediaDisplayCutoutFullscreenButtonHelp:
+ return IDS_AX_MEDIA_DISPLAY_CUT_OUT_FULL_SCREEN_BUTTON_HELP;
case WebLocalizedString::kAXMediaEnterPictureInPictureButtonHelp:
return IDS_AX_MEDIA_ENTER_PICTURE_IN_PICTURE_BUTTON_HELP;
case WebLocalizedString::kAXMediaExitPictureInPictureButtonHelp:
diff --git a/chromium/content/child/child_process.cc b/chromium/content/child/child_process.cc
index 7f70a3408c6..7b55e6f2a25 100644
--- a/chromium/content/child/child_process.cc
+++ b/chromium/content/child/child_process.cc
@@ -11,7 +11,7 @@
#include "base/message_loop/message_loop.h"
#include "base/process/process_handle.h"
#include "base/single_thread_task_runner.h"
-#include "base/task_scheduler/task_scheduler.h"
+#include "base/task/task_scheduler/task_scheduler.h"
#include "base/threading/thread.h"
#include "base/threading/thread_local.h"
#include "build/build_config.h"
diff --git a/chromium/content/child/child_process.h b/chromium/content/child/child_process.h
index e80c6555e1e..0721f11a460 100644
--- a/chromium/content/child/child_process.h
+++ b/chromium/content/child/child_process.h
@@ -10,7 +10,7 @@
#include "base/macros.h"
#include "base/synchronization/waitable_event.h"
-#include "base/task_scheduler/task_scheduler.h"
+#include "base/task/task_scheduler/task_scheduler.h"
#include "base/threading/platform_thread.h"
#include "base/threading/thread.h"
#include "content/common/content_export.h"
diff --git a/chromium/content/child/child_thread_impl.cc b/chromium/content/child/child_thread_impl.cc
index 53f41fc6b2a..f797ee88a23 100644
--- a/chromium/content/child/child_thread_impl.cc
+++ b/chromium/content/child/child_thread_impl.cc
@@ -21,7 +21,6 @@
#include "base/message_loop/timer_slack.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram_macros.h"
-#include "base/no_destructor.h"
#include "base/optional.h"
#include "base/process/process.h"
#include "base/process/process_handle.h"
@@ -78,26 +77,9 @@
#include "content/public/common/content_descriptors.h"
#endif
-#if defined(CLANG_COVERAGE)
-extern "C" int __llvm_profile_dump(void);
-#endif
-
namespace content {
namespace {
-void WriteClangCoverageProfile() {
-#if defined(CLANG_COVERAGE)
- // __llvm_profile_dump() guarantees that it will not dump coverage information
- // if it is being called twice or more. However, it is not thread safe, as it
- // is supposed to be called from atexit() handler rather than being called
- // directly from random places. Since we have to call it ourselves, we must
- // ensure thread safety in order to prevent duplication of coverage counters.
- static base::NoDestructor<base::Lock> lock;
- base::AutoLock auto_lock(*lock);
- __llvm_profile_dump();
-#endif
-}
-
// How long to wait for a connection to the browser process before giving up.
const int kConnectionTimeoutS = 15;
@@ -112,8 +94,8 @@ base::LazyInstance<base::ThreadLocalPointer<ChildThreadImpl>>::DestructorAtExit
#if defined(ADDRESS_SANITIZER) || defined(LEAK_SANITIZER) || \
defined(MEMORY_SANITIZER) || defined(THREAD_SANITIZER) || \
defined(UNDEFINED_SANITIZER)
-// A thread delegate that waits for |duration| and then exits the process with
-// _exit(0).
+// A thread delegate that waits for |duration| and then exits the process
+// immediately, without executing finalizers.
class WaitAndExitDelegate : public base::PlatformThread::Delegate {
public:
explicit WaitAndExitDelegate(base::TimeDelta duration)
@@ -121,8 +103,7 @@ class WaitAndExitDelegate : public base::PlatformThread::Delegate {
void ThreadMain() override {
base::PlatformThread::Sleep(duration_);
- WriteClangCoverageProfile();
- _exit(0);
+ base::Process::TerminateCurrentProcessImmediately(0);
}
private:
@@ -182,8 +163,7 @@ class SuicideOnChannelErrorFilter : public IPC::MessageFilter {
__lsan_do_leak_check();
#endif
#else
- WriteClangCoverageProfile();
- _exit(0);
+ base::Process::TerminateCurrentProcessImmediately(0);
#endif
}
@@ -649,12 +629,7 @@ ChildThreadImpl::~ChildThreadImpl() {
g_lazy_tls.Pointer()->Set(nullptr);
}
-void ChildThreadImpl::Shutdown() {
- // The renderer process (and others) can to fast shutdown by calling _exit(0),
- // in which case the clang-coverage profile does not get written to the file.
- // So force write the profile here before shutting down.
- WriteClangCoverageProfile();
-}
+void ChildThreadImpl::Shutdown() {}
bool ChildThreadImpl::ShouldBeDestroyed() {
return true;
@@ -844,14 +819,14 @@ void ChildThreadImpl::EnsureConnected() {
void ChildThreadImpl::GetRoute(
int32_t routing_id,
- mojom::AssociatedInterfaceProviderAssociatedRequest request) {
+ blink::mojom::AssociatedInterfaceProviderAssociatedRequest request) {
associated_interface_provider_bindings_.AddBinding(
this, std::move(request), routing_id);
}
void ChildThreadImpl::GetAssociatedInterface(
const std::string& name,
- mojom::AssociatedInterfaceAssociatedRequest request) {
+ blink::mojom::AssociatedInterfaceAssociatedRequest request) {
int32_t routing_id =
associated_interface_provider_bindings_.dispatch_context();
Listener* route = router_.GetRoute(routing_id);
diff --git a/chromium/content/child/child_thread_impl.h b/chromium/content/child/child_thread_impl.h
index d44813ed642..3155e449790 100644
--- a/chromium/content/child/child_thread_impl.h
+++ b/chromium/content/child/child_thread_impl.h
@@ -32,6 +32,7 @@
#include "mojo/public/cpp/bindings/associated_binding.h"
#include "mojo/public/cpp/bindings/associated_binding_set.h"
#include "services/tracing/public/cpp/trace_event_agent.h"
+#include "third_party/blink/public/mojom/associated_interfaces/associated_interfaces.mojom.h"
#if defined(OS_WIN)
#include "content/public/common/font_cache_win.mojom.h"
@@ -63,7 +64,7 @@ class CONTENT_EXPORT ChildThreadImpl
private base::FieldTrialList::Observer,
public ChildMemoryCoordinatorDelegate,
public mojom::RouteProvider,
- public mojom::AssociatedInterfaceProvider,
+ public blink::mojom::AssociatedInterfaceProvider,
public mojom::ChildControl {
public:
struct CONTENT_EXPORT Options;
@@ -209,14 +210,14 @@ class CONTENT_EXPORT ChildThreadImpl
void EnsureConnected();
// mojom::RouteProvider:
- void GetRoute(
- int32_t routing_id,
- mojom::AssociatedInterfaceProviderAssociatedRequest request) override;
+ void GetRoute(int32_t routing_id,
+ blink::mojom::AssociatedInterfaceProviderAssociatedRequest
+ request) override;
- // mojom::AssociatedInterfaceProvider:
+ // blink::mojom::AssociatedInterfaceProvider:
void GetAssociatedInterface(
const std::string& name,
- mojom::AssociatedInterfaceAssociatedRequest request) override;
+ blink::mojom::AssociatedInterfaceAssociatedRequest request) override;
#if defined(OS_WIN)
mojom::FontCacheWin* GetFontCacheWin();
@@ -227,7 +228,7 @@ class CONTENT_EXPORT ChildThreadImpl
mojo::BindingSet<mojom::ChildControl> child_control_bindings_;
mojo::AssociatedBinding<mojom::RouteProvider> route_provider_binding_;
- mojo::AssociatedBindingSet<mojom::AssociatedInterfaceProvider, int32_t>
+ mojo::AssociatedBindingSet<blink::mojom::AssociatedInterfaceProvider, int32_t>
associated_interface_provider_bindings_;
mojom::RouteProviderAssociatedPtr remote_route_provider_;
#if defined(OS_WIN)
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 80396e7ce1e..6387f299273 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
@@ -14,7 +14,7 @@
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "content/child/dwrite_font_proxy/dwrite_localized_strings_win.h"
#include "content/public/child/child_thread.h"
#include "content/public/common/service_names.mojom.h"
diff --git a/chromium/content/child/field_trial.cc b/chromium/content/child/field_trial.cc
new file mode 100644
index 00000000000..b33c04ffa4c
--- /dev/null
+++ b/chromium/content/child/field_trial.cc
@@ -0,0 +1,54 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/child/field_trial.h"
+#include "base/base_switches.h"
+#include "base/command_line.h"
+#include "base/debug/leak_annotations.h"
+#include "base/feature_list.h"
+#include "base/macros.h"
+#include "base/metrics/field_trial.h"
+#include "build/build_config.h"
+#include "content/public/common/content_switches.h"
+#include "services/service_manager/embedder/descriptors.h"
+
+namespace content {
+
+void InitializeFieldTrialAndFeatureList() {
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
+
+ // Initialize statistical testing infrastructure. We set the entropy
+ // provider to nullptr to disallow non-browser processes from creating
+ // their own one-time randomized trials; they should be created in the
+ // browser process.
+ //
+ // This is intentionally leaked since it needs to live for the duration of the
+ // process and there's no benefit in cleaning it up at exit.
+ base::FieldTrialList* leaked_field_trial_list =
+ new base::FieldTrialList(nullptr);
+ ANNOTATE_LEAKING_OBJECT_PTR(leaked_field_trial_list);
+ ignore_result(leaked_field_trial_list);
+
+// Ensure any field trials in browser are reflected into the child
+// process.
+#if defined(OS_WIN)
+ base::FieldTrialList::CreateTrialsFromCommandLine(
+ command_line, switches::kFieldTrialHandle, -1);
+#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
+ // On POSIX systems that use the zygote, we get the trials from a shared
+ // memory segment backed by an fd instead of the command line.
+ base::FieldTrialList::CreateTrialsFromCommandLine(
+ command_line, switches::kFieldTrialHandle,
+ service_manager::kFieldTrialDescriptor);
+#endif
+
+ std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
+ base::FieldTrialList::CreateFeaturesFromCommandLine(
+ command_line, switches::kEnableFeatures, switches::kDisableFeatures,
+ feature_list.get());
+ base::FeatureList::SetInstance(std::move(feature_list));
+}
+
+} // namespace content
diff --git a/chromium/content/child/field_trial.h b/chromium/content/child/field_trial.h
new file mode 100644
index 00000000000..8fea81d966a
--- /dev/null
+++ b/chromium/content/child/field_trial.h
@@ -0,0 +1,12 @@
+// 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_CHILD_FIELD_TRIAL_H_
+#define CONTENT_PUBLIC_CHILD_FIELD_TRIAL_H_
+
+namespace content {
+void InitializeFieldTrialAndFeatureList();
+}
+
+#endif // CONTENT_PUBLIC_CHILD_FIELD_TRIAL_H_
diff --git a/chromium/content/child/font_warmup_win_unittest.cc b/chromium/content/child/font_warmup_win_unittest.cc
index 0dea002d4fc..32b556a0827 100644
--- a/chromium/content/child/font_warmup_win_unittest.cc
+++ b/chromium/content/child/font_warmup_win_unittest.cc
@@ -4,213 +4,101 @@
#include "content/child/font_warmup_win.h"
+#include <dwrite.h>
#include <stddef.h>
#include <stdint.h>
#include <windows.h>
+#include <wrl.h>
#include <memory>
#include <vector>
#include "base/files/file_path.h"
#include "base/logging.h"
+#include "base/path_service.h"
#include "base/sys_byteorder.h"
+#include "base/test/scoped_task_environment.h"
#include "base/win/windows_version.h"
+
+#include "content/child/dwrite_font_proxy/dwrite_font_proxy_win.h"
+#include "content/public/common/content_paths.h"
+#include "content/test/dwrite_font_fake_sender_win.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkFontMgr.h"
#include "third_party/skia/include/core/SkRefCnt.h"
#include "third_party/skia/include/core/SkStream.h"
#include "third_party/skia/include/core/SkString.h"
#include "third_party/skia/include/core/SkTypeface.h"
+#include "third_party/skia/include/ports/SkTypeface_win.h"
+
+namespace mswr = Microsoft::WRL;
namespace content {
namespace {
-class TestSkTypeface : public SkTypeface {
+class GDIFontEmulationTest : public testing::Test {
public:
- TestSkTypeface(const SkFontStyle& style,
- const char* familyName,
- SkFontTableTag tag,
- const char* data,
- size_t dataLength)
- : SkTypeface(style, 0),
- familyName_(familyName),
- tag_(tag),
- data_(data, data + dataLength) {}
-
- protected:
- SkScalerContext* onCreateScalerContext(const SkScalerContextEffects&,
- const SkDescriptor*) const override {
- ADD_FAILURE();
- return nullptr;
+ GDIFontEmulationTest() {
+ fake_collection_ = std::make_unique<FakeFontCollection>();
+ SetupFonts(fake_collection_.get());
+ DWriteFontCollectionProxy::Create(&collection_, factory.Get(),
+ fake_collection_->CreatePtr());
+ EXPECT_TRUE(collection_.Get());
+
+ content::SetPreSandboxWarmupFontMgrForTesting(
+ SkFontMgr_New_DirectWrite(factory.Get(), collection_.Get()));
}
- void onFilterRec(SkScalerContextRec*) const override { ADD_FAILURE(); }
- SkStreamAsset* onOpenStream(int* ttcIndex) const override {
- ADD_FAILURE();
- return nullptr;
- }
-
- int onGetVariationDesignPosition(
- SkFontArguments::VariationPosition::Coordinate coordinates[],
- int coordinateCount) const override {
- ADD_FAILURE();
- return -1;
- }
-
- void onGetFontDescriptor(SkFontDescriptor*, bool* isLocal) const override {
- ADD_FAILURE();
- }
-
- int onCharsToGlyphs(const void* chars,
- Encoding,
- uint16_t glyphs[],
- int glyphCount) const override {
- ADD_FAILURE();
- return 0;
- }
-
- int onCountGlyphs() const override {
- ADD_FAILURE();
- return 0;
- }
-
- int onGetUPEM() const override {
- ADD_FAILURE();
- return 0;
- }
- bool onGetKerningPairAdjustments(const uint16_t glyphs[],
- int count,
- int32_t adjustments[]) const override {
- ADD_FAILURE();
- return false;
- }
+ ~GDIFontEmulationTest() override {
+ content::SetPreSandboxWarmupFontMgrForTesting(nullptr);
- void onGetFamilyName(SkString* familyName) const override {
- *familyName = familyName_;
+ if (collection_)
+ collection_->Unregister();
}
- LocalizedStrings* onCreateFamilyNameIterator() const override {
- ADD_FAILURE();
- return nullptr;
- }
+ static void SetupFonts(FakeFontCollection* fonts) {
+ base::FilePath data_path;
+ EXPECT_TRUE(base::PathService::Get(content::DIR_TEST_DATA, &data_path));
- int onGetTableTags(SkFontTableTag tags[]) const override {
- ADD_FAILURE();
- return 0;
+ base::FilePath gdi_path = data_path.AppendASCII("font/gdi_test.ttf");
+ fonts->AddFont(L"GDITest")
+ .AddFamilyName(L"en-us", L"GDITest")
+ .AddFamilyName(L"de-de", L"GDIUntersuchung")
+ .AddFilePath(gdi_path);
}
- size_t onGetTableData(SkFontTableTag tag,
- size_t offset,
- size_t length,
- void* data) const override {
- size_t retsize = 0;
- if (tag == tag_) {
- retsize = length > data_.size() ? data_.size() : length;
- if (data)
- memcpy(data, &data_[0], retsize);
- }
- return retsize;
+ static void SetUpTestCase() {
+ DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory),
+ &factory);
}
- bool onComputeBounds(SkRect*) const override {
- ADD_FAILURE();
- return false;
- }
+ protected:
+ base::test::ScopedTaskEnvironment task_environment;
+ std::unique_ptr<FakeFontCollection> fake_collection_;
+ mswr::ComPtr<DWriteFontCollectionProxy> collection_;
- private:
- SkString familyName_;
- SkFontTableTag tag_;
- std::vector<char> data_;
+ static mswr::ComPtr<IDWriteFactory> factory;
};
+mswr::ComPtr<IDWriteFactory> GDIFontEmulationTest::factory;
-const char* kTestFontFamily = "GDITest";
+// The test fixture will provide a font named "GDITest".
const wchar_t* kTestFontFamilyW = L"GDITest";
-const SkFontTableTag kTestFontTableTag = 0x11223344;
-const char* kTestFontData = "GDITestGDITest";
-const wchar_t* kTestFontFamilyInvalid = L"InvalidFont";
-
-class TestSkFontMgr : public SkFontMgr {
- public:
- TestSkFontMgr() {
- content::SetPreSandboxWarmupFontMgrForTesting(sk_ref_sp(this));
- }
- ~TestSkFontMgr() override {
- content::SetPreSandboxWarmupFontMgrForTesting(nullptr);
- }
- protected:
- int onCountFamilies() const override { return 1; }
+// The "GDITest" font will have an 'hhea' table (all ttf fonts do).
+const DWORD kTestFontTableTag = DWRITE_MAKE_OPENTYPE_TAG('h', 'h', 'e', 'a');
- void onGetFamilyName(int index, SkString* familyName) const override {
- if (index == 0)
- *familyName = kTestFontFamily;
- }
+// The 'hhea' table will be of length 36 (all 'hhea' tables do).
+const size_t kTestFontTableDataLength = 36;
- SkFontStyleSet* onCreateStyleSet(int index) const override {
- ADD_FAILURE();
- return nullptr;
- }
-
- SkFontStyleSet* onMatchFamily(const char familyName[]) const override {
- ADD_FAILURE();
- return nullptr;
- }
-
- SkTypeface* onMatchFamilyStyle(const char familyName[],
- const SkFontStyle&) const override {
- if (strcmp(familyName, kTestFontFamily) == 0)
- return createTypeface();
- return nullptr;
- }
-
- SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
- const SkFontStyle&,
- const char* bcp47[],
- int bcp47Count,
- SkUnichar character) const override {
- ADD_FAILURE();
- return nullptr;
- }
-
- SkTypeface* onMatchFaceStyle(const SkTypeface*,
- const SkFontStyle&) const override {
- ADD_FAILURE();
- return nullptr;
- }
+// The 'hhea' table will contain this content (specific to this font).
+const uint8_t kTestFontTableData[kTestFontTableDataLength] = {
+ 0x00, 0x01, 0x00, 0x00, 0x03, 0x34, 0xFF, 0x33, 0x00, 0x5e, 0x04, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03};
- sk_sp<SkTypeface> onMakeFromData(sk_sp<SkData>, int ttcIndex) const override {
- ADD_FAILURE();
- return nullptr;
- }
-
- sk_sp<SkTypeface> onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset>,
- int ttcIndex) const override {
- ADD_FAILURE();
- return nullptr;
- }
-
- sk_sp<SkTypeface> onMakeFromFile(const char path[],
- int ttcIndex) const override {
- ADD_FAILURE();
- return nullptr;
- }
-
- sk_sp<SkTypeface> onLegacyMakeTypeface(const char familyName[],
- SkFontStyle style) const override {
- ADD_FAILURE();
- return nullptr;
- }
-
- private:
- SkTypeface* createTypeface() const {
- SkFontStyle style(400, 100, SkFontStyle::kUpright_Slant);
-
- return new TestSkTypeface(style, kTestFontFamily,
- base::ByteSwap(kTestFontTableTag), kTestFontData,
- strlen(kTestFontData));
- }
-};
+// The test fixture will not provide a font names "InvalidFont".
+const wchar_t* kTestFontFamilyInvalid = L"InvalidFont";
void InitLogFont(LOGFONTW* logfont, const wchar_t* fontname) {
size_t length = std::min(sizeof(logfont->lfFaceName),
@@ -247,10 +135,9 @@ int CALLBACK EnumFontCallbackTest(const LOGFONT* log_font,
} // namespace
-TEST(GDIFontEmulationTest, CreateDeleteDCSuccess) {
+TEST_F(GDIFontEmulationTest, CreateDeleteDCSuccess) {
if (base::win::GetVersion() < base::win::VERSION_WIN8)
return;
- TestSkFontMgr fontmgr;
std::unique_ptr<GdiFontPatchData> patch_data(SetupTest());
EXPECT_FALSE(!patch_data);
@@ -261,10 +148,9 @@ TEST(GDIFontEmulationTest, CreateDeleteDCSuccess) {
EXPECT_EQ(0u, GetEmulatedGdiHandleCountForTesting());
}
-TEST(GDIFontEmulationTest, CreateUniqueDCSuccess) {
+TEST_F(GDIFontEmulationTest, CreateUniqueDCSuccess) {
if (base::win::GetVersion() < base::win::VERSION_WIN8)
return;
- TestSkFontMgr fontmgr;
std::unique_ptr<GdiFontPatchData> patch_data(SetupTest());
EXPECT_NE(patch_data, nullptr);
@@ -279,10 +165,9 @@ TEST(GDIFontEmulationTest, CreateUniqueDCSuccess) {
EXPECT_EQ(0u, GetEmulatedGdiHandleCountForTesting());
}
-TEST(GDIFontEmulationTest, CreateFontSuccess) {
+TEST_F(GDIFontEmulationTest, CreateFontSuccess) {
if (base::win::GetVersion() < base::win::VERSION_WIN8)
return;
- TestSkFontMgr fontmgr;
std::unique_ptr<GdiFontPatchData> patch_data(SetupTest());
EXPECT_NE(patch_data, nullptr);
LOGFONTW logfont = {0};
@@ -293,10 +178,9 @@ TEST(GDIFontEmulationTest, CreateFontSuccess) {
EXPECT_EQ(0u, GetEmulatedGdiHandleCountForTesting());
}
-TEST(GDIFontEmulationTest, CreateFontFailure) {
+TEST_F(GDIFontEmulationTest, CreateFontFailure) {
if (base::win::GetVersion() < base::win::VERSION_WIN8)
return;
- TestSkFontMgr fontmgr;
std::unique_ptr<GdiFontPatchData> patch_data(SetupTest());
EXPECT_NE(patch_data, nullptr);
LOGFONTW logfont = {0};
@@ -305,10 +189,9 @@ TEST(GDIFontEmulationTest, CreateFontFailure) {
EXPECT_EQ(font, nullptr);
}
-TEST(GDIFontEmulationTest, EnumFontFamilySuccess) {
+TEST_F(GDIFontEmulationTest, EnumFontFamilySuccess) {
if (base::win::GetVersion() < base::win::VERSION_WIN8)
return;
- TestSkFontMgr fontmgr;
std::unique_ptr<GdiFontPatchData> patch_data(SetupTest());
EXPECT_NE(patch_data, nullptr);
HDC hdc = CreateCompatibleDC(0);
@@ -320,10 +203,9 @@ TEST(GDIFontEmulationTest, EnumFontFamilySuccess) {
EXPECT_TRUE(DeleteDC(hdc));
}
-TEST(GDIFontEmulationTest, EnumFontFamilyFailure) {
+TEST_F(GDIFontEmulationTest, EnumFontFamilyFailure) {
if (base::win::GetVersion() < base::win::VERSION_WIN8)
return;
- TestSkFontMgr fontmgr;
std::unique_ptr<GdiFontPatchData> patch_data(SetupTest());
EXPECT_NE(patch_data, nullptr);
HDC hdc = CreateCompatibleDC(0);
@@ -335,30 +217,27 @@ TEST(GDIFontEmulationTest, EnumFontFamilyFailure) {
EXPECT_TRUE(DeleteDC(hdc));
}
-TEST(GDIFontEmulationTest, DeleteDCFailure) {
+TEST_F(GDIFontEmulationTest, DeleteDCFailure) {
if (base::win::GetVersion() < base::win::VERSION_WIN8)
return;
- TestSkFontMgr fontmgr;
std::unique_ptr<GdiFontPatchData> patch_data(SetupTest());
EXPECT_NE(patch_data, nullptr);
HDC hdc = reinterpret_cast<HDC>(0x55667788);
EXPECT_FALSE(DeleteDC(hdc));
}
-TEST(GDIFontEmulationTest, DeleteObjectFailure) {
+TEST_F(GDIFontEmulationTest, DeleteObjectFailure) {
if (base::win::GetVersion() < base::win::VERSION_WIN8)
return;
- TestSkFontMgr fontmgr;
std::unique_ptr<GdiFontPatchData> patch_data(SetupTest());
EXPECT_NE(patch_data, nullptr);
HFONT font = reinterpret_cast<HFONT>(0x88aabbcc);
EXPECT_FALSE(DeleteObject(font));
}
-TEST(GDIFontEmulationTest, GetFontDataSizeSuccess) {
+TEST_F(GDIFontEmulationTest, GetFontDataSizeSuccess) {
if (base::win::GetVersion() < base::win::VERSION_WIN8)
return;
- TestSkFontMgr fontmgr;
std::unique_ptr<GdiFontPatchData> patch_data(SetupTest());
EXPECT_NE(patch_data, nullptr);
HDC hdc = CreateCompatibleDC(0);
@@ -369,16 +248,15 @@ TEST(GDIFontEmulationTest, GetFontDataSizeSuccess) {
EXPECT_NE(font, nullptr);
EXPECT_EQ(SelectObject(hdc, font), nullptr);
DWORD size = GetFontData(hdc, kTestFontTableTag, 0, nullptr, 0);
- DWORD data_size = static_cast<DWORD>(strlen(kTestFontData));
+ DWORD data_size = static_cast<DWORD>(kTestFontTableDataLength);
EXPECT_EQ(size, data_size);
EXPECT_TRUE(DeleteObject(font));
EXPECT_TRUE(DeleteDC(hdc));
}
-TEST(GDIFontEmulationTest, GetFontDataInvalidTagSuccess) {
+TEST_F(GDIFontEmulationTest, GetFontDataInvalidTagSuccess) {
if (base::win::GetVersion() < base::win::VERSION_WIN8)
return;
- TestSkFontMgr fontmgr;
std::unique_ptr<GdiFontPatchData> patch_data(SetupTest());
EXPECT_NE(patch_data, nullptr);
HDC hdc = CreateCompatibleDC(0);
@@ -394,10 +272,9 @@ TEST(GDIFontEmulationTest, GetFontDataInvalidTagSuccess) {
EXPECT_TRUE(DeleteDC(hdc));
}
-TEST(GDIFontEmulationTest, GetFontDataInvalidFontSuccess) {
+TEST_F(GDIFontEmulationTest, GetFontDataInvalidFontSuccess) {
if (base::win::GetVersion() < base::win::VERSION_WIN8)
return;
- TestSkFontMgr fontmgr;
std::unique_ptr<GdiFontPatchData> patch_data(SetupTest());
EXPECT_NE(patch_data, nullptr);
HDC hdc = CreateCompatibleDC(0);
@@ -407,10 +284,9 @@ TEST(GDIFontEmulationTest, GetFontDataInvalidFontSuccess) {
EXPECT_TRUE(DeleteDC(hdc));
}
-TEST(GDIFontEmulationTest, GetFontDataDataSuccess) {
+TEST_F(GDIFontEmulationTest, GetFontDataDataSuccess) {
if (base::win::GetVersion() < base::win::VERSION_WIN8)
return;
- TestSkFontMgr fontmgr;
std::unique_ptr<GdiFontPatchData> patch_data(SetupTest());
EXPECT_NE(patch_data, nullptr);
HDC hdc = CreateCompatibleDC(0);
@@ -420,11 +296,11 @@ TEST(GDIFontEmulationTest, GetFontDataDataSuccess) {
HFONT font = CreateFontIndirectW(&logfont);
EXPECT_NE(font, nullptr);
EXPECT_EQ(SelectObject(hdc, font), nullptr);
- DWORD data_size = static_cast<DWORD>(strlen(kTestFontData));
+ DWORD data_size = static_cast<DWORD>(kTestFontTableDataLength);
std::vector<char> data(data_size);
DWORD size = GetFontData(hdc, kTestFontTableTag, 0, &data[0], data.size());
EXPECT_EQ(size, data_size);
- EXPECT_EQ(memcmp(&data[0], kTestFontData, data.size()), 0);
+ EXPECT_EQ(memcmp(&data[0], kTestFontTableData, data.size()), 0);
EXPECT_TRUE(DeleteObject(font));
EXPECT_TRUE(DeleteDC(hdc));
}
diff --git a/chromium/content/child/runtime_features.cc b/chromium/content/child/runtime_features.cc
index d82d7efe02f..1221dc2adfc 100644
--- a/chromium/content/child/runtime_features.cc
+++ b/chromium/content/child/runtime_features.cc
@@ -15,6 +15,7 @@
#include "content/common/content_switches_internal.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
+#include "gpu/config/gpu_switches.h"
#include "media/base/media_switches.h"
#include "services/device/public/cpp/device_features.h"
#include "services/network/public/cpp/features.h"
@@ -24,6 +25,14 @@
#include "ui/gl/gl_switches.h"
#include "ui/native_theme/native_theme_features.h"
+#if defined(OS_ANDROID)
+#include "base/android/build_info.h"
+#endif
+
+#if defined(OS_WIN)
+#include "base/win/windows_version.h"
+#endif
+
using blink::WebRuntimeFeatures;
namespace content {
@@ -46,7 +55,6 @@ static void SetRuntimeFeatureDefaultsForPlatform() {
WebRuntimeFeatures::EnableNotificationConstructor(false);
// Android does not yet support switching of audio output devices
WebRuntimeFeatures::EnableAudioOutputDevices(false);
- WebRuntimeFeatures::EnableAutoplayMutedVideos(true);
// Android does not yet support SystemMonitor.
WebRuntimeFeatures::EnableOnDeviceChange(false);
WebRuntimeFeatures::EnableMediaSession(true);
@@ -69,11 +77,15 @@ static void SetRuntimeFeatureDefaultsForPlatform() {
WebRuntimeFeatures::EnableNetInfoDownlinkMax(false);
#endif
-// Web Bluetooth is shipped on Android, ChromeOS & MacOS, experimental
-// otherwise.
+// Web Bluetooth is shipped on Android, ChromeOS, MacOS and Windows 10,
+// experimental otherwise.
#if defined(OS_CHROMEOS) || defined(OS_ANDROID) || defined(OS_MACOSX)
WebRuntimeFeatures::EnableWebBluetooth(true);
#endif
+#if defined(OS_WIN)
+ if (base::win::GetVersion() >= base::win::VERSION_WIN10)
+ WebRuntimeFeatures::EnableWebBluetooth(true);
+#endif
#if defined(OS_CHROMEOS)
WebRuntimeFeatures::EnableForceTallerSelectPopup(true);
@@ -261,11 +273,19 @@ void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
WebRuntimeFeatures::EnablePassiveDocumentEventListeners(
base::FeatureList::IsEnabled(features::kPassiveDocumentEventListeners));
+ WebRuntimeFeatures::EnablePassiveDocumentWheelEventListeners(
+ base::FeatureList::IsEnabled(
+ features::kPassiveDocumentWheelEventListeners));
+
WebRuntimeFeatures::EnableFeatureFromString(
"FontCacheScaling",
base::FeatureList::IsEnabled(features::kFontCacheScaling));
WebRuntimeFeatures::EnableFeatureFromString(
+ "FontSrcLocalMatching",
+ base::FeatureList::IsEnabled(features::kFontSrcLocalMatching));
+
+ WebRuntimeFeatures::EnableFeatureFromString(
"FramebustingNeedsSameOriginOrUserGesture",
base::FeatureList::IsEnabled(
features::kFramebustingNeedsSameOriginOrUserGesture));
@@ -336,9 +356,6 @@ void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
if (base::FeatureList::IsEnabled(network::features::kOutOfBlinkCORS))
WebRuntimeFeatures::EnableOutOfBlinkCORS(true);
- if (base::FeatureList::IsEnabled(features::kOriginPolicy))
- WebRuntimeFeatures::EnableOriginPolicy(true);
-
WebRuntimeFeatures::EnableMediaCastOverlayButton(
base::FeatureList::IsEnabled(media::kMediaCastOverlayButton));
@@ -360,11 +377,6 @@ void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
WebRuntimeFeatures::EnableWebNfc(true);
#endif
- if (media::GetEffectiveAutoplayPolicy(command_line) !=
- switches::autoplay::kNoUserGestureRequiredPolicy) {
- WebRuntimeFeatures::EnableAutoplayMutedVideos(true);
- }
-
WebRuntimeFeatures::EnableWebAuth(
base::FeatureList::IsEnabled(features::kWebAuth));
@@ -406,24 +418,21 @@ void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
WebRuntimeFeatures::EnableWorkStealingInScriptRunner(
base::FeatureList::IsEnabled(features::kWorkStealingInScriptRunner));
- WebRuntimeFeatures::EnableFeatureFromString(
- "FeaturePolicyForPermissions",
- base::FeatureList::IsEnabled(features::kUseFeaturePolicyForPermissions));
+ WebRuntimeFeatures::EnableScheduledScriptStreaming(
+ base::FeatureList::IsEnabled(features::kScheduledScriptStreaming));
if (base::FeatureList::IsEnabled(features::kLazyFrameLoading))
WebRuntimeFeatures::EnableLazyFrameLoading(true);
if (base::FeatureList::IsEnabled(features::kLazyFrameVisibleLoadTimeMetrics))
WebRuntimeFeatures::EnableLazyFrameVisibleLoadTimeMetrics(true);
+ if (base::FeatureList::IsEnabled(features::kLazyImageLoading))
+ WebRuntimeFeatures::EnableLazyImageLoading(true);
+ if (base::FeatureList::IsEnabled(features::kLazyImageVisibleLoadTimeMetrics))
+ WebRuntimeFeatures::EnableLazyImageVisibleLoadTimeMetrics(true);
WebRuntimeFeatures::EnableV8ContextSnapshot(
base::FeatureList::IsEnabled(features::kV8ContextSnapshot));
- if (base::FeatureList::IsEnabled(features::kStopInBackground))
- WebRuntimeFeatures::EnableStopInBackground(true);
-
- if (base::FeatureList::IsEnabled(features::kStopNonTimersInBackground))
- WebRuntimeFeatures::EnableStopNonTimersInBackground(true);
-
WebRuntimeFeatures::EnablePWAFullCodeCache(
base::FeatureList::IsEnabled(features::kPWAFullCodeCache));
@@ -436,12 +445,14 @@ void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
WebRuntimeFeatures::EnableCacheInlineScriptCode(
base::FeatureList::IsEnabled(features::kCacheInlineScriptCode));
- // Make srcset on link rel=preload work with SignedHTTPExchange flag too.
- if (base::FeatureList::IsEnabled(features::kSignedHTTPExchange))
- WebRuntimeFeatures::EnablePreloadImageSrcSetEnabled(true);
+ WebRuntimeFeatures::EnableIsolatedCodeCache(
+ base::FeatureList::IsEnabled(features::kIsolatedCodeCache));
- WebRuntimeFeatures::EnableOffMainThreadWebSocket(
- base::FeatureList::IsEnabled(features::kOffMainThreadWebSocket));
+ if (base::FeatureList::IsEnabled(features::kSignedHTTPExchange)) {
+ WebRuntimeFeatures::EnableSignedHTTPExchange(true);
+ // Make srcset on link rel=preload work with SignedHTTPExchange flag too.
+ WebRuntimeFeatures::EnablePreloadImageSrcSetEnabled(true);
+ }
WebRuntimeFeatures::EnableNestedWorkers(
base::FeatureList::IsEnabled(blink::features::kNestedWorkers));
@@ -455,8 +466,11 @@ void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
WebRuntimeFeatures::EnablePageLifecycle(true);
#if defined(OS_ANDROID)
- if (base::FeatureList::IsEnabled(features::kDisplayCutoutAPI))
+ if (base::FeatureList::IsEnabled(features::kDisplayCutoutAPI) &&
+ base::android::BuildInfo::GetInstance()->is_at_least_p()) {
+ // Display Cutout is limited to Android P+.
WebRuntimeFeatures::EnableDisplayCutoutAPI(true);
+ }
#endif
if (command_line.HasSwitch(switches::kEnableAccessibilityObjectModel))
@@ -478,6 +492,10 @@ void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
base::FeatureList::IsEnabled(media::kMediaControlsExpandGesture));
#endif
+ WebRuntimeFeatures::EnableFeatureFromString(
+ "WritableFiles",
+ base::FeatureList::IsEnabled(blink::features::kWritableFilesAPI));
+
// Enable explicitly enabled features, and then disable explicitly disabled
// ones.
for (const std::string& feature :
@@ -488,6 +506,9 @@ void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
FeaturesFromSwitch(command_line, switches::kDisableBlinkFeatures)) {
WebRuntimeFeatures::EnableFeatureFromString(feature, false);
}
+
+ WebRuntimeFeatures::EnablePortals(
+ base::FeatureList::IsEnabled(blink::features::kPortals));
};
} // namespace content
diff --git a/chromium/content/common/BUILD.gn b/chromium/content/common/BUILD.gn
index d02f2ea18aa..1940f0d9774 100644
--- a/chromium/content/common/BUILD.gn
+++ b/chromium/content/common/BUILD.gn
@@ -49,10 +49,6 @@ source_set("common") {
"android/use_zoom_for_dsf_policy_android.cc",
"appcache_interfaces.cc",
"appcache_interfaces.h",
- "associated_interface_provider_impl.cc",
- "associated_interface_provider_impl.h",
- "associated_interface_registry_impl.cc",
- "associated_interface_registry_impl.h",
"ax_content_node_data.cc",
"ax_content_node_data.h",
"background_fetch/background_fetch_struct_traits.cc",
@@ -113,7 +109,6 @@ source_set("common") {
"drag_messages.h",
"drag_traits.h",
"edit_command.h",
- "fileapi/file_system_messages.h",
"fileapi/webblob_messages.h",
"font_cache_dispatcher_win.cc",
"font_list.cc",
@@ -138,17 +133,6 @@ source_set("common") {
"gin_java_bridge_messages.h",
"in_process_child_thread_params.cc",
"in_process_child_thread_params.h",
- "indexed_db/indexed_db_constants.h",
- "indexed_db/indexed_db_key.cc",
- "indexed_db/indexed_db_key.h",
- "indexed_db/indexed_db_key_path.cc",
- "indexed_db/indexed_db_key_path.h",
- "indexed_db/indexed_db_key_range.cc",
- "indexed_db/indexed_db_key_range.h",
- "indexed_db/indexed_db_metadata.cc",
- "indexed_db/indexed_db_metadata.h",
- "indexed_db/indexed_db_struct_traits.cc",
- "indexed_db/indexed_db_struct_traits.h",
"input/event_with_latency_info.h",
"input/gesture_event_stream_validator.cc",
"input/gesture_event_stream_validator.h",
@@ -210,6 +194,10 @@ source_set("common") {
"media/midi_messages.h",
"media/peer_connection_tracker_messages.h",
"media/video_capture.h",
+ "mime_sniffing_throttle.cc",
+ "mime_sniffing_throttle.h",
+ "mime_sniffing_url_loader.cc",
+ "mime_sniffing_url_loader.h",
"navigation_gesture.h",
"navigation_params.cc",
"navigation_params.h",
@@ -224,8 +212,6 @@ source_set("common") {
"notifications/notification_struct_traits.cc",
"notifications/notification_struct_traits.h",
"origin_util.cc",
- "p2p_messages.h",
- "p2p_socket_type.h",
"page_messages.h",
"page_state_serialization.cc",
"page_state_serialization.h",
@@ -236,14 +222,11 @@ source_set("common") {
"pepper_plugin_list.h",
"pepper_renderer_instance_data.cc",
"pepper_renderer_instance_data.h",
- "platform_notification_param_traits.h",
"plugin_list.cc",
"plugin_list.h",
"possibly_associated_interface_ptr.h",
"possibly_associated_interface_ptr_info.h",
"possibly_associated_wrapper_shared_url_loader_factory.h",
- "presentation/presentation_struct_traits.cc",
- "presentation/presentation_struct_traits.h",
"process_type.cc",
"render_widget_surface_properties.cc",
"render_widget_surface_properties.h",
@@ -258,7 +241,6 @@ source_set("common") {
"service_manager/service_manager_connection_impl.h",
"service_worker/service_worker_loader_helpers.cc",
"service_worker/service_worker_loader_helpers.h",
- "service_worker/service_worker_messages.h",
"service_worker/service_worker_types.cc",
"service_worker/service_worker_types.h",
"service_worker/service_worker_utils.cc",
@@ -357,16 +339,14 @@ source_set("common") {
"//services/service_manager/public/mojom",
"//services/service_manager/runner/common",
"//services/service_manager/zygote:zygote_buildflags",
- "//services/ui/public/interfaces",
"//services/video_capture/public/mojom",
"//services/viz/public/interfaces",
+ "//services/ws/public/mojom",
"//skia",
"//storage/common",
"//third_party/angle:angle_gpu_info_util",
"//third_party/boringssl",
"//third_party/icu",
- "//third_party/webrtc/rtc_base:rtc_base",
- "//third_party/webrtc_overrides",
"//ui/base",
"//ui/base/ime",
"//ui/display",
@@ -490,6 +470,7 @@ source_set("common") {
deps += [
"//third_party/fuchsia-sdk:fdio",
"//third_party/fuchsia-sdk:fonts",
+ "//third_party/fuchsia-sdk:scenic",
]
}
}
@@ -508,7 +489,9 @@ mojom("mojo_bindings") {
# This interface is internal to content.
visibility = [ "//content/*" ]
- # indexed_db.mojom uses a native typemap that is not available in Java.
+ # indexed_db.mojom used a native typemap that was not available in Java.
+ # indexed_db.mojom was removed in an earlier commit. This should be removed
+ # at some point.
cpp_only = true
# imports vs deps check is disabled for this target to work around
@@ -530,7 +513,6 @@ mojom("mojo_bindings") {
"histogram_fetcher.mojom",
"host_zoom.mojom",
"image_downloader/image_downloader.mojom",
- "indexed_db/indexed_db.mojom",
"input/input_handler.mojom",
"input/input_injector.mojom",
"input/synchronous_compositor.mojom",
@@ -555,7 +537,6 @@ mojom("mojo_bindings") {
"service_worker/embedded_worker.mojom",
"service_worker/service_worker.mojom",
"service_worker/service_worker_container.mojom",
- "service_worker/service_worker_fetch_response_callback.mojom",
"service_worker/service_worker_provider.mojom",
"shared_worker/shared_worker.mojom",
"shared_worker/shared_worker_client.mojom",
@@ -589,18 +570,23 @@ mojom("mojo_bindings") {
import_dirs = [ "//mojo/services" ]
public_deps = [
+ # Due to component_deps below, we're depending on blink_common, but
+ # blink_common does not export generated types of components/payments/mojom,
+ # so we need to specifically add this dependency here.
+ "//components/payments/mojom",
"//components/services/leveldb/public/interfaces",
"//content/public/common:interfaces",
"//content/public/common:resource_type_bindings",
"//ipc:mojom_constants",
"//media/mojo/interfaces",
"//mojo/public/mojom/base",
+ "//services/audio/public/mojom",
"//services/network/public/mojom",
"//services/service_manager/public/mojom",
- "//services/ui/public/interfaces",
- "//services/ui/public/interfaces/ime",
"//services/video_capture/public/mojom",
"//services/viz/public/interfaces",
+ "//services/ws/public/mojom",
+ "//services/ws/public/mojom/ime",
"//skia/public/interfaces",
"//third_party/blink/public:mojo_bindings",
"//third_party/blink/public:web_feature_mojo_bindings",
diff --git a/chromium/content/common/DEPS b/chromium/content/common/DEPS
index fb1b03bec74..96e605eeb23 100644
--- a/chromium/content/common/DEPS
+++ b/chromium/content/common/DEPS
@@ -55,13 +55,10 @@ include_rules = [
"+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/fetch/fetch_api_request.mojom.h",
- "+third_party/blink/public/platform/modules/fetch/fetch_api_response.mojom.h",
- "+third_party/blink/public/platform/modules/indexeddb/web_idb_types.h",
"+third_party/blink/public/platform/modules/mediasession/media_session.mojom.h",
"+third_party/blink/public/platform/modules/mediastream/media_devices.mojom.h",
"+third_party/blink/public/platform/modules/permissions/permission.mojom.h",
"+third_party/blink/public/platform/modules/permissions/permission_status.mojom.h",
- "+third_party/blink/public/platform/modules/presentation/presentation.mojom.h",
"+third_party/blink/public/platform/modules/push_messaging/web_push_error.h",
"+third_party/blink/public/platform/modules/remoteplayback/web_remote_playback_availability.h",
"+third_party/blink/public/platform/modules/payments/WebPaymentAppRequest.h",
@@ -85,3 +82,8 @@ include_rules = [
"+third_party/blink/public/web/web_triggering_event_info.h",
"+third_party/blink/public/web/win/web_font_rendering.h",
]
+specific_include_rules = {
+ '.*_unittest.*': [
+ "+services/network/test",
+ ]
+}
diff --git a/chromium/content/common/android/gin_java_bridge_value.cc b/chromium/content/common/android/gin_java_bridge_value.cc
index c34d0413581..6f0d034610b 100644
--- a/chromium/content/common/android/gin_java_bridge_value.cc
+++ b/chromium/content/common/android/gin_java_bridge_value.cc
@@ -59,7 +59,8 @@ bool GinJavaBridgeValue::ContainsGinJavaBridgeValue(const base::Value* value) {
return false;
if (value->GetBlob().size() < sizeof(Header))
return false;
- base::Pickle pickle(value->GetBlob().data(), value->GetBlob().size());
+ base::Pickle pickle(reinterpret_cast<const char*>(value->GetBlob().data()),
+ value->GetBlob().size());
// Broken binary value: payload or header size is wrong
if (!pickle.data() || pickle.size() - pickle.payload_size() != sizeof(Header))
return false;
@@ -111,7 +112,8 @@ GinJavaBridgeValue::GinJavaBridgeValue(Type type) :
}
GinJavaBridgeValue::GinJavaBridgeValue(const base::Value* value)
- : pickle_(value->GetBlob().data(), value->GetBlob().size()) {
+ : pickle_(reinterpret_cast<const char*>(value->GetBlob().data()),
+ value->GetBlob().size()) {
DCHECK(ContainsGinJavaBridgeValue(value));
}
diff --git a/chromium/content/common/appcache_interfaces.cc b/chromium/content/common/appcache_interfaces.cc
index 11e24605124..c07a2b700f3 100644
--- a/chromium/content/common/appcache_interfaces.cc
+++ b/chromium/content/common/appcache_interfaces.cc
@@ -17,9 +17,6 @@ namespace content {
const char kHttpGETMethod[] = "GET";
const char kHttpHEADMethod[] = "HEAD";
-const base::FilePath::CharType kAppCacheDatabaseName[] =
- FILE_PATH_LITERAL("Index");
-
AppCacheNamespace::AppCacheNamespace()
: type(APPCACHE_FALLBACK_NAMESPACE), is_pattern(false) {}
diff --git a/chromium/content/common/appcache_interfaces.h b/chromium/content/common/appcache_interfaces.h
index b3d9f0adce3..1e5c678b3ed 100644
--- a/chromium/content/common/appcache_interfaces.h
+++ b/chromium/content/common/appcache_interfaces.h
@@ -42,8 +42,6 @@ enum AppCacheNamespaceType {
APPCACHE_NETWORK_NAMESPACE
};
-typedef std::vector<AppCacheResourceInfo> AppCacheResourceInfoVector;
-
struct CONTENT_EXPORT AppCacheNamespace {
AppCacheNamespace(); // Type is APPCACHE_FALLBACK_NAMESPACE by default.
AppCacheNamespace(AppCacheNamespaceType type, const GURL& url,
@@ -58,8 +56,6 @@ struct CONTENT_EXPORT AppCacheNamespace {
bool is_pattern;
};
-typedef std::vector<AppCacheNamespace> AppCacheNamespaceVector;
-
// Interface used by backend (browser-process) to talk to frontend (renderer).
class CONTENT_EXPORT AppCacheFrontend {
public:
@@ -117,16 +113,10 @@ class CONTENT_EXPORT AppCacheBackend {
CONTENT_EXPORT extern const char kHttpGETMethod[];
CONTENT_EXPORT extern const char kHttpHEADMethod[];
-// base::CommandLine flag to turn this experimental feature on.
-CONTENT_EXPORT extern const char kEnableExecutableHandlers[];
-
CONTENT_EXPORT bool IsSchemeSupportedForAppCache(const GURL& url);
CONTENT_EXPORT bool IsMethodSupportedForAppCache(
const std::string& method);
-CONTENT_EXPORT extern const base::FilePath::CharType
- kAppCacheDatabaseName[];
-
} // namespace
#endif // CONTENT_COMMON_APPCACHE_INTERFACES_H_
diff --git a/chromium/content/common/associated_interface_provider_impl.cc b/chromium/content/common/associated_interface_provider_impl.cc
deleted file mode 100644
index ba5ef4044e0..00000000000
--- a/chromium/content/common/associated_interface_provider_impl.cc
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/associated_interface_provider_impl.h"
-#include "base/callback.h"
-#include "base/run_loop.h"
-#include "mojo/public/cpp/bindings/associated_binding.h"
-
-namespace content {
-
-class AssociatedInterfaceProviderImpl::LocalProvider
- : public mojom::AssociatedInterfaceProvider {
- public:
- LocalProvider(mojom::AssociatedInterfaceProviderAssociatedPtr* proxy,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner)
- : associated_interface_provider_binding_(this) {
- associated_interface_provider_binding_.Bind(
- mojo::MakeRequestAssociatedWithDedicatedPipe(proxy),
- std::move(task_runner));
- }
-
- ~LocalProvider() override {}
-
- void SetBinderForName(
- const std::string& name,
- const base::Callback<void(mojo::ScopedInterfaceEndpointHandle)>& binder) {
- binders_[name] = binder;
- }
-
- private:
- // mojom::AssociatedInterfaceProvider:
- void GetAssociatedInterface(
- const std::string& name,
- mojom::AssociatedInterfaceAssociatedRequest request) override {
- auto it = binders_.find(name);
- if (it != binders_.end())
- it->second.Run(request.PassHandle());
- }
-
- using BinderMap =
- std::map<std::string,
- base::Callback<void(mojo::ScopedInterfaceEndpointHandle)>>;
- BinderMap binders_;
-
- mojo::AssociatedBinding<mojom::AssociatedInterfaceProvider>
- associated_interface_provider_binding_;
-};
-
-AssociatedInterfaceProviderImpl::AssociatedInterfaceProviderImpl(
- mojom::AssociatedInterfaceProviderAssociatedPtr proxy,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner)
- : proxy_(std::move(proxy)), task_runner_(std::move(task_runner)) {
- DCHECK(proxy_.is_bound());
-}
-
-AssociatedInterfaceProviderImpl::AssociatedInterfaceProviderImpl(
- scoped_refptr<base::SingleThreadTaskRunner> task_runner)
- : local_provider_(std::make_unique<LocalProvider>(&proxy_, task_runner)),
- task_runner_(std::move(task_runner)) {}
-
-AssociatedInterfaceProviderImpl::~AssociatedInterfaceProviderImpl() {}
-
-void AssociatedInterfaceProviderImpl::GetInterface(
- const std::string& name,
- mojo::ScopedInterfaceEndpointHandle handle) {
- proxy_->GetAssociatedInterface(
- name, mojom::AssociatedInterfaceAssociatedRequest(std::move(handle)));
-}
-
-void AssociatedInterfaceProviderImpl::OverrideBinderForTesting(
- const std::string& name,
- const base::Callback<void(mojo::ScopedInterfaceEndpointHandle)>& binder) {
- if (!local_provider_) {
- DCHECK(proxy_.is_bound());
- proxy_.reset();
- local_provider_ = std::make_unique<LocalProvider>(&proxy_, task_runner_);
- }
- local_provider_->SetBinderForName(name, binder);
-}
-
-} // namespace content
diff --git a/chromium/content/common/associated_interface_provider_impl.h b/chromium/content/common/associated_interface_provider_impl.h
deleted file mode 100644
index a46b6575ca5..00000000000
--- a/chromium/content/common/associated_interface_provider_impl.h
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_ASSOCIATED_INTERFACE_PROVIDER_IMPL_H_
-#define CONTENT_COMMON_ASSOCIATED_INTERFACE_PROVIDER_IMPL_H_
-
-#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
-
-#include <stdint.h>
-#include <memory>
-
-#include "base/macros.h"
-#include "base/single_thread_task_runner.h"
-#include "content/common/associated_interfaces.mojom.h"
-
-namespace content {
-
-class AssociatedInterfaceProviderImpl
- : public blink::AssociatedInterfaceProvider {
- public:
- // Binds this to a remote mojom::AssociatedInterfaceProvider.
- //
- // |task_runner| must belong to the same thread. It will be used to dispatch
- // all callbacks and connection error notification.
- explicit AssociatedInterfaceProviderImpl(
- mojom::AssociatedInterfaceProviderAssociatedPtr proxy,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner = nullptr);
-
- // Constructs a local provider with no remote interfaces. This is useful in
- // conjunction with OverrideBinderForTesting(), in test environments where
- // there may not be a remote |mojom::AssociatedInterfaceProvider| available.
- //
- // |task_runner| must belong to the same thread. It will be used to dispatch
- // all callbacks and connection error notification.
- explicit AssociatedInterfaceProviderImpl(
- scoped_refptr<base::SingleThreadTaskRunner> task_runner);
- ~AssociatedInterfaceProviderImpl() override;
-
- // AssociatedInterfaceProvider:
- void GetInterface(const std::string& name,
- mojo::ScopedInterfaceEndpointHandle handle) override;
- void OverrideBinderForTesting(
- const std::string& name,
- const base::Callback<void(mojo::ScopedInterfaceEndpointHandle)>& binder)
- override;
-
- private:
- class LocalProvider;
-
- mojom::AssociatedInterfaceProviderAssociatedPtr proxy_;
-
- std::unique_ptr<LocalProvider> local_provider_;
- scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
-
- DISALLOW_COPY_AND_ASSIGN(AssociatedInterfaceProviderImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_ASSOCIATED_INTERFACE_PROVIDER_IMPL_H_
diff --git a/chromium/content/common/associated_interface_registry_impl.cc b/chromium/content/common/associated_interface_registry_impl.cc
deleted file mode 100644
index b10d08d2936..00000000000
--- a/chromium/content/common/associated_interface_registry_impl.cc
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/associated_interface_registry_impl.h"
-
-#include <utility>
-
-#include "base/logging.h"
-
-namespace content {
-
-AssociatedInterfaceRegistryImpl::AssociatedInterfaceRegistryImpl()
- : weak_factory_(this) {}
-
-AssociatedInterfaceRegistryImpl::~AssociatedInterfaceRegistryImpl() {}
-
-bool AssociatedInterfaceRegistryImpl::CanBindRequest(
- const std::string& interface_name) const {
- return interfaces_.find(interface_name) != interfaces_.end();
-}
-
-void AssociatedInterfaceRegistryImpl::BindRequest(
- const std::string& interface_name,
- mojo::ScopedInterfaceEndpointHandle handle) {
- auto it = interfaces_.find(interface_name);
- if (it == interfaces_.end())
- return;
- it->second.Run(std::move(handle));
-}
-
-void AssociatedInterfaceRegistryImpl::AddInterface(const std::string& name,
- const Binder& binder) {
- auto result = interfaces_.insert(std::make_pair(name, binder));
- DCHECK(result.second);
-}
-
-void AssociatedInterfaceRegistryImpl::RemoveInterface(const std::string& name) {
- auto it = interfaces_.find(name);
- DCHECK(it != interfaces_.end());
- interfaces_.erase(it);
-}
-
-base::WeakPtr<AssociatedInterfaceRegistryImpl>
-AssociatedInterfaceRegistryImpl::GetWeakPtr() {
- return weak_factory_.GetWeakPtr();
-}
-
-} // namespace content
diff --git a/chromium/content/common/associated_interface_registry_impl.h b/chromium/content/common/associated_interface_registry_impl.h
deleted file mode 100644
index 4ee97c1bec4..00000000000
--- a/chromium/content/common/associated_interface_registry_impl.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_COMMON_ASSOCIATED_INTERFACE_REGISTRY_IMPL_H_
-#define CONTENT_COMMON_ASSOCIATED_INTERFACE_REGISTRY_IMPL_H_
-
-#include <map>
-#include <string>
-
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
-#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
-
-namespace content {
-
-class AssociatedInterfaceRegistryImpl
- : public blink::AssociatedInterfaceRegistry {
- public:
- AssociatedInterfaceRegistryImpl();
- ~AssociatedInterfaceRegistryImpl() override;
-
- bool CanBindRequest(const std::string& interface_name) const;
- void BindRequest(const std::string& interface_name,
- mojo::ScopedInterfaceEndpointHandle handle);
-
- // AssociatedInterfaceRegistry:
- void AddInterface(const std::string& name, const Binder& binder) override;
- void RemoveInterface(const std::string& name) override;
-
- base::WeakPtr<AssociatedInterfaceRegistryImpl> GetWeakPtr();
-
- private:
- std::map<std::string, Binder> interfaces_;
- base::WeakPtrFactory<AssociatedInterfaceRegistryImpl> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(AssociatedInterfaceRegistryImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_ASSOCIATED_INTERFACE_REGISTRY_IMPL_H_
diff --git a/chromium/content/common/associated_interfaces.mojom b/chromium/content/common/associated_interfaces.mojom
index f6b871a6756..cc8bdcb3f3c 100644
--- a/chromium/content/common/associated_interfaces.mojom
+++ b/chromium/content/common/associated_interfaces.mojom
@@ -4,18 +4,11 @@
module content.mojom;
-// A generic, nominal interface to support transitional Channel-associated
-// interfaces at or above the content layer.
-interface AssociatedInterface {};
-
-// Analogous to the generic InterfaceProvider interface, but for content
-// AssociatedInterfaces.
-interface AssociatedInterfaceProvider {
- GetAssociatedInterface(string name, associated AssociatedInterface& request);
-};
+import "third_party/blink/public/mojom/associated_interfaces/associated_interfaces.mojom";
// Implemented by anything which manages one or more routes, to map a routing
// ID to an AssociatedInterfaceProvider.
interface RouteProvider {
- GetRoute(int32 routing_id, associated AssociatedInterfaceProvider& request);
+ GetRoute(int32 routing_id,
+ associated blink.mojom.AssociatedInterfaceProvider& request);
};
diff --git a/chromium/content/common/background_fetch/background_fetch_struct_traits.cc b/chromium/content/common/background_fetch/background_fetch_struct_traits.cc
index c399fa94167..dd5321bedc3 100644
--- a/chromium/content/common/background_fetch/background_fetch_struct_traits.cc
+++ b/chromium/content/common/background_fetch/background_fetch_struct_traits.cc
@@ -6,7 +6,6 @@
#include "content/common/service_worker/service_worker.mojom.h"
#include "content/common/service_worker/service_worker_fetch_request_mojom_traits.h"
-#include "content/common/service_worker/service_worker_messages.h"
#include "mojo/public/cpp/bindings/array_data_view.h"
#include "third_party/blink/public/common/manifest/manifest_mojom_traits.h"
#include "third_party/blink/public/mojom/manifest/manifest.mojom.h"
@@ -39,13 +38,15 @@ bool StructTraits<blink::mojom::BackgroundFetchRegistrationDataView,
registration->uploaded = data.uploaded();
registration->download_total = data.download_total();
registration->downloaded = data.downloaded();
+ registration->state = data.state();
+ registration->failure_reason = data.failure_reason();
return true;
}
// static
-bool StructTraits<content::mojom::BackgroundFetchSettledFetchDataView,
+bool StructTraits<blink::mojom::BackgroundFetchSettledFetchDataView,
content::BackgroundFetchSettledFetch>::
- Read(content::mojom::BackgroundFetchSettledFetchDataView data,
+ Read(blink::mojom::BackgroundFetchSettledFetchDataView data,
content::BackgroundFetchSettledFetch* fetch) {
return data.ReadRequest(&fetch->request) &&
data.ReadResponse(&fetch->response);
diff --git a/chromium/content/common/background_fetch/background_fetch_struct_traits.h b/chromium/content/common/background_fetch/background_fetch_struct_traits.h
index 380748dbcf1..30dfc0efd95 100644
--- a/chromium/content/common/background_fetch/background_fetch_struct_traits.h
+++ b/chromium/content/common/background_fetch/background_fetch_struct_traits.h
@@ -14,12 +14,6 @@
#include "third_party/blink/public/common/manifest/manifest.h"
#include "third_party/blink/public/platform/modules/background_fetch/background_fetch.mojom.h"
-namespace content {
-namespace mojom {
-class BackgroundFetchSettledFetchDataView;
-}
-}
-
namespace mojo {
template <>
@@ -70,6 +64,14 @@ struct CONTENT_EXPORT
const content::BackgroundFetchRegistration& registration) {
return registration.downloaded;
}
+ static blink::mojom::BackgroundFetchState state(
+ const content::BackgroundFetchRegistration& registration) {
+ return registration.state;
+ }
+ static blink::mojom::BackgroundFetchFailureReason failure_reason(
+ const content::BackgroundFetchRegistration& registration) {
+ return registration.failure_reason;
+ }
static bool Read(blink::mojom::BackgroundFetchRegistrationDataView data,
content::BackgroundFetchRegistration* registration);
@@ -77,18 +79,18 @@ struct CONTENT_EXPORT
template <>
struct CONTENT_EXPORT
- StructTraits<content::mojom::BackgroundFetchSettledFetchDataView,
+ StructTraits<blink::mojom::BackgroundFetchSettledFetchDataView,
content::BackgroundFetchSettledFetch> {
static const content::ServiceWorkerFetchRequest& request(
const content::BackgroundFetchSettledFetch& fetch) {
return fetch.request;
}
- static const content::ServiceWorkerResponse& response(
+ static blink::mojom::FetchAPIResponsePtr response(
const content::BackgroundFetchSettledFetch& fetch) {
- return fetch.response;
+ return content::BackgroundFetchSettledFetch::CloneResponse(fetch.response);
}
- static bool Read(content::mojom::BackgroundFetchSettledFetchDataView data,
+ static bool Read(blink::mojom::BackgroundFetchSettledFetchDataView data,
content::BackgroundFetchSettledFetch* definition);
};
diff --git a/chromium/content/common/background_fetch/background_fetch_struct_traits_unittest.cc b/chromium/content/common/background_fetch/background_fetch_struct_traits_unittest.cc
index a4d48582e2a..98ffea5c591 100644
--- a/chromium/content/common/background_fetch/background_fetch_struct_traits_unittest.cc
+++ b/chromium/content/common/background_fetch/background_fetch_struct_traits_unittest.cc
@@ -20,7 +20,7 @@ namespace content {
namespace {
-// Creates a new IconDefinition object for the given arguments.
+// Creates a new ImageResource object for the given arguments.
blink::Manifest::ImageResource CreateIcon(const std::string& src,
std::vector<gfx::Size> sizes,
const std::string& type) {
@@ -59,6 +59,9 @@ TEST(BackgroundFetchStructTraitsTest, BackgroundFetchRegistrationRoundTrip) {
registration.developer_id = "my_id";
registration.unique_id = "7e57ab1e-c0de-a150-ca75-1e75f005ba11";
registration.download_total = 9001;
+ registration.state = blink::mojom::BackgroundFetchState::FAILURE;
+ registration.failure_reason =
+ blink::mojom::BackgroundFetchFailureReason::CANCELLED_FROM_UI;
BackgroundFetchRegistration roundtrip_registration;
ASSERT_TRUE(blink::mojom::BackgroundFetchRegistration::Deserialize(
@@ -69,9 +72,11 @@ TEST(BackgroundFetchStructTraitsTest, BackgroundFetchRegistrationRoundTrip) {
EXPECT_EQ(roundtrip_registration.unique_id, registration.unique_id);
EXPECT_EQ(roundtrip_registration.download_total, registration.download_total);
+ EXPECT_EQ(roundtrip_registration.state, registration.state);
+ EXPECT_EQ(roundtrip_registration.failure_reason, registration.failure_reason);
}
-TEST(BackgroundFetchStructTraitsTest, IconDefinitionRoundtrip) {
+TEST(BackgroundFetchStructTraitsTest, ImageResourceRoundtrip) {
blink::Manifest::ImageResource icon =
CreateIcon("my_icon.png", {{256, 256}}, "image/png");
diff --git a/chromium/content/common/background_fetch/background_fetch_types.cc b/chromium/content/common/background_fetch/background_fetch_types.cc
index 2d5ba688181..7db59cf5190 100644
--- a/chromium/content/common/background_fetch/background_fetch_types.cc
+++ b/chromium/content/common/background_fetch/background_fetch_types.cc
@@ -3,6 +3,21 @@
// found in the LICENSE file.
#include "content/common/background_fetch/background_fetch_types.h"
+#include "third_party/blink/public/platform/modules/background_fetch/background_fetch.mojom.h"
+
+namespace {
+
+blink::mojom::SerializedBlobPtr CloneSerializedBlob(
+ const blink::mojom::SerializedBlobPtr& blob) {
+ if (!blob)
+ return nullptr;
+ blink::mojom::BlobPtr blob_ptr(std::move(blob->blob));
+ blob_ptr->Clone(mojo::MakeRequest(&blob->blob));
+ return blink::mojom::SerializedBlob::New(
+ blob->uuid, blob->content_type, blob->size, blob_ptr.PassInterface());
+}
+
+} // namespace
namespace content {
@@ -13,17 +28,61 @@ BackgroundFetchOptions::BackgroundFetchOptions(
BackgroundFetchOptions::~BackgroundFetchOptions() = default;
-BackgroundFetchRegistration::BackgroundFetchRegistration() = default;
+BackgroundFetchRegistration::BackgroundFetchRegistration()
+ : state(blink::mojom::BackgroundFetchState::PENDING),
+ failure_reason(blink::mojom::BackgroundFetchFailureReason::NONE) {}
+
+BackgroundFetchRegistration::BackgroundFetchRegistration(
+ const std::string& developer_id,
+ const std::string& unique_id,
+ uint64_t upload_total,
+ uint64_t uploaded,
+ uint64_t download_total,
+ uint64_t downloaded,
+ blink::mojom::BackgroundFetchState state,
+ blink::mojom::BackgroundFetchFailureReason failure_reason)
+ : developer_id(developer_id),
+ unique_id(unique_id),
+ upload_total(upload_total),
+ uploaded(uploaded),
+ download_total(download_total),
+ downloaded(downloaded),
+ state(state),
+ failure_reason(failure_reason) {}
BackgroundFetchRegistration::BackgroundFetchRegistration(
const BackgroundFetchRegistration& other) = default;
BackgroundFetchRegistration::~BackgroundFetchRegistration() = default;
+// static
+blink::mojom::FetchAPIResponsePtr BackgroundFetchSettledFetch::CloneResponse(
+ const blink::mojom::FetchAPIResponsePtr& response) {
+ // TODO(https://crbug.com/876546): Replace this method with response.Clone()
+ // if the associated bug is fixed.
+ if (!response)
+ return nullptr;
+ return blink::mojom::FetchAPIResponse::New(
+ response->url_list, response->status_code, response->status_text,
+ response->response_type, response->headers,
+ CloneSerializedBlob(response->blob), response->error,
+ response->response_time, response->cache_storage_cache_name,
+ response->cors_exposed_header_names, response->is_in_cache_storage,
+ CloneSerializedBlob(response->side_data_blob));
+}
BackgroundFetchSettledFetch::BackgroundFetchSettledFetch() = default;
BackgroundFetchSettledFetch::BackgroundFetchSettledFetch(
- const BackgroundFetchSettledFetch& other) = default;
+ const BackgroundFetchSettledFetch& other) {
+ *this = other;
+}
+
+BackgroundFetchSettledFetch& BackgroundFetchSettledFetch::operator=(
+ const BackgroundFetchSettledFetch& other) {
+ request = other.request;
+ response = CloneResponse(other.response);
+ return *this;
+}
BackgroundFetchSettledFetch::~BackgroundFetchSettledFetch() = default;
diff --git a/chromium/content/common/background_fetch/background_fetch_types.h b/chromium/content/common/background_fetch/background_fetch_types.h
index fd774420426..73685818e47 100644
--- a/chromium/content/common/background_fetch/background_fetch_types.h
+++ b/chromium/content/common/background_fetch/background_fetch_types.h
@@ -12,6 +12,14 @@
#include "content/common/content_export.h"
#include "content/common/service_worker/service_worker_types.h"
#include "third_party/blink/public/common/manifest/manifest.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_response.mojom.h"
+
+namespace blink {
+namespace mojom {
+enum class BackgroundFetchFailureReason;
+enum class BackgroundFetchState;
+} // namespace mojom
+} // namespace blink
namespace content {
@@ -33,6 +41,15 @@ struct CONTENT_EXPORT BackgroundFetchOptions {
// https://wicg.github.io/background-fetch/#background-fetch-registration
struct CONTENT_EXPORT BackgroundFetchRegistration {
BackgroundFetchRegistration();
+ BackgroundFetchRegistration(
+ const std::string& developer_id,
+ const std::string& unique_id,
+ uint64_t upload_total,
+ uint64_t uploaded,
+ uint64_t download_total,
+ uint64_t downloaded,
+ blink::mojom::BackgroundFetchState state,
+ blink::mojom::BackgroundFetchFailureReason failure_reason);
BackgroundFetchRegistration(const BackgroundFetchRegistration& other);
~BackgroundFetchRegistration();
@@ -48,19 +65,24 @@ struct CONTENT_EXPORT BackgroundFetchRegistration {
uint64_t uploaded = 0;
uint64_t download_total = 0;
uint64_t downloaded = 0;
- // TODO(crbug.com/699957): Support the `activeFetches` member.
+ blink::mojom::BackgroundFetchState state;
+ blink::mojom::BackgroundFetchFailureReason failure_reason;
};
// Represents a request/response pair for a settled Background Fetch fetch.
// Analogous to the following structure in the spec:
// http://wicg.github.io/background-fetch/#backgroundfetchsettledfetch
struct CONTENT_EXPORT BackgroundFetchSettledFetch {
+ static blink::mojom::FetchAPIResponsePtr CloneResponse(
+ const blink::mojom::FetchAPIResponsePtr& response);
BackgroundFetchSettledFetch();
BackgroundFetchSettledFetch(const BackgroundFetchSettledFetch& other);
+ BackgroundFetchSettledFetch& operator=(
+ const BackgroundFetchSettledFetch& other);
~BackgroundFetchSettledFetch();
ServiceWorkerFetchRequest request;
- ServiceWorkerResponse response;
+ blink::mojom::FetchAPIResponsePtr response;
};
} // namespace content
diff --git a/chromium/content/common/background_fetch/background_fetch_types.typemap b/chromium/content/common/background_fetch/background_fetch_types.typemap
index 57d741b2848..7e7fafe3019 100644
--- a/chromium/content/common/background_fetch/background_fetch_types.typemap
+++ b/chromium/content/common/background_fetch/background_fetch_types.typemap
@@ -14,6 +14,5 @@ deps = [
type_mappings = [
"blink.mojom.BackgroundFetchOptions=content::BackgroundFetchOptions",
"blink.mojom.BackgroundFetchRegistration=content::BackgroundFetchRegistration",
- "content.mojom.BackgroundFetchSettledFetch=::content::BackgroundFetchSettledFetch",
- "blink.mojom.IconDefinition=content::IconDefinition",
+ "blink.mojom.BackgroundFetchSettledFetch=::content::BackgroundFetchSettledFetch",
]
diff --git a/chromium/content/common/content_constants_internal.cc b/chromium/content/common/content_constants_internal.cc
index 5cd58371095..be2463a12ec 100644
--- a/chromium/content/common/content_constants_internal.cc
+++ b/chromium/content/common/content_constants_internal.cc
@@ -33,4 +33,8 @@ const int kTraceEventRendererMainThreadSortIndex = -1;
const char kDoNotTrackHeader[] = "DNT";
+#if defined(OS_MACOSX)
+const char kMachBootstrapName[] = "rohitfork";
+#endif
+
} // namespace content
diff --git a/chromium/content/common/content_constants_internal.h b/chromium/content/common/content_constants_internal.h
index efd36e67724..9c0767b55ba 100644
--- a/chromium/content/common/content_constants_internal.h
+++ b/chromium/content/common/content_constants_internal.h
@@ -8,6 +8,7 @@
#include <stddef.h>
#include <stdint.h>
+#include "build/build_config.h"
#include "content/common/content_export.h"
namespace content {
@@ -39,6 +40,11 @@ CONTENT_EXPORT extern const int kTraceEventRendererMainThreadSortIndex;
// HTTP header set in requests to indicate they should be marked DoNotTrack.
extern const char kDoNotTrackHeader[];
+#if defined(OS_MACOSX)
+// Name of Mach port used for communication between parent and child processes.
+CONTENT_EXPORT extern const char kMachBootstrapName[];
+#endif
+
} // namespace content
#endif // CONTENT_COMMON_CONTENT_CONSTANTS_INTERNAL_H_
diff --git a/chromium/content/common/content_message_generator.h b/chromium/content/common/content_message_generator.h
index c895849490e..c604ee0e5ba 100644
--- a/chromium/content/common/content_message_generator.h
+++ b/chromium/content/common/content_message_generator.h
@@ -27,11 +27,6 @@
#error "Failed to include content/common/drag_messages.h"
#endif
#include "content/common/drag_traits.h"
-#undef CONTENT_COMMON_FILEAPI_FILE_SYSTEM_MESSAGES_H_
-#include "content/common/fileapi/file_system_messages.h"
-#ifndef CONTENT_COMMON_FILEAPI_FILE_SYSTEM_MESSAGES_H_
-#error "Failed to include content/common/fileapi/file_system_messages.h"
-#endif
#undef CONTENT_COMMON_FILEAPI_WEBBLOB_MESSAGES_H_
#include "content/common/fileapi/webblob_messages.h"
#ifndef CONTENT_COMMON_FILEAPI_WEBBLOB_MESSAGES_H_
@@ -73,22 +68,11 @@
#ifndef CONTENT_COMMON_PAGE_MESSAGES_H_
#error "Failed to include content/common/page_messages.h"
#endif
-#undef CONTENT_COMMON_PLATFORM_NOTIFICATION_PARAM_TRAITS_H_
-#include "content/common/platform_notification_param_traits.h"
-#ifndef CONTENT_COMMON_PLATFORM_NOTIFICATION_PARAM_TRAITS_H_
-#error "Failed to include content/common/platform_notification_param_traits.h"
-#endif
#undef CONTENT_COMMON_RESOURCE_MESSAGES_H_
#include "content/common/resource_messages.h"
#ifndef CONTENT_COMMON_RESOURCE_MESSAGES_H_
#error "Failed to include content/common/resource_messages.h"
#endif
-#undef CONTENT_COMMON_SERVICE_WORKER_SERVICE_WORKER_MESSAGES_H_
-#include "content/common/service_worker/service_worker_messages.h"
-#ifndef CONTENT_COMMON_SERVICE_WORKER_SERVICE_WORKER_MESSAGES_H_
-#error \
- "Failed to include content/common/service_worker/service_worker_messages.h"
-#endif
#undef CONTENT_COMMON_TEXT_INPUT_CLIENT_MESSAGES_H_
#include "content/common/text_input_client_messages.h"
#ifndef CONTENT_COMMON_TEXT_INPUT_CLIENT_MESSAGES_H_
@@ -107,12 +91,6 @@
#error "Failed to include content/common/input/sync_compositor_messages.h"
#endif
-#undef CONTENT_COMMON_P2P_MESSAGES_H_
-#include "content/common/p2p_messages.h"
-#ifndef CONTENT_COMMON_P2P_MESSAGES_H_
-#error "Failed to include content/common/p2p_messages.h"
-#endif
-
#if defined(OS_ANDROID)
#undef CONTENT_COMMON_GIN_JAVA_BRIDGE_MESSAGES_H_
#include "content/common/gin_java_bridge_messages.h"
diff --git a/chromium/content/common/content_param_traits.cc b/chromium/content/common/content_param_traits.cc
index 450aaaf050a..cac6c159e5b 100644
--- a/chromium/content/common/content_param_traits.cc
+++ b/chromium/content/common/content_param_traits.cc
@@ -148,7 +148,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::IsAshInBrowserProcess() ||
+ DCHECK(features::IsUsingWindowService() ||
(p.frame_sink_id.has_value() && p.frame_sink_id->is_valid()));
WriteParam(m, p.frame_sink_id);
}
@@ -159,7 +159,7 @@ bool ParamTraits<content::FrameMsg_ViewChanged_Params>::Read(
param_type* r) {
if (!ReadParam(m, iter, &(r->frame_sink_id)))
return false;
- if (features::IsAshInBrowserProcess() &&
+ if (!features::IsUsingWindowService() &&
(!r->frame_sink_id || !r->frame_sink_id->is_valid())) {
NOTREACHED();
return false;
@@ -211,6 +211,11 @@ void ParamTraits<scoped_refptr<base::RefCountedData<
WriteParam(m, p->data.stack_trace_debugger_id_second);
WriteParam(m, p->data.ports);
WriteParam(m, p->data.has_user_gesture);
+ WriteParam(m, !!p->data.user_activation);
+ if (p->data.user_activation) {
+ WriteParam(m, p->data.user_activation->has_been_active);
+ WriteParam(m, p->data.user_activation->was_active);
+ }
}
bool ParamTraits<
@@ -229,14 +234,27 @@ bool ParamTraits<
// returned message.
(*r)->data.encoded_message =
base::make_span(reinterpret_cast<const uint8_t*>(data), length);
+ bool has_activation = false;
if (!ReadParam(m, iter, &(*r)->data.blobs) ||
!ReadParam(m, iter, &(*r)->data.stack_trace_id) ||
!ReadParam(m, iter, &(*r)->data.stack_trace_debugger_id_first) ||
!ReadParam(m, iter, &(*r)->data.stack_trace_debugger_id_second) ||
!ReadParam(m, iter, &(*r)->data.ports) ||
- !ReadParam(m, iter, &(*r)->data.has_user_gesture)) {
+ !ReadParam(m, iter, &(*r)->data.has_user_gesture) ||
+ !ReadParam(m, iter, &has_activation)) {
return false;
}
+
+ if (has_activation) {
+ bool has_been_active;
+ bool was_active;
+ if (!ReadParam(m, iter, &has_been_active) ||
+ !ReadParam(m, iter, &was_active)) {
+ return false;
+ }
+ (*r)->data.user_activation =
+ blink::mojom::UserActivationSnapshot::New(has_been_active, was_active);
+ }
return true;
}
diff --git a/chromium/content/common/content_param_traits_macros.h b/chromium/content/common/content_param_traits_macros.h
index 65199c2f005..aaddd3ed6d3 100644
--- a/chromium/content/common/content_param_traits_macros.h
+++ b/chromium/content/common/content_param_traits_macros.h
@@ -8,6 +8,7 @@
#ifndef CONTENT_COMMON_CONTENT_PARAM_TRAITS_MACROS_H_
#define CONTENT_COMMON_CONTENT_PARAM_TRAITS_MACROS_H_
+#include "components/viz/common/quads/selection.h"
#include "content/common/content_export.h"
#include "content/common/content_param_traits.h"
#include "content/common/download/mhtml_save_status.h"
@@ -46,8 +47,8 @@ IPC_ENUM_TRAITS_MAX_VALUE(blink::mojom::PageVisibilityState,
blink::mojom::PageVisibilityState::kMaxValue)
IPC_ENUM_TRAITS_MAX_VALUE(blink::WebImeTextSpan::Type,
blink::WebImeTextSpan::Type::kMisspellingSuggestion)
-IPC_ENUM_TRAITS_MAX_VALUE(ui::mojom::ImeTextSpanThickness,
- ui::mojom::ImeTextSpanThickness::kThick)
+IPC_ENUM_TRAITS_MAX_VALUE(ws::mojom::ImeTextSpanThickness,
+ ws::mojom::ImeTextSpanThickness::kThick)
IPC_STRUCT_TRAITS_BEGIN(viz::Selection<gfx::SelectionBound>)
IPC_STRUCT_TRAITS_MEMBER(start)
diff --git a/chromium/content/common/content_security_policy/csp_context.cc b/chromium/content/common/content_security_policy/csp_context.cc
index aa19c5fd533..94b0a96ce6e 100644
--- a/chromium/content/common/content_security_policy/csp_context.cc
+++ b/chromium/content/common/content_security_policy/csp_context.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "content/common/content_security_policy/csp_context.h"
+#include "content/public/common/origin_util.h"
namespace content {
@@ -65,7 +66,7 @@ bool CSPContext::ShouldModifyRequestUrlForCsp(
}
void CSPContext::ModifyRequestUrlForCsp(GURL* url) {
- if (url->SchemeIs(url::kHttpScheme)) {
+ if (url->SchemeIs(url::kHttpScheme) && !IsOriginSecure(*url)) {
// Updating the URL's scheme also implicitly updates the URL's port from 80
// to 443 if needed.
GURL::Replacements replacements;
diff --git a/chromium/content/common/content_security_policy/csp_context_unittest.cc b/chromium/content/common/content_security_policy/csp_context_unittest.cc
index 49ce33e13e1..781b4a38f1c 100644
--- a/chromium/content/common/content_security_policy/csp_context_unittest.cc
+++ b/chromium/content/common/content_security_policy/csp_context_unittest.cc
@@ -277,6 +277,23 @@ TEST(CSPContextTest, ModifyRequestUrlForCsp) {
context.ModifyRequestUrlForCsp(&test_url);
EXPECT_EQ(GURL("https://example-weird-port.com:8088"), test_url);
+ // Trusted Non-HTTPS URLs don't need to be modified.
+ test_url = GURL("http://127.0.0.1");
+ context.ModifyRequestUrlForCsp(&test_url);
+ EXPECT_EQ(GURL("http://127.0.0.1"), test_url);
+
+ test_url = GURL("http://127.0.0.8");
+ context.ModifyRequestUrlForCsp(&test_url);
+ EXPECT_EQ(GURL("http://127.0.0.8"), test_url);
+
+ test_url = GURL("http://localhost");
+ context.ModifyRequestUrlForCsp(&test_url);
+ EXPECT_EQ(GURL("http://localhost"), test_url);
+
+ test_url = GURL("http://sub.localhost");
+ context.ModifyRequestUrlForCsp(&test_url);
+ EXPECT_EQ(GURL("http://sub.localhost"), test_url);
+
// Non-HTTP URLs don't need to be modified.
test_url = GURL("https://example.com");
context.ModifyRequestUrlForCsp(&test_url);
@@ -285,6 +302,10 @@ TEST(CSPContextTest, ModifyRequestUrlForCsp) {
test_url = GURL("data:text/html,<html></html>");
context.ModifyRequestUrlForCsp(&test_url);
EXPECT_EQ(GURL("data:text/html,<html></html>"), test_url);
+
+ test_url = GURL("weird-scheme://this.is.a.url");
+ context.ModifyRequestUrlForCsp(&test_url);
+ EXPECT_EQ(GURL("weird-scheme://this.is.a.url"), test_url);
}
} // namespace content
diff --git a/chromium/content/common/dom_storage/OWNERS b/chromium/content/common/dom_storage/OWNERS
index 74dc2f93524..c91ee103f60 100644
--- a/chromium/content/common/dom_storage/OWNERS
+++ b/chromium/content/common/dom_storage/OWNERS
@@ -1,5 +1,4 @@
-dmurph@chromium.org
-mek@chromium.org
+file://content/browser/dom_storage/OWNERS
per-file *_messages*.h=set noparent
per-file *_messages*.h=file://ipc/SECURITY_OWNERS
diff --git a/chromium/content/common/fileapi/OWNERS b/chromium/content/common/fileapi/OWNERS
index 3a69eb7de67..94df6ef56a2 100644
--- a/chromium/content/common/fileapi/OWNERS
+++ b/chromium/content/common/fileapi/OWNERS
@@ -1,7 +1,4 @@
-mek@chromium.org
-jianli@chromium.org
-tzik@chromium.org
-nhiroki@chromium.org
+file://content/browser/fileapi/OWNERS
per-file *_messages*.h=set noparent
per-file *_messages*.h=file://ipc/SECURITY_OWNERS
diff --git a/chromium/content/common/fileapi/file_system_messages.h b/chromium/content/common/fileapi/file_system_messages.h
deleted file mode 100644
index 971610bdffe..00000000000
--- a/chromium/content/common/fileapi/file_system_messages.h
+++ /dev/null
@@ -1,176 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_FILEAPI_FILE_SYSTEM_MESSAGES_H_
-#define CONTENT_COMMON_FILEAPI_FILE_SYSTEM_MESSAGES_H_
-
-// IPC messages for the file system.
-
-#include <stdint.h>
-
-#include <string>
-#include <vector>
-
-#include "components/services/filesystem/public/interfaces/types.mojom.h"
-#include "ipc/ipc_message_macros.h"
-#include "ipc/ipc_platform_file.h"
-#include "storage/common/fileapi/file_system_info.h"
-#include "storage/common/fileapi/file_system_types.h"
-#include "storage/common/quota/quota_limit_type.h"
-#include "url/gurl.h"
-
-#undef IPC_MESSAGE_EXPORT
-#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
-#define IPC_MESSAGE_START FileSystemMsgStart
-
-IPC_STRUCT_TRAITS_BEGIN(filesystem::mojom::DirectoryEntry)
- IPC_STRUCT_TRAITS_MEMBER(name)
- IPC_STRUCT_TRAITS_MEMBER(type)
-IPC_STRUCT_TRAITS_END()
-
-IPC_STRUCT_TRAITS_BEGIN(storage::FileSystemInfo)
- IPC_STRUCT_TRAITS_MEMBER(name)
- IPC_STRUCT_TRAITS_MEMBER(root_url)
- IPC_STRUCT_TRAITS_MEMBER(mount_type)
-IPC_STRUCT_TRAITS_END()
-
-IPC_ENUM_TRAITS_MAX_VALUE(filesystem::mojom::FsFileType,
- filesystem::mojom::FsFileType::DIRECTORY)
-IPC_ENUM_TRAITS_MAX_VALUE(storage::FileSystemType,
- storage::FileSystemType::kFileSystemTypeLast)
-IPC_ENUM_TRAITS_MAX_VALUE(storage::QuotaLimitType, storage::kQuotaLimitTypeLast)
-
-// File system messages sent from the browser to the child process.
-
-// WebLocalFrameClient::openFileSystem response messages.
-IPC_MESSAGE_CONTROL3(FileSystemMsg_DidOpenFileSystem,
- int /* request_id */,
- std::string /* name */,
- GURL /* root_url */)
-
-// WebFileSystem response messages.
-IPC_MESSAGE_CONTROL4(FileSystemMsg_DidResolveURL,
- int /* request_id */,
- storage::FileSystemInfo /* filesystem_info */,
- base::FilePath /* file_path */,
- bool /* is_directory */)
-IPC_MESSAGE_CONTROL1(FileSystemMsg_DidSucceed,
- int /* request_id */)
-IPC_MESSAGE_CONTROL2(FileSystemMsg_DidReadMetadata,
- int /* request_id */,
- base::File::Info)
-IPC_MESSAGE_CONTROL3(FileSystemMsg_DidCreateSnapshotFile,
- int /* request_id */,
- base::File::Info,
- base::FilePath /* true platform path */)
-IPC_MESSAGE_CONTROL3(
- FileSystemMsg_DidReadDirectory,
- int /* request_id */,
- std::vector<filesystem::mojom::DirectoryEntry> /* entries */,
- bool /* has_more */)
-IPC_MESSAGE_CONTROL3(FileSystemMsg_DidWrite,
- int /* request_id */,
- int64_t /* byte count */,
- bool /* complete */)
-IPC_MESSAGE_CONTROL2(FileSystemMsg_DidFail,
- int /* request_id */,
- base::File::Error /* error_code */)
-
-// File system messages sent from the child process to the browser.
-
-// WebLocalFrameClient::openFileSystem() message.
-IPC_MESSAGE_CONTROL3(FileSystemHostMsg_OpenFileSystem,
- int /* request_id */,
- GURL /* origin_url */,
- storage::FileSystemType /* type */)
-
-// WevFrameClient::resolveURL() message.
-IPC_MESSAGE_CONTROL2(FileSystemHostMsg_ResolveURL,
- int /* request_id */,
- GURL /* filesystem_url */)
-
-// WebFileSystem::move() message.
-IPC_MESSAGE_CONTROL3(FileSystemHostMsg_Move,
- int /* request_id */,
- GURL /* src path */,
- GURL /* dest path */)
-
-// WebFileSystem::copy() message.
-IPC_MESSAGE_CONTROL3(FileSystemHostMsg_Copy,
- int /* request_id */,
- GURL /* src path */,
- GURL /* dest path */)
-
-// WebFileSystem::remove() message.
-IPC_MESSAGE_CONTROL3(FileSystemHostMsg_Remove,
- int /* request_id */,
- GURL /* path */,
- bool /* recursive */)
-
-// WebFileSystem::readMetadata() message.
-IPC_MESSAGE_CONTROL2(FileSystemHostMsg_ReadMetadata,
- int /* request_id */,
- GURL /* path */)
-
-// WebFileSystem::create() message.
-IPC_MESSAGE_CONTROL5(FileSystemHostMsg_Create,
- int /* request_id */,
- GURL /* path */,
- bool /* exclusive */,
- bool /* is_directory */,
- bool /* recursive */)
-
-// WebFileSystem::exists() messages.
-IPC_MESSAGE_CONTROL3(FileSystemHostMsg_Exists,
- int /* request_id */,
- GURL /* path */,
- bool /* is_directory */)
-
-// WebFileSystem::readDirectory() message.
-IPC_MESSAGE_CONTROL2(FileSystemHostMsg_ReadDirectory,
- int /* request_id */,
- GURL /* path */)
-
-// WebFileWriter::write() message.
-IPC_MESSAGE_CONTROL4(FileSystemHostMsg_Write,
- int /* request id */,
- GURL /* file path */,
- std::string /* blob uuid */,
- int64_t /* position */)
-
-// WebFileWriter::truncate() message.
-IPC_MESSAGE_CONTROL3(FileSystemHostMsg_Truncate,
- int /* request id */,
- GURL /* file path */,
- int64_t /* length */)
-
-// Pepper's Touch() message.
-IPC_MESSAGE_CONTROL4(FileSystemHostMsg_TouchFile,
- int /* request_id */,
- GURL /* path */,
- base::Time /* last_access_time */,
- base::Time /* last_modified_time */)
-
-// WebFileWriter::cancel() message.
-IPC_MESSAGE_CONTROL2(FileSystemHostMsg_CancelWrite,
- int /* request id */,
- int /* id of request to cancel */)
-
-// WebFileSystem::createSnapshotFileAndReadMetadata() message.
-IPC_MESSAGE_CONTROL2(FileSystemHostMsg_CreateSnapshotFile,
- int /* request_id */,
- GURL /* file_path */)
-
-// Renderers are expected to send this message after having processed
-// the FileSystemMsg_DidCreateSnapshotFile message. In particular,
-// after having created a BlobDataHandle backed by the snapshot file.
-IPC_MESSAGE_CONTROL1(FileSystemHostMsg_DidReceiveSnapshotFile,
- int /* request_id */)
-
-// For Pepper's URL loader.
-IPC_SYNC_MESSAGE_CONTROL1_1(FileSystemHostMsg_SyncGetPlatformPath,
- GURL /* file path */,
- base::FilePath /* platform_path */)
-
-#endif // CONTENT_COMMON_FILEAPI_FILE_SYSTEM_MESSAGES_H_
diff --git a/chromium/content/common/font_list.cc b/chromium/content/common/font_list.cc
index 6160a2ed569..2f40c9323be 100644
--- a/chromium/content/common/font_list.cc
+++ b/chromium/content/common/font_list.cc
@@ -4,7 +4,7 @@
#include "content/common/font_list.h"
-#include "base/task_scheduler/lazy_task_runner.h"
+#include "base/task/lazy_task_runner.h"
namespace content {
diff --git a/chromium/content/common/frame.mojom b/chromium/content/common/frame.mojom
index fb4732e6e66..c2ce967c17a 100644
--- a/chromium/content/common/frame.mojom
+++ b/chromium/content/common/frame.mojom
@@ -36,6 +36,17 @@ interface Frame {
GetInterfaceProvider(service_manager.mojom.InterfaceProvider& interfaces);
GetCanonicalUrlForSharing() => (url.mojom.Url? canonical_url);
+ // Causes all new subresource requests to be blocked (not being started) until
+ // ResumeBlockedRequests is called.
+ BlockRequests();
+
+ // Resumes blocked requests.
+ // It is safe to call this without calling BlockRequests.
+ ResumeBlockedRequests();
+
+ // Cancels blocked requests. BlockRequests must have been called before.
+ CancelBlockedRequests();
+
// Samsung Galaxy Note-specific "smart clip" stylus text getter.
// Extracts the data at the given rect.
[EnableIf=is_android]
diff --git a/chromium/content/common/frame_messages.h b/chromium/content/common/frame_messages.h
index 4d0712eca8d..c42a88101a4 100644
--- a/chromium/content/common/frame_messages.h
+++ b/chromium/content/common/frame_messages.h
@@ -161,13 +161,6 @@ IPC_STRUCT_TRAITS_BEGIN(blink::WebIntrinsicSizingInfo)
IPC_STRUCT_TRAITS_MEMBER(has_height)
IPC_STRUCT_TRAITS_END()
-IPC_STRUCT_TRAITS_BEGIN(blink::WebFindOptions)
- IPC_STRUCT_TRAITS_MEMBER(forward)
- IPC_STRUCT_TRAITS_MEMBER(match_case)
- IPC_STRUCT_TRAITS_MEMBER(find_next)
- IPC_STRUCT_TRAITS_MEMBER(force)
-IPC_STRUCT_TRAITS_END()
-
IPC_STRUCT_TRAITS_BEGIN(blink::WebFullscreenOptions)
IPC_STRUCT_TRAITS_MEMBER(prefers_navigation_bar)
IPC_STRUCT_TRAITS_END()
@@ -443,6 +436,9 @@ IPC_STRUCT_BEGIN_WITH_PARENT(FrameHostMsg_DidCommitProvisionalLoad_Params,
// identify and discard compositor frames that correspond to now-unloaded
// web content.
IPC_STRUCT_MEMBER(uint32_t, content_source_id)
+
+ // Request ID generated by the renderer.
+ IPC_STRUCT_MEMBER(int, request_id)
IPC_STRUCT_END()
IPC_STRUCT_BEGIN(FrameMsg_PostMessage_Params)
@@ -489,6 +485,7 @@ IPC_STRUCT_TRAITS_BEGIN(content::CommonNavigationParams)
IPC_STRUCT_TRAITS_MEMBER(initiator_csp)
IPC_STRUCT_TRAITS_MEMBER(initiator_self_source)
IPC_STRUCT_TRAITS_MEMBER(origin_policy)
+ IPC_STRUCT_TRAITS_MEMBER(input_start)
IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(content::NavigationTiming)
@@ -1075,16 +1072,6 @@ IPC_MESSAGE_ROUTED2(FrameMsg_AdvanceFocus,
IPC_MESSAGE_ROUTED1(FrameMsg_AdvanceFocusInForm,
blink::WebFocusType /* direction for advancing focus */)
-// Sent when the user wants to search for a word on the page (find-in-page).
-IPC_MESSAGE_ROUTED3(FrameMsg_Find,
- int /* request_id */,
- base::string16 /* search_text */,
- blink::WebFindOptions)
-
-// This message notifies the frame that the user has closed the find-in-page
-// window (and what action to take regarding the selection).
-IPC_MESSAGE_ROUTED1(FrameMsg_StopFinding, content::StopFindAction /* action */)
-
// Copies the image at location x, y to the clipboard (if there indeed is an
// image at that location).
IPC_MESSAGE_ROUTED2(FrameMsg_CopyImageAt,
@@ -1488,9 +1475,10 @@ IPC_MESSAGE_ROUTED2(FrameHostMsg_SynchronizeVisualProperties,
// use by the IntersectionObserver API.
// compositor_rect is dependent on the intersection rect and indicates the
// area of the child frame that needs to be rastered. It is in physical pixels.
-IPC_MESSAGE_ROUTED2(FrameHostMsg_UpdateViewportIntersection,
+IPC_MESSAGE_ROUTED3(FrameHostMsg_UpdateViewportIntersection,
gfx::Rect /* viewport_intersection */,
- gfx::Rect /* compositor_visible_rect */)
+ gfx::Rect /* compositor_visible_rect */,
+ bool /* occluded or obscured */)
// Informs the child that the frame has changed visibility.
IPC_MESSAGE_ROUTED1(FrameHostMsg_VisibilityChanged, bool /* visible */)
@@ -1697,19 +1685,6 @@ IPC_MESSAGE_ROUTED2(FrameHostMsg_AdvanceFocus,
blink::WebFocusType /* type */,
int32_t /* source_routing_id */)
-// Result of string search in the document.
-// Response to FrameMsg_Find with the results of the requested find-in-page
-// search, the number of matches found and the selection rect (in screen
-// coordinates) for the string found. If |final_update| is false, it signals
-// that this is not the last Find_Reply message - more will be sent as the
-// scoping effort continues.
-IPC_MESSAGE_ROUTED5(FrameHostMsg_Find_Reply,
- int /* request_id */,
- int /* number of matches */,
- gfx::Rect /* selection_rect */,
- int /* active_match_ordinal */,
- bool /* final_update */)
-
// Sends hittesting data needed to perform hittesting on the browser process.
IPC_MESSAGE_ROUTED1(FrameHostMsg_HittestData, FrameHostMsg_HittestData_Params)
diff --git a/chromium/content/common/gpu_stream_constants.h b/chromium/content/common/gpu_stream_constants.h
index 8ce61c49379..afcf6f5ef6a 100644
--- a/chromium/content/common/gpu_stream_constants.h
+++ b/chromium/content/common/gpu_stream_constants.h
@@ -13,9 +13,11 @@ enum {
kGpuStreamIdDefault,
kGpuStreamIdWorker,
kGpuStreamIdMedia,
+ kGpuStreamIdHighPriorityWebGL,
};
-// Used for renderer compositor thread context, WebGL, canvas, etc.
+// Used for renderer compositor thread context, WebGL (when high priority is
+// not requested by workaround), canvas, etc.
const gpu::SchedulingPriority kGpuStreamPriorityDefault =
gpu::SchedulingPriority::kNormal;
@@ -31,6 +33,11 @@ const gpu::SchedulingPriority kGpuStreamPriorityMedia =
const gpu::SchedulingPriority kGpuStreamPriorityWorker =
gpu::SchedulingPriority::kLow;
+// Used for WebGL on devices where a hgih priority context is requested by the
+// |use_high_priority_for_webgl| workaround.
+const gpu::SchedulingPriority kGpuStreamPriorityHighPriorityWebGL =
+ gpu::SchedulingPriority::kHigh;
+
} // namespace content
#endif // CONTENT_COMMON_GPU_STREAM_CONSTANTS_H_
diff --git a/chromium/content/common/indexed_db/OWNERS b/chromium/content/common/indexed_db/OWNERS
deleted file mode 100644
index 7b4d02967d7..00000000000
--- a/chromium/content/common/indexed_db/OWNERS
+++ /dev/null
@@ -1,15 +0,0 @@
-file://content/browser/indexed_db/OWNERS
-
-per-file *_messages*.h=set noparent
-per-file *_messages*.h=file://ipc/SECURITY_OWNERS
-per-file *.mojom=set noparent
-per-file *.mojom=file://ipc/SECURITY_OWNERS
-per-file *_param_traits*.*=set noparent
-per-file *_param_traits*.*=file://ipc/SECURITY_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: storage-dev@chromium.org
-# COMPONENT: Blink>Storage>IndexedDB
diff --git a/chromium/content/common/indexed_db/indexed_db.mojom b/chromium/content/common/indexed_db/indexed_db.mojom
deleted file mode 100644
index 15edf0ef4cb..00000000000
--- a/chromium/content/common/indexed_db/indexed_db.mojom
+++ /dev/null
@@ -1,345 +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.
-
-// TODO: This will move to //third_party/WebKit when //content/child/indexed_db
-// is deleted but for now this will depend on //content/common types and so
-// so belongs here.
-
-module indexed_db.mojom;
-
-import "mojo/public/mojom/base/file_path.mojom";
-import "mojo/public/mojom/base/string16.mojom";
-import "mojo/public/mojom/base/string16.mojom";
-import "mojo/public/mojom/base/time.mojom";
-import "third_party/blink/public/mojom/blob/blob.mojom";
-import "url/mojom/origin.mojom";
-
-enum CursorDirection {
- Next,
- NextNoDuplicate,
- Prev,
- PrevNoDuplicate,
-};
-
-enum DataLoss {
- None,
- Total,
-};
-
-// Represents key types that hold no data and so cannot be options in the
-// KeyData union.
-// TODO(jsbell): These types should be cleaned up end-to-end, leaving only the
-// dataful options.
-enum DatalessKeyType {
- Invalid,
- Null,
-};
-
-union KeyData {
- array<Key> key_array;
- array<uint8> binary;
- mojo_base.mojom.String16 string;
- double date;
- double number;
- DatalessKeyType other;
-};
-
-// Defined as a structure so that it can by typemapped with StructTraits.
-struct Key {
- KeyData data;
-};
-
-// Represents WebIDBKeyPathTypeString and WebIDBKeyPathTypeArray in a key path.
-union KeyPathData {
- mojo_base.mojom.String16 string;
- array<mojo_base.mojom.String16> string_array;
-};
-
-struct KeyPath {
- // A null value here corresponds to WebIDBKeyPathTypeNull.
- KeyPathData? data;
-};
-
-struct KeyRange {
- Key lower;
- Key upper;
- bool lower_open;
- bool upper_open;
-};
-
-enum OperationType {
- Add,
- Put,
- Delete,
- Clear,
-};
-
-enum PutMode {
- AddOrUpdate,
- AddOnly,
- CursorUpdate,
-};
-
-enum TaskType {
- Normal,
- Preemptive,
-};
-
-enum TransactionMode {
- ReadOnly,
- ReadWrite,
- VersionChange,
-};
-
-enum Status {
- OK,
- NotFound,
- Corruption,
- NotSupported,
- InvalidArgument,
- IOError,
-};
-
-struct IndexMetadata {
- int64 id;
- mojo_base.mojom.String16 name;
- KeyPath key_path;
- bool unique;
- bool multi_entry;
-};
-
-struct ObjectStoreMetadata {
- int64 id;
- mojo_base.mojom.String16 name;
- KeyPath key_path;
- bool auto_increment;
- int64 max_index_id;
- array<IndexMetadata> indexes;
-};
-
-struct DatabaseMetadata {
- int64 id;
- mojo_base.mojom.String16 name;
- int64 version;
- int64 max_object_store_id;
- array<ObjectStoreMetadata> object_stores;
-};
-
-struct IndexKeys {
- int64 index_id;
- array<Key> index_keys;
-};
-
-struct FileInfo {
- mojo_base.mojom.FilePath path;
- mojo_base.mojom.String16 name;
- mojo_base.mojom.Time last_modified;
-};
-
-struct BlobInfo {
- blink.mojom.Blob blob;
- string uuid;
- mojo_base.mojom.String16 mime_type;
- int64 size;
- FileInfo? file;
-};
-
-struct Value {
- string bits;
- array<BlobInfo> blob_or_file_info;
-};
-
-struct ReturnValue {
- Value value;
- Key primary_key;
- KeyPath key_path;
-};
-
-struct Observation {
- int64 object_store_id;
- OperationType type;
- KeyRange key_range;
- Value? value;
-};
-
-struct ObserverTransaction {
- int64 id;
- array<int64> scope;
-};
-
-struct ObserverChanges {
- map<int32, array<int32>> observation_index_map;
- map<int32, ObserverTransaction> transaction_map;
- array<Observation> observations;
-};
-
-// The Callbacks interface is used to return results for individual requests.
-// Some requests may return multiple results before completion, such as
-// UpgradeNeeded before SuccessDatabase.
-//
-// TODO(https://crbug.com/627484): Many of these could be replaced with
-// replies associated with particular messages.
-interface Callbacks {
- Error(int32 code, mojo_base.mojom.String16 message);
-
- // Factory::GetDatabaseNames
- SuccessStringList(array<mojo_base.mojom.String16> value);
-
- // Factory::Open / DeleteDatabase
- Blocked(int64 existing_version);
-
- // Factory::Open
- UpgradeNeeded(associated Database database, int64 old_version,
- DataLoss data_loss, string data_loss_message,
- DatabaseMetadata db_metadata);
- SuccessDatabase(associated Database? database, DatabaseMetadata metadata);
-
- // Database::OpenCursor
- SuccessCursor(associated Cursor cursor,
- Key key,
- Key primary_key,
- Value? value);
-
- // Database::Get / Cursor::Advance
- SuccessValue(ReturnValue? value);
-
- // Cursor::Continue / Advance
- SuccessCursorContinue(Key key, Key primary_key, Value? value);
-
- // Cursor::Prefetch
- SuccessCursorPrefetch(array<Key> keys,
- array<Key> primary_keys,
- array<Value> values);
-
- // Database::GetAll
- SuccessArray(array<ReturnValue> values);
-
- // Database::Put / Cursor::Update
- SuccessKey(Key key);
-
- // Database::Count / DeleteRange
- // Factory::DeleteDatabase
- SuccessInteger(int64 value);
-
- // Cursor::Continue / Advance
- Success();
-};
-
-// The DatabaseCallbacks interface is used to notification of events out of
-// band to individual requests. A single instance is used for the lifetime of
-// a database connection.
-interface DatabaseCallbacks {
- ForcedClose();
- VersionChange(int64 old_version, int64 new_version);
- Abort(int64 transaction_id, int32 code,
- mojo_base.mojom.String16 message);
- Complete(int64 transaction_id);
- Changes(ObserverChanges changes);
-};
-
-interface Cursor {
- Advance(uint32 count, associated Callbacks callbacks);
- Continue(Key key, Key primary_key, associated Callbacks callbacks);
- Prefetch(int32 count, associated Callbacks callbacks);
- PrefetchReset(int32 used_prefetches, int32 unused_prefetches);
-};
-
-interface Database {
- CreateObjectStore(int64 transaction_id,
- int64 object_store_id,
- mojo_base.mojom.String16 name,
- KeyPath key_path,
- bool auto_increment);
- DeleteObjectStore(int64 transaction_id,
- int64 object_store_id);
- RenameObjectStore(int64 transaction_id,
- int64 object_store_id,
- mojo_base.mojom.String16 new_name);
- CreateTransaction(int64 transaction_id,
- array<int64> object_store_ids,
- TransactionMode mode);
- Close();
- VersionChangeIgnored();
- AddObserver(int64 transaction_id,
- int32 observer_id,
- bool include_transaction,
- bool no_records,
- bool values,
- uint16 operation_types);
- RemoveObservers(array<int32> observers);
- Get(int64 transaction_id,
- int64 object_store_id,
- int64 index_id,
- KeyRange key_range,
- bool key_only,
- associated Callbacks callbacks);
- GetAll(int64 transaction_id,
- int64 object_store_id,
- int64 index_id,
- KeyRange key_range,
- bool key_only,
- int64 max_count,
- associated Callbacks callbacks);
- Put(int64 transaction_id,
- int64 object_store_id,
- Value value,
- Key key,
- PutMode mode,
- array<IndexKeys> index_keys,
- associated Callbacks callbacks);
- SetIndexKeys(int64 transaction_id,
- int64 object_store_id,
- Key primary_key,
- array<IndexKeys> index_keys);
- SetIndexesReady(int64 transaction_id,
- int64 object_store_id,
- array<int64> index_ids);
- OpenCursor(int64 transaction_id,
- int64 object_store_id,
- int64 index_id,
- KeyRange key_range,
- CursorDirection direction,
- bool key_only,
- TaskType task_type,
- associated Callbacks callbacks);
- Count(int64 transaction_id,
- int64 object_store_id,
- int64 index_id,
- KeyRange key_range,
- associated Callbacks callbacks);
- DeleteRange(int64 transaction_id,
- int64 object_store_id,
- KeyRange key_range,
- associated Callbacks callbacks);
- Clear(int64 transaction_id,
- int64 object_store_id,
- associated Callbacks callbacks);
- CreateIndex(int64 transaction_id,
- int64 object_store_id,
- int64 index_id,
- mojo_base.mojom.String16 name,
- KeyPath key_path,
- bool unique,
- bool multi_entry);
- DeleteIndex(int64 transaction_id,
- int64 object_store_id,
- int64 index_id);
- RenameIndex(int64 transaction_id,
- int64 object_store_id,
- int64 index_id,
- mojo_base.mojom.String16 new_name);
- Abort(int64 transaction_id);
- Commit(int64 transaction_id);
-};
-
-interface Factory {
- GetDatabaseNames(associated Callbacks callbacks, url.mojom.Origin origin);
- Open(associated Callbacks callbacks,
- associated DatabaseCallbacks database_callbacks, url.mojom.Origin origin,
- mojo_base.mojom.String16 name, int64 version, int64 transaction_id);
- DeleteDatabase(associated Callbacks callbacks, url.mojom.Origin origin,
- mojo_base.mojom.String16 name, bool force_close);
- AbortTransactionsAndCompactDatabase(url.mojom.Origin origin) => (Status status);
- AbortTransactionsForDatabase(url.mojom.Origin origin) => (Status status);
-};
diff --git a/chromium/content/common/indexed_db/indexed_db.typemap b/chromium/content/common/indexed_db/indexed_db.typemap
deleted file mode 100644
index aad054c269e..00000000000
--- a/chromium/content/common/indexed_db/indexed_db.typemap
+++ /dev/null
@@ -1,28 +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.
-
-mojom = "//content/common/indexed_db/indexed_db.mojom"
-public_headers = [
- "//content/common/indexed_db/indexed_db_key.h",
- "//content/common/indexed_db/indexed_db_key_path.h",
- "//content/common/indexed_db/indexed_db_key_range.h",
- "//content/common/indexed_db/indexed_db_metadata.h",
- "//third_party/blink/public/platform/modules/indexeddb/web_idb_types.h",
-]
-traits_headers = [ "//content/common/indexed_db/indexed_db_struct_traits.h" ]
-type_mappings = [
- "indexed_db.mojom.CursorDirection=blink::WebIDBCursorDirection",
- "indexed_db.mojom.DatabaseMetadata=content::IndexedDBDatabaseMetadata",
- "indexed_db.mojom.DataLoss=blink::WebIDBDataLoss",
- "indexed_db.mojom.IndexKeys=content::IndexedDBIndexKeys",
- "indexed_db.mojom.IndexMetadata=content::IndexedDBIndexMetadata",
- "indexed_db.mojom.Key=content::IndexedDBKey",
- "indexed_db.mojom.KeyPath=content::IndexedDBKeyPath",
- "indexed_db.mojom.KeyRange=content::IndexedDBKeyRange",
- "indexed_db.mojom.ObjectStoreMetadata=content::IndexedDBObjectStoreMetadata",
- "indexed_db.mojom.OperationType=blink::WebIDBOperationType",
- "indexed_db.mojom.PutMode=blink::WebIDBPutMode",
- "indexed_db.mojom.TaskType=blink::WebIDBTaskType",
- "indexed_db.mojom.TransactionMode=blink::WebIDBTransactionMode",
-]
diff --git a/chromium/content/common/indexed_db/indexed_db_constants.h b/chromium/content/common/indexed_db/indexed_db_constants.h
deleted file mode 100644
index 024a18b23bc..00000000000
--- a/chromium/content/common/indexed_db/indexed_db_constants.h
+++ /dev/null
@@ -1,24 +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_INDEXED_DB_INDEXED_DB_CONSTANTS_H_
-#define CONTENT_COMMON_INDEXED_DB_INDEXED_DB_CONSTANTS_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include "ipc/ipc_channel.h"
-
-namespace content {
-
-const int32_t kNoDatabase = -1;
-
-const size_t kMaxIDBMessageOverhead = 1024 * 1024; // 1MB; arbitrarily chosen.
-
-const size_t kMaxIDBMessageSizeInBytes =
- IPC::Channel::kMaximumMessageSize - kMaxIDBMessageOverhead;
-
-} // namespace content
-
-#endif // CONTENT_COMMON_INDEXED_DB_INDEXED_DB_CONSTANTS_H_
diff --git a/chromium/content/common/indexed_db/indexed_db_key.cc b/chromium/content/common/indexed_db/indexed_db_key.cc
deleted file mode 100644
index 740569e40af..00000000000
--- a/chromium/content/common/indexed_db/indexed_db_key.cc
+++ /dev/null
@@ -1,143 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/indexed_db/indexed_db_key.h"
-
-#include <string>
-
-namespace content {
-
-using blink::WebIDBKeyType;
-using blink::kWebIDBKeyTypeArray;
-using blink::kWebIDBKeyTypeBinary;
-using blink::kWebIDBKeyTypeDate;
-using blink::kWebIDBKeyTypeInvalid;
-using blink::kWebIDBKeyTypeMin;
-using blink::kWebIDBKeyTypeNull;
-using blink::kWebIDBKeyTypeNumber;
-using blink::kWebIDBKeyTypeString;
-
-namespace {
-
-// Very rough estimate of minimum key size overhead.
-const size_t kOverheadSize = 16;
-
-static size_t CalculateArraySize(const IndexedDBKey::KeyArray& keys) {
- size_t size(0);
- for (size_t i = 0; i < keys.size(); ++i)
- size += keys[i].size_estimate();
- return size;
-}
-
-template<typename T>
-int Compare(const T& a, const T& b) {
- // Using '<' for both comparisons here is as generic as possible (for e.g.
- // objects which only define operator<() and not operator>() or operator==())
- // and also allows e.g. floating point NaNs to compare equal.
- if (a < b)
- return -1;
- return (b < a) ? 1 : 0;
-}
-
-template <typename T>
-static IndexedDBKey::KeyArray CopyKeyArray(const T& array) {
- IndexedDBKey::KeyArray result;
- result.reserve(array.size());
- for (size_t i = 0; i < array.size(); ++i) {
- result.push_back(IndexedDBKey(array[i]));
- }
- return result;
-}
-
-} // namespace
-
-IndexedDBKey::IndexedDBKey()
- : type_(kWebIDBKeyTypeNull), size_estimate_(kOverheadSize) {}
-
-IndexedDBKey::IndexedDBKey(WebIDBKeyType type)
- : type_(type), size_estimate_(kOverheadSize) {
- DCHECK(type == kWebIDBKeyTypeNull || type == kWebIDBKeyTypeInvalid);
-}
-
-IndexedDBKey::IndexedDBKey(double number, WebIDBKeyType type)
- : type_(type),
- number_(number),
- size_estimate_(kOverheadSize + sizeof(number)) {
- DCHECK(type == kWebIDBKeyTypeNumber || type == kWebIDBKeyTypeDate);
-}
-
-IndexedDBKey::IndexedDBKey(const KeyArray& array)
- : type_(kWebIDBKeyTypeArray),
- array_(CopyKeyArray(array)),
- size_estimate_(kOverheadSize + CalculateArraySize(array)) {}
-
-IndexedDBKey::IndexedDBKey(const std::string& binary)
- : type_(kWebIDBKeyTypeBinary),
- binary_(binary),
- size_estimate_(kOverheadSize +
- (binary.length() * sizeof(std::string::value_type))) {}
-
-IndexedDBKey::IndexedDBKey(const base::string16& string)
- : type_(kWebIDBKeyTypeString),
- string_(string),
- size_estimate_(kOverheadSize +
- (string.length() * sizeof(base::string16::value_type))) {}
-
-IndexedDBKey::IndexedDBKey(const IndexedDBKey& other) = default;
-IndexedDBKey::~IndexedDBKey() = default;
-IndexedDBKey& IndexedDBKey::operator=(const IndexedDBKey& other) = default;
-
-bool IndexedDBKey::IsValid() const {
- if (type_ == kWebIDBKeyTypeInvalid || type_ == kWebIDBKeyTypeNull)
- return false;
-
- if (type_ == kWebIDBKeyTypeArray) {
- for (size_t i = 0; i < array_.size(); i++) {
- if (!array_[i].IsValid())
- return false;
- }
- }
-
- return true;
-}
-
-bool IndexedDBKey::IsLessThan(const IndexedDBKey& other) const {
- return CompareTo(other) < 0;
-}
-
-bool IndexedDBKey::Equals(const IndexedDBKey& other) const {
- return !CompareTo(other);
-}
-
-int IndexedDBKey::CompareTo(const IndexedDBKey& other) const {
- DCHECK(IsValid());
- DCHECK(other.IsValid());
- if (type_ != other.type_)
- return type_ > other.type_ ? -1 : 1;
-
- switch (type_) {
- case kWebIDBKeyTypeArray:
- for (size_t i = 0; i < array_.size() && i < other.array_.size(); ++i) {
- int result = array_[i].CompareTo(other.array_[i]);
- if (result != 0)
- return result;
- }
- return Compare(array_.size(), other.array_.size());
- case kWebIDBKeyTypeBinary:
- return binary_.compare(other.binary_);
- case kWebIDBKeyTypeString:
- return string_.compare(other.string_);
- case kWebIDBKeyTypeDate:
- case kWebIDBKeyTypeNumber:
- return Compare(number_, other.number_);
- case kWebIDBKeyTypeInvalid:
- case kWebIDBKeyTypeNull:
- case kWebIDBKeyTypeMin:
- default:
- NOTREACHED();
- return 0;
- }
-}
-
-} // namespace content
diff --git a/chromium/content/common/indexed_db/indexed_db_key.h b/chromium/content/common/indexed_db/indexed_db_key.h
deleted file mode 100644
index 411f1c5fc28..00000000000
--- a/chromium/content/common/indexed_db/indexed_db_key.h
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_INDEXED_DB_INDEXED_DB_KEY_H_
-#define CONTENT_COMMON_INDEXED_DB_INDEXED_DB_KEY_H_
-
-#include <stddef.h>
-
-#include <string>
-#include <vector>
-
-#include "base/logging.h"
-#include "base/strings/string16.h"
-#include "content/common/content_export.h"
-#include "third_party/blink/public/platform/modules/indexeddb/web_idb_types.h"
-
-namespace content {
-
-class CONTENT_EXPORT IndexedDBKey {
- public:
- typedef std::vector<IndexedDBKey> KeyArray;
-
- IndexedDBKey(); // Defaults to blink::WebIDBKeyTypeInvalid.
- explicit IndexedDBKey(blink::WebIDBKeyType); // must be Null or Invalid
- explicit IndexedDBKey(const KeyArray& array);
- explicit IndexedDBKey(const std::string& binary);
- explicit IndexedDBKey(const base::string16& string);
- IndexedDBKey(double number,
- blink::WebIDBKeyType type); // must be date or number
- IndexedDBKey(const IndexedDBKey& other);
- ~IndexedDBKey();
- IndexedDBKey& operator=(const IndexedDBKey& other);
-
- bool IsValid() const;
-
- bool IsLessThan(const IndexedDBKey& other) const;
- bool Equals(const IndexedDBKey& other) const;
-
- blink::WebIDBKeyType type() const { return type_; }
- const std::vector<IndexedDBKey>& array() const {
- DCHECK_EQ(type_, blink::kWebIDBKeyTypeArray);
- return array_;
- }
- const std::string& binary() const {
- DCHECK_EQ(type_, blink::kWebIDBKeyTypeBinary);
- return binary_;
- }
- const base::string16& string() const {
- DCHECK_EQ(type_, blink::kWebIDBKeyTypeString);
- return string_;
- }
- double date() const {
- DCHECK_EQ(type_, blink::kWebIDBKeyTypeDate);
- return number_;
- }
- double number() const {
- DCHECK_EQ(type_, blink::kWebIDBKeyTypeNumber);
- return number_;
- }
-
- size_t size_estimate() const { return size_estimate_; }
-
- private:
- int CompareTo(const IndexedDBKey& other) const;
-
- blink::WebIDBKeyType type_;
- std::vector<IndexedDBKey> array_;
- std::string binary_;
- base::string16 string_;
- double number_ = 0;
-
- size_t size_estimate_;
-};
-
-// An index id, and corresponding set of keys to insert.
-using IndexedDBIndexKeys = std::pair<int64_t, std::vector<IndexedDBKey>>;
-
-} // namespace content
-
-#endif // CONTENT_COMMON_INDEXED_DB_INDEXED_DB_KEY_H_
diff --git a/chromium/content/common/indexed_db/indexed_db_key_path.cc b/chromium/content/common/indexed_db/indexed_db_key_path.cc
deleted file mode 100644
index 731b12854d0..00000000000
--- a/chromium/content/common/indexed_db/indexed_db_key_path.cc
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/indexed_db/indexed_db_key_path.h"
-
-#include "base/logging.h"
-
-namespace content {
-
-using blink::kWebIDBKeyPathTypeArray;
-using blink::kWebIDBKeyPathTypeNull;
-using blink::kWebIDBKeyPathTypeString;
-
-IndexedDBKeyPath::IndexedDBKeyPath() : type_(kWebIDBKeyPathTypeNull) {}
-
-IndexedDBKeyPath::IndexedDBKeyPath(const base::string16& string)
- : type_(kWebIDBKeyPathTypeString), string_(string) {}
-
-IndexedDBKeyPath::IndexedDBKeyPath(const std::vector<base::string16>& array)
- : type_(kWebIDBKeyPathTypeArray), array_(array) {}
-
-IndexedDBKeyPath::IndexedDBKeyPath(const IndexedDBKeyPath& other) = default;
-IndexedDBKeyPath::IndexedDBKeyPath(IndexedDBKeyPath&& other) = default;
-IndexedDBKeyPath::~IndexedDBKeyPath() = default;
-IndexedDBKeyPath& IndexedDBKeyPath::operator=(const IndexedDBKeyPath& other) =
- default;
-IndexedDBKeyPath& IndexedDBKeyPath::operator=(IndexedDBKeyPath&& other) =
- default;
-
-const std::vector<base::string16>& IndexedDBKeyPath::array() const {
- DCHECK(type_ == blink::kWebIDBKeyPathTypeArray);
- return array_;
-}
-
-const base::string16& IndexedDBKeyPath::string() const {
- DCHECK(type_ == blink::kWebIDBKeyPathTypeString);
- return string_;
-}
-
-bool IndexedDBKeyPath::operator==(const IndexedDBKeyPath& other) const {
- if (type_ != other.type_)
- return false;
-
- switch (type_) {
- case kWebIDBKeyPathTypeNull:
- return true;
- case kWebIDBKeyPathTypeString:
- return string_ == other.string_;
- case kWebIDBKeyPathTypeArray:
- return array_ == other.array_;
- }
- NOTREACHED();
- return false;
-}
-
-} // namespace content
diff --git a/chromium/content/common/indexed_db/indexed_db_key_path.h b/chromium/content/common/indexed_db/indexed_db_key_path.h
deleted file mode 100644
index 70c67f941f4..00000000000
--- a/chromium/content/common/indexed_db/indexed_db_key_path.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_INDEXED_DB_INDEXED_DB_KEY_PATH_H_
-#define CONTENT_COMMON_INDEXED_DB_INDEXED_DB_KEY_PATH_H_
-
-#include <string>
-#include <vector>
-
-#include "base/logging.h"
-#include "base/strings/string16.h"
-#include "content/common/content_export.h"
-#include "third_party/blink/public/platform/modules/indexeddb/web_idb_types.h"
-
-namespace content {
-
-class CONTENT_EXPORT IndexedDBKeyPath {
- public:
- IndexedDBKeyPath(); // Defaults to blink::WebIDBKeyPathTypeNull.
- explicit IndexedDBKeyPath(const base::string16&);
- explicit IndexedDBKeyPath(const std::vector<base::string16>&);
- IndexedDBKeyPath(const IndexedDBKeyPath& other);
- IndexedDBKeyPath(IndexedDBKeyPath&& other);
- ~IndexedDBKeyPath();
- IndexedDBKeyPath& operator=(const IndexedDBKeyPath& other);
- IndexedDBKeyPath& operator=(IndexedDBKeyPath&& other);
-
- bool IsNull() const { return type_ == blink::kWebIDBKeyPathTypeNull; }
- bool operator==(const IndexedDBKeyPath& other) const;
-
- blink::WebIDBKeyPathType type() const { return type_; }
- const std::vector<base::string16>& array() const;
- const base::string16& string() const;
-
- private:
- blink::WebIDBKeyPathType type_;
- base::string16 string_;
- std::vector<base::string16> array_;
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_INDEXED_DB_INDEXED_DB_KEY_PATH_H_
diff --git a/chromium/content/common/indexed_db/indexed_db_key_range.cc b/chromium/content/common/indexed_db/indexed_db_key_range.cc
deleted file mode 100644
index e073e649df4..00000000000
--- a/chromium/content/common/indexed_db/indexed_db_key_range.cc
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/indexed_db/indexed_db_key_range.h"
-
-#include "base/logging.h"
-#include "third_party/blink/public/platform/modules/indexeddb/web_idb_types.h"
-
-namespace content {
-
-IndexedDBKeyRange::IndexedDBKeyRange() = default;
-
-IndexedDBKeyRange::IndexedDBKeyRange(const IndexedDBKey& lower,
- const IndexedDBKey& upper,
- bool lower_open,
- bool upper_open)
- : lower_(lower),
- upper_(upper),
- lower_open_(lower_open),
- upper_open_(upper_open) {}
-
-IndexedDBKeyRange::IndexedDBKeyRange(const IndexedDBKey& key)
- : lower_(key), upper_(key) {
-}
-
-IndexedDBKeyRange::IndexedDBKeyRange(const IndexedDBKeyRange& other) = default;
-IndexedDBKeyRange::~IndexedDBKeyRange() = default;
-IndexedDBKeyRange& IndexedDBKeyRange::operator=(
- const IndexedDBKeyRange& other) = default;
-
-bool IndexedDBKeyRange::IsOnlyKey() const {
- if (lower_open_ || upper_open_)
- return false;
- if (IsEmpty())
- return false;
-
- return lower_.Equals(upper_);
-}
-
-bool IndexedDBKeyRange::IsEmpty() const {
- return !lower_.IsValid() && !upper_.IsValid();
-}
-
-} // namespace content
diff --git a/chromium/content/common/indexed_db/indexed_db_key_range.h b/chromium/content/common/indexed_db/indexed_db_key_range.h
deleted file mode 100644
index ac334de12dc..00000000000
--- a/chromium/content/common/indexed_db/indexed_db_key_range.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_COMMON_INDEXED_DB_INDEXED_DB_KEY_RANGE_H_
-#define CONTENT_COMMON_INDEXED_DB_INDEXED_DB_KEY_RANGE_H_
-
-#include "content/common/content_export.h"
-#include "content/common/indexed_db/indexed_db_key.h"
-
-namespace content {
-
-class CONTENT_EXPORT IndexedDBKeyRange {
- public:
- IndexedDBKeyRange();
- explicit IndexedDBKeyRange(const IndexedDBKey& key);
- IndexedDBKeyRange(const IndexedDBKey& lower,
- const IndexedDBKey& upper,
- bool lower_open,
- bool upper_open);
- IndexedDBKeyRange(const IndexedDBKeyRange& other);
- ~IndexedDBKeyRange();
- IndexedDBKeyRange& operator=(const IndexedDBKeyRange& other);
-
- const IndexedDBKey& lower() const { return lower_; }
- const IndexedDBKey& upper() const { return upper_; }
- bool lower_open() const { return lower_open_; }
- bool upper_open() const { return upper_open_; }
-
- bool IsOnlyKey() const;
- bool IsEmpty() const;
-
- private:
- IndexedDBKey lower_ = IndexedDBKey(blink::kWebIDBKeyTypeNull);
- IndexedDBKey upper_ = IndexedDBKey(blink::kWebIDBKeyTypeNull);
- bool lower_open_ = false;
- bool upper_open_ = false;
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_INDEXED_DB_INDEXED_DB_KEY_RANGE_H_
diff --git a/chromium/content/common/indexed_db/indexed_db_key_unittest.cc b/chromium/content/common/indexed_db/indexed_db_key_unittest.cc
deleted file mode 100644
index 30f1c815c26..00000000000
--- a/chromium/content/common/indexed_db/indexed_db_key_unittest.cc
+++ /dev/null
@@ -1,58 +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 <stddef.h>
-
-#include <vector>
-
-#include "base/strings/string16.h"
-#include "content/common/indexed_db/indexed_db_key.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-
-namespace {
-
-TEST(IndexedDBKeyTest, KeySizeEstimates) {
- std::vector<IndexedDBKey> keys;
- std::vector<size_t> estimates;
-
- keys.push_back(IndexedDBKey());
- estimates.push_back(16u); // Overhead.
-
- keys.push_back(IndexedDBKey(blink::kWebIDBKeyTypeNull));
- estimates.push_back(16u);
-
- double number = 3.14159;
- keys.push_back(IndexedDBKey(number, blink::kWebIDBKeyTypeNumber));
- estimates.push_back(24u); // Overhead + sizeof(double).
-
- double date = 1370884329.0;
- keys.push_back(IndexedDBKey(date, blink::kWebIDBKeyTypeDate));
- estimates.push_back(24u); // Overhead + sizeof(double).
-
- const base::string16 string(1024, static_cast<base::char16>('X'));
- keys.push_back(IndexedDBKey(string));
- // Overhead + string length * sizeof(base::char16).
- estimates.push_back(2064u);
-
- const size_t array_size = 1024;
- IndexedDBKey::KeyArray array;
- double value = 123.456;
- for (size_t i = 0; i < array_size; ++i) {
- array.push_back(IndexedDBKey(value, blink::kWebIDBKeyTypeNumber));
- }
- keys.push_back(IndexedDBKey(array));
- // Overhead + array length * (Overhead + sizeof(double)).
- estimates.push_back(24592u);
-
- ASSERT_EQ(keys.size(), estimates.size());
- for (size_t i = 0; i < keys.size(); ++i) {
- EXPECT_EQ(estimates[i], keys[i].size_estimate());
- }
-}
-
-} // namespace
-
-} // namespace content
diff --git a/chromium/content/common/indexed_db/indexed_db_metadata.cc b/chromium/content/common/indexed_db/indexed_db_metadata.cc
deleted file mode 100644
index 82cf74380be..00000000000
--- a/chromium/content/common/indexed_db/indexed_db_metadata.cc
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/indexed_db/indexed_db_metadata.h"
-
-namespace content {
-
-IndexedDBIndexMetadata::IndexedDBIndexMetadata() = default;
-
-IndexedDBIndexMetadata::IndexedDBIndexMetadata(const base::string16& name,
- int64_t id,
- const IndexedDBKeyPath& key_path,
- bool unique,
- bool multi_entry)
- : name(name),
- id(id),
- key_path(key_path),
- unique(unique),
- multi_entry(multi_entry) {}
-
-IndexedDBIndexMetadata::IndexedDBIndexMetadata(
- const IndexedDBIndexMetadata& other) = default;
-IndexedDBIndexMetadata::IndexedDBIndexMetadata(IndexedDBIndexMetadata&& other) =
- default;
-
-IndexedDBIndexMetadata::~IndexedDBIndexMetadata() = default;
-
-IndexedDBIndexMetadata& IndexedDBIndexMetadata::operator=(
- const IndexedDBIndexMetadata& other) = default;
-IndexedDBIndexMetadata& IndexedDBIndexMetadata::operator=(
- IndexedDBIndexMetadata&& other) = default;
-
-bool IndexedDBIndexMetadata::operator==(
- const IndexedDBIndexMetadata& other) const {
- return name == other.name && id == other.id && key_path == other.key_path &&
- unique == other.unique && multi_entry == other.multi_entry;
-}
-
-IndexedDBObjectStoreMetadata::IndexedDBObjectStoreMetadata(
- const base::string16& name,
- int64_t id,
- const IndexedDBKeyPath& key_path,
- bool auto_increment,
- int64_t max_index_id)
- : name(name),
- id(id),
- key_path(key_path),
- auto_increment(auto_increment),
- max_index_id(max_index_id) {}
-
-IndexedDBObjectStoreMetadata::IndexedDBObjectStoreMetadata() = default;
-
-IndexedDBObjectStoreMetadata::IndexedDBObjectStoreMetadata(
- const IndexedDBObjectStoreMetadata& other) = default;
-IndexedDBObjectStoreMetadata::IndexedDBObjectStoreMetadata(
- IndexedDBObjectStoreMetadata&& other) = default;
-
-IndexedDBObjectStoreMetadata::~IndexedDBObjectStoreMetadata() = default;
-
-IndexedDBObjectStoreMetadata& IndexedDBObjectStoreMetadata::operator=(
- const IndexedDBObjectStoreMetadata& other) = default;
-IndexedDBObjectStoreMetadata& IndexedDBObjectStoreMetadata::operator=(
- IndexedDBObjectStoreMetadata&& other) = default;
-
-bool IndexedDBObjectStoreMetadata::operator==(
- const IndexedDBObjectStoreMetadata& other) const {
- return name == other.name && id == other.id && key_path == other.key_path &&
- auto_increment == other.auto_increment &&
- max_index_id == other.max_index_id && indexes == other.indexes;
-}
-
-IndexedDBDatabaseMetadata::IndexedDBDatabaseMetadata() : version(NO_VERSION) {}
-
-IndexedDBDatabaseMetadata::IndexedDBDatabaseMetadata(
- const base::string16& name,
- int64_t id,
- int64_t version,
- int64_t max_object_store_id)
- : name(name),
- id(id),
- version(version),
- max_object_store_id(max_object_store_id) {}
-
-IndexedDBDatabaseMetadata::IndexedDBDatabaseMetadata(
- const IndexedDBDatabaseMetadata& other) = default;
-IndexedDBDatabaseMetadata::IndexedDBDatabaseMetadata(
- IndexedDBDatabaseMetadata&& other) = default;
-
-IndexedDBDatabaseMetadata::~IndexedDBDatabaseMetadata() = default;
-
-IndexedDBDatabaseMetadata& IndexedDBDatabaseMetadata::operator=(
- const IndexedDBDatabaseMetadata& other) = default;
-IndexedDBDatabaseMetadata& IndexedDBDatabaseMetadata::operator=(
- IndexedDBDatabaseMetadata&& other) = default;
-
-bool IndexedDBDatabaseMetadata::operator==(
- const IndexedDBDatabaseMetadata& other) const {
- return name == other.name && id == other.id && version == other.version &&
- max_object_store_id == other.max_object_store_id &&
- object_stores == other.object_stores;
-}
-
-} // namespace content
diff --git a/chromium/content/common/indexed_db/indexed_db_metadata.h b/chromium/content/common/indexed_db/indexed_db_metadata.h
deleted file mode 100644
index 30b4de66b01..00000000000
--- a/chromium/content/common/indexed_db/indexed_db_metadata.h
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_METADATA_H_
-#define CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_METADATA_H_
-
-#include <stdint.h>
-
-#include <map>
-#include <string>
-
-#include "base/strings/string16.h"
-#include "content/common/indexed_db/indexed_db_key_path.h"
-
-namespace content {
-
-struct CONTENT_EXPORT IndexedDBIndexMetadata {
- static const int64_t kInvalidId = -1;
-
- IndexedDBIndexMetadata();
- IndexedDBIndexMetadata(const base::string16& name,
- int64_t id,
- const IndexedDBKeyPath& key_path,
- bool unique,
- bool multi_entry);
- IndexedDBIndexMetadata(const IndexedDBIndexMetadata& other);
- IndexedDBIndexMetadata(IndexedDBIndexMetadata&& other);
- ~IndexedDBIndexMetadata();
- IndexedDBIndexMetadata& operator=(const IndexedDBIndexMetadata& other);
- IndexedDBIndexMetadata& operator=(IndexedDBIndexMetadata&& other);
- bool operator==(const IndexedDBIndexMetadata& other) const;
-
- base::string16 name;
- int64_t id;
- IndexedDBKeyPath key_path;
- bool unique;
- bool multi_entry;
-};
-
-struct CONTENT_EXPORT IndexedDBObjectStoreMetadata {
- static const int64_t kInvalidId = -1;
- static const int64_t kMinimumIndexId = 30;
-
- IndexedDBObjectStoreMetadata();
- IndexedDBObjectStoreMetadata(const base::string16& name,
- int64_t id,
- const IndexedDBKeyPath& key_path,
- bool auto_increment,
- int64_t max_index_id);
- IndexedDBObjectStoreMetadata(const IndexedDBObjectStoreMetadata& other);
- IndexedDBObjectStoreMetadata(IndexedDBObjectStoreMetadata&& other);
- ~IndexedDBObjectStoreMetadata();
- IndexedDBObjectStoreMetadata& operator=(
- const IndexedDBObjectStoreMetadata& other);
- IndexedDBObjectStoreMetadata& operator=(IndexedDBObjectStoreMetadata&& other);
- bool operator==(const IndexedDBObjectStoreMetadata& other) const;
-
- base::string16 name;
- int64_t id;
- IndexedDBKeyPath key_path;
- bool auto_increment;
- int64_t max_index_id;
-
- std::map<int64_t, IndexedDBIndexMetadata> indexes;
-};
-
-struct CONTENT_EXPORT IndexedDBDatabaseMetadata {
- // TODO(jsbell): These can probably be collapsed into 0.
- enum { NO_VERSION = -1, DEFAULT_VERSION = 0 };
-
- IndexedDBDatabaseMetadata();
- IndexedDBDatabaseMetadata(const base::string16& name,
- int64_t id,
- int64_t version,
- int64_t max_object_store_id);
- IndexedDBDatabaseMetadata(const IndexedDBDatabaseMetadata& other);
- IndexedDBDatabaseMetadata(IndexedDBDatabaseMetadata&& other);
- ~IndexedDBDatabaseMetadata();
- IndexedDBDatabaseMetadata& operator=(const IndexedDBDatabaseMetadata& other);
- IndexedDBDatabaseMetadata& operator=(IndexedDBDatabaseMetadata&& other);
- bool operator==(const IndexedDBDatabaseMetadata& other) const;
-
- base::string16 name;
- int64_t id;
- int64_t version;
- int64_t max_object_store_id;
-
- std::map<int64_t, IndexedDBObjectStoreMetadata> object_stores;
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_METADATA_H_
diff --git a/chromium/content/common/indexed_db/indexed_db_struct_traits.cc b/chromium/content/common/indexed_db/indexed_db_struct_traits.cc
deleted file mode 100644
index 7c714cd7b9f..00000000000
--- a/chromium/content/common/indexed_db/indexed_db_struct_traits.cc
+++ /dev/null
@@ -1,450 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/indexed_db/indexed_db_struct_traits.h"
-
-#include "base/stl_util.h"
-#include "mojo/public/cpp/base/string16_mojom_traits.h"
-
-using content::IndexedDBKey;
-using content::IndexedDBKeyPath;
-using content::IndexedDBKeyRange;
-using indexed_db::mojom::CursorDirection;
-using indexed_db::mojom::DataLoss;
-using indexed_db::mojom::OperationType;
-using indexed_db::mojom::PutMode;
-using indexed_db::mojom::TaskType;
-using indexed_db::mojom::TransactionMode;
-
-namespace mojo {
-
-// static
-indexed_db::mojom::KeyDataPtr
-StructTraits<indexed_db::mojom::KeyDataView, IndexedDBKey>::data(
- const IndexedDBKey& key) {
- auto data = indexed_db::mojom::KeyData::New();
- switch (key.type()) {
- case blink::kWebIDBKeyTypeInvalid:
- data->set_other(indexed_db::mojom::DatalessKeyType::Invalid);
- return data;
- case blink::kWebIDBKeyTypeArray:
- data->set_key_array(key.array());
- return data;
- case blink::kWebIDBKeyTypeBinary:
- data->set_binary(std::vector<uint8_t>(
- key.binary().data(), key.binary().data() + key.binary().size()));
- return data;
- case blink::kWebIDBKeyTypeString:
- data->set_string(key.string());
- return data;
- case blink::kWebIDBKeyTypeDate:
- data->set_date(key.date());
- return data;
- case blink::kWebIDBKeyTypeNumber:
- data->set_number(key.number());
- return data;
- case blink::kWebIDBKeyTypeNull:
- data->set_other(indexed_db::mojom::DatalessKeyType::Null);
- return data;
- case blink::kWebIDBKeyTypeMin:
- break;
- }
- NOTREACHED();
- return data;
-}
-
-// static
-bool StructTraits<indexed_db::mojom::KeyDataView, IndexedDBKey>::Read(
- indexed_db::mojom::KeyDataView data,
- IndexedDBKey* out) {
- indexed_db::mojom::KeyDataDataView data_view;
- data.GetDataDataView(&data_view);
-
- switch (data_view.tag()) {
- case indexed_db::mojom::KeyDataDataView::Tag::KEY_ARRAY: {
- std::vector<IndexedDBKey> array;
- if (!data_view.ReadKeyArray(&array))
- return false;
- *out = IndexedDBKey(array);
- return true;
- }
- case indexed_db::mojom::KeyDataDataView::Tag::BINARY: {
- std::vector<uint8_t> binary;
- if (!data_view.ReadBinary(&binary))
- return false;
- *out = IndexedDBKey(
- std::string(binary.data(), binary.data() + binary.size()));
- return true;
- }
- case indexed_db::mojom::KeyDataDataView::Tag::STRING: {
- base::string16 string;
- if (!data_view.ReadString(&string))
- return false;
- *out = IndexedDBKey(string);
- return true;
- }
- case indexed_db::mojom::KeyDataDataView::Tag::DATE:
- *out = IndexedDBKey(data_view.date(), blink::kWebIDBKeyTypeDate);
- return true;
- case indexed_db::mojom::KeyDataDataView::Tag::NUMBER:
- *out = IndexedDBKey(data_view.number(), blink::kWebIDBKeyTypeNumber);
- return true;
- case indexed_db::mojom::KeyDataDataView::Tag::OTHER:
- switch (data_view.other()) {
- case indexed_db::mojom::DatalessKeyType::Invalid:
- *out = IndexedDBKey(blink::kWebIDBKeyTypeInvalid);
- return true;
- case indexed_db::mojom::DatalessKeyType::Null:
- *out = IndexedDBKey(blink::kWebIDBKeyTypeNull);
- return true;
- }
- }
-
- return false;
-}
-
-// static
-indexed_db::mojom::KeyPathDataPtr
-StructTraits<indexed_db::mojom::KeyPathDataView, IndexedDBKeyPath>::data(
- const IndexedDBKeyPath& key_path) {
- if (key_path.IsNull())
- return nullptr;
-
- auto data = indexed_db::mojom::KeyPathData::New();
- switch (key_path.type()) {
- case blink::kWebIDBKeyPathTypeString:
- data->set_string(key_path.string());
- return data;
- case blink::kWebIDBKeyPathTypeArray:
- data->set_string_array(key_path.array());
- return data;
- default:
- NOTREACHED();
- return data;
- }
-}
-
-// static
-bool StructTraits<indexed_db::mojom::KeyPathDataView, IndexedDBKeyPath>::Read(
- indexed_db::mojom::KeyPathDataView data,
- IndexedDBKeyPath* out) {
- indexed_db::mojom::KeyPathDataDataView data_view;
- data.GetDataDataView(&data_view);
-
- if (data_view.is_null()) {
- *out = IndexedDBKeyPath();
- return true;
- }
-
- switch (data_view.tag()) {
- case indexed_db::mojom::KeyPathDataDataView::Tag::STRING: {
- base::string16 string;
- if (!data_view.ReadString(&string))
- return false;
- *out = IndexedDBKeyPath(string);
- return true;
- }
- case indexed_db::mojom::KeyPathDataDataView::Tag::STRING_ARRAY: {
- std::vector<base::string16> array;
- if (!data_view.ReadStringArray(&array))
- return false;
- *out = IndexedDBKeyPath(array);
- return true;
- }
- }
-
- return false;
-}
-
-// static
-bool StructTraits<indexed_db::mojom::KeyRangeDataView, IndexedDBKeyRange>::Read(
- indexed_db::mojom::KeyRangeDataView data,
- IndexedDBKeyRange* out) {
- IndexedDBKey lower;
- IndexedDBKey upper;
- if (!data.ReadLower(&lower) || !data.ReadUpper(&upper))
- return false;
-
- *out = IndexedDBKeyRange(lower, upper, data.lower_open(), data.upper_open());
- return true;
-}
-
-// static
-bool StructTraits<indexed_db::mojom::IndexKeysDataView,
- content::IndexedDBIndexKeys>::
- Read(indexed_db::mojom::IndexKeysDataView data,
- content::IndexedDBIndexKeys* out) {
- out->first = data.index_id();
- return data.ReadIndexKeys(&out->second);
-}
-
-// static
-bool StructTraits<indexed_db::mojom::IndexMetadataDataView,
- content::IndexedDBIndexMetadata>::
- Read(indexed_db::mojom::IndexMetadataDataView data,
- content::IndexedDBIndexMetadata* out) {
- out->id = data.id();
- if (!data.ReadName(&out->name))
- return false;
- if (!data.ReadKeyPath(&out->key_path))
- return false;
- out->unique = data.unique();
- out->multi_entry = data.multi_entry();
- return true;
-}
-
-// static
-bool StructTraits<indexed_db::mojom::ObjectStoreMetadataDataView,
- content::IndexedDBObjectStoreMetadata>::
- Read(indexed_db::mojom::ObjectStoreMetadataDataView data,
- content::IndexedDBObjectStoreMetadata* out) {
- out->id = data.id();
- if (!data.ReadName(&out->name))
- return false;
- if (!data.ReadKeyPath(&out->key_path))
- return false;
- out->auto_increment = data.auto_increment();
- out->max_index_id = data.max_index_id();
- ArrayDataView<indexed_db::mojom::IndexMetadataDataView> indexes;
- data.GetIndexesDataView(&indexes);
- for (size_t i = 0; i < indexes.size(); ++i) {
- indexed_db::mojom::IndexMetadataDataView index;
- indexes.GetDataView(i, &index);
- DCHECK(!base::ContainsKey(out->indexes, index.id()));
- if (!StructTraits<
- indexed_db::mojom::IndexMetadataDataView,
- content::IndexedDBIndexMetadata>::Read(index,
- &out->indexes[index.id()]))
- return false;
- }
- return true;
-}
-
-// static
-bool StructTraits<indexed_db::mojom::DatabaseMetadataDataView,
- content::IndexedDBDatabaseMetadata>::
- Read(indexed_db::mojom::DatabaseMetadataDataView data,
- content::IndexedDBDatabaseMetadata* out) {
- out->id = data.id();
- if (!data.ReadName(&out->name))
- return false;
- out->version = data.version();
- out->max_object_store_id = data.max_object_store_id();
- ArrayDataView<indexed_db::mojom::ObjectStoreMetadataDataView> object_stores;
- data.GetObjectStoresDataView(&object_stores);
- for (size_t i = 0; i < object_stores.size(); ++i) {
- indexed_db::mojom::ObjectStoreMetadataDataView object_store;
- object_stores.GetDataView(i, &object_store);
- DCHECK(!base::ContainsKey(out->object_stores, object_store.id()));
- if (!StructTraits<indexed_db::mojom::ObjectStoreMetadataDataView,
- content::IndexedDBObjectStoreMetadata>::
- Read(object_store, &out->object_stores[object_store.id()]))
- return false;
- }
- return true;
-}
-
-// static
-CursorDirection
-EnumTraits<CursorDirection, blink::WebIDBCursorDirection>::ToMojom(
- blink::WebIDBCursorDirection input) {
- switch (input) {
- case blink::kWebIDBCursorDirectionNext:
- return CursorDirection::Next;
- case blink::kWebIDBCursorDirectionNextNoDuplicate:
- return CursorDirection::NextNoDuplicate;
- case blink::kWebIDBCursorDirectionPrev:
- return CursorDirection::Prev;
- case blink::kWebIDBCursorDirectionPrevNoDuplicate:
- return CursorDirection::PrevNoDuplicate;
- }
- NOTREACHED();
- return CursorDirection::Next;
-}
-
-// static
-bool EnumTraits<CursorDirection, blink::WebIDBCursorDirection>::FromMojom(
- CursorDirection input,
- blink::WebIDBCursorDirection* output) {
- switch (input) {
- case CursorDirection::Next:
- *output = blink::kWebIDBCursorDirectionNext;
- return true;
- case CursorDirection::NextNoDuplicate:
- *output = blink::kWebIDBCursorDirectionNextNoDuplicate;
- return true;
- case CursorDirection::Prev:
- *output = blink::kWebIDBCursorDirectionPrev;
- return true;
- case CursorDirection::PrevNoDuplicate:
- *output = blink::kWebIDBCursorDirectionPrevNoDuplicate;
- return true;
- }
- return false;
-}
-
-// static
-DataLoss EnumTraits<DataLoss, blink::WebIDBDataLoss>::ToMojom(
- blink::WebIDBDataLoss input) {
- switch (input) {
- case blink::kWebIDBDataLossNone:
- return DataLoss::None;
- case blink::kWebIDBDataLossTotal:
- return DataLoss::Total;
- }
- NOTREACHED();
- return DataLoss::None;
-}
-
-// static
-bool EnumTraits<DataLoss, blink::WebIDBDataLoss>::FromMojom(
- DataLoss input,
- blink::WebIDBDataLoss* output) {
- switch (input) {
- case DataLoss::None:
- *output = blink::kWebIDBDataLossNone;
- return true;
- case DataLoss::Total:
- *output = blink::kWebIDBDataLossTotal;
- return true;
- }
- return false;
-}
-
-// static
-OperationType EnumTraits<OperationType, blink::WebIDBOperationType>::ToMojom(
- blink::WebIDBOperationType input) {
- switch (input) {
- case blink::kWebIDBAdd:
- return OperationType::Add;
- case blink::kWebIDBPut:
- return OperationType::Put;
- case blink::kWebIDBDelete:
- return OperationType::Delete;
- case blink::kWebIDBClear:
- return OperationType::Clear;
- case blink::kWebIDBOperationTypeCount:
- // WebIDBOperationTypeCount is not a valid option.
- break;
- }
- NOTREACHED();
- return OperationType::Add;
-}
-
-// static
-bool EnumTraits<OperationType, blink::WebIDBOperationType>::FromMojom(
- OperationType input,
- blink::WebIDBOperationType* output) {
- switch (input) {
- case OperationType::Add:
- *output = blink::kWebIDBAdd;
- return true;
- case OperationType::Put:
- *output = blink::kWebIDBPut;
- return true;
- case OperationType::Delete:
- *output = blink::kWebIDBDelete;
- return true;
- case OperationType::Clear:
- *output = blink::kWebIDBClear;
- return true;
- }
- return false;
-}
-
-// static
-PutMode EnumTraits<PutMode, blink::WebIDBPutMode>::ToMojom(
- blink::WebIDBPutMode input) {
- switch (input) {
- case blink::kWebIDBPutModeAddOrUpdate:
- return PutMode::AddOrUpdate;
- case blink::kWebIDBPutModeAddOnly:
- return PutMode::AddOnly;
- case blink::kWebIDBPutModeCursorUpdate:
- return PutMode::CursorUpdate;
- }
- NOTREACHED();
- return PutMode::AddOrUpdate;
-}
-
-// static
-bool EnumTraits<PutMode, blink::WebIDBPutMode>::FromMojom(
- PutMode input,
- blink::WebIDBPutMode* output) {
- switch (input) {
- case PutMode::AddOrUpdate:
- *output = blink::kWebIDBPutModeAddOrUpdate;
- return true;
- case PutMode::AddOnly:
- *output = blink::kWebIDBPutModeAddOnly;
- return true;
- case PutMode::CursorUpdate:
- *output = blink::kWebIDBPutModeCursorUpdate;
- return true;
- }
- return false;
-}
-
-// static
-TaskType EnumTraits<TaskType, blink::WebIDBTaskType>::ToMojom(
- blink::WebIDBTaskType input) {
- switch (input) {
- case blink::kWebIDBTaskTypeNormal:
- return TaskType::Normal;
- case blink::kWebIDBTaskTypePreemptive:
- return TaskType::Preemptive;
- }
- NOTREACHED();
- return TaskType::Normal;
-}
-
-// static
-bool EnumTraits<TaskType, blink::WebIDBTaskType>::FromMojom(
- TaskType input,
- blink::WebIDBTaskType* output) {
- switch (input) {
- case TaskType::Normal:
- *output = blink::kWebIDBTaskTypeNormal;
- return true;
- case TaskType::Preemptive:
- *output = blink::kWebIDBTaskTypePreemptive;
- return true;
- }
- return false;
-}
-
-// static
-TransactionMode
-EnumTraits<TransactionMode, blink::WebIDBTransactionMode>::ToMojom(
- blink::WebIDBTransactionMode input) {
- switch (input) {
- case blink::kWebIDBTransactionModeReadOnly:
- return TransactionMode::ReadOnly;
- case blink::kWebIDBTransactionModeReadWrite:
- return TransactionMode::ReadWrite;
- case blink::kWebIDBTransactionModeVersionChange:
- return TransactionMode::VersionChange;
- }
- NOTREACHED();
- return TransactionMode::ReadOnly;
-}
-
-// static
-bool EnumTraits<TransactionMode, blink::WebIDBTransactionMode>::FromMojom(
- TransactionMode input,
- blink::WebIDBTransactionMode* output) {
- switch (input) {
- case TransactionMode::ReadOnly:
- *output = blink::kWebIDBTransactionModeReadOnly;
- return true;
- case TransactionMode::ReadWrite:
- *output = blink::kWebIDBTransactionModeReadWrite;
- return true;
- case TransactionMode::VersionChange:
- *output = blink::kWebIDBTransactionModeVersionChange;
- return true;
- }
- return false;
-}
-} // namespace mojo
diff --git a/chromium/content/common/indexed_db/indexed_db_struct_traits.h b/chromium/content/common/indexed_db/indexed_db_struct_traits.h
deleted file mode 100644
index 913b5629264..00000000000
--- a/chromium/content/common/indexed_db/indexed_db_struct_traits.h
+++ /dev/null
@@ -1,191 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_INDEXED_DB_INDEXED_DB_STRUCT_TRAITS_H_
-#define CONTENT_COMMON_INDEXED_DB_INDEXED_DB_STRUCT_TRAITS_H_
-
-#include "content/common/indexed_db/indexed_db.mojom.h"
-
-namespace mojo {
-
-template <>
-struct StructTraits<indexed_db::mojom::KeyDataView, content::IndexedDBKey> {
- static indexed_db::mojom::KeyDataPtr data(const content::IndexedDBKey& key);
- static bool Read(indexed_db::mojom::KeyDataView data,
- content::IndexedDBKey* out);
-};
-
-template <>
-struct StructTraits<indexed_db::mojom::KeyPathDataView,
- content::IndexedDBKeyPath> {
- static indexed_db::mojom::KeyPathDataPtr data(
- const content::IndexedDBKeyPath& key_path);
- static bool Read(indexed_db::mojom::KeyPathDataView data,
- content::IndexedDBKeyPath* out);
-};
-
-template <>
-struct StructTraits<indexed_db::mojom::KeyRangeDataView,
- content::IndexedDBKeyRange> {
- static const content::IndexedDBKey& lower(
- const content::IndexedDBKeyRange& key_range) {
- return key_range.lower();
- }
- static const content::IndexedDBKey& upper(
- const content::IndexedDBKeyRange& key_range) {
- return key_range.upper();
- }
- static bool lower_open(const content::IndexedDBKeyRange& key_range) {
- return key_range.lower_open();
- }
- static bool upper_open(const content::IndexedDBKeyRange& key_range) {
- return key_range.upper_open();
- }
- static bool Read(indexed_db::mojom::KeyRangeDataView data,
- content::IndexedDBKeyRange* out);
-};
-
-template <>
-struct StructTraits<indexed_db::mojom::IndexKeysDataView,
- content::IndexedDBIndexKeys> {
- static int64_t index_id(const content::IndexedDBIndexKeys& index_keys) {
- return index_keys.first;
- }
- static const std::vector<content::IndexedDBKey>& index_keys(
- const content::IndexedDBIndexKeys& index_keys) {
- return index_keys.second;
- }
- static bool Read(indexed_db::mojom::IndexKeysDataView data,
- content::IndexedDBIndexKeys* out);
-};
-
-template <>
-struct StructTraits<indexed_db::mojom::IndexMetadataDataView,
- content::IndexedDBIndexMetadata> {
- static int64_t id(const content::IndexedDBIndexMetadata& metadata) {
- return metadata.id;
- }
- static base::string16 name(const content::IndexedDBIndexMetadata& metadata) {
- return metadata.name;
- }
- static const content::IndexedDBKeyPath& key_path(
- const content::IndexedDBIndexMetadata& metadata) {
- return metadata.key_path;
- }
- static bool unique(const content::IndexedDBIndexMetadata& metadata) {
- return metadata.unique;
- }
- static bool multi_entry(const content::IndexedDBIndexMetadata& metadata) {
- return metadata.multi_entry;
- }
- static bool Read(indexed_db::mojom::IndexMetadataDataView data,
- content::IndexedDBIndexMetadata* out);
-};
-
-template <>
-struct StructTraits<indexed_db::mojom::ObjectStoreMetadataDataView,
- content::IndexedDBObjectStoreMetadata> {
- static int64_t id(const content::IndexedDBObjectStoreMetadata& metadata) {
- return metadata.id;
- }
- static base::string16 name(
- const content::IndexedDBObjectStoreMetadata& metadata) {
- return metadata.name;
- }
- static const content::IndexedDBKeyPath& key_path(
- const content::IndexedDBObjectStoreMetadata& metadata) {
- return metadata.key_path;
- }
- static bool auto_increment(
- const content::IndexedDBObjectStoreMetadata& metadata) {
- return metadata.auto_increment;
- }
- static int64_t max_index_id(
- const content::IndexedDBObjectStoreMetadata& metadata) {
- return metadata.max_index_id;
- }
- static MapValuesArrayView<int64_t, content::IndexedDBIndexMetadata> indexes(
- const content::IndexedDBObjectStoreMetadata& metadata) {
- return MapValuesToArray(metadata.indexes);
- }
- static bool Read(indexed_db::mojom::ObjectStoreMetadataDataView data,
- content::IndexedDBObjectStoreMetadata* out);
-};
-
-template <>
-struct StructTraits<indexed_db::mojom::DatabaseMetadataDataView,
- content::IndexedDBDatabaseMetadata> {
- static int64_t id(const content::IndexedDBDatabaseMetadata& metadata) {
- return metadata.id;
- }
- static base::string16 name(
- const content::IndexedDBDatabaseMetadata& metadata) {
- return metadata.name;
- }
- static int64_t version(const content::IndexedDBDatabaseMetadata& metadata) {
- return metadata.version;
- }
- static int64_t max_object_store_id(
- const content::IndexedDBDatabaseMetadata& metadata) {
- return metadata.max_object_store_id;
- }
- static MapValuesArrayView<int64_t, content::IndexedDBObjectStoreMetadata>
- object_stores(const content::IndexedDBDatabaseMetadata& metadata) {
- return MapValuesToArray(metadata.object_stores);
- }
- static bool Read(indexed_db::mojom::DatabaseMetadataDataView data,
- content::IndexedDBDatabaseMetadata* out);
-};
-
-template <>
-struct EnumTraits<indexed_db::mojom::CursorDirection,
- blink::WebIDBCursorDirection> {
- static indexed_db::mojom::CursorDirection ToMojom(
- blink::WebIDBCursorDirection input);
- static bool FromMojom(indexed_db::mojom::CursorDirection input,
- blink::WebIDBCursorDirection* output);
-};
-
-template <>
-struct EnumTraits<indexed_db::mojom::DataLoss, blink::WebIDBDataLoss> {
- static indexed_db::mojom::DataLoss ToMojom(blink::WebIDBDataLoss input);
- static bool FromMojom(indexed_db::mojom::DataLoss input,
- blink::WebIDBDataLoss* output);
-};
-
-template <>
-struct EnumTraits<indexed_db::mojom::OperationType,
- blink::WebIDBOperationType> {
- static indexed_db::mojom::OperationType ToMojom(
- blink::WebIDBOperationType input);
- static bool FromMojom(indexed_db::mojom::OperationType input,
- blink::WebIDBOperationType* output);
-};
-
-template <>
-struct EnumTraits<indexed_db::mojom::PutMode, blink::WebIDBPutMode> {
- static indexed_db::mojom::PutMode ToMojom(blink::WebIDBPutMode input);
- static bool FromMojom(indexed_db::mojom::PutMode input,
- blink::WebIDBPutMode* output);
-};
-
-template <>
-struct EnumTraits<indexed_db::mojom::TaskType, blink::WebIDBTaskType> {
- static indexed_db::mojom::TaskType ToMojom(blink::WebIDBTaskType input);
- static bool FromMojom(indexed_db::mojom::TaskType input,
- blink::WebIDBTaskType* output);
-};
-
-template <>
-struct EnumTraits<indexed_db::mojom::TransactionMode,
- blink::WebIDBTransactionMode> {
- static indexed_db::mojom::TransactionMode ToMojom(
- blink::WebIDBTransactionMode input);
- static bool FromMojom(indexed_db::mojom::TransactionMode input,
- blink::WebIDBTransactionMode* output);
-};
-
-} // namespace mojo
-
-#endif // CONTENT_COMMON_INDEXED_DB_INDEXED_DB_STRUCT_TRAITS_H_
diff --git a/chromium/content/common/indexed_db/typemaps.gni b/chromium/content/common/indexed_db/typemaps.gni
deleted file mode 100644
index 04b6903653f..00000000000
--- a/chromium/content/common/indexed_db/typemaps.gni
+++ /dev/null
@@ -1,5 +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.
-
-typemaps = [ "//content/common/indexed_db/indexed_db.typemap" ]
diff --git a/chromium/content/common/input/ime_text_span_conversions.cc b/chromium/content/common/input/ime_text_span_conversions.cc
index cd83e90b704..f02fce09afd 100644
--- a/chromium/content/common/input/ime_text_span_conversions.cc
+++ b/chromium/content/common/input/ime_text_span_conversions.cc
@@ -38,29 +38,29 @@ ui::ImeTextSpan::Type ConvertWebImeTextSpanTypeToUiType(
return ui::ImeTextSpan::Type::kComposition;
}
-ui::mojom::ImeTextSpanThickness ConvertUiThicknessToUiImeTextSpanThickness(
+ws::mojom::ImeTextSpanThickness ConvertUiThicknessToUiImeTextSpanThickness(
ui::ImeTextSpan::Thickness thickness) {
switch (thickness) {
case ui::ImeTextSpan::Thickness::kNone:
- return ui::mojom::ImeTextSpanThickness::kNone;
+ return ws::mojom::ImeTextSpanThickness::kNone;
case ui::ImeTextSpan::Thickness::kThin:
- return ui::mojom::ImeTextSpanThickness::kThin;
+ return ws::mojom::ImeTextSpanThickness::kThin;
case ui::ImeTextSpan::Thickness::kThick:
- return ui::mojom::ImeTextSpanThickness::kThick;
+ return ws::mojom::ImeTextSpanThickness::kThick;
}
NOTREACHED();
- return ui::mojom::ImeTextSpanThickness::kThin;
+ return ws::mojom::ImeTextSpanThickness::kThin;
}
ui::ImeTextSpan::Thickness ConvertUiImeTextSpanThicknessToUiThickness(
- ui::mojom::ImeTextSpanThickness thickness) {
+ ws::mojom::ImeTextSpanThickness thickness) {
switch (thickness) {
- case ui::mojom::ImeTextSpanThickness::kNone:
+ case ws::mojom::ImeTextSpanThickness::kNone:
return ui::ImeTextSpan::Thickness::kNone;
- case ui::mojom::ImeTextSpanThickness::kThin:
+ case ws::mojom::ImeTextSpanThickness::kThin:
return ui::ImeTextSpan::Thickness::kThin;
- case ui::mojom::ImeTextSpanThickness::kThick:
+ case ws::mojom::ImeTextSpanThickness::kThick:
return ui::ImeTextSpan::Thickness::kThick;
}
diff --git a/chromium/content/common/input/ime_text_span_conversions.h b/chromium/content/common/input/ime_text_span_conversions.h
index 18353d300d7..846a550fa13 100644
--- a/chromium/content/common/input/ime_text_span_conversions.h
+++ b/chromium/content/common/input/ime_text_span_conversions.h
@@ -14,10 +14,10 @@ blink::WebImeTextSpan::Type ConvertUiImeTextSpanTypeToWebType(
ui::ImeTextSpan::Type type);
ui::ImeTextSpan::Type ConvertWebImeTextSpanTypeToUiType(
blink::WebImeTextSpan::Type type);
-ui::mojom::ImeTextSpanThickness ConvertUiThicknessToUiImeTextSpanThickness(
+ws::mojom::ImeTextSpanThickness ConvertUiThicknessToUiImeTextSpanThickness(
ui::ImeTextSpan::Thickness thickness);
ui::ImeTextSpan::Thickness ConvertUiImeTextSpanThicknessToUiThickness(
- ui::mojom::ImeTextSpanThickness thickness);
+ ws::mojom::ImeTextSpanThickness thickness);
blink::WebImeTextSpan ConvertUiImeTextSpanToBlinkImeTextSpan(
const ui::ImeTextSpan&);
ui::ImeTextSpan ConvertBlinkImeTextSpanToUiImeTextSpan(
diff --git a/chromium/content/common/input/input_handler.mojom b/chromium/content/common/input/input_handler.mojom
index 3f33f6c004f..1dd238373a5 100644
--- a/chromium/content/common/input/input_handler.mojom
+++ b/chromium/content/common/input/input_handler.mojom
@@ -8,7 +8,7 @@ import "content/common/input/synchronous_compositor.mojom";
import "content/common/native_types.mojom";
import "mojo/public/mojom/base/string16.mojom";
import "mojo/public/mojom/base/time.mojom";
-import "services/ui/public/interfaces/ime/ime.mojom";
+import "services/ws/public/mojom/ime/ime.mojom";
import "third_party/blink/public/web/selection_menu_behavior.mojom";
import "ui/events/mojo/event.mojom";
import "ui/events/mojo/event_constants.mojom";
@@ -174,9 +174,6 @@ interface WidgetInputHandlerHost {
// restrictions on the root scroll offset.
DidOverscroll(DidOverscrollParams params);
- // Sent by the compositor when a fling animation is stopped.
- DidStopFlinging();
-
// Sent by the compositor when a GSB has started scrolling the viewport.
DidStartScrollingViewport();
@@ -225,14 +222,14 @@ interface WidgetInputHandler {
// This message sends a string being composed with an input method.
ImeSetComposition(mojo_base.mojom.String16 text,
- array<ui.mojom.ImeTextSpan> ime_text_spans,
+ array<ws.mojom.ImeTextSpan> ime_text_spans,
gfx.mojom.Range range, int32 start, int32 end);
// This message deletes the current composition, inserts specified text, and
// moves the cursor.
ImeCommitText(mojo_base.mojom.String16 text,
- array<ui.mojom.ImeTextSpan> ime_text_spans,
- gfx.mojom.Range range, int32 relative_cursor_position);
+ array<ws.mojom.ImeTextSpan> ime_text_spans,
+ gfx.mojom.Range range, int32 relative_cursor_position) => ();
// This message inserts the ongoing composition.
ImeFinishComposingText(bool keep_selection);
@@ -280,7 +277,7 @@ interface FrameInputHandler {
// Sets the text composition to be between the given start and end offsets in
// the currently focused editable field.
SetCompositionFromExistingText(
- int32 start, int32 end, array<ui.mojom.ImeTextSpan> ime_text_spans);
+ int32 start, int32 end, array<ws.mojom.ImeTextSpan> ime_text_spans);
// Deletes the current selection plus the specified number of characters
// before and after the selection or caret.
diff --git a/chromium/content/common/input/synthetic_gesture_params.h b/chromium/content/common/input/synthetic_gesture_params.h
index 9f5dfc47b46..a648be60195 100644
--- a/chromium/content/common/input/synthetic_gesture_params.h
+++ b/chromium/content/common/input/synthetic_gesture_params.h
@@ -29,6 +29,7 @@ struct CONTENT_EXPORT SyntheticGestureParams {
DEFAULT_INPUT,
TOUCH_INPUT,
MOUSE_INPUT,
+ TOUCHPAD_INPUT = MOUSE_INPUT,
PEN_INPUT,
GESTURE_SOURCE_TYPE_MAX = PEN_INPUT
};
diff --git a/chromium/content/common/input/synthetic_pointer_action_params.h b/chromium/content/common/input/synthetic_pointer_action_params.h
index 7b30e830d41..534a01365c7 100644
--- a/chromium/content/common/input/synthetic_pointer_action_params.h
+++ b/chromium/content/common/input/synthetic_pointer_action_params.h
@@ -29,6 +29,7 @@ struct CONTENT_EXPORT SyntheticPointerActionParams {
PRESS,
MOVE,
RELEASE,
+ LEAVE,
IDLE,
POINTER_ACTION_TYPE_MAX = IDLE
};
diff --git a/chromium/content/common/input/synthetic_smooth_scroll_gesture_params.cc b/chromium/content/common/input/synthetic_smooth_scroll_gesture_params.cc
index 8e1c9748270..ee9ec1e1933 100644
--- a/chromium/content/common/input/synthetic_smooth_scroll_gesture_params.cc
+++ b/chromium/content/common/input/synthetic_smooth_scroll_gesture_params.cc
@@ -14,15 +14,15 @@ const float kDefaultSpeedInPixelsS = 800;
} // namespace
SyntheticSmoothScrollGestureParams::SyntheticSmoothScrollGestureParams()
- : prevent_fling(true), speed_in_pixels_s(kDefaultSpeedInPixelsS) {}
+ : prevent_fling(true),
+ speed_in_pixels_s(kDefaultSpeedInPixelsS),
+ fling_velocity_x(0),
+ fling_velocity_y(0),
+ precise_scrolling_deltas(false),
+ scroll_by_page(false) {}
SyntheticSmoothScrollGestureParams::SyntheticSmoothScrollGestureParams(
- const SyntheticSmoothScrollGestureParams& other)
- : SyntheticGestureParams(other),
- anchor(other.anchor),
- distances(other.distances),
- prevent_fling(other.prevent_fling),
- speed_in_pixels_s(other.speed_in_pixels_s) {}
+ const SyntheticSmoothScrollGestureParams& other) = default;
SyntheticSmoothScrollGestureParams::~SyntheticSmoothScrollGestureParams() {}
diff --git a/chromium/content/common/input/synthetic_smooth_scroll_gesture_params.h b/chromium/content/common/input/synthetic_smooth_scroll_gesture_params.h
index d9e8591fcce..d590892d409 100644
--- a/chromium/content/common/input/synthetic_smooth_scroll_gesture_params.h
+++ b/chromium/content/common/input/synthetic_smooth_scroll_gesture_params.h
@@ -28,6 +28,10 @@ struct CONTENT_EXPORT SyntheticSmoothScrollGestureParams
std::vector<gfx::Vector2dF> distances; // Positive X/Y to scroll left/up.
bool prevent_fling; // Defaults to true.
float speed_in_pixels_s;
+ float fling_velocity_x;
+ float fling_velocity_y;
+ bool precise_scrolling_deltas;
+ bool scroll_by_page;
static const SyntheticSmoothScrollGestureParams* Cast(
const SyntheticGestureParams* gesture_params);
diff --git a/chromium/content/common/input/synthetic_web_input_event_builders.cc b/chromium/content/common/input/synthetic_web_input_event_builders.cc
index 3bf1ed2b37a..e4b9aad042d 100644
--- a/chromium/content/common/input/synthetic_web_input_event_builders.cc
+++ b/chromium/content/common/input/synthetic_web_input_event_builders.cc
@@ -50,23 +50,27 @@ WebMouseWheelEvent SyntheticWebMouseWheelEventBuilder::Build(
return result;
}
-WebMouseWheelEvent SyntheticWebMouseWheelEventBuilder::Build(float x,
- float y,
- float dx,
- float dy,
- int modifiers,
- bool precise) {
- return Build(x, y, 0, 0, dx, dy, modifiers, precise);
+WebMouseWheelEvent SyntheticWebMouseWheelEventBuilder::Build(
+ float x,
+ float y,
+ float dx,
+ float dy,
+ int modifiers,
+ bool precise,
+ bool scroll_by_page) {
+ return Build(x, y, 0, 0, dx, dy, modifiers, precise, scroll_by_page);
}
-WebMouseWheelEvent SyntheticWebMouseWheelEventBuilder::Build(float x,
- float y,
- float global_x,
- float global_y,
- float dx,
- float dy,
- int modifiers,
- bool precise) {
+WebMouseWheelEvent SyntheticWebMouseWheelEventBuilder::Build(
+ float x,
+ float y,
+ float global_x,
+ float global_y,
+ float dx,
+ float dy,
+ int modifiers,
+ bool precise,
+ bool scroll_by_page) {
WebMouseWheelEvent result(WebInputEvent::kMouseWheel, modifiers,
ui::EventTimeForNow());
result.SetPositionInScreen(global_x, global_y);
@@ -78,6 +82,7 @@ WebMouseWheelEvent SyntheticWebMouseWheelEventBuilder::Build(float x,
if (dy)
result.wheel_ticks_y = dy > 0.0f ? 1.0f : -1.0f;
result.has_precise_scrolling_deltas = precise;
+ result.scroll_by_page = scroll_by_page;
return result;
}
@@ -162,6 +167,7 @@ WebGestureEvent SyntheticWebGestureEventBuilder::BuildFling(
SyntheticWebTouchEvent::SyntheticWebTouchEvent() : WebTouchEvent() {
unique_touch_event_id = ui::GetNextTouchEventId();
SetTimestamp(ui::EventTimeForNow());
+ pointer_id_ = 0;
}
void SyntheticWebTouchEvent::ResetPoints() {
@@ -198,7 +204,7 @@ int SyntheticWebTouchEvent::PressPoint(float x, float y) {
if (index == -1)
return -1;
WebTouchPoint& point = touches[index];
- point.id = index;
+ point.id = pointer_id_++;
point.SetPositionInWidget(x, y);
point.SetPositionInScreen(x, y);
point.state = WebTouchPoint::kStatePressed;
@@ -210,7 +216,7 @@ int SyntheticWebTouchEvent::PressPoint(float x, float y) {
point.pointer_type = blink::WebPointerProperties::PointerType::kTouch;
++touches_length;
WebTouchEventTraits::ResetType(WebInputEvent::kTouchStart, TimeStamp(), this);
- return point.id;
+ return index;
}
void SyntheticWebTouchEvent::MovePoint(int index, float x, float y) {
diff --git a/chromium/content/common/input/synthetic_web_input_event_builders.h b/chromium/content/common/input/synthetic_web_input_event_builders.h
index 3247d0d243d..52c0b723e65 100644
--- a/chromium/content/common/input/synthetic_web_input_event_builders.h
+++ b/chromium/content/common/input/synthetic_web_input_event_builders.h
@@ -38,7 +38,8 @@ class CONTENT_EXPORT SyntheticWebMouseWheelEventBuilder {
float dx,
float dy,
int modifiers,
- bool precise);
+ bool precise,
+ bool scroll_by_page = false);
static blink::WebMouseWheelEvent Build(float x,
float y,
float global_x,
@@ -46,7 +47,8 @@ class CONTENT_EXPORT SyntheticWebMouseWheelEventBuilder {
float dx,
float dy,
int modifiers,
- bool precise);
+ bool precise,
+ bool scroll_by_page = false);
};
class CONTENT_EXPORT SyntheticWebKeyboardEventBuilder {
@@ -97,6 +99,11 @@ class CONTENT_EXPORT SyntheticWebTouchEvent : public blink::WebTouchEvent {
void SetTimestamp(base::TimeTicks timestamp);
int FirstFreeIndex();
+
+ private:
+ // A pointer id of each touch pointer. Every time when a pointer is pressed
+ // the screen, it will be assigned to a new pointer id.
+ unsigned pointer_id_;
};
} // namespace content
diff --git a/chromium/content/common/input/synthetic_web_input_event_builders_unittest.cc b/chromium/content/common/input/synthetic_web_input_event_builders_unittest.cc
new file mode 100644
index 00000000000..e93d32c89db
--- /dev/null
+++ b/chromium/content/common/input/synthetic_web_input_event_builders_unittest.cc
@@ -0,0 +1,65 @@
+// 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/common/input/touch_event_stream_validator.h"
+
+#include <stddef.h>
+
+#include "content/common/input/synthetic_web_input_event_builders.h"
+#include "content/common/input/web_touch_event_traits.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using blink::WebFloatPoint;
+using blink::WebInputEvent;
+using blink::WebTouchEvent;
+using blink::WebTouchPoint;
+
+namespace content {
+
+TEST(SyntheticWebInputEventBuilders, BuildWebTouchEvent) {
+ SyntheticWebTouchEvent event;
+
+ event.PressPoint(1, 2);
+ EXPECT_EQ(1U, event.touches_length);
+ EXPECT_EQ(0, event.touches[0].id);
+ EXPECT_EQ(WebTouchPoint::kStatePressed, event.touches[0].state);
+ EXPECT_EQ(WebFloatPoint(1, 2), event.touches[0].PositionInWidget());
+ event.ResetPoints();
+
+ event.PressPoint(3, 4);
+ EXPECT_EQ(2U, event.touches_length);
+ EXPECT_EQ(1, event.touches[1].id);
+ EXPECT_EQ(WebTouchPoint::kStatePressed, event.touches[1].state);
+ EXPECT_EQ(WebFloatPoint(3, 4), event.touches[1].PositionInWidget());
+ event.ResetPoints();
+
+ event.MovePoint(1, 5, 6);
+ EXPECT_EQ(2U, event.touches_length);
+ EXPECT_EQ(1, event.touches[1].id);
+ EXPECT_EQ(WebTouchPoint::kStateMoved, event.touches[1].state);
+ EXPECT_EQ(WebFloatPoint(5, 6), event.touches[1].PositionInWidget());
+ event.ResetPoints();
+
+ event.ReleasePoint(0);
+ EXPECT_EQ(2U, event.touches_length);
+ EXPECT_EQ(0, event.touches[0].id);
+ EXPECT_EQ(WebTouchPoint::kStateReleased, event.touches[0].state);
+ event.ResetPoints();
+
+ event.MovePoint(1, 7, 8);
+ EXPECT_EQ(1U, event.touches_length);
+ EXPECT_EQ(1, event.touches[1].id);
+ EXPECT_EQ(WebTouchPoint::kStateMoved, event.touches[1].state);
+ EXPECT_EQ(WebFloatPoint(7, 8), event.touches[1].PositionInWidget());
+ EXPECT_EQ(WebTouchPoint::kStateUndefined, event.touches[0].state);
+ event.ResetPoints();
+
+ event.PressPoint(9, 10);
+ EXPECT_EQ(2U, event.touches_length);
+ EXPECT_EQ(2, event.touches[0].id);
+ EXPECT_EQ(WebTouchPoint::kStatePressed, event.touches[0].state);
+ EXPECT_EQ(WebFloatPoint(9, 10), event.touches[0].PositionInWidget());
+}
+
+} // namespace content
diff --git a/chromium/content/common/input_messages.h b/chromium/content/common/input_messages.h
index 81f0759d605..7d5b879a20b 100644
--- a/chromium/content/common/input_messages.h
+++ b/chromium/content/common/input_messages.h
@@ -120,6 +120,10 @@ IPC_STRUCT_TRAITS_BEGIN(content::SyntheticSmoothScrollGestureParams)
IPC_STRUCT_TRAITS_MEMBER(distances)
IPC_STRUCT_TRAITS_MEMBER(prevent_fling)
IPC_STRUCT_TRAITS_MEMBER(speed_in_pixels_s)
+ IPC_STRUCT_TRAITS_MEMBER(fling_velocity_x)
+ IPC_STRUCT_TRAITS_MEMBER(fling_velocity_y)
+ IPC_STRUCT_TRAITS_MEMBER(precise_scrolling_deltas)
+ IPC_STRUCT_TRAITS_MEMBER(scroll_by_page)
IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(content::SyntheticPinchGestureParams)
diff --git a/chromium/content/common/mac/font_loader.mm b/chromium/content/common/mac/font_loader.mm
index c802bdb5514..2bfdbfbe17b 100644
--- a/chromium/content/common/mac/font_loader.mm
+++ b/chromium/content/common/mac/font_loader.mm
@@ -18,7 +18,7 @@
#include "base/mac/scoped_cftyperef.h"
#import "base/mac/scoped_nsobject.h"
#include "base/strings/sys_string_conversions.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_restrictions.h"
namespace content {
diff --git a/chromium/content/common/media/OWNERS b/chromium/content/common/media/OWNERS
index be853ae7284..85d741118e3 100644
--- a/chromium/content/common/media/OWNERS
+++ b/chromium/content/common/media/OWNERS
@@ -7,6 +7,9 @@ per-file *_messages*.h=file://ipc/SECURITY_OWNERS
per-file *.mojom=set noparent
per-file *.mojom=file://ipc/SECURITY_OWNERS
+per-file *_mojom_traits*.*=set noparent
+per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
+
per-file *_param_traits*.*=set noparent
per-file *_param_traits*.*=file://ipc/SECURITY_OWNERS
@@ -16,7 +19,4 @@ per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS
per-file *.typemap=set noparent
per-file *.typemap=file://ipc/SECURITY_OWNERS
-per-file *_typemap_traits*.*=set noparent
-per-file *_typemap_traits*.*=file://ipc/SECURITY_OWNERS
-
# COMPONENT: Internals>Media
diff --git a/chromium/content/common/media/media_devices.typemap b/chromium/content/common/media/media_devices.typemap
index 2451e202204..eaf7eb51812 100644
--- a/chromium/content/common/media/media_devices.typemap
+++ b/chromium/content/common/media/media_devices.typemap
@@ -4,9 +4,9 @@
mojom = "//third_party/blink/public/platform/modules/mediastream/media_devices.mojom"
public_headers = [ "//content/common/media/media_devices.h" ]
-traits_headers = [ "//content/common/media/media_devices_typemap_traits.h" ]
+traits_headers = [ "//content/common/media/media_devices_mojom_traits.h" ]
sources = [
- "//content/common/media/media_devices_typemap_traits.cc",
+ "//content/common/media/media_devices_mojom_traits.cc",
]
type_mappings = [
"blink.mojom.MediaDeviceType=content::MediaDeviceType",
diff --git a/chromium/content/common/media/media_devices_typemap_traits.cc b/chromium/content/common/media/media_devices_mojom_traits.cc
index 3a46450496f..ff6b2053171 100644
--- a/chromium/content/common/media/media_devices_typemap_traits.cc
+++ b/chromium/content/common/media/media_devices_mojom_traits.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/media/media_devices_typemap_traits.h"
+#include "content/common/media/media_devices_mojom_traits.h"
#include "base/logging.h"
diff --git a/chromium/content/common/media/media_devices_typemap_traits.h b/chromium/content/common/media/media_devices_mojom_traits.h
index b15e8001f6f..8274b11e2d8 100644
--- a/chromium/content/common/media/media_devices_typemap_traits.h
+++ b/chromium/content/common/media/media_devices_mojom_traits.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_COMMON_MEDIA_MEDIA_DEVICES_TYPEMAP_TRAITS_H_
-#define CONTENT_COMMON_MEDIA_MEDIA_DEVICES_TYPEMAP_TRAITS_H_
+#ifndef CONTENT_COMMON_MEDIA_MEDIA_DEVICES_MOJOM_TRAITS_H_
+#define CONTENT_COMMON_MEDIA_MEDIA_DEVICES_MOJOM_TRAITS_H_
#include "content/common/media/media_devices.h"
#include "third_party/blink/public/platform/modules/mediastream/media_devices.mojom.h"
@@ -47,4 +47,4 @@ struct StructTraits<blink::mojom::MediaDeviceInfoDataView,
} // namespace mojo
-#endif // CONTENT_COMMON_MEDIA_MEDIA_DEVICES_TYPEMAP_TRAITS_H_ \ No newline at end of file
+#endif // CONTENT_COMMON_MEDIA_MEDIA_DEVICES_MOJOM_TRAITS_H_
diff --git a/chromium/content/common/media/media_player_delegate_messages.h b/chromium/content/common/media/media_player_delegate_messages.h
index 0b82193e462..e352c277348 100644
--- a/chromium/content/common/media/media_player_delegate_messages.h
+++ b/chromium/content/common/media/media_player_delegate_messages.h
@@ -17,6 +17,7 @@
#include "content/common/content_export.h"
#include "ipc/ipc_message_macros.h"
#include "media/base/media_content_type.h"
+#include "third_party/blink/public/common/picture_in_picture/picture_in_picture_control_info.h"
#include "third_party/blink/public/platform/web_fullscreen_video_status.h"
#include "ui/gfx/ipc/geometry/gfx_param_traits.h"
@@ -24,6 +25,18 @@
#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
#define IPC_MESSAGE_START MediaPlayerDelegateMsgStart
+IPC_STRUCT_TRAITS_BEGIN(blink::PictureInPictureControlInfo::Icon)
+ IPC_STRUCT_TRAITS_MEMBER(src)
+ IPC_STRUCT_TRAITS_MEMBER(sizes)
+ IPC_STRUCT_TRAITS_MEMBER(type)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(blink::PictureInPictureControlInfo)
+ IPC_STRUCT_TRAITS_MEMBER(id)
+ IPC_STRUCT_TRAITS_MEMBER(label)
+ IPC_STRUCT_TRAITS_MEMBER(icons)
+IPC_STRUCT_TRAITS_END()
+
IPC_ENUM_TRAITS_MAX_VALUE(media::MediaContentType, media::MediaContentType::Max)
IPC_ENUM_TRAITS_MAX_VALUE(blink::WebFullscreenVideoStatus,
blink::WebFullscreenVideoStatus::kMax)
@@ -126,4 +139,9 @@ IPC_MESSAGE_ROUTED3(MediaPlayerDelegateHostMsg_OnPictureInPictureSurfaceChanged,
viz::SurfaceId /* surface_id */,
gfx::Size /* natural_size */)
+IPC_MESSAGE_ROUTED2(
+ MediaPlayerDelegateHostMsg_OnSetPictureInPictureCustomControls,
+ int /* delegate id */,
+ std::vector<blink::PictureInPictureControlInfo> /* custom controls */)
+
#endif // CONTENT_COMMON_MEDIA_MEDIA_PLAYER_DELEGATE_MESSAGES_H_
diff --git a/chromium/content/common/media/media_stream.mojom b/chromium/content/common/media/media_stream.mojom
index 483ac0c1253..99faa657e2d 100644
--- a/chromium/content/common/media/media_stream.mojom
+++ b/chromium/content/common/media/media_stream.mojom
@@ -16,10 +16,11 @@ enum MediaStreamType {
MEDIA_NO_SERVICE,
MEDIA_DEVICE_AUDIO_CAPTURE,
MEDIA_DEVICE_VIDEO_CAPTURE,
- MEDIA_TAB_AUDIO_CAPTURE,
- MEDIA_TAB_VIDEO_CAPTURE,
- MEDIA_DESKTOP_VIDEO_CAPTURE,
- MEDIA_DESKTOP_AUDIO_CAPTURE,
+ MEDIA_GUM_TAB_AUDIO_CAPTURE,
+ MEDIA_GUM_TAB_VIDEO_CAPTURE,
+ MEDIA_GUM_DESKTOP_VIDEO_CAPTURE,
+ MEDIA_GUM_DESKTOP_AUDIO_CAPTURE,
+ MEDIA_DISPLAY_VIDEO_CAPTURE,
NUM_MEDIA_TYPES
};
@@ -45,7 +46,7 @@ enum MediaStreamRequestResult {
// See content/common/media/media_stream_controls.h.
struct TrackControls {
bool requested;
- string stream_source;
+ MediaStreamType stream_type;
string device_id;
};
diff --git a/chromium/content/common/media/media_stream.typemap b/chromium/content/common/media/media_stream.typemap
index dca615202b3..eacf4d619a8 100644
--- a/chromium/content/common/media/media_stream.typemap
+++ b/chromium/content/common/media/media_stream.typemap
@@ -11,11 +11,11 @@ public_headers = [
traits_headers = [
"//content/common/media/media_stream_param_traits.h",
- "//content/common/media/media_stream_typemap_traits.h",
+ "//content/common/media/media_stream_mojom_traits.h",
]
sources = [
- "//content/common/media/media_stream_typemap_traits.cc",
+ "//content/common/media/media_stream_mojom_traits.cc",
]
deps = [
diff --git a/chromium/content/common/media/media_stream_controls.cc b/chromium/content/common/media/media_stream_controls.cc
index bcd9cdfb147..74dc5081866 100644
--- a/chromium/content/common/media/media_stream_controls.cc
+++ b/chromium/content/common/media/media_stream_controls.cc
@@ -6,14 +6,10 @@
namespace content {
-const char kMediaStreamSourceTab[] = "tab";
-const char kMediaStreamSourceScreen[] = "screen";
-const char kMediaStreamSourceDesktop[] = "desktop";
-const char kMediaStreamSourceSystem[] = "system";
-
TrackControls::TrackControls() {}
-TrackControls::TrackControls(bool request) : requested(request) {}
+TrackControls::TrackControls(bool request, MediaStreamType type)
+ : requested(request), stream_type(type) {}
TrackControls::TrackControls(const TrackControls& other) = default;
@@ -22,7 +18,10 @@ TrackControls::~TrackControls() {}
StreamControls::StreamControls() {}
StreamControls::StreamControls(bool request_audio, bool request_video)
- : audio(request_audio), video(request_video) {}
+ : audio(request_audio,
+ request_audio ? MEDIA_DEVICE_AUDIO_CAPTURE : MEDIA_NO_SERVICE),
+ video(request_video,
+ request_video ? MEDIA_DEVICE_VIDEO_CAPTURE : MEDIA_NO_SERVICE) {}
StreamControls::~StreamControls() {}
diff --git a/chromium/content/common/media/media_stream_controls.h b/chromium/content/common/media/media_stream_controls.h
index 39d351345db..3c077959c38 100644
--- a/chromium/content/common/media/media_stream_controls.h
+++ b/chromium/content/common/media/media_stream_controls.h
@@ -8,28 +8,27 @@
#include <string>
#include "content/common/content_export.h"
+#include "content/public/common/media_stream_request.h"
namespace content {
// Names for media stream source capture types.
-// These are values of the "TrackControls.stream_source" field, and are
-// set via the "chromeMediaSource" constraint.
+// These are values set via the "chromeMediaSource" constraint.
CONTENT_EXPORT extern const char kMediaStreamSourceTab[];
-CONTENT_EXPORT extern const char kMediaStreamSourceScreen[];
+CONTENT_EXPORT extern const char kMediaStreamSourceScreen[]; /* video only */
CONTENT_EXPORT extern const char kMediaStreamSourceDesktop[];
-CONTENT_EXPORT extern const char kMediaStreamSourceSystem[];
+CONTENT_EXPORT extern const char kMediaStreamSourceSystem[]; /* audio only */
struct CONTENT_EXPORT TrackControls {
TrackControls();
- explicit TrackControls(bool request);
+ explicit TrackControls(bool request, MediaStreamType type);
explicit TrackControls(const TrackControls& other);
~TrackControls();
bool requested = false;
- // Source. This is "tab", "screen", "desktop", "system", or blank.
- // Consider replacing with MediaStreamType enum variables.
- std::string stream_source; // audio.kMediaStreamSource
+ // Represents the requested stream type.
+ MediaStreamType stream_type = MEDIA_NO_SERVICE;
// An empty string represents the default device.
// A nonempty string represents a specific device.
diff --git a/chromium/content/common/media/media_stream_typemap_traits.cc b/chromium/content/common/media/media_stream_mojom_traits.cc
index 843a7b0aa47..d88a188c3b4 100644
--- a/chromium/content/common/media/media_stream_typemap_traits.cc
+++ b/chromium/content/common/media/media_stream_mojom_traits.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/media/media_stream_typemap_traits.h"
+#include "content/common/media/media_stream_mojom_traits.h"
#include "base/logging.h"
@@ -19,14 +19,16 @@ EnumTraits<content::mojom::MediaStreamType, content::MediaStreamType>::ToMojom(
return content::mojom::MediaStreamType::MEDIA_DEVICE_AUDIO_CAPTURE;
case content::MediaStreamType::MEDIA_DEVICE_VIDEO_CAPTURE:
return content::mojom::MediaStreamType::MEDIA_DEVICE_VIDEO_CAPTURE;
- case content::MediaStreamType::MEDIA_TAB_AUDIO_CAPTURE:
- return content::mojom::MediaStreamType::MEDIA_TAB_AUDIO_CAPTURE;
- case content::MediaStreamType::MEDIA_TAB_VIDEO_CAPTURE:
- return content::mojom::MediaStreamType::MEDIA_TAB_VIDEO_CAPTURE;
- case content::MediaStreamType::MEDIA_DESKTOP_VIDEO_CAPTURE:
- return content::mojom::MediaStreamType::MEDIA_DESKTOP_VIDEO_CAPTURE;
- case content::MediaStreamType::MEDIA_DESKTOP_AUDIO_CAPTURE:
- return content::mojom::MediaStreamType::MEDIA_DESKTOP_AUDIO_CAPTURE;
+ case content::MediaStreamType::MEDIA_GUM_TAB_AUDIO_CAPTURE:
+ return content::mojom::MediaStreamType::MEDIA_GUM_TAB_AUDIO_CAPTURE;
+ case content::MediaStreamType::MEDIA_GUM_TAB_VIDEO_CAPTURE:
+ return content::mojom::MediaStreamType::MEDIA_GUM_TAB_VIDEO_CAPTURE;
+ case content::MediaStreamType::MEDIA_GUM_DESKTOP_VIDEO_CAPTURE:
+ return content::mojom::MediaStreamType::MEDIA_GUM_DESKTOP_VIDEO_CAPTURE;
+ case content::MediaStreamType::MEDIA_GUM_DESKTOP_AUDIO_CAPTURE:
+ return content::mojom::MediaStreamType::MEDIA_GUM_DESKTOP_AUDIO_CAPTURE;
+ case content::MediaStreamType::MEDIA_DISPLAY_VIDEO_CAPTURE:
+ return content::mojom::MediaStreamType::MEDIA_DISPLAY_VIDEO_CAPTURE;
case content::MediaStreamType::NUM_MEDIA_TYPES:
return content::mojom::MediaStreamType::NUM_MEDIA_TYPES;
}
@@ -48,17 +50,20 @@ bool EnumTraits<content::mojom::MediaStreamType, content::MediaStreamType>::
case content::mojom::MediaStreamType::MEDIA_DEVICE_VIDEO_CAPTURE:
*out = content::MediaStreamType::MEDIA_DEVICE_VIDEO_CAPTURE;
return true;
- case content::mojom::MediaStreamType::MEDIA_TAB_AUDIO_CAPTURE:
- *out = content::MediaStreamType::MEDIA_TAB_AUDIO_CAPTURE;
+ case content::mojom::MediaStreamType::MEDIA_GUM_TAB_AUDIO_CAPTURE:
+ *out = content::MediaStreamType::MEDIA_GUM_TAB_AUDIO_CAPTURE;
return true;
- case content::mojom::MediaStreamType::MEDIA_TAB_VIDEO_CAPTURE:
- *out = content::MediaStreamType::MEDIA_TAB_VIDEO_CAPTURE;
+ case content::mojom::MediaStreamType::MEDIA_GUM_TAB_VIDEO_CAPTURE:
+ *out = content::MediaStreamType::MEDIA_GUM_TAB_VIDEO_CAPTURE;
return true;
- case content::mojom::MediaStreamType::MEDIA_DESKTOP_VIDEO_CAPTURE:
- *out = content::MediaStreamType::MEDIA_DESKTOP_VIDEO_CAPTURE;
+ case content::mojom::MediaStreamType::MEDIA_GUM_DESKTOP_VIDEO_CAPTURE:
+ *out = content::MediaStreamType::MEDIA_GUM_DESKTOP_VIDEO_CAPTURE;
return true;
- case content::mojom::MediaStreamType::MEDIA_DESKTOP_AUDIO_CAPTURE:
- *out = content::MediaStreamType::MEDIA_DESKTOP_AUDIO_CAPTURE;
+ case content::mojom::MediaStreamType::MEDIA_GUM_DESKTOP_AUDIO_CAPTURE:
+ *out = content::MediaStreamType::MEDIA_GUM_DESKTOP_AUDIO_CAPTURE;
+ return true;
+ case content::mojom::MediaStreamType::MEDIA_DISPLAY_VIDEO_CAPTURE:
+ *out = content::MediaStreamType::MEDIA_DISPLAY_VIDEO_CAPTURE;
return true;
case content::mojom::MediaStreamType::NUM_MEDIA_TYPES:
*out = content::MediaStreamType::NUM_MEDIA_TYPES;
@@ -187,7 +192,7 @@ bool StructTraits<
content::TrackControls>::Read(content::mojom::TrackControlsDataView input,
content::TrackControls* out) {
out->requested = input.requested();
- if (!input.ReadStreamSource(&out->stream_source))
+ if (!input.ReadStreamType(&out->stream_type))
return false;
if (!input.ReadDeviceId(&out->device_id))
return false;
diff --git a/chromium/content/common/media/media_stream_typemap_traits.h b/chromium/content/common/media/media_stream_mojom_traits.h
index de811eacdf9..69abea71225 100644
--- a/chromium/content/common/media/media_stream_typemap_traits.h
+++ b/chromium/content/common/media/media_stream_mojom_traits.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_COMMON_MEDIA_MEDIA_STREAM_TYPEMAP_TRAITS_H_
-#define CONTENT_COMMON_MEDIA_MEDIA_STREAM_TYPEMAP_TRAITS_H_
+#ifndef CONTENT_COMMON_MEDIA_MEDIA_STREAM_MOJOM_TRAITS_H_
+#define CONTENT_COMMON_MEDIA_MEDIA_STREAM_MOJOM_TRAITS_H_
#include "content/common/media/media_stream.mojom.h"
#include "content/common/media/media_stream_controls.h"
@@ -36,9 +36,9 @@ struct StructTraits<content::mojom::TrackControlsDataView,
return controls.requested;
}
- static const std::string& stream_source(
+ static const content::MediaStreamType& stream_type(
const content::TrackControls& controls) {
- return controls.stream_source;
+ return controls.stream_type;
}
static const std::string& device_id(const content::TrackControls& controls) {
@@ -76,4 +76,4 @@ struct StructTraits<content::mojom::StreamControlsDataView,
} // namespace mojo
-#endif // CONTENT_COMMON_MEDIA_MEDIA_STREAM_TYPEMAP_TRAITS_H_ \ No newline at end of file
+#endif // CONTENT_COMMON_MEDIA_MEDIA_STREAM_MOJOM_TRAITS_H_
diff --git a/chromium/content/common/media/renderer_audio_input_stream_factory.mojom b/chromium/content/common/media/renderer_audio_input_stream_factory.mojom
index 8f258d924f9..28ffee8d282 100644
--- a/chromium/content/common/media/renderer_audio_input_stream_factory.mojom
+++ b/chromium/content/common/media/renderer_audio_input_stream_factory.mojom
@@ -9,6 +9,7 @@ import "media/mojo/interfaces/audio_input_stream.mojom";
import "media/mojo/interfaces/audio_parameters.mojom";
import "media/mojo/interfaces/media_types.mojom";
import "mojo/public/mojom/base/unguessable_token.mojom";
+import "services/audio/public/mojom/audio_processing.mojom";
// This interface is used by the renderer to ask the browser to create input
// streams. The renderer supplies the desired audio parameters, and a client
@@ -20,7 +21,8 @@ interface RendererAudioInputStreamFactory {
int32 session_id,
media.mojom.AudioParameters params,
bool automatic_gain_control,
- uint32 shared_memory_count);
+ uint32 shared_memory_count,
+ audio.mojom.AudioProcessingConfig? processing_config);
// Associates an output device with an input stream, so that the input knows
// which output device to cancel echo from. |input_stream_id| is the id
diff --git a/chromium/content/common/mime_sniffing_throttle.cc b/chromium/content/common/mime_sniffing_throttle.cc
new file mode 100644
index 00000000000..11f3f4056cb
--- /dev/null
+++ b/chromium/content/common/mime_sniffing_throttle.cc
@@ -0,0 +1,60 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/mime_sniffing_throttle.h"
+
+#include "content/common/mime_sniffing_url_loader.h"
+#include "net/base/mime_sniffer.h"
+
+namespace content {
+
+MimeSniffingThrottle::MimeSniffingThrottle() : weak_factory_(this) {}
+
+MimeSniffingThrottle::~MimeSniffingThrottle() = default;
+
+void MimeSniffingThrottle::WillProcessResponse(
+ const GURL& response_url,
+ network::ResourceResponseHead* response_head,
+ bool* defer) {
+ // No need to do mime sniffing again.
+ if (response_head->did_mime_sniff)
+ return;
+
+ bool blocked_sniffing_mime = false;
+ std::string content_type_options;
+ if (response_head->headers &&
+ response_head->headers->GetNormalizedHeader("x-content-type-options",
+ &content_type_options)) {
+ blocked_sniffing_mime =
+ base::LowerCaseEqualsASCII(content_type_options, "nosniff");
+ }
+
+ if (!blocked_sniffing_mime &&
+ net::ShouldSniffMimeType(response_url, response_head->mime_type)) {
+ // Pause the response until the mime type becomes ready.
+ *defer = true;
+
+ network::mojom::URLLoaderPtr new_loader;
+ network::mojom::URLLoaderClientRequest new_loader_request;
+ network::mojom::URLLoaderPtr source_loader;
+ network::mojom::URLLoaderClientRequest source_client_request;
+ MimeSniffingURLLoader* mime_sniffing_loader;
+ std::tie(new_loader, new_loader_request, mime_sniffing_loader) =
+ MimeSniffingURLLoader::CreateLoader(weak_factory_.GetWeakPtr(),
+ response_url, *response_head);
+ delegate_->InterceptResponse(std::move(new_loader),
+ std::move(new_loader_request), &source_loader,
+ &source_client_request);
+ mime_sniffing_loader->Start(std::move(source_loader),
+ std::move(source_client_request));
+ }
+}
+
+void MimeSniffingThrottle::ResumeWithNewResponseHead(
+ const network::ResourceResponseHead& new_response_head) {
+ delegate_->UpdateDeferredResponseHead(new_response_head);
+ delegate_->Resume();
+}
+
+} // namespace content
diff --git a/chromium/content/common/mime_sniffing_throttle.h b/chromium/content/common/mime_sniffing_throttle.h
new file mode 100644
index 00000000000..c4940f991ea
--- /dev/null
+++ b/chromium/content/common/mime_sniffing_throttle.h
@@ -0,0 +1,36 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_COMMON_MIME_SNIFFING_THROTTLE_H_
+#define CONTENT_COMMON_MIME_SNIFFING_THROTTLE_H_
+
+#include "base/memory/weak_ptr.h"
+#include "content/common/content_export.h"
+#include "content/public/common/url_loader_throttle.h"
+
+namespace content {
+
+// Throttle for mime type sniffing. This may intercept the request and
+// modify the response's mime type in the response head.
+class CONTENT_EXPORT MimeSniffingThrottle : public URLLoaderThrottle {
+ public:
+ MimeSniffingThrottle();
+ ~MimeSniffingThrottle() override;
+
+ // Implements URLLoaderThrottle.
+ void WillProcessResponse(const GURL& response_url,
+ network::ResourceResponseHead* response_head,
+ bool* defer) override;
+
+ // Called from MimeSniffingURLLoader once mime type is ready.
+ void ResumeWithNewResponseHead(
+ const network::ResourceResponseHead& new_response_head);
+
+ private:
+ base::WeakPtrFactory<MimeSniffingThrottle> weak_factory_;
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_MIME_SNIFFING_THROTTLE_H_
diff --git a/chromium/content/common/mime_sniffing_throttle_unittest.cc b/chromium/content/common/mime_sniffing_throttle_unittest.cc
new file mode 100644
index 00000000000..ab74617fe9c
--- /dev/null
+++ b/chromium/content/common/mime_sniffing_throttle_unittest.cc
@@ -0,0 +1,459 @@
+// 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/common/mime_sniffing_throttle.h"
+
+#include <memory>
+
+#include "base/run_loop.h"
+#include "base/test/scoped_task_environment.h"
+#include "content/common/mime_sniffing_url_loader.h"
+#include "content/public/common/url_loader_throttle.h"
+#include "mojo/public/cpp/system/data_pipe_utils.h"
+#include "services/network/test/test_url_loader_client.h"
+#include "services/network/test/test_url_loader_factory.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace content {
+
+namespace {
+
+class MojoDataPipeSender {
+ public:
+ MojoDataPipeSender(mojo::ScopedDataPipeProducerHandle handle)
+ : handle_(std::move(handle)),
+ watcher_(FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::AUTOMATIC) {}
+
+ void Start(std::string data, base::OnceClosure done_callback) {
+ data_ = std::move(data);
+ done_callback_ = std::move(done_callback);
+ watcher_.Watch(handle_.get(),
+ MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ base::BindRepeating(&MojoDataPipeSender::OnWritable,
+ base::Unretained(this)));
+ }
+
+ void OnWritable(MojoResult) {
+ uint32_t sending_bytes = data_.size() - sent_bytes_;
+ MojoResult result = handle_->WriteData(
+ data_.c_str() + sent_bytes_, &sending_bytes, MOJO_WRITE_DATA_FLAG_NONE);
+ switch (result) {
+ case MOJO_RESULT_OK:
+ break;
+ case MOJO_RESULT_FAILED_PRECONDITION:
+ // Finished unexpectedly.
+ std::move(done_callback_).Run();
+ return;
+ case MOJO_RESULT_SHOULD_WAIT:
+ // Just wait until OnWritable() is called by the watcher.
+ return;
+ default:
+ NOTREACHED();
+ return;
+ }
+ sent_bytes_ += sending_bytes;
+ if (data_.size() == sent_bytes_)
+ std::move(done_callback_).Run();
+ }
+
+ mojo::ScopedDataPipeProducerHandle ReleaseHandle() {
+ return std::move(handle_);
+ }
+
+ bool has_succeeded() const { return data_.size() == sent_bytes_; }
+
+ private:
+ mojo::ScopedDataPipeProducerHandle handle_;
+ mojo::SimpleWatcher watcher_;
+ base::OnceClosure done_callback_;
+ std::string data_;
+ uint32_t sent_bytes_ = 0;
+};
+
+class MockDelegate : public URLLoaderThrottle::Delegate {
+ public:
+ // Implements URLLoaderThrottle::Delegate.
+ void CancelWithError(int error_code,
+ base::StringPiece custom_reason) override {
+ NOTIMPLEMENTED();
+ }
+ void Resume() override {
+ is_resumed_ = true;
+ // Resume from OnReceiveResponse() with a customized response header.
+ destination_loader_client()->OnReceiveResponse(
+ updated_response_head().value());
+ }
+
+ void SetPriority(net::RequestPriority priority) override { NOTIMPLEMENTED(); }
+ void UpdateDeferredResponseHead(
+ const network::ResourceResponseHead& new_response_head) override {
+ updated_response_head_ = new_response_head;
+ }
+ void PauseReadingBodyFromNet() override { NOTIMPLEMENTED(); }
+ void ResumeReadingBodyFromNet() override { NOTIMPLEMENTED(); }
+ void InterceptResponse(
+ network::mojom::URLLoaderPtr new_loader,
+ network::mojom::URLLoaderClientRequest new_client_request,
+ network::mojom::URLLoaderPtr* original_loader,
+ network::mojom::URLLoaderClientRequest* original_client_request)
+ override {
+ is_intercepted_ = true;
+
+ destination_loader_ptr_ = std::move(new_loader);
+ ASSERT_TRUE(mojo::FuseInterface(
+ std::move(new_client_request),
+ destination_loader_client_.CreateInterfacePtr().PassInterface()));
+ source_loader_request_ = mojo::MakeRequest(original_loader);
+ *original_client_request = mojo::MakeRequest(&source_loader_client_ptr_);
+ }
+
+ void LoadResponseBody(const std::string& body) {
+ if (!source_body_handle_.is_valid()) {
+ // Send OnStartLoadingResponseBody() if it's the first call.
+ mojo::ScopedDataPipeConsumerHandle consumer;
+ EXPECT_EQ(MOJO_RESULT_OK,
+ mojo::CreateDataPipe(nullptr, &source_body_handle_, &consumer));
+ source_loader_client()->OnStartLoadingResponseBody(std::move(consumer));
+ }
+
+ MojoDataPipeSender sender(std::move(source_body_handle_));
+ base::RunLoop loop;
+ sender.Start(body, loop.QuitClosure());
+ loop.Run();
+
+ EXPECT_TRUE(sender.has_succeeded());
+ source_body_handle_ = sender.ReleaseHandle();
+ }
+
+ void CompleteResponse() {
+ source_loader_client()->OnComplete(network::URLLoaderCompletionStatus());
+ source_body_handle_.reset();
+ }
+
+ uint32_t ReadResponseBody(uint32_t size) {
+ std::vector<uint8_t> buffer(size);
+ MojoResult result = destination_loader_client_.response_body().ReadData(
+ buffer.data(), &size, MOJO_READ_DATA_FLAG_NONE);
+ switch (result) {
+ case MOJO_RESULT_OK:
+ return size;
+ case MOJO_RESULT_FAILED_PRECONDITION:
+ return 0;
+ case MOJO_RESULT_SHOULD_WAIT:
+ return 0;
+ default:
+ NOTREACHED();
+ }
+ return 0;
+ }
+
+ bool is_intercepted() const { return is_intercepted_; }
+ bool is_resumed() const { return is_resumed_; }
+
+ const base::Optional<network::ResourceResponseHead>& updated_response_head()
+ const {
+ return updated_response_head_;
+ }
+
+ network::TestURLLoaderClient* destination_loader_client() {
+ return &destination_loader_client_;
+ }
+
+ network::mojom::URLLoaderClient* source_loader_client() {
+ return source_loader_client_ptr_.get();
+ }
+
+ private:
+ bool is_intercepted_ = false;
+ bool is_resumed_ = false;
+ base::Optional<network::ResourceResponseHead> updated_response_head_;
+
+ // A pair of a loader and a loader client for destination of the response.
+ network::mojom::URLLoaderPtr destination_loader_ptr_;
+ network::TestURLLoaderClient destination_loader_client_;
+
+ // A pair of a loader and a loader client for source of the response.
+ network::mojom::URLLoaderClientPtr source_loader_client_ptr_;
+ network::mojom::URLLoaderRequest source_loader_request_;
+
+ mojo::ScopedDataPipeProducerHandle source_body_handle_;
+};
+
+} // namespace
+
+class MimeSniffingThrottleTest : public testing::Test {
+ protected:
+ // Be the first member so it is destroyed last.
+ base::test::ScopedTaskEnvironment scoped_task_environment_;
+};
+
+TEST_F(MimeSniffingThrottleTest, NoMimeTypeWithSniffableScheme) {
+ auto throttle = std::make_unique<MimeSniffingThrottle>();
+ auto delegate = std::make_unique<MockDelegate>();
+ throttle->set_delegate(delegate.get());
+
+ network::ResourceResponseHead response_head;
+ bool defer = false;
+ throttle->WillProcessResponse(GURL("https://example.com"), &response_head,
+ &defer);
+ EXPECT_TRUE(defer);
+ EXPECT_TRUE(delegate->is_intercepted());
+}
+
+TEST_F(MimeSniffingThrottleTest, SniffableMimeTypeWithSniffableScheme) {
+ auto throttle = std::make_unique<MimeSniffingThrottle>();
+ auto delegate = std::make_unique<MockDelegate>();
+ throttle->set_delegate(delegate.get());
+
+ network::ResourceResponseHead response_head;
+ response_head.mime_type = "text/plain";
+ bool defer = false;
+ throttle->WillProcessResponse(GURL("https://example.com"), &response_head,
+ &defer);
+ EXPECT_TRUE(defer);
+ EXPECT_TRUE(delegate->is_intercepted());
+}
+
+TEST_F(MimeSniffingThrottleTest, NotSniffableMimeTypeWithSniffableScheme) {
+ auto throttle = std::make_unique<MimeSniffingThrottle>();
+ auto delegate = std::make_unique<MockDelegate>();
+ throttle->set_delegate(delegate.get());
+
+ network::ResourceResponseHead response_head;
+ response_head.mime_type = "text/javascript";
+ bool defer = false;
+ throttle->WillProcessResponse(GURL("https://example.com"), &response_head,
+ &defer);
+ EXPECT_FALSE(defer);
+ EXPECT_FALSE(delegate->is_intercepted());
+}
+
+TEST_F(MimeSniffingThrottleTest, NoMimeTypeWithNotSniffableScheme) {
+ auto throttle = std::make_unique<MimeSniffingThrottle>();
+ auto delegate = std::make_unique<MockDelegate>();
+ throttle->set_delegate(delegate.get());
+
+ network::ResourceResponseHead response_head;
+ bool defer = false;
+ throttle->WillProcessResponse(GURL("wss://example.com"), &response_head,
+ &defer);
+ EXPECT_FALSE(defer);
+ EXPECT_FALSE(delegate->is_intercepted());
+}
+
+TEST_F(MimeSniffingThrottleTest, SniffableMimeTypeWithNotSniffableScheme) {
+ auto throttle = std::make_unique<MimeSniffingThrottle>();
+ auto delegate = std::make_unique<MockDelegate>();
+ throttle->set_delegate(delegate.get());
+
+ network::ResourceResponseHead response_head;
+ response_head.mime_type = "text/plain";
+ bool defer = false;
+ throttle->WillProcessResponse(GURL("wss://example.com"), &response_head,
+ &defer);
+ EXPECT_FALSE(defer);
+ EXPECT_FALSE(delegate->is_intercepted());
+}
+
+TEST_F(MimeSniffingThrottleTest, NotSniffableMimeTypeWithNotSniffableScheme) {
+ auto throttle = std::make_unique<MimeSniffingThrottle>();
+ auto delegate = std::make_unique<MockDelegate>();
+ throttle->set_delegate(delegate.get());
+
+ network::ResourceResponseHead response_head;
+ response_head.mime_type = "text/javascript";
+ bool defer = false;
+ throttle->WillProcessResponse(GURL("wss://example.com"), &response_head,
+ &defer);
+ EXPECT_FALSE(defer);
+ EXPECT_FALSE(delegate->is_intercepted());
+}
+
+TEST_F(MimeSniffingThrottleTest, SniffableButAlreadySniffed) {
+ auto throttle = std::make_unique<MimeSniffingThrottle>();
+ auto delegate = std::make_unique<MockDelegate>();
+ throttle->set_delegate(delegate.get());
+
+ network::ResourceResponseHead response_head;
+ response_head.mime_type = "text/plain";
+ response_head.did_mime_sniff = true;
+ bool defer = false;
+ throttle->WillProcessResponse(GURL("https://example.com"), &response_head,
+ &defer);
+ EXPECT_FALSE(defer);
+ EXPECT_FALSE(delegate->is_intercepted());
+}
+
+TEST_F(MimeSniffingThrottleTest, NoBody) {
+ auto throttle = std::make_unique<MimeSniffingThrottle>();
+ auto delegate = std::make_unique<MockDelegate>();
+ throttle->set_delegate(delegate.get());
+
+ GURL response_url("https://example.com");
+ network::ResourceResponseHead response_head;
+ bool defer = false;
+ throttle->WillProcessResponse(response_url, &response_head, &defer);
+ EXPECT_TRUE(defer);
+ EXPECT_TRUE(delegate->is_intercepted());
+
+ // Call OnComplete() without sending body.
+ delegate->source_loader_client()->OnComplete(
+ network::URLLoaderCompletionStatus());
+ delegate->destination_loader_client()->RunUntilComplete();
+
+ // The mime type should be updated to the default mime type ("text/plain").
+ EXPECT_TRUE(delegate->destination_loader_client()->has_received_response());
+ EXPECT_EQ("text/plain",
+ delegate->destination_loader_client()->response_head().mime_type);
+}
+
+TEST_F(MimeSniffingThrottleTest, Body_PlainText) {
+ auto throttle = std::make_unique<MimeSniffingThrottle>();
+ auto delegate = std::make_unique<MockDelegate>();
+ throttle->set_delegate(delegate.get());
+
+ GURL response_url("https://example.com");
+ network::ResourceResponseHead response_head;
+ bool defer = false;
+ throttle->WillProcessResponse(response_url, &response_head, &defer);
+ EXPECT_TRUE(defer);
+ EXPECT_TRUE(delegate->is_intercepted());
+
+ // Send the body and complete the response.
+ delegate->LoadResponseBody("This is a text.");
+ delegate->CompleteResponse();
+ delegate->destination_loader_client()->RunUntilComplete();
+
+ // The mime type should be updated.
+ EXPECT_TRUE(delegate->is_resumed());
+ EXPECT_EQ("text/plain",
+ delegate->destination_loader_client()->response_head().mime_type);
+}
+
+TEST_F(MimeSniffingThrottleTest, Body_Docx) {
+ auto throttle = std::make_unique<MimeSniffingThrottle>();
+ auto delegate = std::make_unique<MockDelegate>();
+ throttle->set_delegate(delegate.get());
+
+ GURL response_url("https://example.com/hogehoge.docx");
+ network::ResourceResponseHead response_head;
+ bool defer = false;
+ throttle->WillProcessResponse(response_url, &response_head, &defer);
+ EXPECT_TRUE(defer);
+ EXPECT_TRUE(delegate->is_intercepted());
+
+ // Send the body and complete the response.
+ delegate->LoadResponseBody("\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1");
+ delegate->CompleteResponse();
+ delegate->destination_loader_client()->RunUntilComplete();
+
+ // The mime type should be updated.
+ EXPECT_TRUE(delegate->is_resumed());
+ EXPECT_EQ("application/msword",
+ delegate->destination_loader_client()->response_head().mime_type);
+}
+
+TEST_F(MimeSniffingThrottleTest, Body_PNG) {
+ auto throttle = std::make_unique<MimeSniffingThrottle>();
+ auto delegate = std::make_unique<MockDelegate>();
+ throttle->set_delegate(delegate.get());
+
+ GURL response_url("https://example.com/hogehoge.docx");
+ network::ResourceResponseHead response_head;
+ bool defer = false;
+ throttle->WillProcessResponse(response_url, &response_head, &defer);
+ EXPECT_TRUE(defer);
+ EXPECT_TRUE(delegate->is_intercepted());
+
+ // Send the body and complete the response.
+ delegate->LoadResponseBody("\x89PNG\x0D\x0A\x1A\x0A");
+ delegate->CompleteResponse();
+ delegate->destination_loader_client()->RunUntilComplete();
+
+ // The mime type should be updated.
+ EXPECT_TRUE(delegate->is_resumed());
+ EXPECT_EQ("image/png",
+ delegate->destination_loader_client()->response_head().mime_type);
+}
+
+TEST_F(MimeSniffingThrottleTest, Body_LongPlainText) {
+ auto throttle = std::make_unique<MimeSniffingThrottle>();
+ auto delegate = std::make_unique<MockDelegate>();
+ throttle->set_delegate(delegate.get());
+
+ GURL response_url("https://example.com");
+ network::ResourceResponseHead response_head;
+ bool defer = false;
+ throttle->WillProcessResponse(response_url, &response_head, &defer);
+ EXPECT_TRUE(defer);
+ EXPECT_TRUE(delegate->is_intercepted());
+
+ // 64KiB is coming from the default value used in
+ // mojo::core::Core::CreateDataPipe().
+ const uint32_t kDefaultDataPipeBufferSize = 64 * 1024;
+ std::string long_body(kDefaultDataPipeBufferSize * 2, 'x');
+
+ // Send the data to the MimeSniffingURLLoader.
+ // |delegate|'s MojoDataPipeSender sends the first
+ // |kDefaultDataPipeBufferSize| bytes to MimeSniffingURLLoader and
+ // MimeSniffingURLLoader will read the first |kDefaultDataPipeBufferSize|
+ // bytes of the body, so the MojoDataPipeSender can push the rest of
+ // |kDefaultDataPipeBufferSize| of the body soon and finishes sending the
+ // body. After this, MimeSniffingURLLoader is waiting to push the body to the
+ // destination data pipe since the pipe should be full until it's read.
+ delegate->LoadResponseBody(long_body);
+ scoped_task_environment_.RunUntilIdle();
+
+ // Read the half of the body. This unblocks MimeSniffingURLLoader to push the
+ // rest of the body to the data pipe.
+ uint32_t read_bytes = delegate->ReadResponseBody(long_body.size() / 2);
+ scoped_task_environment_.RunUntilIdle();
+
+ // Read the rest of the body.
+ read_bytes += delegate->ReadResponseBody(long_body.size() / 2);
+ scoped_task_environment_.RunUntilIdle();
+ delegate->CompleteResponse();
+ delegate->destination_loader_client()->RunUntilComplete();
+
+ // Check if all data has been read.
+ EXPECT_EQ(long_body.size(), read_bytes);
+
+ // The mime type should be updated.
+ EXPECT_TRUE(delegate->is_resumed());
+ EXPECT_EQ("text/plain",
+ delegate->destination_loader_client()->response_head().mime_type);
+}
+
+TEST_F(MimeSniffingThrottleTest, Abort_NoBodyPipe) {
+ auto throttle = std::make_unique<MimeSniffingThrottle>();
+ auto delegate = std::make_unique<MockDelegate>();
+ throttle->set_delegate(delegate.get());
+
+ GURL response_url("https://example.com");
+ network::ResourceResponseHead response_head;
+ bool defer = false;
+ throttle->WillProcessResponse(response_url, &response_head, &defer);
+ EXPECT_TRUE(defer);
+ EXPECT_TRUE(delegate->is_intercepted());
+
+ // Send the body
+ std::string body = "This should be long enough to complete sniffing.";
+ body.resize(1024, 'a');
+ delegate->LoadResponseBody(body);
+ scoped_task_environment_.RunUntilIdle();
+
+ // Release a pipe for the body on the receiver side.
+ delegate->destination_loader_client()->response_body_release();
+ scoped_task_environment_.RunUntilIdle();
+
+ // Send the body after the pipe is closed. The the loader aborts.
+ delegate->LoadResponseBody("This is a text.");
+
+ // Calling OnComplete should not crash.
+ delegate->CompleteResponse();
+ scoped_task_environment_.RunUntilIdle();
+}
+
+} // namespace content
diff --git a/chromium/content/common/mime_sniffing_url_loader.cc b/chromium/content/common/mime_sniffing_url_loader.cc
new file mode 100644
index 00000000000..2df2493d005
--- /dev/null
+++ b/chromium/content/common/mime_sniffing_url_loader.cc
@@ -0,0 +1,370 @@
+// 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/common/mime_sniffing_url_loader.h"
+
+#include "content/common/mime_sniffing_throttle.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "net/base/mime_sniffer.h"
+
+namespace content {
+
+// static
+const char MimeSniffingURLLoader::kDefaultMimeType[] = "text/plain";
+
+// static
+std::tuple<network::mojom::URLLoaderPtr,
+ network::mojom::URLLoaderClientRequest,
+ MimeSniffingURLLoader*>
+MimeSniffingURLLoader::CreateLoader(
+ base::WeakPtr<MimeSniffingThrottle> throttle,
+ const GURL& response_url,
+ const network::ResourceResponseHead& response_head) {
+ network::mojom::URLLoaderPtr url_loader;
+ network::mojom::URLLoaderClientPtr url_loader_client;
+ network::mojom::URLLoaderClientRequest url_loader_client_request =
+ mojo::MakeRequest(&url_loader_client);
+ auto loader = base::WrapUnique(
+ new MimeSniffingURLLoader(std::move(throttle), response_url,
+ response_head, std::move(url_loader_client)));
+ MimeSniffingURLLoader* loader_rawptr = loader.get();
+ mojo::MakeStrongBinding(std::move(loader), mojo::MakeRequest(&url_loader));
+ return std::make_tuple(std::move(url_loader),
+ std::move(url_loader_client_request), loader_rawptr);
+}
+
+MimeSniffingURLLoader::MimeSniffingURLLoader(
+ base::WeakPtr<MimeSniffingThrottle> throttle,
+ const GURL& response_url,
+ const network::ResourceResponseHead& response_head,
+ network::mojom::URLLoaderClientPtr destination_url_loader_client)
+ : throttle_(throttle),
+ source_url_client_binding_(this),
+ destination_url_loader_client_(std::move(destination_url_loader_client)),
+ response_url_(response_url),
+ response_head_(response_head),
+ body_consumer_watcher_(FROM_HERE,
+ mojo::SimpleWatcher::ArmingPolicy::MANUAL),
+ body_producer_watcher_(FROM_HERE,
+ mojo::SimpleWatcher::ArmingPolicy::MANUAL) {}
+
+MimeSniffingURLLoader::~MimeSniffingURLLoader() = default;
+
+void MimeSniffingURLLoader::Start(
+ network::mojom::URLLoaderPtr source_url_loader,
+ network::mojom::URLLoaderClientRequest source_url_loader_client_request) {
+ source_url_loader_ = std::move(source_url_loader);
+ source_url_client_binding_.Bind(std::move(source_url_loader_client_request));
+}
+
+void MimeSniffingURLLoader::OnReceiveResponse(
+ const network::ResourceResponseHead& response_head) {
+ // OnReceiveResponse() shouldn't be called because MimeSniffingURLLoader is
+ // created by MimeSniffingThrottle::WillProcessResponse(), which is equivalent
+ // to OnReceiveResponse().
+ NOTREACHED();
+}
+
+void MimeSniffingURLLoader::OnReceiveRedirect(
+ const net::RedirectInfo& redirect_info,
+ const network::ResourceResponseHead& response_head) {
+ // OnReceiveRedirect() shouldn't be called because MimeSniffingURLLoader is
+ // created by MimeSniffingThrottle::WillProcessResponse(), which is equivalent
+ // to OnReceiveResponse().
+ NOTREACHED();
+}
+
+void MimeSniffingURLLoader::OnUploadProgress(
+ int64_t current_position,
+ int64_t total_size,
+ OnUploadProgressCallback ack_callback) {
+ destination_url_loader_client_->OnUploadProgress(current_position, total_size,
+ std::move(ack_callback));
+}
+
+void MimeSniffingURLLoader::OnReceiveCachedMetadata(
+ const std::vector<uint8_t>& data) {
+ destination_url_loader_client_->OnReceiveCachedMetadata(data);
+}
+
+void MimeSniffingURLLoader::OnTransferSizeUpdated(int32_t transfer_size_diff) {
+ destination_url_loader_client_->OnTransferSizeUpdated(transfer_size_diff);
+}
+
+void MimeSniffingURLLoader::OnStartLoadingResponseBody(
+ mojo::ScopedDataPipeConsumerHandle body) {
+ state_ = State::kSniffing;
+ body_consumer_handle_ = std::move(body);
+ body_consumer_watcher_.Watch(
+ body_consumer_handle_.get(),
+ MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ base::BindRepeating(&MimeSniffingURLLoader::OnBodyReadable,
+ base::Unretained(this)));
+ body_consumer_watcher_.ArmOrNotify();
+}
+
+void MimeSniffingURLLoader::OnComplete(
+ const network::URLLoaderCompletionStatus& status) {
+ DCHECK(!complete_status_.has_value());
+ switch (state_) {
+ case State::kWaitForBody:
+ // OnComplete() is called without OnStartLoadingResponseBody(). There is
+ // no response body in this case. Use |kDefaultMimeType| as its mime type
+ // even though it's empty.
+ state_ = State::kCompleted;
+ response_head_.mime_type = kDefaultMimeType;
+ if (!throttle_) {
+ Abort();
+ return;
+ }
+ throttle_->ResumeWithNewResponseHead(response_head_);
+ destination_url_loader_client_->OnComplete(status);
+ return;
+ case State::kSniffing:
+ // Defer calling OnComplete() since we defer calling
+ // OnStartLoadingResponseBody() until mime sniffing has been finished.
+ complete_status_ = status;
+ return;
+ case State::kSending:
+ case State::kCompleted:
+ destination_url_loader_client_->OnComplete(status);
+ return;
+ case State::kAborted:
+ NOTREACHED();
+ return;
+ }
+ NOTREACHED();
+}
+
+void MimeSniffingURLLoader::FollowRedirect(
+ const base::Optional<std::vector<std::string>>&
+ to_be_removed_request_headers,
+ const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
+ // MimeSniffingURLLoader starts handling the request after
+ // OnReceivedResponse(). A redirect response is not expected.
+ NOTREACHED();
+}
+
+void MimeSniffingURLLoader::ProceedWithResponse() {
+ if (state_ == State::kAborted)
+ return;
+ source_url_loader_->ProceedWithResponse();
+}
+
+void MimeSniffingURLLoader::SetPriority(net::RequestPriority priority,
+ int32_t intra_priority_value) {
+ if (state_ == State::kAborted)
+ return;
+ source_url_loader_->SetPriority(priority, intra_priority_value);
+}
+
+void MimeSniffingURLLoader::PauseReadingBodyFromNet() {
+ if (state_ == State::kAborted)
+ return;
+ source_url_loader_->PauseReadingBodyFromNet();
+}
+
+void MimeSniffingURLLoader::ResumeReadingBodyFromNet() {
+ if (state_ == State::kAborted)
+ return;
+ source_url_loader_->ResumeReadingBodyFromNet();
+}
+
+void MimeSniffingURLLoader::OnBodyReadable(MojoResult) {
+ if (state_ == State::kSending) {
+ // The pipe becoming readable when kSending means all buffered body has
+ // already been sent.
+ ForwardBodyToClient();
+ return;
+ }
+ DCHECK_EQ(State::kSniffing, state_);
+
+ size_t start_size = buffered_body_.size();
+ uint32_t read_bytes = net::kMaxBytesToSniff;
+ buffered_body_.resize(start_size + read_bytes);
+ MojoResult result =
+ body_consumer_handle_->ReadData(buffered_body_.data() + start_size,
+ &read_bytes, MOJO_READ_DATA_FLAG_NONE);
+ switch (result) {
+ case MOJO_RESULT_OK:
+ break;
+ case MOJO_RESULT_FAILED_PRECONDITION:
+ // Finished the body before mime type is completely decided.
+ buffered_body_.resize(start_size);
+ CompleteSniffing();
+ return;
+ case MOJO_RESULT_SHOULD_WAIT:
+ body_consumer_watcher_.ArmOrNotify();
+ return;
+ default:
+ NOTREACHED();
+ return;
+ }
+
+ DCHECK_EQ(MOJO_RESULT_OK, result);
+ buffered_body_.resize(start_size + read_bytes);
+ std::string new_type;
+ bool made_final_decision =
+ net::SniffMimeType(buffered_body_.data(), buffered_body_.size(),
+ response_url_, response_head_.mime_type,
+ net::ForceSniffFileUrlsForHtml::kDisabled, &new_type);
+ response_head_.mime_type = new_type;
+ response_head_.did_mime_sniff = true;
+ if (made_final_decision) {
+ CompleteSniffing();
+ return;
+ }
+ body_consumer_watcher_.ArmOrNotify();
+}
+
+void MimeSniffingURLLoader::OnBodyWritable(MojoResult) {
+ DCHECK_EQ(State::kSending, state_);
+ if (bytes_remaining_in_buffer_ > 0) {
+ SendReceivedBodyToClient();
+ } else {
+ ForwardBodyToClient();
+ }
+}
+
+void MimeSniffingURLLoader::CompleteSniffing() {
+ DCHECK_EQ(State::kSniffing, state_);
+ if (buffered_body_.empty()) {
+ // A data pipe for the body was received but no body was provided. Don't
+ // propagate OnStartLoadingResponseBody() in this case. We treat this
+ // situation as the same as when OnStartLoadingResponseBody() was not
+ // called.
+ //
+ // TODO(crbug.com/826868): Remove this once all loaders are aligned.
+ state_ = State::kWaitForBody;
+ if (complete_status_.has_value()) {
+ auto status = complete_status_.value();
+ complete_status_.reset();
+ OnComplete(status);
+ }
+ return;
+ }
+
+ state_ = State::kSending;
+ bytes_remaining_in_buffer_ = buffered_body_.size();
+ if (!throttle_) {
+ Abort();
+ return;
+ }
+ throttle_->ResumeWithNewResponseHead(response_head_);
+ mojo::ScopedDataPipeConsumerHandle body_to_send;
+ MojoResult result =
+ mojo::CreateDataPipe(nullptr, &body_producer_handle_, &body_to_send);
+ if (result != MOJO_RESULT_OK) {
+ Abort();
+ return;
+ }
+ // Set up the watcher for the producer handle.
+ body_producer_watcher_.Watch(
+ body_producer_handle_.get(),
+ MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ base::BindRepeating(&MimeSniffingURLLoader::OnBodyWritable,
+ base::Unretained(this)));
+ // Send deferred messages.
+ destination_url_loader_client_->OnStartLoadingResponseBody(
+ std::move(body_to_send));
+ // Call OnComplete() if OnComplete() has already been called.
+ if (complete_status_.has_value())
+ destination_url_loader_client_->OnComplete(complete_status_.value());
+ SendReceivedBodyToClient();
+}
+
+void MimeSniffingURLLoader::CompleteSending() {
+ DCHECK_EQ(State::kSending, state_);
+ state_ = State::kCompleted;
+ body_consumer_watcher_.Cancel();
+ body_producer_watcher_.Cancel();
+ body_consumer_handle_.reset();
+ body_producer_handle_.reset();
+}
+
+void MimeSniffingURLLoader::SendReceivedBodyToClient() {
+ DCHECK_EQ(State::kSending, state_);
+ // Send the buffered data first.
+ DCHECK_GT(bytes_remaining_in_buffer_, 0u);
+ size_t start_position = buffered_body_.size() - bytes_remaining_in_buffer_;
+ uint32_t bytes_sent = bytes_remaining_in_buffer_;
+ MojoResult result =
+ body_producer_handle_->WriteData(buffered_body_.data() + start_position,
+ &bytes_sent, MOJO_WRITE_DATA_FLAG_NONE);
+ switch (result) {
+ case MOJO_RESULT_OK:
+ break;
+ case MOJO_RESULT_FAILED_PRECONDITION:
+ // The pipe is closed unexpectedly. |this| should be deleted once
+ // URLLoaderPtr on the destination is released.
+ Abort();
+ return;
+ case MOJO_RESULT_SHOULD_WAIT:
+ body_producer_watcher_.ArmOrNotify();
+ return;
+ default:
+ NOTREACHED();
+ return;
+ }
+ bytes_remaining_in_buffer_ -= bytes_sent;
+ body_producer_watcher_.ArmOrNotify();
+}
+
+void MimeSniffingURLLoader::ForwardBodyToClient() {
+ DCHECK_EQ(0u, bytes_remaining_in_buffer_);
+ // Send the body from the consumer to the producer.
+ const void* buffer;
+ uint32_t buffer_size = 0;
+ MojoResult result = body_consumer_handle_->BeginReadData(
+ &buffer, &buffer_size, MOJO_BEGIN_READ_DATA_FLAG_NONE);
+ switch (result) {
+ case MOJO_RESULT_OK:
+ break;
+ case MOJO_RESULT_SHOULD_WAIT:
+ body_consumer_watcher_.ArmOrNotify();
+ return;
+ case MOJO_RESULT_FAILED_PRECONDITION:
+ // All data has been sent.
+ CompleteSending();
+ return;
+ default:
+ NOTREACHED();
+ return;
+ }
+
+ result = body_producer_handle_->WriteData(buffer, &buffer_size,
+ MOJO_WRITE_DATA_FLAG_NONE);
+ switch (result) {
+ case MOJO_RESULT_OK:
+ break;
+ case MOJO_RESULT_FAILED_PRECONDITION:
+ // The pipe is closed unexpectedly. |this| should be deleted once
+ // URLLoaderPtr on the destination is released.
+ Abort();
+ return;
+ case MOJO_RESULT_SHOULD_WAIT:
+ body_consumer_handle_->EndReadData(0);
+ body_producer_watcher_.ArmOrNotify();
+ return;
+ default:
+ NOTREACHED();
+ return;
+ }
+
+ body_consumer_handle_->EndReadData(buffer_size);
+ body_consumer_watcher_.ArmOrNotify();
+}
+
+void MimeSniffingURLLoader::Abort() {
+ state_ = State::kAborted;
+ body_consumer_watcher_.Cancel();
+ body_producer_watcher_.Cancel();
+ source_url_loader_.reset();
+ source_url_client_binding_.Close();
+ destination_url_loader_client_.reset();
+ // |this| should be removed since the owner will destroy |this| or the owner
+ // has already been destroyed by some reason.
+}
+
+} // namespace content
diff --git a/chromium/content/common/mime_sniffing_url_loader.h b/chromium/content/common/mime_sniffing_url_loader.h
new file mode 100644
index 00000000000..64365c28da6
--- /dev/null
+++ b/chromium/content/common/mime_sniffing_url_loader.h
@@ -0,0 +1,149 @@
+// 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_COMMON_MIME_SNIFFING_URL_LOADER_H_
+#define CONTENT_COMMON_MIME_SNIFFING_URL_LOADER_H_
+
+#include <tuple>
+
+#include "base/callback.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/strings/string_piece.h"
+#include "content/common/content_export.h"
+#include "content/common/possibly_associated_interface_ptr.h"
+#include "content/public/common/url_loader_throttle.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/system/data_pipe.h"
+#include "mojo/public/cpp/system/simple_watcher.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "services/network/public/mojom/url_loader.mojom.h"
+#include "services/network/public/mojom/url_loader_factory.mojom.h"
+
+namespace content {
+
+class MimeSniffingThrottle;
+
+// Reads the response body and determines its mime type. This url loader buffers
+// the response body until the mime type is decided. MimeSniffingURLLoader
+// is expected to be created just after receiving OnReceiveResponse(), so this
+// handles only OnStartLoadingResponseBody() and OnComplete() as a
+// network::mojom::URLLoaderClient.
+//
+// This loader has five states:
+// kWaitForBody: The initial state until the body is received (=
+// OnStartLoadingResponseBody() is called) or the response is
+// finished (= OnComplete() is called). When body is provided, the
+// state is changed to kSniffing. Otherwise the state goes to
+// kCompleted.
+// kSniffing: Receives the body from the source loader and estimate the mime
+// type. The received body is kept in this loader until the mime type
+// is decided. When the mime type is decided or all body has been
+// received, this loader will dispatch queued messages like
+// OnStartLoadingResponseBody() and OnComplete() to the destination
+// loader client, and then the state is changed to kSending.
+// kSending: Receives the body and send it to the destination loader client. All
+// data has been read by this loader, the state goes to kCompleted.
+// kCompleted: All data has been sent to the destination loader.
+// kAborted: Unexpected behavior happens. Watchers, pipes and the binding from
+// the source loader to |this| are stopped. All incoming messages from
+// the destination (through network::mojom::URLLoader) are ignored in
+// this state.
+class CONTENT_EXPORT MimeSniffingURLLoader
+ : public network::mojom::URLLoaderClient,
+ public network::mojom::URLLoader {
+ public:
+ ~MimeSniffingURLLoader() override;
+
+ // Start waiting for the body.
+ void Start(
+ network::mojom::URLLoaderPtr source_url_loader,
+ network::mojom::URLLoaderClientRequest source_url_loader_client_request);
+
+ // network::mojom::URLLoaderPtr controls the lifetime of the loader.
+ static std::tuple<network::mojom::URLLoaderPtr,
+ network::mojom::URLLoaderClientRequest,
+ MimeSniffingURLLoader*>
+ CreateLoader(base::WeakPtr<MimeSniffingThrottle> throttle,
+ const GURL& response_url,
+ const network::ResourceResponseHead& response_head);
+
+ private:
+ MimeSniffingURLLoader(
+ base::WeakPtr<MimeSniffingThrottle> throttle,
+ const GURL& response_url,
+ const network::ResourceResponseHead& response_head,
+ network::mojom::URLLoaderClientPtr destination_url_loader_client);
+
+ // network::mojom::URLLoaderClient implementation (called from the source of
+ // the response):
+ void OnReceiveResponse(
+ const network::ResourceResponseHead& response_head) override;
+ void OnReceiveRedirect(
+ const net::RedirectInfo& redirect_info,
+ const network::ResourceResponseHead& response_head) override;
+ void OnUploadProgress(int64_t current_position,
+ int64_t total_size,
+ OnUploadProgressCallback ack_callback) override;
+ void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override;
+ void OnTransferSizeUpdated(int32_t transfer_size_diff) override;
+ void OnStartLoadingResponseBody(
+ mojo::ScopedDataPipeConsumerHandle body) override;
+ void OnComplete(const network::URLLoaderCompletionStatus& status) override;
+
+ // network::mojom::URLLoader implementation (called from the destination of
+ // the response):
+ void FollowRedirect(const base::Optional<std::vector<std::string>>&
+ to_be_removed_request_headers,
+ const base::Optional<net::HttpRequestHeaders>&
+ modified_request_headers) override;
+ void ProceedWithResponse() override;
+ void SetPriority(net::RequestPriority priority,
+ int32_t intra_priority_value) override;
+ void PauseReadingBodyFromNet() override;
+ void ResumeReadingBodyFromNet() override;
+
+ void OnBodyReadable(MojoResult);
+ void OnBodyWritable(MojoResult);
+ void CompleteSniffing();
+ void CompleteSending();
+ void SendReceivedBodyToClient();
+ void ForwardBodyToClient();
+
+ void Abort();
+
+ static const char kDefaultMimeType[];
+
+ base::WeakPtr<MimeSniffingThrottle> throttle_;
+
+ mojo::Binding<network::mojom::URLLoaderClient> source_url_client_binding_;
+ network::mojom::URLLoaderPtr source_url_loader_;
+ network::mojom::URLLoaderClientPtr destination_url_loader_client_;
+
+ GURL response_url_;
+
+ // Capture the response head to defer to send it to the destination until the
+ // mime type is decided.
+ network::ResourceResponseHead response_head_;
+
+ enum class State { kWaitForBody, kSniffing, kSending, kCompleted, kAborted };
+ State state_ = State::kWaitForBody;
+
+ // Set if OnComplete() is called during sniffing.
+ base::Optional<network::URLLoaderCompletionStatus> complete_status_;
+
+ std::vector<char> buffered_body_;
+ size_t bytes_remaining_in_buffer_;
+
+ mojo::ScopedDataPipeConsumerHandle body_consumer_handle_;
+ mojo::ScopedDataPipeProducerHandle body_producer_handle_;
+ mojo::SimpleWatcher body_consumer_watcher_;
+ mojo::SimpleWatcher body_producer_watcher_;
+
+ DISALLOW_COPY_AND_ASSIGN(MimeSniffingURLLoader);
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_MIME_SNIFFING_URL_LOADER_H_
diff --git a/chromium/content/common/native_types.mojom b/chromium/content/common/native_types.mojom
index 9ac02ea16b1..7754ec1dc0f 100644
--- a/chromium/content/common/native_types.mojom
+++ b/chromium/content/common/native_types.mojom
@@ -19,9 +19,6 @@ struct FrameOwnerProperties;
struct FrameReplicationState;
[Native]
-struct RendererPreferences;
-
-[Native]
struct VisualProperties;
// NOTE: This type is only mapped and usable on Mac.
diff --git a/chromium/content/common/native_types.typemap b/chromium/content/common/native_types.typemap
index 8d6420575db..3caf59a4c87 100644
--- a/chromium/content/common/native_types.typemap
+++ b/chromium/content/common/native_types.typemap
@@ -18,7 +18,6 @@ public_headers = [
"//content/common/input/synthetic_smooth_drag_gesture_params.h",
"//content/common/input/synthetic_smooth_scroll_gesture_params.h",
"//content/common/input/synthetic_tap_gesture_params.h",
- "//content/public/common/renderer_preferences.h",
"//content/public/common/web_preferences.h",
"//net/base/network_change_notifier.h",
"//third_party/blink/public/platform/web_gesture_device.h",
@@ -39,6 +38,7 @@ traits_headers = [
"//content/common/input/touch_action_optional_struct_traits.h",
"//content/common/view_messages.h",
"//content/public/common/common_param_traits.h",
+ "//services/network/public/cpp/p2p_param_traits.h",
]
public_deps = [
# NOTE: These dependencies are here to satisfy gn check because
@@ -77,7 +77,6 @@ type_mappings = [
"content.mojom.NetworkConnectionType=net::NetworkChangeNotifier::ConnectionType",
"content.mojom.DidOverscrollParams=ui::DidOverscrollParams",
"content.mojom.PointerType=blink::WebPointerProperties::PointerType",
- "content.mojom.RendererPreferences=content::RendererPreferences",
"content.mojom.VisualProperties=content::VisualProperties",
"content.mojom.ScrollUnits=blink::WebGestureEvent::ScrollUnits",
"content.mojom.SyntheticSmoothDrag=content::SyntheticSmoothDragGestureParams",
diff --git a/chromium/content/common/navigation_client.mojom b/chromium/content/common/navigation_client.mojom
index d4331b67801..49c5db432fb 100644
--- a/chromium/content/common/navigation_client.mojom
+++ b/chromium/content/common/navigation_client.mojom
@@ -61,7 +61,8 @@ interface NavigationClient {
array<TransferrableURLLoader>? subresource_overrides,
ControllerServiceWorkerInfo? controller_service_worker_info,
network.mojom.URLLoaderFactory? prefetch_loader_factory,
- mojo_base.mojom.UnguessableToken devtools_navigation_token);
+ mojo_base.mojom.UnguessableToken devtools_navigation_token)
+ => (blink.mojom.CommitResult commit_result);
// Tells the renderer that a failed navigation is ready to commit.
//
@@ -78,6 +79,7 @@ interface NavigationClient {
bool has_stale_copy_in_cache,
int32 error_code,
string? error_page_content,
- URLLoaderFactoryBundle? subresource_loader_factories);
+ URLLoaderFactoryBundle? subresource_loader_factories)
+ => (blink.mojom.CommitResult commit_result);
};
diff --git a/chromium/content/common/navigation_params.cc b/chromium/content/common/navigation_params.cc
index 1ee0fe12301..04cf967022a 100644
--- a/chromium/content/common/navigation_params.cc
+++ b/chromium/content/common/navigation_params.cc
@@ -36,7 +36,7 @@ CommonNavigationParams::CommonNavigationParams(
const GURL& base_url_for_data_url,
const GURL& history_url_for_data_url,
PreviewsState previews_state,
- const base::TimeTicks& navigation_start,
+ base::TimeTicks navigation_start,
std::string method,
const scoped_refptr<network::ResourceRequestBody>& post_data,
base::Optional<SourceLocation> source_location,
@@ -44,7 +44,8 @@ CommonNavigationParams::CommonNavigationParams(
bool started_from_context_menu,
bool has_user_gesture,
const std::vector<ContentSecurityPolicy>& initiator_csp,
- const base::Optional<CSPSource>& initiator_self_source)
+ const base::Optional<CSPSource>& initiator_self_source,
+ base::TimeTicks input_start)
: url(url),
referrer(referrer),
transition(transition),
@@ -62,7 +63,8 @@ CommonNavigationParams::CommonNavigationParams(
started_from_context_menu(started_from_context_menu),
has_user_gesture(has_user_gesture),
initiator_csp(initiator_csp),
- initiator_self_source(initiator_self_source) {
+ initiator_self_source(initiator_self_source),
+ input_start(input_start) {
// |method != "POST"| should imply absence of |post_data|.
if (method != "POST" && post_data) {
NOTREACHED();
diff --git a/chromium/content/common/navigation_params.h b/chromium/content/common/navigation_params.h
index 08a7d0cf8f3..748f4c20324 100644
--- a/chromium/content/common/navigation_params.h
+++ b/chromium/content/common/navigation_params.h
@@ -69,7 +69,7 @@ struct CONTENT_EXPORT CommonNavigationParams {
const GURL& base_url_for_data_url,
const GURL& history_url_for_data_url,
PreviewsState previews_state,
- const base::TimeTicks& navigation_start,
+ base::TimeTicks navigation_start,
std::string method,
const scoped_refptr<network::ResourceRequestBody>& post_data,
base::Optional<SourceLocation> source_location,
@@ -77,7 +77,8 @@ struct CONTENT_EXPORT CommonNavigationParams {
bool started_from_context_menu,
bool has_user_gesture,
const std::vector<ContentSecurityPolicy>& initiator_csp,
- const base::Optional<CSPSource>& initiator_self_source);
+ const base::Optional<CSPSource>& initiator_self_source,
+ base::TimeTicks input_start = base::TimeTicks());
CommonNavigationParams(const CommonNavigationParams& other);
~CommonNavigationParams();
@@ -160,6 +161,11 @@ struct CONTENT_EXPORT CommonNavigationParams {
// The current origin policy for this request's origin.
// (Empty if none applies.)
std::string origin_policy;
+
+ // 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.
+ base::TimeTicks input_start;
};
// Provided by the browser -----------------------------------------------------
@@ -279,7 +285,6 @@ struct CONTENT_EXPORT RequestNavigationParams {
// navigation commits.
bool should_clear_history_list = false;
- // PlzNavigate
// Whether a ServiceWorkerProviderHost should be created for the window.
bool should_create_service_worker = false;
@@ -287,11 +292,8 @@ struct CONTENT_EXPORT RequestNavigationParams {
// Timing of navigation events.
NavigationTiming navigation_timing;
- // PlzNavigate
// The ServiceWorkerProviderHost ID used for navigations, if it was already
// created by the browser. Set to kInvalidServiceWorkerProviderId otherwise.
- // This parameter is not used in the current navigation architecture, where
- // it will always be equal to kInvalidServiceWorkerProviderId.
int service_worker_provider_id = kInvalidServiceWorkerProviderId;
// PlzNavigate
diff --git a/chromium/content/common/notifications/OWNERS b/chromium/content/common/notifications/OWNERS
index c96491e93f9..cb33c42852f 100644
--- a/chromium/content/common/notifications/OWNERS
+++ b/chromium/content/common/notifications/OWNERS
@@ -1,7 +1,5 @@
file://content/browser/notifications/OWNERS
-awdf@chromium.org
-
per-file *_struct_traits*.*=set noparent
per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS
diff --git a/chromium/content/common/notifications/notification_struct_traits.cc b/chromium/content/common/notifications/notification_struct_traits.cc
index 6c8fa6bb2b7..f51f378610c 100644
--- a/chromium/content/common/notifications/notification_struct_traits.cc
+++ b/chromium/content/common/notifications/notification_struct_traits.cc
@@ -143,7 +143,7 @@ bool StructTraits<blink::mojom::NotificationDataDataView,
content::PlatformNotificationData* platform_notification_data) {
// TODO(https://crbug.com/798466): Read the data directly into
// platform_notification_data.data once it stores a vector of ints not chars.
- std::vector<int8_t> data;
+ std::vector<uint8_t> data;
if (!notification_data.ReadTitle(&platform_notification_data->title) ||
!notification_data.ReadDirection(
diff --git a/chromium/content/common/notifications/notification_struct_traits.h b/chromium/content/common/notifications/notification_struct_traits.h
index b4ee6075e5f..bf2fccb4d5d 100644
--- a/chromium/content/common/notifications/notification_struct_traits.h
+++ b/chromium/content/common/notifications/notification_struct_traits.h
@@ -134,10 +134,10 @@ struct CONTENT_EXPORT StructTraits<blink::mojom::NotificationDataDataView,
return data.require_interaction;
}
- static const base::span<const int8_t> data(
+ static const base::span<const uint8_t> data(
const content::PlatformNotificationData& data) {
// TODO(https://crbug.com/798466): Align data types to avoid this cast.
- return base::make_span(reinterpret_cast<const int8_t*>(data.data.data()),
+ return base::make_span(reinterpret_cast<const uint8_t*>(data.data.data()),
data.data.size());
}
diff --git a/chromium/content/common/p2p_messages.h b/chromium/content/common/p2p_messages.h
deleted file mode 100644
index 45c245dadba..00000000000
--- a/chromium/content/common/p2p_messages.h
+++ /dev/null
@@ -1,149 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_P2P_MESSAGES_H_
-#define CONTENT_COMMON_P2P_MESSAGES_H_
-
-// IPC messages for the P2P Transport API.
-
-#include <stdint.h>
-
-#include "base/time/time.h"
-#include "content/common/content_export.h"
-#include "content/common/p2p_socket_type.h"
-#include "ipc/ipc_message_macros.h"
-#include "net/base/ip_address.h"
-#include "net/base/network_interfaces.h"
-#include "net/traffic_annotation/network_traffic_annotation.h"
-#include "third_party/webrtc/rtc_base/asyncpacketsocket.h"
-
-#undef IPC_MESSAGE_EXPORT
-#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
-#define IPC_MESSAGE_START P2PMsgStart
-
-IPC_ENUM_TRAITS_MAX_VALUE(content::P2PSocketType,
- content::P2P_SOCKET_TYPE_LAST)
-IPC_ENUM_TRAITS_MAX_VALUE(content::P2PSocketOption,
- content::P2P_SOCKET_OPT_MAX - 1)
-IPC_ENUM_TRAITS_MIN_MAX_VALUE(rtc::DiffServCodePoint,
- rtc::DSCP_NO_CHANGE,
- rtc::DSCP_CS7)
-
-IPC_STRUCT_TRAITS_BEGIN(net::NetworkInterface)
- IPC_STRUCT_TRAITS_MEMBER(name)
- IPC_STRUCT_TRAITS_MEMBER(type)
- IPC_STRUCT_TRAITS_MEMBER(address)
- IPC_STRUCT_TRAITS_MEMBER(prefix_length)
- IPC_STRUCT_TRAITS_MEMBER(ip_address_attributes)
-IPC_STRUCT_TRAITS_END()
-
-IPC_STRUCT_TRAITS_BEGIN(rtc::PacketTimeUpdateParams)
- IPC_STRUCT_TRAITS_MEMBER(rtp_sendtime_extension_id)
- IPC_STRUCT_TRAITS_MEMBER(srtp_auth_key)
- IPC_STRUCT_TRAITS_MEMBER(srtp_auth_tag_len)
- IPC_STRUCT_TRAITS_MEMBER(srtp_packet_index)
-IPC_STRUCT_TRAITS_END()
-
-IPC_STRUCT_TRAITS_BEGIN(rtc::PacketOptions)
- IPC_STRUCT_TRAITS_MEMBER(dscp)
- IPC_STRUCT_TRAITS_MEMBER(packet_id)
- IPC_STRUCT_TRAITS_MEMBER(packet_time_params)
-IPC_STRUCT_TRAITS_END()
-
-IPC_STRUCT_TRAITS_BEGIN(content::P2PHostAndIPEndPoint)
- IPC_STRUCT_TRAITS_MEMBER(hostname)
- IPC_STRUCT_TRAITS_MEMBER(ip_address)
-IPC_STRUCT_TRAITS_END()
-
-IPC_STRUCT_TRAITS_BEGIN(content::P2PSendPacketMetrics)
- IPC_STRUCT_TRAITS_MEMBER(packet_id)
- IPC_STRUCT_TRAITS_MEMBER(rtc_packet_id)
- IPC_STRUCT_TRAITS_MEMBER(send_time)
-IPC_STRUCT_TRAITS_END()
-
-IPC_STRUCT_TRAITS_BEGIN(content::P2PPortRange)
- IPC_STRUCT_TRAITS_MEMBER(min_port)
- IPC_STRUCT_TRAITS_MEMBER(max_port)
-IPC_STRUCT_TRAITS_END()
-
-IPC_STRUCT_TRAITS_BEGIN(content::P2PPacketInfo)
- IPC_STRUCT_TRAITS_MEMBER(destination)
- IPC_STRUCT_TRAITS_MEMBER(packet_options)
- IPC_STRUCT_TRAITS_MEMBER(packet_id)
-IPC_STRUCT_TRAITS_END()
-
-// P2P Socket messages sent from the browser to the renderer.
-
-IPC_MESSAGE_CONTROL3(P2PMsg_NetworkListChanged,
- net::NetworkInterfaceList /* networks */,
- net::IPAddress /* default_ipv4_local_address */,
- net::IPAddress /* default_ipv6_local_address */)
-
-IPC_MESSAGE_CONTROL2(P2PMsg_GetHostAddressResult,
- int32_t /* request_id */,
- net::IPAddressList /* address list*/)
-
-IPC_MESSAGE_CONTROL3(P2PMsg_OnSocketCreated,
- int /* socket_id */,
- net::IPEndPoint /* local_address */,
- net::IPEndPoint /* remote_address */)
-
-// |send_metrics| carries packet_id for this packet.
-IPC_MESSAGE_CONTROL2(P2PMsg_OnSendComplete,
- int /* socket_id */,
- content::P2PSendPacketMetrics /* send_metrics */)
-
-IPC_MESSAGE_CONTROL1(P2PMsg_OnError,
- int /* socket_id */)
-
-IPC_MESSAGE_CONTROL2(P2PMsg_OnIncomingTcpConnection,
- int /* socket_id */,
- net::IPEndPoint /* socket_address */)
-
-IPC_MESSAGE_CONTROL4(P2PMsg_OnDataReceived,
- int /* socket_id */,
- net::IPEndPoint /* socket_address */,
- std::vector<char> /* data */,
- base::TimeTicks /* timestamp */ )
-
-// P2P Socket messages sent from the renderer to the browser.
-
-// Start/stop sending P2PMsg_NetworkListChanged messages when network
-// configuration changes.
-IPC_MESSAGE_CONTROL0(P2PHostMsg_StartNetworkNotifications)
-IPC_MESSAGE_CONTROL0(P2PHostMsg_StopNetworkNotifications)
-
-IPC_MESSAGE_CONTROL2(P2PHostMsg_GetHostAddress,
- std::string /* host_name */,
- int32_t /* request_id */)
-
-IPC_MESSAGE_CONTROL5(P2PHostMsg_CreateSocket,
- content::P2PSocketType /* type */,
- int /* socket_id */,
- net::IPEndPoint /* local_address */,
- content::P2PPortRange /* port_range */,
- content::P2PHostAndIPEndPoint /* remote_address */)
-
-IPC_MESSAGE_CONTROL3(P2PHostMsg_AcceptIncomingTcpConnection,
- int /* listen_socket_id */,
- net::IPEndPoint /* remote_address */,
- int /* connected_socket_id */)
-
-// TODO(sergeyu): Use shared memory to pass the data.
-IPC_MESSAGE_CONTROL4(
- P2PHostMsg_Send,
- int /* socket_id */,
- std::vector<char> /* data */,
- content::P2PPacketInfo /* packet_info */,
- net::MutableNetworkTrafficAnnotationTag /* traffic_annotation */)
-
-IPC_MESSAGE_CONTROL1(P2PHostMsg_DestroySocket,
- int /* socket_id */)
-
-IPC_MESSAGE_CONTROL3(P2PHostMsg_SetOption,
- int /* socket_id */,
- content::P2PSocketOption /* socket option type */,
- int /* value */)
-
-#endif // CONTENT_COMMON_P2P_MESSAGES_H_
diff --git a/chromium/content/common/p2p_socket_type.h b/chromium/content/common/p2p_socket_type.h
deleted file mode 100644
index c526477bdba..00000000000
--- a/chromium/content/common/p2p_socket_type.h
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This file defines some basic types used by the P2P-related IPC
-// messages.
-
-#ifndef CONTENT_COMMON_P2P_SOCKET_TYPE_H_
-#define CONTENT_COMMON_P2P_SOCKET_TYPE_H_
-
-#include <stdint.h>
-
-#include <string>
-
-#include "base/time/time.h"
-#include "net/base/ip_endpoint.h"
-#include "third_party/webrtc/rtc_base/asyncpacketsocket.h"
-
-namespace content {
-
-enum P2PSocketOption {
- P2P_SOCKET_OPT_RCVBUF, // Receive buffer size.
- P2P_SOCKET_OPT_SNDBUF, // Send buffer size.
- P2P_SOCKET_OPT_DSCP, // DSCP code.
- P2P_SOCKET_OPT_MAX
-};
-
-// Type of P2P Socket.
-enum P2PSocketType {
- P2P_SOCKET_UDP,
- P2P_SOCKET_TCP_SERVER,
- P2P_SOCKET_STUN_TCP_SERVER,
- P2P_SOCKET_TCP_CLIENT,
- P2P_SOCKET_STUN_TCP_CLIENT,
- P2P_SOCKET_SSLTCP_CLIENT,
- P2P_SOCKET_STUN_SSLTCP_CLIENT,
- P2P_SOCKET_TLS_CLIENT,
- P2P_SOCKET_STUN_TLS_CLIENT,
- P2P_SOCKET_TYPE_LAST = P2P_SOCKET_STUN_TLS_CLIENT
-};
-
-// Struct which carries both resolved IP address and host string literal.
-// Port number will be part of |ip_address|.
-struct P2PHostAndIPEndPoint {
- P2PHostAndIPEndPoint() {}
- P2PHostAndIPEndPoint(const std::string& hostname,
- const net::IPEndPoint& ip_address)
- : hostname(hostname), ip_address(ip_address) {
- }
-
- std::string hostname;
- net::IPEndPoint ip_address;
-};
-
-// Struct which keeps track of metrics during a send operation on P2P sockets.
-struct P2PSendPacketMetrics {
- P2PSendPacketMetrics() {}
- P2PSendPacketMetrics(uint64_t packet_id,
- int32_t rtc_packet_id,
- base::TimeTicks send_time)
- : packet_id(packet_id),
- rtc_packet_id(rtc_packet_id),
- send_time(send_time) {}
-
- uint64_t packet_id = 0;
- // rtc_packet_id is a sequential packet counter written in the RTP header and
- // used by RTP receivers to ACK received packets. It is sent back with a
- // corresponding send time to WebRTC in the browser process so that it can be
- // combined with ACKs to compute inter-packet delay variations.
- int32_t rtc_packet_id = -1;
- base::TimeTicks send_time;
-};
-
-// Struct that carries a port range.
-struct P2PPortRange {
- P2PPortRange() : P2PPortRange(0, 0) {}
- P2PPortRange(uint16_t min_port, uint16_t max_port)
- : min_port(min_port), max_port(max_port) {
- DCHECK_LE(min_port, max_port);
- DCHECK((min_port == 0 && max_port == 0) || min_port > 0);
- }
- uint16_t min_port;
- uint16_t max_port;
-};
-
-// Struct that carries information about an outgoing packet.
-struct P2PPacketInfo {
- P2PPacketInfo() {}
- P2PPacketInfo(const net::IPEndPoint& destination,
- const rtc::PacketOptions& packet_options,
- uint64_t packet_id)
- : destination(destination),
- packet_options(packet_options),
- packet_id(packet_id) {}
- net::IPEndPoint destination;
- rtc::PacketOptions packet_options;
- uint64_t packet_id;
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_P2P_SOCKET_TYPE_H_
diff --git a/chromium/content/common/platform_notification_param_traits.h b/chromium/content/common/platform_notification_param_traits.h
deleted file mode 100644
index 22d6b927e19..00000000000
--- a/chromium/content/common/platform_notification_param_traits.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_PLATFORM_NOTIFICATION_PARAM_TRAITS_H_
-#define CONTENT_COMMON_PLATFORM_NOTIFICATION_PARAM_TRAITS_H_
-
-// Messages for platform-native notifications using the Web Notification API.
-
-#include <stdint.h>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "content/public/common/common_param_traits_macros.h"
-#include "content/public/common/notification_resources.h"
-#include "content/public/common/platform_notification_data.h"
-#include "ipc/ipc_message_macros.h"
-
-// TODO(https://crbug.com/841329): Delete this legacy IPC code, use a pure
-// mojo struct instead from ServiceWorker mojo interface.
-IPC_ENUM_TRAITS_MAX_VALUE(content::PlatformNotificationData::Direction,
- content::PlatformNotificationData::DIRECTION_LAST)
-
-IPC_ENUM_TRAITS_MAX_VALUE(content::PlatformNotificationActionType,
- content::PLATFORM_NOTIFICATION_ACTION_TYPE_TEXT)
-
-IPC_STRUCT_TRAITS_BEGIN(content::PlatformNotificationAction)
- IPC_STRUCT_TRAITS_MEMBER(type)
- IPC_STRUCT_TRAITS_MEMBER(action)
- IPC_STRUCT_TRAITS_MEMBER(title)
- IPC_STRUCT_TRAITS_MEMBER(icon)
- IPC_STRUCT_TRAITS_MEMBER(placeholder)
-IPC_STRUCT_TRAITS_END()
-
-IPC_STRUCT_TRAITS_BEGIN(content::PlatformNotificationData)
- IPC_STRUCT_TRAITS_MEMBER(title)
- IPC_STRUCT_TRAITS_MEMBER(direction)
- IPC_STRUCT_TRAITS_MEMBER(lang)
- IPC_STRUCT_TRAITS_MEMBER(body)
- IPC_STRUCT_TRAITS_MEMBER(tag)
- IPC_STRUCT_TRAITS_MEMBER(image)
- IPC_STRUCT_TRAITS_MEMBER(icon)
- IPC_STRUCT_TRAITS_MEMBER(badge)
- IPC_STRUCT_TRAITS_MEMBER(vibration_pattern)
- IPC_STRUCT_TRAITS_MEMBER(timestamp)
- IPC_STRUCT_TRAITS_MEMBER(renotify)
- IPC_STRUCT_TRAITS_MEMBER(silent)
- IPC_STRUCT_TRAITS_MEMBER(require_interaction)
- IPC_STRUCT_TRAITS_MEMBER(data)
- IPC_STRUCT_TRAITS_MEMBER(actions)
-IPC_STRUCT_TRAITS_END()
-
-#endif // CONTENT_COMMON_PLATFORM_NOTIFICATION_PARAM_TRAITS_H_
diff --git a/chromium/content/common/plugin_list.cc b/chromium/content/common/plugin_list.cc
index bc350650084..2dbe9f64b0e 100644
--- a/chromium/content/common/plugin_list.cc
+++ b/chromium/content/common/plugin_list.cc
@@ -27,6 +27,45 @@ namespace {
base::LazyInstance<PluginList>::DestructorAtExit g_singleton =
LAZY_INSTANCE_INITIALIZER;
+// Returns true if the plugin supports |mime_type|. |mime_type| should be all
+// lower case.
+bool SupportsType(const WebPluginInfo& plugin,
+ const std::string& mime_type,
+ bool allow_wildcard) {
+ // Webkit will ask for a plugin to handle empty mime types.
+ if (mime_type.empty())
+ return false;
+
+ for (size_t i = 0; i < plugin.mime_types.size(); ++i) {
+ const WebPluginMimeType& mime_info = plugin.mime_types[i];
+ if (net::MatchesMimeType(mime_info.mime_type, mime_type)) {
+ if (!allow_wildcard && mime_info.mime_type == "*")
+ continue;
+ return true;
+ }
+ }
+ return false;
+}
+
+// Returns true if the given plugin supports a given file extension.
+// |extension| should be all lower case. |actual_mime_type| will be set to the
+// MIME type if found. The MIME type which corresponds to the extension is
+// optionally returned back.
+bool SupportsExtension(const WebPluginInfo& plugin,
+ const std::string& extension,
+ std::string* actual_mime_type) {
+ for (size_t i = 0; i < plugin.mime_types.size(); ++i) {
+ const WebPluginMimeType& mime_type = plugin.mime_types[i];
+ for (size_t j = 0; j < mime_type.file_extensions.size(); ++j) {
+ if (mime_type.file_extensions[j] == extension) {
+ *actual_mime_type = mime_type.mime_type;
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
} // namespace
// static
@@ -256,40 +295,6 @@ void PluginList::GetPluginInfoArray(
}
}
-bool PluginList::SupportsType(const WebPluginInfo& plugin,
- const std::string& mime_type,
- bool allow_wildcard) {
- // Webkit will ask for a plugin to handle empty mime types.
- if (mime_type.empty())
- return false;
-
- for (size_t i = 0; i < plugin.mime_types.size(); ++i) {
- const WebPluginMimeType& mime_info = plugin.mime_types[i];
- if (net::MatchesMimeType(mime_info.mime_type, mime_type)) {
- if (!allow_wildcard && mime_info.mime_type == "*")
- continue;
- return true;
- }
- }
- return false;
-}
-
-bool PluginList::SupportsExtension(const WebPluginInfo& plugin,
- const std::string& extension,
- std::string* actual_mime_type) {
- for (size_t i = 0; i < plugin.mime_types.size(); ++i) {
- const WebPluginMimeType& mime_type = plugin.mime_types[i];
- for (size_t j = 0; j < mime_type.file_extensions.size(); ++j) {
- if (mime_type.file_extensions[j] == extension) {
- if (actual_mime_type)
- *actual_mime_type = mime_type.mime_type;
- return true;
- }
- }
- }
- return false;
-}
-
void PluginList::RemoveExtraPluginPathLocked(
const base::FilePath& plugin_path) {
lock_.AssertAcquired();
diff --git a/chromium/content/common/plugin_list.h b/chromium/content/common/plugin_list.h
index 59aa05d47c4..35ff2d0b735 100644
--- a/chromium/content/common/plugin_list.h
+++ b/chromium/content/common/plugin_list.h
@@ -41,12 +41,6 @@ class CONTENT_EXPORT PluginList {
// Gets the one instance of the PluginList.
static PluginList* Singleton();
- // Returns true if the plugin supports |mime_type|. |mime_type| should be all
- // lower case.
- static bool SupportsType(const WebPluginInfo& plugin,
- const std::string& mime_type,
- bool allow_wildcard);
-
// Cause the plugin list to refresh next time they are accessed, regardless
// of whether they are already loaded.
void RefreshPlugins();
@@ -66,12 +60,6 @@ class CONTENT_EXPORT PluginList {
// Gets a list of all the registered internal plugins.
void GetInternalPlugins(std::vector<WebPluginInfo>* plugins);
- // Creates a WebPluginInfo structure given a plugin's path. On success
- // returns true, with the information being put into "info".
- // Returns false if the library couldn't be found, or if it's not a plugin.
- bool ReadPluginInfo(const base::FilePath& filename,
- WebPluginInfo* info);
-
// Get all the plugins synchronously, loading them if necessary.
void GetPlugins(std::vector<WebPluginInfo>* plugins);
@@ -98,11 +86,20 @@ class CONTENT_EXPORT PluginList {
std::vector<WebPluginInfo>* info,
std::vector<std::string>* actual_mime_types);
- // Load a specific plugin with full path. Return true iff loading the plugin
- // was successful.
- bool LoadPluginIntoPluginList(const base::FilePath& filename,
- std::vector<WebPluginInfo>* plugins,
- WebPluginInfo* plugin_info);
+ void set_will_load_plugins_callback(const base::Closure& callback);
+
+ private:
+ enum LoadingState {
+ LOADING_STATE_NEEDS_REFRESH,
+ LOADING_STATE_REFRESHING,
+ LOADING_STATE_UP_TO_DATE,
+ };
+
+ friend class PluginListTest;
+ friend struct base::LazyInstanceTraitsBase<PluginList>;
+
+ PluginList();
+ ~PluginList();
// The following functions are used to support probing for WebPluginInfo
// using a different instance of this class.
@@ -120,37 +117,24 @@ class CONTENT_EXPORT PluginList {
// Clears the internal list of Plugins and copies them from the vector.
void SetPlugins(const std::vector<WebPluginInfo>& plugins);
- void set_will_load_plugins_callback(const base::Closure& callback);
-
- virtual ~PluginList();
-
- private:
- enum LoadingState {
- LOADING_STATE_NEEDS_REFRESH,
- LOADING_STATE_REFRESHING,
- LOADING_STATE_UP_TO_DATE,
- };
-
- friend class PluginListTest;
- friend struct base::LazyInstanceTraitsBase<PluginList>;
-
- PluginList();
-
// Load all plugins from the default plugins directory.
void LoadPlugins();
- // Returns true if the given plugin supports a given file extension.
- // |extension| should be all lower case. If |mime_type| is not NULL, it will
- // be set to the MIME type if found. The MIME type which corresponds to the
- // extension is optionally returned back.
- bool SupportsExtension(const WebPluginInfo& plugin,
- const std::string& extension,
- std::string* actual_mime_type);
-
// Removes |plugin_path| from the list of extra plugin paths. Should only be
// called while holding |lock_|.
void RemoveExtraPluginPathLocked(const base::FilePath& plugin_path);
+ // Creates a WebPluginInfo structure given a plugin's path. On success
+ // returns true, with the information being put into "info".
+ // Returns false if the library couldn't be found, or if it's not a plugin.
+ bool ReadPluginInfo(const base::FilePath& filename, WebPluginInfo* info);
+
+ // Load a specific plugin with full path. Return true iff loading the plugin
+ // was successful.
+ bool LoadPluginIntoPluginList(const base::FilePath& filename,
+ std::vector<WebPluginInfo>* plugins,
+ WebPluginInfo* plugin_info);
+
//
// Internals
//
diff --git a/chromium/content/common/presentation/OWNERS b/chromium/content/common/presentation/OWNERS
deleted file mode 100644
index 27a12f5e147..00000000000
--- a/chromium/content/common/presentation/OWNERS
+++ /dev/null
@@ -1,7 +0,0 @@
-file://content/browser/presentation/OWNERS
-
-# For SECURITY_OWNERS review of Mojo typemaps.
-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 \ No newline at end of file
diff --git a/chromium/content/common/presentation/presentation.typemap b/chromium/content/common/presentation/presentation.typemap
deleted file mode 100644
index f69f4453021..00000000000
--- a/chromium/content/common/presentation/presentation.typemap
+++ /dev/null
@@ -1,12 +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 = "//third_party/blink/public/platform/modules/presentation/presentation.mojom"
-public_headers = [ "//content/public/common/presentation_connection_message.h" ]
-traits_headers =
- [ "//content/common/presentation/presentation_struct_traits.h" ]
-deps = [
- "//url",
-]
-type_mappings = [ "blink.mojom.PresentationConnectionMessage=content::PresentationConnectionMessage[move_only]" ]
diff --git a/chromium/content/common/presentation/presentation_struct_traits.cc b/chromium/content/common/presentation/presentation_struct_traits.cc
deleted file mode 100644
index 484a772a84e..00000000000
--- a/chromium/content/common/presentation/presentation_struct_traits.cc
+++ /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.
-
-#include "content/common/presentation/presentation_struct_traits.h"
-
-#include "url/mojom/url_gurl_mojom_traits.h"
-
-namespace mojo {
-
-bool UnionTraits<blink::mojom::PresentationConnectionMessageDataView,
- content::PresentationConnectionMessage>::
- Read(blink::mojom::PresentationConnectionMessageDataView data,
- content::PresentationConnectionMessage* out) {
- if (data.is_message()) {
- if (!data.ReadMessage(&(out->message))) {
- return false;
- }
- } else {
- if (!data.ReadData(&(out->data))) {
- return false;
- }
- }
- return true;
-}
-}
diff --git a/chromium/content/common/presentation/presentation_struct_traits.h b/chromium/content/common/presentation/presentation_struct_traits.h
deleted file mode 100644
index 01e5e1ab535..00000000000
--- a/chromium/content/common/presentation/presentation_struct_traits.h
+++ /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.
-
-#ifndef CONTENT_COMMON_PRESENTATION_PRESENTATION_STRUCT_TRAITS_H_
-#define CONTENT_COMMON_PRESENTATION_PRESENTATION_STRUCT_TRAITS_H_
-
-#include <string>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/optional.h"
-#include "base/strings/string_util.h"
-#include "content/public/common/presentation_connection_message.h"
-#include "third_party/blink/public/platform/modules/presentation/presentation.mojom.h"
-#include "url/mojom/url.mojom.h"
-
-namespace mojo {
-
-template <>
-struct UnionTraits<blink::mojom::PresentationConnectionMessageDataView,
- content::PresentationConnectionMessage> {
- static blink::mojom::PresentationConnectionMessageDataView::Tag GetTag(
- const content::PresentationConnectionMessage& message) {
- return message.is_binary()
- ? blink::mojom::PresentationConnectionMessageDataView::Tag::DATA
- : blink::mojom::PresentationConnectionMessageDataView::Tag::
- MESSAGE;
- }
-
- static const std::string& message(
- const content::PresentationConnectionMessage& message) {
- DCHECK(!message.is_binary());
- return message.message.value();
- }
-
- static const std::vector<uint8_t>& data(
- const content::PresentationConnectionMessage& message) {
- DCHECK(message.is_binary());
- return message.data.value();
- }
-
- static bool Read(blink::mojom::PresentationConnectionMessageDataView data,
- content::PresentationConnectionMessage* out);
-};
-
-} // namespace mojo
-
-#endif // CONTENT_COMMON_PRESENTATION_PRESENTATION_STRUCT_TRAITS_H_
diff --git a/chromium/content/common/presentation/typemaps.gni b/chromium/content/common/presentation/typemaps.gni
deleted file mode 100644
index dbc927c6eee..00000000000
--- a/chromium/content/common/presentation/typemaps.gni
+++ /dev/null
@@ -1,5 +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.
-
-typemaps = [ "//content/common/presentation/presentation.typemap" ]
diff --git a/chromium/content/common/render_message_filter.mojom b/chromium/content/common/render_message_filter.mojom
index 15d97f9b140..e78a32d98ae 100644
--- a/chromium/content/common/render_message_filter.mojom
+++ b/chromium/content/common/render_message_filter.mojom
@@ -7,6 +7,7 @@ module content.mojom;
import "content/common/input/input_handler.mojom";
import "content/common/native_types.mojom";
import "content/common/widget.mojom";
+import "content/public/common/renderer_preferences.mojom";
import "mojo/public/mojom/base/thread_priority.mojom";
import "mojo/public/mojom/base/time.mojom";
import "url/mojom/origin.mojom";
@@ -31,6 +32,13 @@ interface RenderMessageFilter {
mojo_base.mojom.Time expected_response_time,
array<uint8> data);
+ // TODO(crbug.com/867848) Pass the data as mojo data_pipe instead of
+ // array<unit8>.
+ FetchCachedCode(url.mojom.Url url) => (mojo_base.mojom.Time response_time,
+ array<uint8> data);
+
+ ClearCodeCacheEntry(url.mojom.Url url);
+
// Requests that the browser cache |data| for the specified CacheStorage entry.
DidGenerateCacheableMetadataInCacheStorage(
url.mojom.Url url, mojo_base.mojom.Time expected_response_time,
diff --git a/chromium/content/common/render_widget_host_ns_view.mojom b/chromium/content/common/render_widget_host_ns_view.mojom
index 08667c119ac..4d435ea86b0 100644
--- a/chromium/content/common/render_widget_host_ns_view.mojom
+++ b/chromium/content/common/render_widget_host_ns_view.mojom
@@ -7,7 +7,7 @@ module content.mojom;
import "content/common/native_types.mojom";
import "content/common/input/input_handler.mojom";
import "mojo/public/mojom/base/string16.mojom";
-import "services/ui/public/interfaces/ime/ime.mojom";
+import "services/ws/public/mojom/ime/ime.mojom";
import "ui/display/mojo/display.mojom";
import "ui/events/mojo/event.mojom";
import "ui/gfx/geometry/mojo/geometry.mojom";
@@ -143,6 +143,7 @@ interface RenderWidgetHostNSViewClient {
// Forward events to the renderer or the input router, as appropriate.
RouteOrProcessMouseEvent(Event event);
+ RouteOrProcessTouchEvent(Event event);
RouteOrProcessWheelEvent(Event event);
// Special case forwarding of synthetic events to the renderer.
@@ -164,7 +165,7 @@ interface RenderWidgetHostNSViewClient {
// it is the result of GetActiveWidget.
ImeSetComposition(
mojo_base.mojom.String16 text,
- array<ui.mojom.ImeTextSpan> ime_text_spans,
+ array<ws.mojom.ImeTextSpan> ime_text_spans,
gfx.mojom.Range replacement_range,
int32 selection_start,
int32 selection_end);
diff --git a/chromium/content/common/render_widget_window_tree_client_factory.mojom b/chromium/content/common/render_widget_window_tree_client_factory.mojom
index 0c1ae21b5cc..7a92ea9cb05 100644
--- a/chromium/content/common/render_widget_window_tree_client_factory.mojom
+++ b/chromium/content/common/render_widget_window_tree_client_factory.mojom
@@ -5,7 +5,7 @@
module content.mojom;
import "mojo/public/mojom/base/unguessable_token.mojom";
-import "services/ui/public/interfaces/window_tree.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
@@ -22,6 +22,6 @@ interface RenderWidgetWindowTreeClient {
interface RenderWidgetWindowTreeClientFactory {
CreateWindowTreeClientForRenderWidget(
uint32 render_widget_host_routing_id,
- ui.mojom.WindowTreeClient& window_tree_client,
+ ws.mojom.WindowTreeClient& window_tree_client,
RenderWidgetWindowTreeClient& render_widget_window_tree_client_request);
};
diff --git a/chromium/content/common/renderer.mojom b/chromium/content/common/renderer.mojom
index 31266ed6077..d9f31e0238e 100644
--- a/chromium/content/common/renderer.mojom
+++ b/chromium/content/common/renderer.mojom
@@ -6,6 +6,7 @@ module content.mojom;
import "content/common/native_types.mojom";
import "content/common/service_worker/embedded_worker.mojom";
+import "content/public/common/renderer_preferences.mojom";
import "ipc/constants.mojom";
import "mojo/public/mojom/base/time.mojom";
import "mojo/public/mojom/base/unguessable_token.mojom";
diff --git a/chromium/content/common/renderer_host.mojom b/chromium/content/common/renderer_host.mojom
index 9b35f6fb75f..9e63799ce86 100644
--- a/chromium/content/common/renderer_host.mojom
+++ b/chromium/content/common/renderer_host.mojom
@@ -7,17 +7,15 @@ module content.mojom;
// The primordial interface implemented by a render process host. This should be
// used for implementing renderer-to-browser messages.
interface RendererHost {
- // Request a histogram from the browser. The browser will send the histogram
- // data only if it has been passed the command line flag
- // switches::kDomAutomationController.
+ // Request a histogram from the browser process. The browser will send the
+ // histogram data only if it has been passed the command line flag
+ // switches::kStatsCollectionController. This may or may not include
+ // histograms and some or all of their data from subprocesses and other
+ // sources outside the actual browser process.
[Sync]
GetBrowserHistogram(string name) => (string histogram_json);
// Notify the browser that this render process can or can't be suddenly
// terminated.
SuddenTerminationChanged(bool enabled);
-
- // Request a child_control.Shutdown message to be sent to the renderer. This
- // may not initiate a shutdown sequence in some cases.
- ShutdownRequest();
};
diff --git a/chromium/content/common/sandbox_init_mac.cc b/chromium/content/common/sandbox_init_mac.cc
index 6bd5d2b657e..0a4a263a2ca 100644
--- a/chromium/content/common/sandbox_init_mac.cc
+++ b/chromium/content/common/sandbox_init_mac.cc
@@ -61,7 +61,7 @@ base::OnceClosure MaybeWrapWithGPUSandboxHook(
gpu::EnableSwiftShaderIfNeeded(
command_line, gpu_feature_info,
gpu_preferences.disable_software_rasterizer, needs_more_info);
- // Preload either the desktop GL or the osmesa so, depending on the
+ // Preload either the desktop GL or SwiftShader so, depending on the
// --use-gl flag.
gl::init::InitializeGLOneOff();
diff --git a/chromium/content/common/sandbox_policy_fuchsia.cc b/chromium/content/common/sandbox_policy_fuchsia.cc
index ae20792dbb3..723586c97a4 100644
--- a/chromium/content/common/sandbox_policy_fuchsia.cc
+++ b/chromium/content/common/sandbox_policy_fuchsia.cc
@@ -4,27 +4,58 @@
#include "content/common/sandbox_policy_fuchsia.h"
-#include <fuchsia/fonts/cpp/fidl.h>
#include <lib/fdio/spawn.h>
+#include <stdio.h>
#include <zircon/processargs.h>
+#include <fuchsia/fonts/cpp/fidl.h>
+#include <fuchsia/ui/scenic/cpp/fidl.h>
+#include <memory>
+#include <utility>
+
#include "base/base_paths_fuchsia.h"
#include "base/command_line.h"
+#include "base/containers/span.h"
#include "base/files/file_util.h"
#include "base/fuchsia/component_context.h"
#include "base/fuchsia/filtered_service_directory.h"
#include "base/process/launch.h"
#include "base/process/process.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "content/public/common/content_switches.h"
#include "services/service_manager/sandbox/switches.h"
namespace content {
+namespace {
constexpr const char* const kRendererServices[] = {
fuchsia::fonts::FontProvider::Name_};
+constexpr const char* const kGpuServices[] = {
+ fuchsia::ui::scenic::Scenic::Name_};
+
+base::span<const char* const> GetServicesListForSandboxType(
+ service_manager::SandboxType type) {
+ switch (type) {
+ case service_manager::SANDBOX_TYPE_RENDERER:
+ return base::make_span(kRendererServices);
+ case service_manager::SANDBOX_TYPE_GPU:
+ return base::make_span(kGpuServices);
+ default:
+ return base::span<const char* const>();
+ }
+}
+
+} // namespace
+
SandboxPolicyFuchsia::SandboxPolicyFuchsia() = default;
-SandboxPolicyFuchsia::~SandboxPolicyFuchsia() = default;
+
+SandboxPolicyFuchsia::~SandboxPolicyFuchsia() {
+ if (service_directory_) {
+ service_directory_task_runner_->DeleteSoon(FROM_HERE,
+ std::move(service_directory_));
+ }
+}
void SandboxPolicyFuchsia::Initialize(service_manager::SandboxType type) {
DCHECK_NE(type, service_manager::SANDBOX_TYPE_INVALID);
@@ -37,15 +68,23 @@ void SandboxPolicyFuchsia::Initialize(service_manager::SandboxType type) {
type_ = service_manager::SANDBOX_TYPE_NO_SANDBOX;
}
- if (type_ == service_manager::SANDBOX_TYPE_RENDERER) {
- // Create FilteredServicesDirectory for the renderer process and export all
- // services in kRendererServices. ServiceDirectoryProxy must be initialized
- // on a thread that has async_dispatcher.
+ // If we need to pass some services for the given sandbox type then create
+ // |sandbox_directory_| and initialize it with the corresponding list of
+ // services. FilteredServiceDirectory must be initialized on a thread that has
+ // async_dispatcher.
+ auto services_list = GetServicesListForSandboxType(type_);
+ if (!services_list.empty()) {
+ service_directory_task_runner_ = base::ThreadTaskRunnerHandle::Get();
service_directory_ =
std::make_unique<base::fuchsia::FilteredServiceDirectory>(
base::fuchsia::ComponentContext::GetDefault());
- for (const char* service_name : kRendererServices)
+ for (const char* service_name : services_list)
service_directory_->AddService(service_name);
+
+ // Bind the service directory and store the client channel for
+ // UpdateLaunchOptionsForSandbox()'s use.
+ service_directory_client_channel_ = service_directory_->ConnectClient();
+ CHECK(service_directory_client_channel_);
}
}
@@ -53,31 +92,30 @@ void SandboxPolicyFuchsia::UpdateLaunchOptionsForSandbox(
base::LaunchOptions* options) {
DCHECK_NE(type_, service_manager::SANDBOX_TYPE_INVALID);
+ // Always clone stderr to get logs output.
+ options->fds_to_remap.push_back(std::make_pair(STDERR_FILENO, STDERR_FILENO));
+
if (type_ == service_manager::SANDBOX_TYPE_NO_SANDBOX) {
- options->spawn_flags = FDIO_SPAWN_CLONE_NAMESPACE | FDIO_SPAWN_CLONE_JOB |
- FDIO_SPAWN_CLONE_STDIO;
+ options->spawn_flags = FDIO_SPAWN_CLONE_NAMESPACE | FDIO_SPAWN_CLONE_JOB;
options->clear_environ = false;
return;
}
- // Map /pkg (read-only files deployed from the package) and /tmp into the
- // child's namespace.
+ // Map /pkg (read-only files deployed from the package) into the child's
+ // namespace.
options->paths_to_clone.push_back(base::GetPackageRoot());
- base::FilePath temp_dir;
- base::GetTempDir(&temp_dir);
- options->paths_to_clone.push_back(temp_dir);
// Clear environmental variables to better isolate the child from
// this process.
options->clear_environ = true;
- // Propagate stdout/stderr/stdin to the child.
- options->spawn_flags = FDIO_SPAWN_CLONE_STDIO;
+ // Don't clone anything by default.
+ options->spawn_flags = 0;
if (service_directory_) {
// Provide the child process with a restricted set of services.
options->paths_to_transfer.push_back(base::PathToTransfer{
- base::FilePath("/svc"), service_directory_->ConnectClient().release()});
+ base::FilePath("/svc"), service_directory_client_channel_.release()});
}
}
diff --git a/chromium/content/common/sandbox_policy_fuchsia.h b/chromium/content/common/sandbox_policy_fuchsia.h
index 0637e35ce91..e3ba8532a41 100644
--- a/chromium/content/common/sandbox_policy_fuchsia.h
+++ b/chromium/content/common/sandbox_policy_fuchsia.h
@@ -5,10 +5,14 @@
#ifndef CONTENT_COMMON_SANDBOX_POLICY_FUCHSIA_H_
#define CONTENT_COMMON_SANDBOX_POLICY_FUCHSIA_H_
+#include <lib/zx/channel.h>
+
+#include "base/memory/ref_counted.h"
#include "services/service_manager/sandbox/sandbox_type.h"
namespace base {
struct LaunchOptions;
+class SequencedTaskRunner;
namespace fuchsia {
class FilteredServiceDirectory;
@@ -38,6 +42,8 @@ class SandboxPolicyFuchsia {
// Services directory used for the /svc namespace of the child process.
std::unique_ptr<base::fuchsia::FilteredServiceDirectory> service_directory_;
+ zx::channel service_directory_client_channel_;
+ scoped_refptr<base::SequencedTaskRunner> service_directory_task_runner_;
};
} // namespace content
diff --git a/chromium/content/common/service_worker/controller_service_worker.mojom b/chromium/content/common/service_worker/controller_service_worker.mojom
index 8c5b5201ad1..901ffcb7c85 100644
--- a/chromium/content/common/service_worker/controller_service_worker.mojom
+++ b/chromium/content/common/service_worker/controller_service_worker.mojom
@@ -5,11 +5,11 @@
module content.mojom;
import "content/common/service_worker/service_worker.mojom";
-import "content/common/service_worker/service_worker_fetch_response_callback.mojom";
import "mojo/public/mojom/base/time.mojom";
import "services/network/public/mojom/url_loader.mojom";
import "third_party/blink/public/mojom/service_worker/dispatch_fetch_event_params.mojom";
import "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom";
+import "third_party/blink/public/mojom/service_worker/service_worker_fetch_response_callback.mojom";
import "third_party/blink/public/mojom/service_worker/service_worker_object.mojom";
import "third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom";
@@ -37,8 +37,9 @@ interface ControllerServiceWorker {
// handler ran and all outstanding respondWith() and waitUntil() promises have
// settled. |response_callback| is called once the promise to respondWith()
// settles, or when the event handler ran without calling respondWith().
- DispatchFetchEvent(blink.mojom.DispatchFetchEventParams params,
- ServiceWorkerFetchResponseCallback response_callback)
+ DispatchFetchEvent(
+ blink.mojom.DispatchFetchEventParams params,
+ blink.mojom.ServiceWorkerFetchResponseCallback response_callback)
=> (blink.mojom.ServiceWorkerEventStatus status,
mojo_base.mojom.Time dispatch_event_time);
diff --git a/chromium/content/common/service_worker/embedded_worker.mojom b/chromium/content/common/service_worker/embedded_worker.mojom
index b377941756e..adb7fbbce13 100644
--- a/chromium/content/common/service_worker/embedded_worker.mojom
+++ b/chromium/content/common/service_worker/embedded_worker.mojom
@@ -8,6 +8,9 @@ import "content/common/native_types.mojom";
import "content/common/service_worker/controller_service_worker.mojom";
import "content/common/service_worker/service_worker.mojom";
import "content/common/service_worker/service_worker_provider.mojom";
+import "content/common/url_loader_factory_bundle.mojom";
+import "content/public/common/renderer_preference_watcher.mojom";
+import "content/public/common/renderer_preferences.mojom";
import "mojo/public/mojom/base/string16.mojom";
import "mojo/public/mojom/base/time.mojom";
import "mojo/public/mojom/base/unguessable_token.mojom";
@@ -64,6 +67,12 @@ struct EmbeddedWorkerStartParams {
ServiceWorkerProviderInfoForStartWorker provider_info;
// Interface for the renderer to query the content settings in the browser.
blink.mojom.WorkerContentSettingsProxy content_settings_proxy;
+ // Interface for keeping track of the renderer preferences.
+ RendererPreferenceWatcher& preference_watcher_request;
+ // S13nServiceWorker: Used to load subresources in the service worker.
+ // This allows the service worker to load chrome-extension:// URLs which
+ // the renderer's default loader factory can't load.
+ URLLoaderFactoryBundle? subresource_loader_factories;
};
// Holds timing information about the start worker sequence for UMA.
@@ -84,6 +93,9 @@ struct EmbeddedWorkerStartTiming {
// EmbeddedWorkerInstanceHost. It allows control of a renderer-side
// embedded worker. The browser uses this interface to start, stop, and
// issue commands to the worker.
+//
+// This interface is the master interface of a dedicated message pipe. It has
+// some interfaces associated with it, like EmbeddedWorkerInstanceHost.
interface EmbeddedWorkerInstanceClient {
// Called back as various functions in EmbeddedWorkerInstanceHost, such
// as OnThreadStarted(), OnStarted().
@@ -98,21 +110,23 @@ interface EmbeddedWorkerInstanceClient {
};
// EmbeddedWorkerInstanceHost is the browser-side ("Host") of
-// EmbeddedWorkerInstanceClient. It allows control of a browser-side
-// embedded worker instance. The renderer uses this interface to report
-// embedded worker state back to the browser, or request termination of the
-// worker. This interface is associated with the EmbeddedWorkerInstanceClient
-// interface.
+// EmbeddedWorkerInstanceClient. It allows control of a browser-side embedded
+// worker instance. The renderer uses this interface to report embedded worker
+// state back to the browser, or request termination of the worker. This
+// interface is associated with the master interface
+// EmbeddedWorkerInstanceClient, so it lives on the same message pipe as
+// EmbeddedWorkerInstanceClient.
interface EmbeddedWorkerInstanceHost {
// S13nServiceWorker:
// Called when the worker requests to be terminated. The worker will request
// to be terminated when it realizes it has been idle for some time. The
- // request may be ignored, for example when there are inflight events issued
- // just before RequestTermination(). Note that the browser can terminate the
- // worker at any time even if RequestTermination() is not called. For example,
- // if the worker thread is continuously busy and the browser's periodic ping
- // message has been missed, the browser will terminate the service worker.
- RequestTermination();
+ // browser doesn't terminate the worker when there are inflight events or
+ // DevTools is attached, and in that case the callback will be called with
+ // false. Note that the browser can terminate the worker at any time even if
+ // RequestTermination() is not called. For example, if the worker thread is
+ // continuously busy and the browser's periodic ping message has been missed,
+ // the browser will terminate the service worker.
+ RequestTermination() => (bool will_be_terminated);
// Tells the browser process that this service worker used |feature|, for
// UseCounter purposes. The browser process propagates the feature usage bit
diff --git a/chromium/content/common/service_worker/service_worker.mojom b/chromium/content/common/service_worker/service_worker.mojom
index 03b78388227..a764a6023bc 100644
--- a/chromium/content/common/service_worker/service_worker.mojom
+++ b/chromium/content/common/service_worker/service_worker.mojom
@@ -4,44 +4,24 @@
module content.mojom;
-import "content/common/service_worker/service_worker_fetch_response_callback.mojom";
import "mojo/public/mojom/base/string16.mojom";
import "mojo/public/mojom/base/time.mojom";
import "services/network/public/mojom/cookie_manager.mojom";
-import "third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom";
-import "third_party/blink/public/platform/modules/payments/payment_app.mojom";
+import "third_party/blink/public/mojom/fetch/fetch_api_response.mojom";
import "third_party/blink/public/mojom/message_port/message_port.mojom";
+import "third_party/blink/public/mojom/payments/payment_app.mojom";
import "third_party/blink/public/mojom/service_worker/dispatch_fetch_event_params.mojom";
import "third_party/blink/public/mojom/service_worker/service_worker.mojom";
import "third_party/blink/public/mojom/service_worker/service_worker_client.mojom";
import "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom";
+import "third_party/blink/public/mojom/service_worker/service_worker_fetch_response_callback.mojom";
import "third_party/blink/public/mojom/service_worker/service_worker_object.mojom";
import "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom";
+import "third_party/blink/public/platform/modules/background_fetch/background_fetch.mojom";
+import "third_party/blink/public/platform/modules/notifications/notification.mojom";
import "url/mojom/origin.mojom";
import "url/mojom/url.mojom";
-[Native]
-struct PlatformNotificationData;
-
-[Native]
-struct PushEventPayload;
-
-[Native]
-struct ServiceWorkerResponse;
-
-// TODO(peter): Move this to Blink when ServiceWorkerResponse has a Mojo
-// counterpart.
-struct BackgroundFetchSettledFetch {
- blink.mojom.FetchAPIRequest request;
- ServiceWorkerResponse response;
-};
-
-enum BackgroundFetchState {
- PENDING,
- SUCCEEDED,
- FAILED
-};
-
struct ExtendableMessageEvent {
blink.mojom.TransferableMessage message;
url.mojom.Origin source_origin;
@@ -105,23 +85,20 @@ interface ServiceWorker {
// The callbacks are called once the event handler has run and waitUntil()
// promise has settled. |developer_id| and |unique_id| are documented in
// content::BackgroundFetchRegistrationId.
- DispatchBackgroundFetchAbortEvent(string developer_id,
- string unique_id,
- array<BackgroundFetchSettledFetch> fetches)
+ DispatchBackgroundFetchAbortEvent(
+ blink.mojom.BackgroundFetchRegistration registration)
=> (blink.mojom.ServiceWorkerEventStatus status,
mojo_base.mojom.Time dispatch_event_time);
- DispatchBackgroundFetchClickEvent(string developer_id,
- BackgroundFetchState state)
+ DispatchBackgroundFetchClickEvent(
+ blink.mojom.BackgroundFetchRegistration registration)
=> (blink.mojom.ServiceWorkerEventStatus status,
mojo_base.mojom.Time dispatch_event_time);
- DispatchBackgroundFetchFailEvent(string developer_id,
- string unique_id,
- array<BackgroundFetchSettledFetch> fetches)
+ DispatchBackgroundFetchFailEvent(
+ blink.mojom.BackgroundFetchRegistration registration)
=> (blink.mojom.ServiceWorkerEventStatus status,
mojo_base.mojom.Time dispatch_event_time);
- DispatchBackgroundFetchedEvent(string developer_id,
- string unique_id,
- array<BackgroundFetchSettledFetch> fetches)
+ DispatchBackgroundFetchSuccessEvent(
+ blink.mojom.BackgroundFetchRegistration registration)
=> (blink.mojom.ServiceWorkerEventStatus status,
mojo_base.mojom.Time dispatch_event_time);
@@ -140,22 +117,27 @@ interface ServiceWorker {
// waitUntil() promises have settled. |response_callback| is called once the
// promise to respondWith() settles, or when the event handler ran without
// calling respondWith().
- DispatchFetchEvent(blink.mojom.DispatchFetchEventParams params,
- ServiceWorkerFetchResponseCallback response_callback)
+ DispatchFetchEvent(
+ blink.mojom.DispatchFetchEventParams params,
+ blink.mojom.ServiceWorkerFetchResponseCallback response_callback)
=> (blink.mojom.ServiceWorkerEventStatus status,
mojo_base.mojom.Time dispatch_event_time);
- DispatchNotificationClickEvent(string notification_id,
- PlatformNotificationData notification_data,
- int32 action_index,
- mojo_base.mojom.String16? reply)
+ DispatchNotificationClickEvent(
+ string notification_id,
+ blink.mojom.NotificationData notification_data,
+ int32 action_index,
+ mojo_base.mojom.String16? reply)
=> (blink.mojom.ServiceWorkerEventStatus status,
mojo_base.mojom.Time dispatch_event_time);
- DispatchNotificationCloseEvent(string notification_id,
- PlatformNotificationData notification_data)
+ DispatchNotificationCloseEvent(
+ string notification_id,
+ blink.mojom.NotificationData notification_data)
=> (blink.mojom.ServiceWorkerEventStatus status,
mojo_base.mojom.Time dispatch_event_time);
- DispatchPushEvent(PushEventPayload payload)
+ // The payload of a push message can be valid with content, valid with empty
+ // content, or null.
+ DispatchPushEvent(string? payload)
=> (blink.mojom.ServiceWorkerEventStatus status,
mojo_base.mojom.Time dispatch_event_time);
// Arguments are passed to the event handler as parameters of SyncEvent.
@@ -186,6 +168,13 @@ interface ServiceWorker {
=> (blink.mojom.ServiceWorkerEventStatus status,
mojo_base.mojom.Time dispatch_event_time);
+ // TODO(crbug.com/869714): Remove this code for long living service workers
+ // when Android Messages no longer requires it.
+ DispatchExtendableMessageEventWithCustomTimeout(ExtendableMessageEvent event,
+ mojo_base.mojom.TimeDelta timeout)
+ => (blink.mojom.ServiceWorkerEventStatus status,
+ mojo_base.mojom.Time dispatch_event_time);
+
// Pings the service worker to check if it is responsive. If the callback is
// not called within a certain period of time, the browser will terminate the
// worker.
diff --git a/chromium/content/common/service_worker/service_worker.typemap b/chromium/content/common/service_worker/service_worker.typemap
deleted file mode 100644
index e64c14e9c3d..00000000000
--- a/chromium/content/common/service_worker/service_worker.typemap
+++ /dev/null
@@ -1,23 +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.
-
-mojom = "//content/common/service_worker/service_worker.mojom"
-public_headers = [
- "//content/common/background_fetch/background_fetch_types.h",
- "//third_party/blink/public/common/service_worker/service_worker_status_code.h",
- "//content/common/service_worker/service_worker_types.h",
- "//content/public/common/platform_notification_data.h",
- "//content/public/common/push_event_payload.h",
-]
-traits_headers = [
- "//content/common/platform_notification_param_traits.h",
- "//content/common/service_worker/service_worker_messages.h",
-]
-type_mappings = [
- "content.mojom.ExtendableMessageEventSource=::content::ExtendableMessageEventSource",
- "content.mojom.PlatformNotificationData=::content::PlatformNotificationData",
- "content.mojom.PushEventPayload=::content::PushEventPayload",
- "content.mojom.ServiceWorkerFetchRequest=::content::ServiceWorkerFetchRequest",
- "content.mojom.ServiceWorkerResponse=::content::ServiceWorkerResponse",
-]
diff --git a/chromium/content/common/service_worker/service_worker_container.mojom b/chromium/content/common/service_worker/service_worker_container.mojom
index b7bae47af99..b8d4e2fe4cd 100644
--- a/chromium/content/common/service_worker/service_worker_container.mojom
+++ b/chromium/content/common/service_worker/service_worker_container.mojom
@@ -19,9 +19,25 @@ enum ControllerServiceWorkerPurpose {
FETCH_SUB_RESOURCE
};
-// mojom::ServiceWorkerContainerHost is a browser-side interface. The renderer
-// process uses this interface to request the browser process to do operations
-// involving service worker registrations.
+// ServiceWorkerContainerHost is an interface implemented by the browser
+// process. The renderer process uses this interface to request the browser
+// process to do operations involving service worker registrations.
+//
+// This interface is associated with its counterpart ServiceWorkerContainer.
+// The message pipe it's used on depends on the container type.
+// - For service workers:
+// Associated with EmbeddedWorkerInstanceClient, which is on a dedicated
+// message pipe.
+// - For shared workers (S13nSW):
+// Associated with SharedWorkerFactory, which is on a dedicated message
+// pipe.
+// - For shared workers (non-S13nSW):
+// Associated with ServiceWorkerDispatcherHost, which is on the
+// channel-associated interface to the renderer process.
+// IPC channel.
+// - For documents:
+// Associated with ServiceWorkerDispatcherHost, which is on the
+// channel-associated interface to the renderer process.
interface ServiceWorkerContainerHost {
// Corresponds to navigator.serviceWorker.register().
// Registers a service worker from |script_url| with |options|.
@@ -93,9 +109,9 @@ interface ServiceWorkerContainerHost {
HintToUpdateServiceWorker();
};
-// mojom::ServiceWorkerContainer is a renderer-side interface.
-// The browser process uses this interface to send messages to documents or
-// the service worker.
+// ServiceWorkerContainer is an interface implemented by the renderer process.
+// The browser process uses this interface to send messages to documents or the
+// service worker.
//
// Roughly corresponds to the web-exposed ServiceWorkerContainer interface,
// i.e., navigator.serviceWorker. Actually, the plan is for this interface to be
@@ -105,6 +121,11 @@ interface ServiceWorkerContainerHost {
// implement navigator.serviceWorker for Worker yet. But eventually anything
// that can touch these objects should be a ServiceWorkerContainer, so it’s OK
// to use this name.
+//
+// This interface is associated with its counterpart,
+// ServiceWorkerContainerHost, as they are sent on the same master interface
+// together. See ServiceWorkerContainerHost for documentation about the message
+// pipe they live on.
interface ServiceWorkerContainer {
// Corresponds to setting ServiceWorkerContainer#controller.
// If |controller_info| is invalid (its |object_info| is null), then
diff --git a/chromium/content/common/service_worker/service_worker_fetch_request.typemap b/chromium/content/common/service_worker/service_worker_fetch_request.typemap
index 013db542c01..70e608f8207 100644
--- a/chromium/content/common/service_worker/service_worker_fetch_request.typemap
+++ b/chromium/content/common/service_worker/service_worker_fetch_request.typemap
@@ -7,8 +7,6 @@ mojom =
public_headers = [
"//content/common/service_worker/service_worker_types.h",
"//content/public/common/request_context_type.h",
- "//storage/common/blob_storage/blob_handle.h",
- "//storage/common/storage_common_export.h",
]
traits_headers = [
"//content/common/service_worker/service_worker_fetch_request_mojom_traits.h",
@@ -19,5 +17,4 @@ sources = [
type_mappings = [
"blink.mojom.FetchAPIRequest=::content::ServiceWorkerFetchRequest",
"blink.mojom.RequestContextType=::content::RequestContextType",
- "blink.mojom.ServiceWorkerFetchType=::content::ServiceWorkerFetchType",
]
diff --git a/chromium/content/common/service_worker/service_worker_fetch_response.typemap b/chromium/content/common/service_worker/service_worker_fetch_response.typemap
deleted file mode 100644
index 60c7e5d5aa3..00000000000
--- a/chromium/content/common/service_worker/service_worker_fetch_response.typemap
+++ /dev/null
@@ -1,13 +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.
-
-mojom =
- "//third_party/blink/public/platform/modules/fetch/fetch_api_response.mojom"
-public_headers = [ "//content/common/service_worker/service_worker_types.h" ]
-traits_headers = [ "//content/common/service_worker/service_worker_fetch_response_mojom_traits.h" ]
-sources = [
- "//content/common/service_worker/service_worker_fetch_response_mojom_traits.cc",
-]
-type_mappings =
- [ "blink.mojom.FetchAPIResponse=::content::ServiceWorkerResponse" ]
diff --git a/chromium/content/common/service_worker/service_worker_fetch_response_callback.mojom b/chromium/content/common/service_worker/service_worker_fetch_response_callback.mojom
deleted file mode 100644
index 43f64fba119..00000000000
--- a/chromium/content/common/service_worker/service_worker_fetch_response_callback.mojom
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-module content.mojom;
-
-import "mojo/public/mojom/base/time.mojom";
-import "third_party/blink/public/mojom/blob/blob.mojom";
-import "third_party/blink/public/mojom/service_worker/service_worker_stream_handle.mojom";
-
-[Native]
-struct ServiceWorkerResponse;
-
-// Callback interface which is passed to a controller service worker through
-// DispatchFetchEvent (either via ServiceWorker or via ControllerServiceWorker
-// interface).
-// The receiver service worker uses this interface to respond to a fetch event.
-interface ServiceWorkerFetchResponseCallback {
- // Responds to the request with |response|. The body is empty.
- OnResponse(ServiceWorkerResponse response,
- mojo_base.mojom.Time dispatch_event_time);
- // Responds to the request with |response|. The body is returned as a blob.
- // TODO(kinuko): This should not be necessary once we properly support
- // transferring blob within |response|. See crbug.com/75523 for more details.
- OnResponseBlob(ServiceWorkerResponse response,
- blink.mojom.Blob body_as_blob,
- mojo_base.mojom.Time dispatch_event_time);
- // Responds to the request with |response|. The body is returned as a stream.
- OnResponseStream(ServiceWorkerResponse response,
- blink.mojom.ServiceWorkerStreamHandle body_as_stream,
- mojo_base.mojom.Time dispatch_event_time);
- // Provides no response to the request. The callee should fall back to the
- // network.
- OnFallback(mojo_base.mojom.Time dispatch_event_time);
-};
diff --git a/chromium/content/common/service_worker/service_worker_fetch_response_mojom_traits.cc b/chromium/content/common/service_worker/service_worker_fetch_response_mojom_traits.cc
deleted file mode 100644
index 64a9ed1b85f..00000000000
--- a/chromium/content/common/service_worker/service_worker_fetch_response_mojom_traits.cc
+++ /dev/null
@@ -1,63 +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/common/service_worker/service_worker_fetch_response_mojom_traits.h"
-
-#include <map>
-#include <string>
-#include <unordered_map>
-#include <utility>
-#include <vector>
-
-#include "base/memory/scoped_refptr.h"
-#include "content/common/service_worker/service_worker_types.h"
-#include "content/public/common/referrer_struct_traits.h"
-#include "ipc/ipc_message_utils.h"
-#include "mojo/public/cpp/base/time_mojom_traits.h"
-#include "url/mojom/url_gurl_mojom_traits.h"
-
-namespace mojo {
-
-bool StructTraits<blink::mojom::FetchAPIResponseDataView,
- content::ServiceWorkerResponse>::
- Read(blink::mojom::FetchAPIResponseDataView data,
- content::ServiceWorkerResponse* out) {
- blink::mojom::SerializedBlobPtr serialized_blob_ptr;
- blink::mojom::SerializedBlobPtr serialized_side_data_blob_ptr;
- if (!data.ReadUrlList(&out->url_list) ||
- !data.ReadStatusText(&out->status_text) ||
- !data.ReadResponseType(&out->response_type) ||
- !data.ReadHeaders(&out->headers) ||
- !data.ReadBlob(&serialized_blob_ptr) || !data.ReadError(&out->error) ||
- !data.ReadResponseTime(&out->response_time) ||
- !data.ReadCacheStorageCacheName(&out->cache_storage_cache_name) ||
- !data.ReadCorsExposedHeaderNames(&out->cors_exposed_header_names) ||
- !data.ReadSideDataBlob(&serialized_side_data_blob_ptr)) {
- return false;
- }
-
- out->status_code = data.status_code();
- out->is_in_cache_storage = data.is_in_cache_storage();
-
- if (serialized_blob_ptr) {
- out->blob_uuid = serialized_blob_ptr->uuid;
- out->blob_size = serialized_blob_ptr->size;
- blink::mojom::BlobPtr blob_ptr;
- blob_ptr.Bind(std::move(serialized_blob_ptr->blob));
- out->blob = base::MakeRefCounted<storage::BlobHandle>(std::move(blob_ptr));
- }
-
- if (serialized_side_data_blob_ptr) {
- out->side_data_blob_uuid = serialized_side_data_blob_ptr->uuid;
- out->side_data_blob_size = serialized_side_data_blob_ptr->size;
- blink::mojom::BlobPtr blob_ptr;
- blob_ptr.Bind(std::move(serialized_side_data_blob_ptr->blob));
- out->side_data_blob =
- base::MakeRefCounted<storage::BlobHandle>(std::move(blob_ptr));
- }
-
- return true;
-}
-
-} // namespace mojo
diff --git a/chromium/content/common/service_worker/service_worker_fetch_response_mojom_traits.h b/chromium/content/common/service_worker/service_worker_fetch_response_mojom_traits.h
deleted file mode 100644
index 287ac17b670..00000000000
--- a/chromium/content/common/service_worker/service_worker_fetch_response_mojom_traits.h
+++ /dev/null
@@ -1,94 +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_COMMON_SERVICE_WORKER_SERVICE_WORKER_FETCH_RESPONSE_MOJOM_TRAITS_H_
-#define CONTENT_COMMON_SERVICE_WORKER_SERVICE_WORKER_FETCH_RESPONSE_MOJOM_TRAITS_H_
-
-#include <map>
-#include <string>
-#include <vector>
-
-#include "base/numerics/safe_conversions.h"
-#include "content/common/content_export.h"
-#include "content/common/service_worker/service_worker_types.h"
-#include "third_party/blink/public/mojom/blob/blob.mojom.h"
-#include "third_party/blink/public/platform/modules/fetch/fetch_api_response.mojom.h"
-
-namespace mojo {
-
-template <>
-struct CONTENT_EXPORT StructTraits<blink::mojom::FetchAPIResponseDataView,
- content::ServiceWorkerResponse> {
- static const std::vector<GURL>& url_list(
- const content::ServiceWorkerResponse& response) {
- return response.url_list;
- }
- static int status_code(const content::ServiceWorkerResponse& response) {
- return response.status_code;
- }
- static bool is_in_cache_storage(
- const content::ServiceWorkerResponse& response) {
- return response.is_in_cache_storage;
- }
- static blink::mojom::SerializedBlobPtr blob(
- const content::ServiceWorkerResponse& response) {
- if (response.blob) {
- blink::mojom::SerializedBlobPtr serialized_blob_ptr =
- blink::mojom::SerializedBlob::New();
- serialized_blob_ptr->uuid = response.blob_uuid;
- serialized_blob_ptr->size = response.blob_size;
- serialized_blob_ptr->blob = response.blob->Clone().PassInterface();
- return serialized_blob_ptr;
- }
- return nullptr;
- }
- static const std::string& status_text(
- const content::ServiceWorkerResponse& response) {
- return response.status_text;
- }
- static network::mojom::FetchResponseType response_type(
- const content::ServiceWorkerResponse& response) {
- return response.response_type;
- }
- static std::map<std::string,
- std::string,
- content::ServiceWorkerCaseInsensitiveCompare>
- headers(const content::ServiceWorkerResponse& response) {
- return response.headers;
- }
- static blink::mojom::ServiceWorkerResponseError error(
- const content::ServiceWorkerResponse& response) {
- return response.error;
- }
- static const base::Time& response_time(
- const content::ServiceWorkerResponse& response) {
- return response.response_time;
- }
- static const std::string& cache_storage_cache_name(
- const content::ServiceWorkerResponse& response) {
- return response.cache_storage_cache_name;
- }
- static const std::vector<std::string>& cors_exposed_header_names(
- const content::ServiceWorkerResponse& response) {
- return response.cors_exposed_header_names;
- }
- static blink::mojom::SerializedBlobPtr side_data_blob(
- const content::ServiceWorkerResponse& response) {
- if (response.side_data_blob) {
- blink::mojom::SerializedBlobPtr serialized_blob_ptr =
- blink::mojom::SerializedBlob::New();
- serialized_blob_ptr->uuid = response.side_data_blob_uuid;
- serialized_blob_ptr->size = response.side_data_blob_size;
- serialized_blob_ptr->blob =
- response.side_data_blob->Clone().PassInterface();
- return serialized_blob_ptr;
- }
- return nullptr;
- }
- static bool Read(blink::mojom::FetchAPIResponseDataView,
- content::ServiceWorkerResponse* output);
-};
-
-} // namespace mojo
-
-#endif // CONTENT_COMMON_SERVICE_WORKER_SERVICE_WORKER_FETCH_RESPONSE_MOJOM_TRAITS_H_
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 b01b6825bcf..7b3949594f8 100644
--- a/chromium/content/common/service_worker/service_worker_loader_helpers.cc
+++ b/chromium/content/common/service_worker/service_worker_loader_helpers.cc
@@ -5,11 +5,13 @@
#include "content/common/service_worker/service_worker_loader_helpers.h"
#include <memory>
+#include <string>
#include <utility>
+#include <vector>
#include "base/strings/stringprintf.h"
-#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/common/content_features.h"
+#include "content/public/common/resource_type.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "net/http/http_util.h"
#include "services/network/loader_util.h"
@@ -40,13 +42,65 @@ class BlobCompleteCaller : public blink::mojom::BlobReaderClient {
BlobCompleteCallback callback_;
};
+// Sets |has_range_out| to true if |headers| specify a single range request, and
+// |offset_out| and |size_out| to the range. Returns true on valid input
+// (regardless of |has_range_out|), and false if there is more than one range or
+// if the bounds overflow.
+bool ExtractSinglePartHttpRange(const net::HttpRequestHeaders& headers,
+ bool* has_range_out,
+ uint64_t* offset_out,
+ uint64_t* length_out) {
+ std::string range_header;
+ *has_range_out = false;
+ if (!headers.GetHeader(net::HttpRequestHeaders::kRange, &range_header))
+ return true;
+
+ std::vector<net::HttpByteRange> ranges;
+ if (!net::HttpUtil::ParseRangeHeader(range_header, &ranges))
+ return true;
+
+ // Multi-part (or invalid) ranges are not supported.
+ if (ranges.size() != 1)
+ return false;
+
+ // Safely parse the single range to our more-sane output format.
+ *has_range_out = true;
+ const net::HttpByteRange& byte_range = ranges[0];
+ if (byte_range.first_byte_position() < 0)
+ return false;
+ // Allow the range [0, -1] to be valid and specify the entire range.
+ if (byte_range.first_byte_position() == 0 &&
+ byte_range.last_byte_position() == -1) {
+ *has_range_out = false;
+ return true;
+ }
+ if (byte_range.last_byte_position() < 0)
+ return false;
+
+ uint64_t first_byte_position =
+ static_cast<uint64_t>(byte_range.first_byte_position());
+ uint64_t last_byte_position =
+ static_cast<uint64_t>(byte_range.last_byte_position());
+
+ base::CheckedNumeric<uint64_t> length = last_byte_position;
+ length -= first_byte_position;
+ length += 1;
+
+ if (!length.IsValid())
+ return false;
+
+ *offset_out = static_cast<uint64_t>(byte_range.first_byte_position());
+ *length_out = length.ValueOrDie();
+ return true;
+}
+
} // namespace
// static
void ServiceWorkerLoaderHelpers::SaveResponseHeaders(
const int status_code,
const std::string& status_text,
- const ServiceWorkerHeaderMap& headers,
+ const base::flat_map<std::string, std::string>& headers,
network::ResourceResponseHead* out_head) {
// Build a string instead of using HttpResponseHeaders::AddHeader on
// each header, since AddHeader has O(n^2) performance.
@@ -64,15 +118,11 @@ void ServiceWorkerLoaderHelpers::SaveResponseHeaders(
net::HttpUtil::AssembleRawHeaders(buf.c_str(), buf.size()));
// Populate |out_head|'s MIME type with the value from the HTTP response
- // headers. If there is none, set a default value.
- // TODO(crbug.com/771118): Make the MIME sniffer work for SW controlled page
- // loads, so we don't need to set a simple default value.
+ // headers.
if (out_head->mime_type.empty()) {
std::string mime_type;
- out_head->headers->GetMimeType(&mime_type);
- if (mime_type.empty())
- mime_type = "text/plain";
- out_head->mime_type = mime_type;
+ if (out_head->headers->GetMimeType(&mime_type))
+ out_head->mime_type = mime_type;
}
// Populate |out_head|'s charset with the value from the HTTP response
@@ -86,15 +136,18 @@ void ServiceWorkerLoaderHelpers::SaveResponseHeaders(
// static
void ServiceWorkerLoaderHelpers::SaveResponseInfo(
- const ServiceWorkerResponse& response,
+ const blink::mojom::FetchAPIResponse& response,
network::ResourceResponseHead* out_head) {
out_head->was_fetched_via_service_worker = true;
out_head->was_fallback_required_by_service_worker = false;
out_head->url_list_via_service_worker = response.url_list;
- out_head->response_type_via_service_worker = response.response_type;
+ out_head->response_type = response.response_type;
out_head->response_time = response.response_time;
out_head->is_in_cache_storage = response.is_in_cache_storage;
- out_head->cache_storage_cache_name = response.cache_storage_cache_name;
+ if (response.cache_storage_cache_name)
+ out_head->cache_storage_cache_name = *(response.cache_storage_cache_name);
+ else
+ out_head->cache_storage_cache_name.clear();
out_head->cors_exposed_header_names = response.cors_exposed_header_names;
out_head->did_service_worker_navigation_preload = false;
}
@@ -136,8 +189,7 @@ int ServiceWorkerLoaderHelpers::ReadBlobResponseBody(
// We don't support multiple range requests in one single URL request,
// because we need to do multipart encoding here.
// TODO(falken): Support multipart byte range requests.
- if (!ServiceWorkerUtils::ExtractSinglePartHttpRange(headers, &byte_range_set,
- &offset, &length)) {
+ if (!ExtractSinglePartHttpRange(headers, &byte_range_set, &offset, &length)) {
return net::ERR_REQUEST_RANGE_NOT_SATISFIABLE;
}
diff --git a/chromium/content/common/service_worker/service_worker_loader_helpers.h b/chromium/content/common/service_worker/service_worker_loader_helpers.h
index a709385b4f2..89d36f1facc 100644
--- a/chromium/content/common/service_worker/service_worker_loader_helpers.h
+++ b/chromium/content/common/service_worker/service_worker_loader_helpers.h
@@ -5,11 +5,12 @@
#ifndef CONTENT_COMMON_SERVICE_WORKER_SERVICE_WORKER_LOADER_HELPERS_H_
#define CONTENT_COMMON_SERVICE_WORKER_SERVICE_WORKER_LOADER_HELPERS_H_
+#include "base/containers/flat_map.h"
#include "base/optional.h"
-#include "content/common/service_worker/service_worker_types.h"
#include "net/http/http_request_headers.h"
#include "net/url_request/redirect_info.h"
#include "third_party/blink/public/mojom/blob/blob.mojom.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_response.mojom.h"
namespace network {
struct ResourceRequest;
@@ -24,12 +25,13 @@ class ServiceWorkerLoaderHelpers {
public:
// Populates |out_head->headers| with the given |status_code|, |status_text|,
// and |headers|.
- static void SaveResponseHeaders(const int status_code,
- const std::string& status_text,
- const ServiceWorkerHeaderMap& headers,
- network::ResourceResponseHead* out_head);
+ static void SaveResponseHeaders(
+ const int status_code,
+ const std::string& status_text,
+ const base::flat_map<std::string, std::string>& headers,
+ network::ResourceResponseHead* out_head);
// Populates |out_head| (except for headers) with given |response|.
- static void SaveResponseInfo(const ServiceWorkerResponse& response,
+ static void SaveResponseInfo(const blink::mojom::FetchAPIResponse& response,
network::ResourceResponseHead* out_head);
// Returns a redirect info if |response_head| is an redirect response.
diff --git a/chromium/content/common/service_worker/service_worker_messages.h b/chromium/content/common/service_worker/service_worker_messages.h
deleted file mode 100644
index 3fa8620e6e5..00000000000
--- a/chromium/content/common/service_worker/service_worker_messages.h
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_SERVICE_WORKER_SERVICE_WORKER_MESSAGES_H_
-#define CONTENT_COMMON_SERVICE_WORKER_SERVICE_WORKER_MESSAGES_H_
-
-#include <stdint.h>
-
-#include <string>
-#include <vector>
-
-#include "base/strings/string16.h"
-#include "base/time/time.h"
-#include "content/common/service_worker/service_worker_types.h"
-#include "content/public/common/platform_notification_data.h"
-#include "content/public/common/push_event_payload.h"
-#include "ipc/ipc_message_macros.h"
-#include "ipc/ipc_param_traits.h"
-#include "services/network/public/mojom/fetch_api.mojom.h"
-#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
-#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_error.h"
-
-#undef IPC_MESSAGE_EXPORT
-#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
-
-#define IPC_MESSAGE_START ServiceWorkerMsgStart
-
-// TODO(leonhsl): Figure out what's the purpose of all these traits then
-// eliminate this file finally.
-IPC_ENUM_TRAITS_MAX_VALUE(blink::mojom::ServiceWorkerResponseError,
- blink::mojom::ServiceWorkerResponseError::kMaxValue)
-
-IPC_STRUCT_TRAITS_BEGIN(content::ServiceWorkerFetchRequest)
- IPC_STRUCT_TRAITS_MEMBER(mode)
- IPC_STRUCT_TRAITS_MEMBER(is_main_resource_load)
- IPC_STRUCT_TRAITS_MEMBER(request_context_type)
- IPC_STRUCT_TRAITS_MEMBER(frame_type)
- IPC_STRUCT_TRAITS_MEMBER(url)
- IPC_STRUCT_TRAITS_MEMBER(method)
- IPC_STRUCT_TRAITS_MEMBER(headers)
- IPC_STRUCT_TRAITS_MEMBER(referrer)
- IPC_STRUCT_TRAITS_MEMBER(credentials_mode)
- IPC_STRUCT_TRAITS_MEMBER(redirect_mode)
- IPC_STRUCT_TRAITS_MEMBER(integrity)
- IPC_STRUCT_TRAITS_MEMBER(keepalive)
- IPC_STRUCT_TRAITS_MEMBER(client_id)
- IPC_STRUCT_TRAITS_MEMBER(is_reload)
-IPC_STRUCT_TRAITS_END()
-
-IPC_STRUCT_TRAITS_BEGIN(content::ServiceWorkerResponse)
- IPC_STRUCT_TRAITS_MEMBER(url_list)
- IPC_STRUCT_TRAITS_MEMBER(status_code)
- IPC_STRUCT_TRAITS_MEMBER(status_text)
- IPC_STRUCT_TRAITS_MEMBER(response_type)
- IPC_STRUCT_TRAITS_MEMBER(headers)
- IPC_STRUCT_TRAITS_MEMBER(blob_uuid)
- IPC_STRUCT_TRAITS_MEMBER(blob_size)
- IPC_STRUCT_TRAITS_MEMBER(blob)
- IPC_STRUCT_TRAITS_MEMBER(error)
- IPC_STRUCT_TRAITS_MEMBER(response_time)
- IPC_STRUCT_TRAITS_MEMBER(is_in_cache_storage)
- IPC_STRUCT_TRAITS_MEMBER(cache_storage_cache_name)
- IPC_STRUCT_TRAITS_MEMBER(cors_exposed_header_names)
- IPC_STRUCT_TRAITS_MEMBER(side_data_blob_uuid)
- IPC_STRUCT_TRAITS_MEMBER(side_data_blob_size)
- IPC_STRUCT_TRAITS_MEMBER(side_data_blob)
-IPC_STRUCT_TRAITS_END()
-
-IPC_STRUCT_TRAITS_BEGIN(content::PushEventPayload)
- IPC_STRUCT_TRAITS_MEMBER(data)
- IPC_STRUCT_TRAITS_MEMBER(is_null)
-IPC_STRUCT_TRAITS_END()
-
-#endif // CONTENT_COMMON_SERVICE_WORKER_SERVICE_WORKER_MESSAGES_H_
diff --git a/chromium/content/common/service_worker/service_worker_provider.mojom b/chromium/content/common/service_worker/service_worker_provider.mojom
index 1ac547c5547..d3ae678faa4 100644
--- a/chromium/content/common/service_worker/service_worker_provider.mojom
+++ b/chromium/content/common/service_worker/service_worker_provider.mojom
@@ -95,13 +95,9 @@ struct ServiceWorkerProviderHostInfo {
};
// ServiceWorkerWorkerClient represents a service worker client that is a worker
-// (i.e., a shared worker or dedicated worker). We use this interface to let the
-// WebWorkerFetchContextImpl in the worker thread know about the change of
-// controlling service worker by calling OnControllerChanged() from the
-// ServiceWorkerProviderContext in the main thread of the renderer process.
-//
-// TODO(horo): We should implement ServiceWorkerProvider in the worker thread
-// instead of using this interface to support WorkerNavigator.serviceWorker.
+// (i.e., a shared worker or dedicated worker). The main thread of
+// the renderer process uses this interface to tell the worker thread
+// when the controller service worker changes.
interface ServiceWorkerWorkerClient {
// Called when the worker is controlled by a new service worker. This is only
// used to let the worker know that we now have a service worker (while there
@@ -124,9 +120,12 @@ interface ServiceWorkerWorkerClientRegistry {
CloneWorkerClientRegistry(ServiceWorkerWorkerClientRegistry& host);
};
-// Per-process browser-side interface.
-// The renderer uses this interface to tell the browser when potential service
-// worker clients are created and when service workers are starting up.
+// An interface implemented by the browser process, with one implementation per
+// renderer process. The renderer uses this interface to tell the browser when
+// potential service worker clients are created.
+//
+// This interface is on the channel-associated interface to the renderer
+// process.
interface ServiceWorkerDispatcherHost {
// Creates a content::ServiceWorkerProviderHost on the browser
// process. |provider_info| has Mojo endpoints to connect the container host
diff --git a/chromium/content/common/service_worker/service_worker_types.cc b/chromium/content/common/service_worker/service_worker_types.cc
index 598a7df25d8..c8c98cd9ed3 100644
--- a/chromium/content/common/service_worker/service_worker_types.cc
+++ b/chromium/content/common/service_worker/service_worker_types.cc
@@ -156,63 +156,4 @@ ServiceWorkerFetchRequest::GetCacheModeFromLoadFlags(int load_flags) {
return blink::mojom::FetchCacheMode::kDefault;
}
-ServiceWorkerResponse::ServiceWorkerResponse()
- : status_code(0),
- response_type(network::mojom::FetchResponseType::kOpaque),
- blob_size(0),
- error(blink::mojom::ServiceWorkerResponseError::kUnknown) {}
-
-ServiceWorkerResponse::ServiceWorkerResponse(
- std::unique_ptr<std::vector<GURL>> url_list,
- int status_code,
- const std::string& status_text,
- network::mojom::FetchResponseType response_type,
- std::unique_ptr<ServiceWorkerHeaderMap> headers,
- const std::string& blob_uuid,
- uint64_t blob_size,
- scoped_refptr<storage::BlobHandle> blob,
- blink::mojom::ServiceWorkerResponseError error,
- base::Time response_time,
- bool is_in_cache_storage,
- const std::string& cache_storage_cache_name,
- std::unique_ptr<ServiceWorkerHeaderList> cors_exposed_headers)
- : status_code(status_code),
- status_text(status_text),
- response_type(response_type),
- blob_uuid(blob_uuid),
- blob_size(blob_size),
- blob(std::move(blob)),
- error(error),
- response_time(response_time),
- is_in_cache_storage(is_in_cache_storage),
- cache_storage_cache_name(cache_storage_cache_name) {
- this->url_list.swap(*url_list);
- this->headers.swap(*headers);
- this->cors_exposed_header_names.swap(*cors_exposed_headers);
-}
-
-ServiceWorkerResponse::ServiceWorkerResponse(
- const ServiceWorkerResponse& other) = default;
-
-ServiceWorkerResponse& ServiceWorkerResponse::operator=(
- const ServiceWorkerResponse& other) = default;
-
-ServiceWorkerResponse::~ServiceWorkerResponse() {}
-
-size_t ServiceWorkerResponse::EstimatedStructSize() {
- size_t size = sizeof(ServiceWorkerResponse);
- for (const auto& url : url_list)
- size += url.spec().size();
- size += blob_uuid.size();
- size += cache_storage_cache_name.size();
- for (const auto& key_and_value : headers) {
- size += key_and_value.first.size();
- size += key_and_value.second.size();
- }
- for (const auto& header : cors_exposed_header_names)
- size += header.size();
- size += side_data_blob_uuid.size();
- return size;
-}
-
} // namespace content
diff --git a/chromium/content/common/service_worker/service_worker_types.h b/chromium/content/common/service_worker/service_worker_types.h
index cdcade92d1d..99f262fce6e 100644
--- a/chromium/content/common/service_worker/service_worker_types.h
+++ b/chromium/content/common/service_worker/service_worker_types.h
@@ -121,62 +121,6 @@ struct CONTENT_EXPORT ServiceWorkerFetchRequest {
bool is_history_navigation = false;
};
-// Roughly corresponds to the Fetch API's Response type. This struct has several
-// users:
-// - Service Worker API: The renderer sends the browser this type to
-// represent the response a service worker provided to FetchEvent#respondWith.
-// - Background Fetch API: Uses this type to represent responses to background
-// fetches.
-// - Cache Storage API: Uses this type to represent responses to requests.
-// Note that the Fetch API does not use this type; it uses ResourceResponse
-// instead.
-// TODO(falken): Can everyone just use ResourceResponse?
-struct CONTENT_EXPORT ServiceWorkerResponse {
- ServiceWorkerResponse();
- ServiceWorkerResponse(
- std::unique_ptr<std::vector<GURL>> url_list,
- int status_code,
- const std::string& status_text,
- network::mojom::FetchResponseType response_type,
- std::unique_ptr<ServiceWorkerHeaderMap> headers,
- const std::string& blob_uuid,
- uint64_t blob_size,
- scoped_refptr<storage::BlobHandle> blob,
- blink::mojom::ServiceWorkerResponseError error,
- base::Time response_time,
- bool is_in_cache_storage,
- const std::string& cache_storage_cache_name,
- std::unique_ptr<ServiceWorkerHeaderList> cors_exposed_header_names);
- ServiceWorkerResponse(const ServiceWorkerResponse& other);
- ServiceWorkerResponse& operator=(const ServiceWorkerResponse& other);
- ~ServiceWorkerResponse();
- size_t EstimatedStructSize();
-
- // Be sure to update EstimatedStructSize() when adding members.
- std::vector<GURL> url_list;
- int status_code;
- std::string status_text;
- network::mojom::FetchResponseType response_type;
- ServiceWorkerHeaderMap headers;
- // |blob_uuid| and |blob_size| are set when the body is a blob. For other
- // types of responses, the body is provided separately in Mojo IPC via
- // ServiceWorkerFetchResponseCallback.
- std::string blob_uuid;
- uint64_t blob_size;
- scoped_refptr<storage::BlobHandle> blob;
- blink::mojom::ServiceWorkerResponseError error;
- base::Time response_time;
- bool is_in_cache_storage = false;
- std::string cache_storage_cache_name;
- ServiceWorkerHeaderList cors_exposed_header_names;
-
- // Side data is used to pass the metadata of the response (eg: V8 code cache).
- std::string side_data_blob_uuid;
- uint64_t side_data_blob_size = 0;
- // |side_data_blob| is only used when features::kMojoBlobs is enabled.
- scoped_refptr<storage::BlobHandle> side_data_blob;
-};
-
class ChangedVersionAttributesMask {
public:
enum {
diff --git a/chromium/content/common/service_worker/service_worker_types_unittest.cc b/chromium/content/common/service_worker/service_worker_types_unittest.cc
index 8a077d53982..3de9f20ea9f 100644
--- a/chromium/content/common/service_worker/service_worker_types_unittest.cc
+++ b/chromium/content/common/service_worker/service_worker_types_unittest.cc
@@ -4,11 +4,10 @@
#include "content/common/service_worker/service_worker_types.h"
#include "base/guid.h"
-#include "content/common/service_worker/service_worker_fetch_response_mojom_traits.h"
#include "mojo/public/cpp/base/time_mojom_traits.h"
#include "mojo/public/cpp/test_support/test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/modules/fetch/fetch_api_response.mojom.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_response.mojom.h"
#include "url/mojom/url_gurl_mojom_traits.h"
#include "net/base/load_flags.h"
@@ -45,42 +44,6 @@ TEST(ServiceWorkerFetchRequestTest, CacheModeTest) {
net::LOAD_ONLY_FROM_CACHE | net::LOAD_BYPASS_CACHE));
}
-// Tests that mojo serialization/deserialization of ServiceWorkerResponse works.
-TEST(ServiceWorkerResponseTest, StructTraits) {
- ServiceWorkerResponse input;
- ServiceWorkerResponse output;
-
- input.url_list = {GURL("https://www.google.ca/"),
- GURL("https://www.google.com")};
- input.status_code = 200;
- input.status_text = "status_text";
- input.response_type = network::mojom::FetchResponseType::kDefault;
- input.headers.insert(
- std::pair<std::string, std::string>("header1", "value1"));
- input.headers.insert(
- std::pair<std::string, std::string>("header2", "value2"));
- input.error = blink::mojom::ServiceWorkerResponseError::kUnknown;
- input.response_time = base::Time::Now();
- input.is_in_cache_storage = true;
- input.cache_storage_cache_name = "cache_name";
-
- mojo::test::SerializeAndDeserialize<blink::mojom::FetchAPIResponse>(&input,
- &output);
-
- EXPECT_EQ(input.url_list, output.url_list);
- EXPECT_EQ(input.status_code, output.status_code);
- EXPECT_EQ(input.status_text, output.status_text);
- EXPECT_EQ(input.response_type, output.response_type);
- EXPECT_EQ(input.headers, output.headers);
- EXPECT_EQ(input.blob, output.blob);
- EXPECT_EQ(input.error, output.error);
- EXPECT_EQ(input.response_time, output.response_time);
- EXPECT_EQ(input.is_in_cache_storage, output.is_in_cache_storage);
- EXPECT_EQ(input.cache_storage_cache_name, output.cache_storage_cache_name);
- EXPECT_EQ(input.cors_exposed_header_names, output.cors_exposed_header_names);
- EXPECT_EQ(input.side_data_blob, output.side_data_blob);
-}
-
TEST(ServiceWorkerRequestTest, SerialiazeDeserializeRoundTrip) {
ServiceWorkerFetchRequest request(
GURL("foo.com"), "GET", {{"User-Agent", "Chrome"}},
diff --git a/chromium/content/common/service_worker/service_worker_utils.cc b/chromium/content/common/service_worker/service_worker_utils.cc
index 5abbb6e9dfb..191ec845603 100644
--- a/chromium/content/common/service_worker/service_worker_utils.cc
+++ b/chromium/content/common/service_worker/service_worker_utils.cc
@@ -166,55 +166,6 @@ bool ServiceWorkerUtils::AllOriginsMatchAndCanAccessServiceWorkers(
return true;
}
-bool ServiceWorkerUtils::ExtractSinglePartHttpRange(
- const net::HttpRequestHeaders& headers,
- bool* has_range_out,
- uint64_t* offset_out,
- uint64_t* length_out) {
- std::string range_header;
- *has_range_out = false;
- if (!headers.GetHeader(net::HttpRequestHeaders::kRange, &range_header))
- return true;
-
- std::vector<net::HttpByteRange> ranges;
- if (!net::HttpUtil::ParseRangeHeader(range_header, &ranges))
- return true;
-
- // Multi-part (or invalid) ranges are not supported.
- if (ranges.size() != 1)
- return false;
-
- // Safely parse the single range to our more-sane output format.
- *has_range_out = true;
- const net::HttpByteRange& byte_range = ranges[0];
- if (byte_range.first_byte_position() < 0)
- return false;
- // Allow the range [0, -1] to be valid and specify the entire range.
- if (byte_range.first_byte_position() == 0 &&
- byte_range.last_byte_position() == -1) {
- *has_range_out = false;
- return true;
- }
- if (byte_range.last_byte_position() < 0)
- return false;
-
- uint64_t first_byte_position =
- static_cast<uint64_t>(byte_range.first_byte_position());
- uint64_t last_byte_position =
- static_cast<uint64_t>(byte_range.last_byte_position());
-
- base::CheckedNumeric<uint64_t> length = last_byte_position;
- length -= first_byte_position;
- length += 1;
-
- if (!length.IsValid())
- return false;
-
- *offset_out = static_cast<uint64_t>(byte_range.first_byte_position());
- *length_out = length.ValueOrDie();
- return true;
-}
-
bool ServiceWorkerUtils::ShouldBypassCacheDueToUpdateViaCache(
bool is_main_script,
blink::mojom::ServiceWorkerUpdateViaCache cache_mode) {
diff --git a/chromium/content/common/service_worker/service_worker_utils.h b/chromium/content/common/service_worker/service_worker_utils.h
index 6260688108a..f0f25a65a64 100644
--- a/chromium/content/common/service_worker/service_worker_utils.h
+++ b/chromium/content/common/service_worker/service_worker_utils.h
@@ -7,6 +7,7 @@
#include <sstream>
#include <string>
+#include <vector>
#include "base/command_line.h"
#include "base/macros.h"
@@ -69,14 +70,6 @@ class ServiceWorkerUtils {
return oss.str();
}
- // Sets |has_range| to true if |headers| specify a single range request, and
- // |offset| and |size| to the range. Returns true on valid input (regardless
- // of |has_range|), and false if there is more than one range or if the bounds
- // overflow.
- static bool ExtractSinglePartHttpRange(const net::HttpRequestHeaders& headers,
- bool* has_range_out,
- uint64_t* offset_out,
- uint64_t* size_out);
static bool ShouldBypassCacheDueToUpdateViaCache(
bool is_main_script,
diff --git a/chromium/content/common/shared_worker/shared_worker_factory.mojom b/chromium/content/common/shared_worker/shared_worker_factory.mojom
index 50332f4af33..3287a07a4e5 100644
--- a/chromium/content/common/shared_worker/shared_worker_factory.mojom
+++ b/chromium/content/common/shared_worker/shared_worker_factory.mojom
@@ -4,12 +4,13 @@
module content.mojom;
-import "content/common/native_types.mojom";
import "content/common/service_worker/service_worker_provider.mojom";
import "content/common/shared_worker/shared_worker.mojom";
import "content/common/shared_worker/shared_worker_host.mojom";
import "content/common/shared_worker/shared_worker_info.mojom";
import "content/common/url_loader_factory_bundle.mojom";
+import "content/public/common/renderer_preference_watcher.mojom";
+import "content/public/common/renderer_preferences.mojom";
import "mojo/public/mojom/base/unguessable_token.mojom";
import "services/network/public/mojom/url_loader_factory.mojom";
import "services/service_manager/public/mojom/interface_provider.mojom";
@@ -33,14 +34,21 @@ interface SharedWorkerFactory {
bool pause_on_start,
mojo_base.mojom.UnguessableToken devtools_worker_token,
RendererPreferences renderer_preferences,
+ RendererPreferenceWatcher& preference_watcher_request,
blink.mojom.WorkerContentSettingsProxy content_settings,
// S13nServiceWorker:
- // The info about the host in the browser process that provides support
- // for this shared worker to be a service worker client. Null when
- // S13nServiceWorker is disabled.
+ // The info about the service worker host in the browser process that
+ // provides support for this shared worker to be a service worker client.
+ // Null when S13nServiceWorker is disabled.
ServiceWorkerProviderInfoForSharedWorker? service_worker_provider_info,
+ // NetworkService:
+ // The ID of the AppCacheHost in the browser process that serves resources
+ // for this shared worker. This is kAppCacheNoHostId when NetworkService
+ // is disabled or AppCache doesn't serve resources for this shared worker.
+ int32 appcache_host_id,
+
// S13nServiceWorker:
// The URLLoaderFactory to use to request the shared worker's script
// (just the main script resource; importScripts() should go through the
diff --git a/chromium/content/common/single_request_url_loader_factory.cc b/chromium/content/common/single_request_url_loader_factory.cc
index 3c1a19b1bd6..c709898e827 100644
--- a/chromium/content/common/single_request_url_loader_factory.cc
+++ b/chromium/content/common/single_request_url_loader_factory.cc
@@ -23,17 +23,20 @@ class SingleRequestURLLoaderFactory::HandlerState
: handler_(std::move(handler)),
handler_task_runner_(base::SequencedTaskRunnerHandle::Get()) {}
- void HandleRequest(network::mojom::URLLoaderRequest loader,
+ void HandleRequest(const network::ResourceRequest& resource_request,
+ network::mojom::URLLoaderRequest loader,
network::mojom::URLLoaderClientPtr client) {
if (!handler_task_runner_->RunsTasksInCurrentSequence()) {
handler_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&HandlerState::HandleRequest, this,
- std::move(loader), std::move(client)));
+ FROM_HERE,
+ base::BindOnce(&HandlerState::HandleRequest, this, resource_request,
+ std::move(loader), std::move(client)));
return;
}
DCHECK(handler_);
- std::move(handler_).Run(std::move(loader), std::move(client));
+ std::move(handler_).Run(resource_request, std::move(loader),
+ std::move(client));
}
private:
@@ -85,7 +88,7 @@ void SingleRequestURLLoaderFactory::CreateLoaderAndStart(
const network::ResourceRequest& request,
network::mojom::URLLoaderClientPtr client,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
- state_->HandleRequest(std::move(loader), std::move(client));
+ state_->HandleRequest(request, std::move(loader), std::move(client));
}
void SingleRequestURLLoaderFactory::Clone(
diff --git a/chromium/content/common/single_request_url_loader_factory.h b/chromium/content/common/single_request_url_loader_factory.h
index 9069591c060..41e8689aad8 100644
--- a/chromium/content/common/single_request_url_loader_factory.h
+++ b/chromium/content/common/single_request_url_loader_factory.h
@@ -18,7 +18,8 @@ namespace content {
class SingleRequestURLLoaderFactory : public network::SharedURLLoaderFactory {
public:
using RequestHandler =
- base::OnceCallback<void(network::mojom::URLLoaderRequest,
+ base::OnceCallback<void(const network::ResourceRequest& resource_request,
+ network::mojom::URLLoaderRequest,
network::mojom::URLLoaderClientPtr)>;
explicit SingleRequestURLLoaderFactory(RequestHandler handler);
diff --git a/chromium/content/common/throttling_url_loader.cc b/chromium/content/common/throttling_url_loader.cc
index 1a3324800c8..4387f6e4983 100644
--- a/chromium/content/common/throttling_url_loader.cc
+++ b/chromium/content/common/throttling_url_loader.cc
@@ -5,8 +5,11 @@
#include "content/common/throttling_url_loader.h"
#include "base/single_thread_task_runner.h"
+#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/public/common/browser_side_navigation_policy.h"
+#include "net/http/http_status_code.h"
+#include "net/http/http_util.h"
namespace content {
@@ -44,6 +47,14 @@ class ThrottlingURLLoader::ForwardingThrottleDelegate
loader_->SetPriority(priority);
}
+ void UpdateDeferredResponseHead(
+ const network::ResourceResponseHead& new_response_head) override {
+ if (!loader_)
+ return;
+ ScopedDelegateCall scoped_delegate_call(this);
+ loader_->UpdateDeferredResponseHead(new_response_head);
+ }
+
void PauseReadingBodyFromNet() override {
if (!loader_)
return;
@@ -178,22 +189,68 @@ ThrottlingURLLoader::~ThrottlingURLLoader() {
}
void ThrottlingURLLoader::FollowRedirect(
- const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
+ const base::Optional<net::HttpRequestHeaders>& modified_headers) {
+ const base::Optional<net::HttpRequestHeaders>* modified_headers_to_send =
+ &modified_headers;
+ if (modified_request_headers_) {
+ if (modified_headers)
+ modified_request_headers_->MergeFrom(*modified_headers);
+ modified_headers_to_send = &modified_request_headers_;
+ }
+
+ if (!throttle_redirect_url_.is_empty()) {
+ throttle_redirect_url_ = GURL();
+ // This is a synthesized redirect, so no need to tell the URLLoader.
+ DCHECK(!modified_headers_to_send->has_value())
+ << "ThrottlingURLLoader doesn't support modifying headers for "
+ "synthesized requests.";
+ StartNow();
+ return;
+ }
+
if (url_loader_) {
- if (to_be_removed_request_headers_.empty()) {
- url_loader_->FollowRedirect(base::nullopt, modified_request_headers);
- } else {
- url_loader_->FollowRedirect(to_be_removed_request_headers_,
- modified_request_headers);
- }
- to_be_removed_request_headers_.clear();
+ url_loader_->FollowRedirect(to_be_removed_request_headers_,
+ *modified_headers_to_send);
+ }
+
+ to_be_removed_request_headers_.reset();
+ modified_request_headers_.reset();
+}
+
+void ThrottlingURLLoader::FollowRedirectForcingRestart() {
+ url_loader_.reset();
+ client_binding_.Close();
+
+ if (to_be_removed_request_headers_) {
+ for (const std::string& key : *to_be_removed_request_headers_)
+ start_info_->url_request.headers.RemoveHeader(key);
+ to_be_removed_request_headers_.reset();
}
+
+ if (modified_request_headers_) {
+ start_info_->url_request.headers.MergeFrom(*modified_request_headers_);
+ modified_request_headers_.reset();
+ }
+
+ StartNow();
+}
+
+void ThrottlingURLLoader::RestartWithFactory(
+ scoped_refptr<network::SharedURLLoaderFactory> factory,
+ uint32_t url_loader_options) {
+ DCHECK_EQ(DEFERRED_NONE, deferred_stage_);
+ DCHECK(!loader_completed_);
+ url_loader_.reset();
+ client_binding_.Close();
+ start_info_->url_loader_factory = std::move(factory);
+ start_info_->options = url_loader_options;
+ StartNow();
}
void ThrottlingURLLoader::SetPriority(net::RequestPriority priority,
int32_t intra_priority_value) {
if (!url_loader_) {
- if (!loader_cancelled_) {
+ if (!loader_completed_) {
DCHECK_EQ(DEFERRED_START, deferred_stage_);
priority_info_ =
std::make_unique<PriorityInfo>(priority, intra_priority_value);
@@ -230,51 +287,82 @@ void ThrottlingURLLoader::Start(
network::ResourceRequest* url_request,
scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
DCHECK_EQ(DEFERRED_NONE, deferred_stage_);
- DCHECK(!loader_cancelled_);
+ DCHECK(!loader_completed_);
if (options & network::mojom::kURLLoadOptionSynchronous)
is_synchronous_ = true;
+ bool deferred = false;
DCHECK(deferring_throttles_.empty());
if (!throttles_.empty()) {
- bool deferred = false;
for (auto& entry : throttles_) {
auto* throttle = entry.throttle.get();
bool throttle_deferred = false;
+ GURL original_url = url_request->url;
throttle->WillStartRequest(url_request, &throttle_deferred);
+ if (original_url != url_request->url) {
+ DCHECK(throttle_redirect_url_.is_empty())
+ << "ThrottlingURLLoader doesn't support multiple throttles "
+ "changing the URL.";
+ CHECK_EQ(original_url.GetOrigin(), url_request->url.GetOrigin())
+ << "ThrottlingURLLoader doesn't support a throttle making a "
+ << "cross-origin redirect.";
+ throttle_redirect_url_ = url_request->url;
+ // Restore the original URL so that all throttles see the same original
+ // URL.
+ url_request->url = original_url;
+ }
if (!HandleThrottleResult(throttle, throttle_deferred, &deferred))
return;
}
- if (deferred) {
- deferred_stage_ = DEFERRED_START;
- start_info_ = std::make_unique<StartInfo>(
- std::move(factory), routing_id, request_id, options, url_request,
- std::move(task_runner));
- 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_redirect_url_.is_empty())
+ url_request->url = throttle_redirect_url_;
}
- StartNow(factory.get(), routing_id, request_id, options, url_request,
- std::move(task_runner));
+ start_info_ =
+ std::make_unique<StartInfo>(factory, routing_id, request_id, options,
+ url_request, std::move(task_runner));
+ if (deferred)
+ deferred_stage_ = DEFERRED_START;
+ else
+ StartNow();
}
-void ThrottlingURLLoader::StartNow(
- network::SharedURLLoaderFactory* factory,
- int32_t routing_id,
- int32_t request_id,
- uint32_t options,
- network::ResourceRequest* url_request,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
+void ThrottlingURLLoader::StartNow() {
+ DCHECK(start_info_);
+ if (!throttle_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_redirect_url_;
+ redirect_info.new_site_for_cookies = throttle_redirect_url_;
+
+ network::ResourceResponseHead response_head;
+ std::string header_string = base::StringPrintf(
+ "HTTP/1.1 %i Internal Redirect\n"
+ "Location: %s\n",
+ net::HTTP_TEMPORARY_REDIRECT, throttle_redirect_url_.spec().c_str());
+ response_head.headers =
+ new net::HttpResponseHeaders(net::HttpUtil::AssembleRawHeaders(
+ header_string.c_str(), header_string.length()));
+ response_head.encoded_data_length = header_string.size();
+ OnReceiveRedirect(redirect_info, response_head);
+ return;
+ }
+
network::mojom::URLLoaderClientPtr client;
- client_binding_.Bind(mojo::MakeRequest(&client), std::move(task_runner));
+ client_binding_.Bind(mojo::MakeRequest(&client), start_info_->task_runner);
client_binding_.set_connection_error_handler(base::BindOnce(
&ThrottlingURLLoader::OnClientConnectionError, base::Unretained(this)));
- DCHECK(factory);
- factory->CreateLoaderAndStart(
- mojo::MakeRequest(&url_loader_), routing_id, request_id, options,
- *url_request, std::move(client),
+ DCHECK(start_info_->url_loader_factory);
+ start_info_->url_loader_factory->CreateLoaderAndStart(
+ mojo::MakeRequest(&url_loader_), start_info_->routing_id,
+ start_info_->request_id, start_info_->options, start_info_->url_request,
+ std::move(client),
net::MutableNetworkTrafficAnnotationTag(traffic_annotation_));
if (!pausing_reading_body_from_net_throttles_.empty())
@@ -287,14 +375,14 @@ void ThrottlingURLLoader::StartNow(
}
// Initialize with the request URL, may be updated when on redirects
- response_url_ = url_request->url;
+ response_url_ = start_info_->url_request.url;
}
bool ThrottlingURLLoader::HandleThrottleResult(URLLoaderThrottle* throttle,
bool throttle_deferred,
bool* should_defer) {
DCHECK(!deferring_throttles_.count(throttle));
- if (loader_cancelled_)
+ if (loader_completed_)
return false;
*should_defer |= throttle_deferred;
if (throttle_deferred)
@@ -308,22 +396,23 @@ void ThrottlingURLLoader::StopDeferringForThrottle(
return;
deferring_throttles_.erase(throttle);
- if (deferring_throttles_.empty() && !loader_cancelled_)
+ if (deferring_throttles_.empty() && !loader_completed_)
Resume();
}
void ThrottlingURLLoader::OnReceiveResponse(
const network::ResourceResponseHead& response_head) {
DCHECK_EQ(DEFERRED_NONE, deferred_stage_);
- DCHECK(!loader_cancelled_);
+ DCHECK(!loader_completed_);
DCHECK(deferring_throttles_.empty());
+ network::ResourceResponseHead response_head_copy = response_head;
if (!throttles_.empty()) {
bool deferred = false;
for (auto& entry : throttles_) {
auto* throttle = entry.throttle.get();
bool throttle_deferred = false;
- throttle->WillProcessResponse(response_url_, response_head,
+ throttle->WillProcessResponse(response_url_, &response_head_copy,
&throttle_deferred);
if (!HandleThrottleResult(throttle, throttle_deferred, &deferred))
return;
@@ -331,20 +420,20 @@ void ThrottlingURLLoader::OnReceiveResponse(
if (deferred) {
deferred_stage_ = DEFERRED_RESPONSE;
- response_info_ = std::make_unique<ResponseInfo>(response_head);
+ response_info_ = std::make_unique<ResponseInfo>(response_head_copy);
client_binding_.PauseIncomingMethodCallProcessing();
return;
}
}
- forwarding_client_->OnReceiveResponse(response_head);
+ forwarding_client_->OnReceiveResponse(response_head_copy);
}
void ThrottlingURLLoader::OnReceiveRedirect(
const net::RedirectInfo& redirect_info,
const network::ResourceResponseHead& response_head) {
DCHECK_EQ(DEFERRED_NONE, deferred_stage_);
- DCHECK(!loader_cancelled_);
+ DCHECK(!loader_completed_);
DCHECK(deferring_throttles_.empty());
if (!throttles_.empty()) {
@@ -353,16 +442,33 @@ void ThrottlingURLLoader::OnReceiveRedirect(
auto* throttle = entry.throttle.get();
bool throttle_deferred = false;
auto weak_ptr = weak_factory_.GetWeakPtr();
- std::vector<std::string> headers;
+ std::vector<std::string> to_be_removed_headers;
+ net::HttpRequestHeaders modified_headers;
throttle->WillRedirectRequest(redirect_info, response_head,
- &throttle_deferred, &headers);
+ &throttle_deferred, &to_be_removed_headers,
+ &modified_headers);
if (!weak_ptr)
return;
if (!HandleThrottleResult(throttle, throttle_deferred, &deferred))
return;
- to_be_removed_request_headers_.insert(
- to_be_removed_request_headers_.end(), headers.begin(), headers.end());
+ if (!to_be_removed_headers.empty()) {
+ if (to_be_removed_request_headers_) {
+ for (auto& header : to_be_removed_headers) {
+ if (!base::ContainsValue(*to_be_removed_request_headers_, header))
+ to_be_removed_request_headers_->push_back(std::move(header));
+ }
+ } else {
+ to_be_removed_request_headers_ = std::move(to_be_removed_headers);
+ }
+ }
+
+ if (!modified_headers.IsEmpty()) {
+ if (modified_request_headers_)
+ modified_request_headers_->MergeFrom(modified_headers);
+ else
+ modified_request_headers_ = std::move(modified_headers);
+ }
}
if (deferred) {
@@ -374,6 +480,15 @@ void ThrottlingURLLoader::OnReceiveRedirect(
}
}
+ // Update the request in case |FollowRedirectForcingRestart()| is called, and
+ // needs to use the request updated for the redirect.
+ network::ResourceRequest& request = start_info_->url_request;
+ request.url = redirect_info.new_url;
+ request.method = redirect_info.new_method;
+ request.site_for_cookies = redirect_info.new_site_for_cookies;
+ request.referrer = GURL(redirect_info.new_referrer);
+ request.referrer_policy = redirect_info.new_referrer_policy;
+
// TODO(dhausknecht) at this point we do not actually know if we commit to the
// redirect or if it will be cancelled. FollowRedirect would be a more
// suitable place to set this URL but there we do not have the data.
@@ -386,7 +501,7 @@ void ThrottlingURLLoader::OnUploadProgress(
int64_t total_size,
OnUploadProgressCallback ack_callback) {
DCHECK_EQ(DEFERRED_NONE, deferred_stage_);
- DCHECK(!loader_cancelled_);
+ DCHECK(!loader_completed_);
forwarding_client_->OnUploadProgress(current_position, total_size,
std::move(ack_callback));
@@ -395,14 +510,14 @@ void ThrottlingURLLoader::OnUploadProgress(
void ThrottlingURLLoader::OnReceiveCachedMetadata(
const std::vector<uint8_t>& data) {
DCHECK_EQ(DEFERRED_NONE, deferred_stage_);
- DCHECK(!loader_cancelled_);
+ DCHECK(!loader_completed_);
forwarding_client_->OnReceiveCachedMetadata(data);
}
void ThrottlingURLLoader::OnTransferSizeUpdated(int32_t transfer_size_diff) {
DCHECK_EQ(DEFERRED_NONE, deferred_stage_);
- DCHECK(!loader_cancelled_);
+ DCHECK(!loader_completed_);
forwarding_client_->OnTransferSizeUpdated(transfer_size_diff);
}
@@ -410,7 +525,7 @@ void ThrottlingURLLoader::OnTransferSizeUpdated(int32_t transfer_size_diff) {
void ThrottlingURLLoader::OnStartLoadingResponseBody(
mojo::ScopedDataPipeConsumerHandle body) {
DCHECK_EQ(DEFERRED_NONE, deferred_stage_);
- DCHECK(!loader_cancelled_);
+ DCHECK(!loader_completed_);
forwarding_client_->OnStartLoadingResponseBody(std::move(body));
}
@@ -418,12 +533,14 @@ void ThrottlingURLLoader::OnStartLoadingResponseBody(
void ThrottlingURLLoader::OnComplete(
const network::URLLoaderCompletionStatus& status) {
DCHECK_EQ(DEFERRED_NONE, deferred_stage_);
- DCHECK(!loader_cancelled_);
+ DCHECK(!loader_completed_);
// This is the last expected message. Pipe closure before this is an error
// (see OnClientConnectionError). After this it is expected and should be
- // ignored.
- DisconnectClient(nullptr);
+ // ignored. The owner of |this| is expected to destroy |this| when
+ // OnComplete() and all data has been read. Destruction of |this| will
+ // destroy |url_loader_| appropriately.
+ loader_completed_ = true;
forwarding_client_->OnComplete(status);
}
@@ -437,7 +554,7 @@ void ThrottlingURLLoader::OnClientConnectionError() {
void ThrottlingURLLoader::CancelWithError(int error_code,
base::StringPiece custom_reason) {
- if (loader_cancelled_)
+ if (loader_completed_)
return;
network::URLLoaderCompletionStatus status;
@@ -450,16 +567,14 @@ void ThrottlingURLLoader::CancelWithError(int error_code,
}
void ThrottlingURLLoader::Resume() {
- if (loader_cancelled_ || deferred_stage_ == DEFERRED_NONE)
+ if (loader_completed_ || deferred_stage_ == DEFERRED_NONE)
return;
auto prev_deferred_stage = deferred_stage_;
deferred_stage_ = DEFERRED_NONE;
switch (prev_deferred_stage) {
case DEFERRED_START: {
- StartNow(start_info_->url_loader_factory.get(), start_info_->routing_id,
- start_info_->request_id, start_info_->options,
- &start_info_->url_request, std::move(start_info_->task_runner));
+ StartNow();
break;
}
case DEFERRED_REDIRECT: {
@@ -490,6 +605,13 @@ void ThrottlingURLLoader::SetPriority(net::RequestPriority priority) {
url_loader_->SetPriority(priority, -1);
}
+void ThrottlingURLLoader::UpdateDeferredResponseHead(
+ const network::ResourceResponseHead& new_response_head) {
+ DCHECK(response_info_);
+ DCHECK_EQ(DEFERRED_RESPONSE, deferred_stage_);
+ response_info_->response_head = new_response_head;
+}
+
void ThrottlingURLLoader::PauseReadingBodyFromNet(URLLoaderThrottle* throttle) {
if (pausing_reading_body_from_net_throttles_.empty() && url_loader_)
url_loader_->PauseReadingBodyFromNet();
@@ -537,7 +659,7 @@ void ThrottlingURLLoader::DisconnectClient(base::StringPiece custom_reason) {
url_loader_ = nullptr;
}
- loader_cancelled_ = true;
+ loader_completed_ = true;
}
ThrottlingURLLoader::ThrottleEntry::ThrottleEntry(
diff --git a/chromium/content/common/throttling_url_loader.h b/chromium/content/common/throttling_url_loader.h
index 9fb0cdf9817..7c8a6027e57 100644
--- a/chromium/content/common/throttling_url_loader.h
+++ b/chromium/content/common/throttling_url_loader.h
@@ -52,8 +52,23 @@ class CONTENT_EXPORT ThrottlingURLLoader
void FollowRedirect(
const base::Optional<net::HttpRequestHeaders>& modified_request_headers);
+ // Follows a redirect, calling CreateLoaderAndStart() on the factory. This
+ // is useful if the factory uses different loaders for different URLs.
+ void FollowRedirectForcingRestart();
void SetPriority(net::RequestPriority priority, int32_t intra_priority_value);
+ // Restarts the load immediately with |factory| and |url_loader_options|.
+ // It must only be called when the following conditions are met:
+ // 1. The request already started and the original factory decided to not
+ // handle the request. This condition is required because throttles are not
+ // consulted prior to restarting.
+ // 2. The original factory did not call URLLoaderClient callbacks (e.g.,
+ // OnReceiveResponse).
+ // This function is useful in the case of service worker network fallback.
+ void RestartWithFactory(
+ scoped_refptr<network::SharedURLLoaderFactory> factory,
+ uint32_t url_loader_options);
+
// Disconnect the forwarding URLLoaderClient and the URLLoader. Returns the
// datapipe endpoints.
network::mojom::URLLoaderClientEndpointsPtr Unbind();
@@ -80,12 +95,7 @@ class CONTENT_EXPORT ThrottlingURLLoader
network::ResourceRequest* url_request,
scoped_refptr<base::SingleThreadTaskRunner> task_runner);
- void StartNow(network::SharedURLLoaderFactory* factory,
- int32_t routing_id,
- int32_t request_id,
- uint32_t options,
- network::ResourceRequest* url_request,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+ void StartNow();
// Processes the result of a URLLoaderThrottle call, adding the throttle to
// the blocking set if it deferred and updating |*should_defer| accordingly.
@@ -120,6 +130,8 @@ class CONTENT_EXPORT ThrottlingURLLoader
void CancelWithError(int error_code, base::StringPiece custom_reason);
void Resume();
void SetPriority(net::RequestPriority priority);
+ void UpdateDeferredResponseHead(
+ const network::ResourceResponseHead& new_response_head);
void PauseReadingBodyFromNet(URLLoaderThrottle* throttle);
void ResumeReadingBodyFromNet(URLLoaderThrottle* throttle);
void InterceptResponse(
@@ -138,7 +150,7 @@ class CONTENT_EXPORT ThrottlingURLLoader
DEFERRED_RESPONSE
};
DeferredStage deferred_stage_ = DEFERRED_NONE;
- bool loader_cancelled_ = false;
+ bool loader_completed_ = false;
bool is_synchronous_ = false;
struct ThrottleEntry {
@@ -187,7 +199,8 @@ class CONTENT_EXPORT ThrottlingURLLoader
// |task_runner_| is used to set up |client_binding_|.
scoped_refptr<base::SingleThreadTaskRunner> task_runner;
};
- // Set if start is deferred.
+ // Holds any info needed to start or restart the request. Used when start is
+ // deferred or when FollowRedirectForcingRestart() is called.
std::unique_ptr<StartInfo> start_info_;
struct ResponseInfo {
@@ -222,6 +235,9 @@ class CONTENT_EXPORT ThrottlingURLLoader
// Set if request is deferred and SetPriority() is called.
std::unique_ptr<PriorityInfo> priority_info_;
+ // Set if a throttle changed the URL in WillStartRequest.
+ GURL throttle_redirect_url_;
+
const net::NetworkTrafficAnnotationTag traffic_annotation_;
uint32_t inside_delegate_calls_ = 0;
@@ -231,7 +247,8 @@ class CONTENT_EXPORT ThrottlingURLLoader
bool response_intercepted_ = false;
- std::vector<std::string> to_be_removed_request_headers_;
+ base::Optional<std::vector<std::string>> to_be_removed_request_headers_;
+ base::Optional<net::HttpRequestHeaders> modified_request_headers_;
base::WeakPtrFactory<ThrottlingURLLoader> weak_factory_;
diff --git a/chromium/content/common/throttling_url_loader_unittest.cc b/chromium/content/common/throttling_url_loader_unittest.cc
index 4893336ebb0..31bcfc4402e 100644
--- a/chromium/content/common/throttling_url_loader_unittest.cc
+++ b/chromium/content/common/throttling_url_loader_unittest.cc
@@ -6,6 +6,7 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/run_loop.h"
+#include "base/test/bind_test_util.h"
#include "base/test/scoped_task_environment.h"
#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/url_loader_throttle.h"
@@ -13,6 +14,7 @@
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/public/mojom/url_loader.mojom.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
@@ -46,6 +48,16 @@ class TestURLLoaderFactory : public network::mojom::URLLoaderFactory,
return create_loader_and_start_called_;
}
+ const base::Optional<std::vector<std::string>>& headers_removed_on_redirect()
+ const {
+ return headers_removed_on_redirect_;
+ }
+
+ const base::Optional<net::HttpRequestHeaders>& headers_modified_on_redirect()
+ const {
+ return headers_modified_on_redirect_;
+ }
+
size_t pause_reading_body_from_net_called() const {
return pause_reading_body_from_net_called_;
}
@@ -98,7 +110,11 @@ class TestURLLoaderFactory : public network::mojom::URLLoaderFactory,
void FollowRedirect(const base::Optional<std::vector<std::string>>&
to_be_removed_request_headers,
const base::Optional<net::HttpRequestHeaders>&
- modified_request_headers) override {}
+ modified_request_headers) override {
+ headers_removed_on_redirect_ = to_be_removed_request_headers;
+ headers_modified_on_redirect_ = modified_request_headers;
+ }
+
void ProceedWithResponse() override {}
void SetPriority(net::RequestPriority priority,
@@ -113,6 +129,8 @@ class TestURLLoaderFactory : public network::mojom::URLLoaderFactory,
}
size_t create_loader_and_start_called_ = 0;
+ base::Optional<std::vector<std::string>> headers_removed_on_redirect_;
+ base::Optional<net::HttpRequestHeaders> headers_modified_on_redirect_;
size_t pause_reading_body_from_net_called_ = 0;
size_t resume_reading_body_from_net_called_ = 0;
@@ -204,7 +222,13 @@ class TestURLLoaderThrottle : public URLLoaderThrottle {
}
using ThrottleCallback =
- base::Callback<void(URLLoaderThrottle::Delegate* delegate, bool* defer)>;
+ base::RepeatingCallback<void(URLLoaderThrottle::Delegate* delegate,
+ bool* defer)>;
+ using ThrottleRedirectCallback = base::RepeatingCallback<void(
+ URLLoaderThrottle::Delegate* delegate,
+ bool* defer,
+ std::vector<std::string>* to_be_removed_headers,
+ net::HttpRequestHeaders* modified_headers)>;
size_t will_start_request_called() const {
return will_start_request_called_;
@@ -222,7 +246,8 @@ class TestURLLoaderThrottle : public URLLoaderThrottle {
will_start_request_callback_ = callback;
}
- void set_will_redirect_request_callback(const ThrottleCallback& callback) {
+ void set_will_redirect_request_callback(
+ const ThrottleRedirectCallback& callback) {
will_redirect_request_callback_ = callback;
}
@@ -230,6 +255,10 @@ class TestURLLoaderThrottle : public URLLoaderThrottle {
will_process_response_callback_ = callback;
}
+ void set_modify_url_in_will_start(const GURL& url) {
+ modify_url_in_will_start_ = url;
+ }
+
Delegate* delegate() const { return delegate_; }
private:
@@ -237,6 +266,9 @@ class TestURLLoaderThrottle : public URLLoaderThrottle {
void WillStartRequest(network::ResourceRequest* request,
bool* defer) override {
will_start_request_called_++;
+ if (!modify_url_in_will_start_.is_empty())
+ request->url = modify_url_in_will_start_;
+
if (will_start_request_callback_)
will_start_request_callback_.Run(delegate_, defer);
}
@@ -245,14 +277,18 @@ class TestURLLoaderThrottle : public URLLoaderThrottle {
const net::RedirectInfo& redirect_info,
const network::ResourceResponseHead& response_head,
bool* defer,
- std::vector<std::string>* to_be_removed_request_headers) override {
+ std::vector<std::string>* to_be_removed_request_headers,
+ net::HttpRequestHeaders* modified_request_headers) override {
will_redirect_request_called_++;
- if (will_redirect_request_callback_)
- will_redirect_request_callback_.Run(delegate_, defer);
+ if (will_redirect_request_callback_) {
+ will_redirect_request_callback_.Run(delegate_, defer,
+ to_be_removed_request_headers,
+ modified_request_headers);
+ }
}
void WillProcessResponse(const GURL& response_url,
- const network::ResourceResponseHead& response_head,
+ network::ResourceResponseHead* response_head,
bool* defer) override {
will_process_response_called_++;
if (will_process_response_callback_)
@@ -267,9 +303,11 @@ class TestURLLoaderThrottle : public URLLoaderThrottle {
GURL response_url_;
ThrottleCallback will_start_request_callback_;
- ThrottleCallback will_redirect_request_callback_;
+ ThrottleRedirectCallback will_redirect_request_callback_;
ThrottleCallback will_process_response_callback_;
+ GURL modify_url_in_will_start_;
+
base::Closure destruction_notifier_;
DISALLOW_COPY_AND_ASSIGN(TestURLLoaderThrottle);
@@ -402,19 +440,29 @@ TEST_F(ThrottlingURLLoaderTest, DeferBeforeStart) {
EXPECT_EQ(1u, client_.on_complete_called());
}
+TEST_F(ThrottlingURLLoaderTest, ModifyURLBeforeStart) {
+ throttle_->set_modify_url_in_will_start(GURL("http://example.org/foo"));
+
+ CreateLoaderAndStart();
+
+ EXPECT_EQ(1u, throttle_->will_start_request_called());
+ EXPECT_EQ(1u, throttle_->will_redirect_request_called());
+}
+
TEST_F(ThrottlingURLLoaderTest, CancelBeforeRedirect) {
- throttle_->set_will_redirect_request_callback(
- base::Bind([](URLLoaderThrottle::Delegate* delegate, bool* defer) {
+ throttle_->set_will_redirect_request_callback(base::BindRepeating(
+ [](URLLoaderThrottle::Delegate* delegate, bool* /* defer */,
+ std::vector<std::string>* /* to_be_removed_headers */,
+ net::HttpRequestHeaders* /* modified_headers */) {
delegate->CancelWithError(net::ERR_ACCESS_DENIED);
}));
base::RunLoop run_loop;
- client_.set_on_complete_callback(base::Bind(
- [](const base::Closure& quit_closure, int error) {
+ client_.set_on_complete_callback(
+ base::BindLambdaForTesting([&run_loop](int error) {
EXPECT_EQ(net::ERR_ACCESS_DENIED, error);
- quit_closure.Run();
- },
- run_loop.QuitClosure()));
+ run_loop.Quit();
+ }));
CreateLoaderAndStart();
@@ -435,7 +483,9 @@ TEST_F(ThrottlingURLLoaderTest, DeferBeforeRedirect) {
base::RunLoop run_loop1;
throttle_->set_will_redirect_request_callback(base::Bind(
[](const base::Closure& quit_closure,
- URLLoaderThrottle::Delegate* delegate, bool* defer) {
+ URLLoaderThrottle::Delegate* delegate, bool* defer,
+ std::vector<std::string>* /* to_be_removed_headers */,
+ net::HttpRequestHeaders* /* modified_headers */) {
*defer = true;
quit_closure.Run();
},
@@ -480,6 +530,79 @@ TEST_F(ThrottlingURLLoaderTest, DeferBeforeRedirect) {
EXPECT_EQ(1u, client_.on_complete_called());
}
+TEST_F(ThrottlingURLLoaderTest, ModifyHeadersBeforeRedirect) {
+ throttle_->set_will_redirect_request_callback(base::BindRepeating(
+ [](URLLoaderThrottle::Delegate* delegate, bool* /* defer */,
+ std::vector<std::string>* to_be_removed_headers,
+ net::HttpRequestHeaders* modified_headers) {
+ to_be_removed_headers->push_back("X-Test-Header-1");
+ modified_headers->SetHeader("X-Test-Header-2", "Foo");
+ modified_headers->SetHeader("X-Test-Header-3", "Throttle Value");
+ }));
+
+ client_.set_on_received_redirect_callback(base::BindLambdaForTesting([&]() {
+ net::HttpRequestHeaders modified_headers;
+ modified_headers.SetHeader("X-Test-Header-3", "Client Value");
+ modified_headers.SetHeader("X-Test-Header-4", "Bar");
+ loader_->FollowRedirect(modified_headers);
+ }));
+
+ CreateLoaderAndStart();
+ factory_.NotifyClientOnReceiveRedirect();
+ base::RunLoop().RunUntilIdle();
+
+ ASSERT_TRUE(factory_.headers_removed_on_redirect().has_value());
+ EXPECT_THAT(*factory_.headers_removed_on_redirect(),
+ testing::ElementsAre("X-Test-Header-1"));
+ ASSERT_TRUE(factory_.headers_modified_on_redirect().has_value());
+ EXPECT_EQ(
+ "X-Test-Header-2: Foo\r\n"
+ "X-Test-Header-3: Client Value\r\n"
+ "X-Test-Header-4: Bar\r\n\r\n",
+ factory_.headers_modified_on_redirect()->ToString());
+}
+
+TEST_F(ThrottlingURLLoaderTest, MultipleThrottlesModifyHeadersBeforeRedirect) {
+ auto* throttle2 = new TestURLLoaderThrottle();
+ throttles_.push_back(base::WrapUnique(throttle2));
+
+ throttle_->set_will_redirect_request_callback(base::BindRepeating(
+ [](URLLoaderThrottle::Delegate* delegate, bool* /* defer */,
+ std::vector<std::string>* to_be_removed_headers,
+ net::HttpRequestHeaders* modified_headers) {
+ to_be_removed_headers->push_back("X-Test-Header-0");
+ to_be_removed_headers->push_back("X-Test-Header-1");
+ modified_headers->SetHeader("X-Test-Header-3", "Foo");
+ modified_headers->SetHeader("X-Test-Header-4", "Throttle1");
+ }));
+
+ throttle2->set_will_redirect_request_callback(base::BindRepeating(
+ [](URLLoaderThrottle::Delegate* delegate, bool* /* defer */,
+ std::vector<std::string>* to_be_removed_headers,
+ net::HttpRequestHeaders* modified_headers) {
+ to_be_removed_headers->push_back("X-Test-Header-1");
+ to_be_removed_headers->push_back("X-Test-Header-2");
+ modified_headers->SetHeader("X-Test-Header-4", "Throttle2");
+ }));
+
+ client_.set_on_received_redirect_callback(base::BindLambdaForTesting(
+ [&]() { loader_->FollowRedirect(base::nullopt); }));
+
+ CreateLoaderAndStart();
+ factory_.NotifyClientOnReceiveRedirect();
+ base::RunLoop().RunUntilIdle();
+
+ ASSERT_TRUE(factory_.headers_removed_on_redirect().has_value());
+ EXPECT_THAT(*factory_.headers_removed_on_redirect(),
+ testing::ElementsAre("X-Test-Header-0", "X-Test-Header-1",
+ "X-Test-Header-2"));
+ ASSERT_TRUE(factory_.headers_modified_on_redirect().has_value());
+ EXPECT_EQ(
+ "X-Test-Header-3: Foo\r\n"
+ "X-Test-Header-4: Throttle2\r\n\r\n",
+ factory_.headers_modified_on_redirect()->ToString());
+}
+
TEST_F(ThrottlingURLLoaderTest, CancelBeforeResponse) {
throttle_->set_will_process_response_callback(
base::Bind([](URLLoaderThrottle::Delegate* delegate, bool* defer) {
@@ -618,22 +741,27 @@ TEST_F(ThrottlingURLLoaderTest, PipeClosureBeforeAsyncResponse) {
}
TEST_F(ThrottlingURLLoaderTest, ResumeNoOpIfNotDeferred) {
- auto resume_callback =
- base::Bind([](URLLoaderThrottle::Delegate* delegate, bool* defer) {
+ auto resume_callback = base::BindRepeating(
+ [](URLLoaderThrottle::Delegate* delegate, bool* /* defer */) {
delegate->Resume();
delegate->Resume();
});
throttle_->set_will_start_request_callback(resume_callback);
- throttle_->set_will_redirect_request_callback(resume_callback);
throttle_->set_will_process_response_callback(std::move(resume_callback));
+ throttle_->set_will_redirect_request_callback(base::BindRepeating(
+ [](URLLoaderThrottle::Delegate* delegate, bool* /* defer */,
+ std::vector<std::string>* /* to_be_removed_headers */,
+ net::HttpRequestHeaders* /* modified_headers */) {
+ delegate->Resume();
+ delegate->Resume();
+ }));
base::RunLoop run_loop;
- client_.set_on_complete_callback(base::Bind(
- [](const base::Closure& quit_closure, int error) {
+ client_.set_on_complete_callback(
+ base::BindLambdaForTesting([&run_loop](int error) {
EXPECT_EQ(net::OK, error);
- quit_closure.Run();
- },
- run_loop.QuitClosure()));
+ run_loop.Quit();
+ }));
CreateLoaderAndStart();
factory_.NotifyClientOnReceiveRedirect();
@@ -973,7 +1101,9 @@ TEST_F(ThrottlingURLLoaderTest,
base::RunLoop run_loop1;
throttle_->set_will_redirect_request_callback(base::BindRepeating(
[](const base::RepeatingClosure& quit_closure,
- URLLoaderThrottle::Delegate* delegate, bool* defer) {
+ URLLoaderThrottle::Delegate* delegate, bool* defer,
+ std::vector<std::string>* /* to_be_removed_headers */,
+ net::HttpRequestHeaders* /* modified_headers */) {
*defer = true;
quit_closure.Run();
},
diff --git a/chromium/content/common/typemaps.gni b/chromium/content/common/typemaps.gni
index 6219420ded5..e78dd1b145c 100644
--- a/chromium/content/common/typemaps.gni
+++ b/chromium/content/common/typemaps.gni
@@ -15,9 +15,7 @@ typemaps = [
"//content/common/notifications/notification_types.typemap",
"//content/common/push_messaging.typemap",
"//content/common/render_frame_metadata.typemap",
- "//content/common/service_worker/service_worker.typemap",
"//content/common/service_worker/service_worker_fetch_request.typemap",
- "//content/common/service_worker/service_worker_fetch_response.typemap",
"//content/common/url_loader_factory_bundle.typemap",
"//content/common/web_preferences.typemap",
"//content/common/media/media_session.typemap",
diff --git a/chromium/content/common/url_loader_factory_bundle.cc b/chromium/content/common/url_loader_factory_bundle.cc
index 28fd78fde19..8e6726f149a 100644
--- a/chromium/content/common/url_loader_factory_bundle.cc
+++ b/chromium/content/common/url_loader_factory_bundle.cc
@@ -14,9 +14,11 @@ URLLoaderFactoryBundleInfo::URLLoaderFactoryBundleInfo() = default;
URLLoaderFactoryBundleInfo::URLLoaderFactoryBundleInfo(
network::mojom::URLLoaderFactoryPtrInfo default_factory_info,
std::map<std::string, network::mojom::URLLoaderFactoryPtrInfo>
- factories_info)
+ factories_info,
+ bool bypass_redirect_checks)
: default_factory_info_(std::move(default_factory_info)),
- factories_info_(std::move(factories_info)) {}
+ factories_info_(std::move(factories_info)),
+ bypass_redirect_checks_(bypass_redirect_checks) {}
URLLoaderFactoryBundleInfo::~URLLoaderFactoryBundleInfo() = default;
@@ -25,6 +27,7 @@ URLLoaderFactoryBundleInfo::CreateFactory() {
auto other = std::make_unique<URLLoaderFactoryBundleInfo>();
other->default_factory_info_ = std::move(default_factory_info_);
other->factories_info_ = std::move(factories_info_);
+ other->bypass_redirect_checks_ = bypass_redirect_checks_;
return base::MakeRefCounted<URLLoaderFactoryBundle>(std::move(other));
}
@@ -97,7 +100,12 @@ URLLoaderFactoryBundle::Clone() {
}
return std::make_unique<URLLoaderFactoryBundleInfo>(
- std::move(default_factory_info), std::move(factories_info));
+ std::move(default_factory_info), std::move(factories_info),
+ bypass_redirect_checks_);
+}
+
+bool URLLoaderFactoryBundle::BypassRedirectChecks() const {
+ return bypass_redirect_checks_;
}
void URLLoaderFactoryBundle::Update(
@@ -106,6 +114,7 @@ void URLLoaderFactoryBundle::Update(
default_factory_.Bind(std::move(info->default_factory_info()));
for (auto& factory_info : info->factories_info())
factories_[factory_info.first].Bind(std::move(factory_info.second));
+ bypass_redirect_checks_ = info->bypass_redirect_checks();
}
} // namespace content
diff --git a/chromium/content/common/url_loader_factory_bundle.h b/chromium/content/common/url_loader_factory_bundle.h
index 1883f494ebc..252152ae87b 100644
--- a/chromium/content/common/url_loader_factory_bundle.h
+++ b/chromium/content/common/url_loader_factory_bundle.h
@@ -26,7 +26,8 @@ class CONTENT_EXPORT URLLoaderFactoryBundleInfo
URLLoaderFactoryBundleInfo(
network::mojom::URLLoaderFactoryPtrInfo default_factory_info,
std::map<std::string, network::mojom::URLLoaderFactoryPtrInfo>
- factories_info);
+ factories_info,
+ bool bypass_redirect_checks);
~URLLoaderFactoryBundleInfo() override;
network::mojom::URLLoaderFactoryPtrInfo& default_factory_info() {
@@ -38,6 +39,11 @@ class CONTENT_EXPORT URLLoaderFactoryBundleInfo
return factories_info_;
}
+ bool bypass_redirect_checks() const { return bypass_redirect_checks_; }
+ void set_bypass_redirect_checks(bool bypass_redirect_checks) {
+ bypass_redirect_checks_ = bypass_redirect_checks;
+ }
+
protected:
// SharedURLLoaderFactoryInfo implementation.
scoped_refptr<network::SharedURLLoaderFactory> CreateFactory() override;
@@ -45,6 +51,7 @@ class CONTENT_EXPORT URLLoaderFactoryBundleInfo
network::mojom::URLLoaderFactoryPtrInfo default_factory_info_;
std::map<std::string, network::mojom::URLLoaderFactoryPtrInfo>
factories_info_;
+ bool bypass_redirect_checks_ = false;
DISALLOW_COPY_AND_ASSIGN(URLLoaderFactoryBundleInfo);
};
@@ -83,6 +90,7 @@ class CONTENT_EXPORT URLLoaderFactoryBundle
traffic_annotation) override;
void Clone(network::mojom::URLLoaderFactoryRequest request) override;
std::unique_ptr<network::SharedURLLoaderFactoryInfo> Clone() override;
+ bool BypassRedirectChecks() const override;
// The |info| contains replacement factories for a subset of the existing
// bundle.
@@ -93,6 +101,7 @@ class CONTENT_EXPORT URLLoaderFactoryBundle
network::mojom::URLLoaderFactoryPtr default_factory_;
std::map<std::string, network::mojom::URLLoaderFactoryPtr> factories_;
+ bool bypass_redirect_checks_ = false;
};
} // namespace content
diff --git a/chromium/content/common/url_loader_factory_bundle.mojom b/chromium/content/common/url_loader_factory_bundle.mojom
index 672bb669962..348f891ffa8 100644
--- a/chromium/content/common/url_loader_factory_bundle.mojom
+++ b/chromium/content/common/url_loader_factory_bundle.mojom
@@ -13,4 +13,8 @@ struct URLLoaderFactoryBundle {
// A mapping from URL scheme to factory interface.
map<string, network.mojom.URLLoaderFactory> factories;
+
+ // Whether redirect checks should be bypassed, since they are happening in the
+ // browser.
+ bool bypass_redirect_checks = false;
};
diff --git a/chromium/content/common/url_loader_factory_bundle_struct_traits.cc b/chromium/content/common/url_loader_factory_bundle_struct_traits.cc
index e0627fbb4fe..60a4538a02a 100644
--- a/chromium/content/common/url_loader_factory_bundle_struct_traits.cc
+++ b/chromium/content/common/url_loader_factory_bundle_struct_traits.cc
@@ -23,6 +23,11 @@ Traits::factories(BundleInfoType& bundle) {
}
// static
+bool Traits::bypass_redirect_checks(BundleInfoType& bundle) {
+ return bundle->bypass_redirect_checks();
+}
+
+// static
bool Traits::Read(content::mojom::URLLoaderFactoryBundleDataView data,
BundleInfoType* out_bundle) {
*out_bundle = std::make_unique<content::URLLoaderFactoryBundleInfo>();
@@ -32,6 +37,8 @@ bool Traits::Read(content::mojom::URLLoaderFactoryBundleDataView data,
if (!data.ReadFactories(&(*out_bundle)->factories_info()))
return false;
+ (*out_bundle)->set_bypass_redirect_checks(data.bypass_redirect_checks());
+
return true;
}
diff --git a/chromium/content/common/url_loader_factory_bundle_struct_traits.h b/chromium/content/common/url_loader_factory_bundle_struct_traits.h
index e8d9220e04f..70713c9617b 100644
--- a/chromium/content/common/url_loader_factory_bundle_struct_traits.h
+++ b/chromium/content/common/url_loader_factory_bundle_struct_traits.h
@@ -26,6 +26,8 @@ struct StructTraits<content::mojom::URLLoaderFactoryBundleDataView,
static std::map<std::string, network::mojom::URLLoaderFactoryPtrInfo>
factories(BundleInfoType& bundle);
+ static bool bypass_redirect_checks(BundleInfoType& bundle);
+
static bool Read(content::mojom::URLLoaderFactoryBundleDataView data,
BundleInfoType* out_bundle);
};
diff --git a/chromium/content/common/user_agent.cc b/chromium/content/common/user_agent.cc
index e4565757f88..cf3b6df7b1a 100644
--- a/chromium/content/common/user_agent.cc
+++ b/chromium/content/common/user_agent.cc
@@ -6,6 +6,7 @@
#include <stdint.h>
+#include "base/feature_list.h"
#include "base/logging.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
@@ -21,6 +22,11 @@
namespace content {
+#if defined(OS_ANDROID)
+const base::Feature kAndroidUserAgentStringContainsBuildId{
+ "AndroidUserAgentStringContainsBuildId", base::FEATURE_DISABLED_BY_DEFAULT};
+#endif // defined(OS_ANDROID)
+
std::string GetWebKitVersion() {
return base::StringPrintf("%d.%d (%s)",
WEBKIT_VERSION_MAJOR,
@@ -32,7 +38,7 @@ std::string GetWebKitRevision() {
return WEBKIT_SVN_REVISION;
}
-std::string BuildOSCpuInfo() {
+std::string BuildOSCpuInfo(bool include_android_build_number) {
std::string os_cpu;
#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_CHROMEOS) ||\
@@ -73,13 +79,17 @@ std::string BuildOSCpuInfo() {
}
// Append the build ID.
- std::string android_build_id = base::SysInfo::GetAndroidBuildID();
- if (android_build_id.size() > 0) {
- if (!semicolon_inserted) {
- android_info_str += ";";
+ if (base::FeatureList::IsEnabled(kAndroidUserAgentStringContainsBuildId) ||
+ include_android_build_number) {
+ std::string android_build_id = base::SysInfo::GetAndroidBuildID();
+ if (android_build_id.size() > 0) {
+ if (!semicolon_inserted) {
+ android_info_str += ";";
+ }
+ android_info_str += " Build/" + android_build_id;
}
- android_info_str += " Build/" + android_build_id;
}
+
#elif (defined(OS_POSIX) && !defined(OS_MACOSX)) || defined(OS_FUCHSIA)
// Should work on any Posix system.
struct utsname unixinfo;
@@ -145,26 +155,23 @@ std::string getUserAgentPlatform() {
std::string BuildUserAgentFromProduct(const std::string& product) {
std::string os_info;
- base::StringAppendF(
- &os_info,
- "%s%s",
- getUserAgentPlatform().c_str(),
- BuildOSCpuInfo().c_str());
+ base::StringAppendF(&os_info, "%s%s", getUserAgentPlatform().c_str(),
+ BuildOSCpuInfo(false).c_str());
return BuildUserAgentFromOSAndProduct(os_info, product);
}
+#if defined(OS_ANDROID)
std::string BuildUserAgentFromProductAndExtraOSInfo(
const std::string& product,
- const std::string& extra_os_info) {
+ const std::string& extra_os_info,
+ const bool include_android_build_number) {
std::string os_info;
- base::StringAppendF(
- &os_info,
- "%s%s%s",
- getUserAgentPlatform().c_str(),
- BuildOSCpuInfo().c_str(),
- extra_os_info.c_str());
+ base::StringAppendF(&os_info, "%s%s%s", getUserAgentPlatform().c_str(),
+ BuildOSCpuInfo(include_android_build_number).c_str(),
+ extra_os_info.c_str());
return BuildUserAgentFromOSAndProduct(os_info, product);
}
+#endif
std::string BuildUserAgentFromOSAndProduct(const std::string& os_info,
const std::string& product) {
diff --git a/chromium/content/common/view_messages.h b/chromium/content/common/view_messages.h
index 74d2df78226..cb6ce7bcfb3 100644
--- a/chromium/content/common/view_messages.h
+++ b/chromium/content/common/view_messages.h
@@ -97,14 +97,8 @@ IPC_ENUM_TRAITS_MAX_VALUE(content::NavigationGesture,
IPC_ENUM_TRAITS_MIN_MAX_VALUE(content::PageZoom,
content::PageZoom::PAGE_ZOOM_OUT,
content::PageZoom::PAGE_ZOOM_IN)
-IPC_ENUM_TRAITS_MAX_VALUE(gfx::FontRenderParams::Hinting,
- gfx::FontRenderParams::HINTING_MAX)
-IPC_ENUM_TRAITS_MAX_VALUE(gfx::FontRenderParams::SubpixelRendering,
- gfx::FontRenderParams::SUBPIXEL_RENDERING_MAX)
IPC_ENUM_TRAITS_MAX_VALUE(content::ScreenOrientationValues,
content::SCREEN_ORIENTATION_VALUES_LAST)
-IPC_ENUM_TRAITS_MAX_VALUE(content::TapMultipleTargetsStrategy,
- content::TAP_MULTIPLE_TARGETS_STRATEGY_MAX)
IPC_ENUM_TRAITS_MAX_VALUE(content::ThreeDAPIType,
content::THREE_D_API_TYPE_LAST)
IPC_ENUM_TRAITS_MAX_VALUE(ui::TextInputMode, ui::TEXT_INPUT_MODE_MAX)
@@ -190,58 +184,6 @@ IPC_STRUCT_TRAITS_BEGIN(content::DateTimeSuggestion)
IPC_STRUCT_TRAITS_MEMBER(label)
IPC_STRUCT_TRAITS_END()
-IPC_STRUCT_TRAITS_BEGIN(content::RendererPreferences)
- IPC_STRUCT_TRAITS_MEMBER(can_accept_load_drops)
- IPC_STRUCT_TRAITS_MEMBER(should_antialias_text)
- IPC_STRUCT_TRAITS_MEMBER(hinting)
- IPC_STRUCT_TRAITS_MEMBER(use_autohinter)
- IPC_STRUCT_TRAITS_MEMBER(use_bitmaps)
- IPC_STRUCT_TRAITS_MEMBER(subpixel_rendering)
- IPC_STRUCT_TRAITS_MEMBER(use_subpixel_positioning)
- IPC_STRUCT_TRAITS_MEMBER(focus_ring_color)
- IPC_STRUCT_TRAITS_MEMBER(thumb_active_color)
- IPC_STRUCT_TRAITS_MEMBER(thumb_inactive_color)
- IPC_STRUCT_TRAITS_MEMBER(track_color)
- IPC_STRUCT_TRAITS_MEMBER(active_selection_bg_color)
- IPC_STRUCT_TRAITS_MEMBER(active_selection_fg_color)
- IPC_STRUCT_TRAITS_MEMBER(inactive_selection_bg_color)
- IPC_STRUCT_TRAITS_MEMBER(inactive_selection_fg_color)
- IPC_STRUCT_TRAITS_MEMBER(browser_handles_all_top_level_requests)
- IPC_STRUCT_TRAITS_MEMBER(caret_blink_interval)
- IPC_STRUCT_TRAITS_MEMBER(use_custom_colors)
- IPC_STRUCT_TRAITS_MEMBER(enable_referrers)
- IPC_STRUCT_TRAITS_MEMBER(enable_do_not_track)
- IPC_STRUCT_TRAITS_MEMBER(enable_encrypted_media)
- IPC_STRUCT_TRAITS_MEMBER(webrtc_ip_handling_policy)
- IPC_STRUCT_TRAITS_MEMBER(webrtc_udp_min_port)
- IPC_STRUCT_TRAITS_MEMBER(webrtc_udp_max_port)
- IPC_STRUCT_TRAITS_MEMBER(user_agent_override)
- IPC_STRUCT_TRAITS_MEMBER(accept_languages)
- IPC_STRUCT_TRAITS_MEMBER(tap_multiple_targets_strategy)
- IPC_STRUCT_TRAITS_MEMBER(disable_client_blocked_error_page)
- IPC_STRUCT_TRAITS_MEMBER(plugin_fullscreen_allowed)
- IPC_STRUCT_TRAITS_MEMBER(network_contry_iso)
-#if defined(OS_LINUX)
- IPC_STRUCT_TRAITS_MEMBER(system_font_family_name)
-#endif
-#if defined(OS_WIN)
- IPC_STRUCT_TRAITS_MEMBER(caption_font_family_name)
- IPC_STRUCT_TRAITS_MEMBER(caption_font_height)
- IPC_STRUCT_TRAITS_MEMBER(small_caption_font_family_name)
- IPC_STRUCT_TRAITS_MEMBER(small_caption_font_height)
- IPC_STRUCT_TRAITS_MEMBER(menu_font_family_name)
- IPC_STRUCT_TRAITS_MEMBER(menu_font_height)
- IPC_STRUCT_TRAITS_MEMBER(status_font_family_name)
- IPC_STRUCT_TRAITS_MEMBER(status_font_height)
- IPC_STRUCT_TRAITS_MEMBER(message_font_family_name)
- IPC_STRUCT_TRAITS_MEMBER(message_font_height)
- IPC_STRUCT_TRAITS_MEMBER(vertical_scroll_bar_width_in_dips)
- IPC_STRUCT_TRAITS_MEMBER(horizontal_scroll_bar_height_in_dips)
- IPC_STRUCT_TRAITS_MEMBER(arrow_bitmap_height_vertical_scroll_bar_in_dips)
- IPC_STRUCT_TRAITS_MEMBER(arrow_bitmap_width_horizontal_scroll_bar_in_dips)
-#endif
-IPC_STRUCT_TRAITS_END()
-
IPC_STRUCT_TRAITS_BEGIN(content::TextInputState)
IPC_STRUCT_TRAITS_MEMBER(type)
IPC_STRUCT_TRAITS_MEMBER(mode)
@@ -455,14 +397,6 @@ IPC_MESSAGE_ROUTED1(ViewMsg_PpapiBrokerPermissionResult,
bool /* result */)
#endif
-// If the ViewHostMsg_ShowDisambiguationPopup resulted in the user tapping
-// inside the popup, instruct the renderer to generate a synthetic tap at that
-// offset.
-IPC_MESSAGE_ROUTED3(ViewMsg_ResolveTapDisambiguation,
- base::TimeTicks /* timestamp */,
- gfx::Point /* tap_viewport_offset */,
- bool /* is_long_press */)
-
IPC_MESSAGE_ROUTED0(ViewMsg_SelectWordAroundCaret)
// Sent by the browser to ask the renderer to redraw. Robust to events that can
@@ -472,9 +406,10 @@ IPC_MESSAGE_ROUTED1(ViewMsg_ForceRedraw, int /* snapshot_id */)
// Sets the viewport intersection and compositor raster area on the widget for
// an out-of-process iframe.
-IPC_MESSAGE_ROUTED2(ViewMsg_SetViewportIntersection,
+IPC_MESSAGE_ROUTED3(ViewMsg_SetViewportIntersection,
gfx::Rect /* viewport_intersection */,
- gfx::Rect /* compositor_visible_rect */)
+ gfx::Rect /* compositor_visible_rect */,
+ bool /* occluded or obscured */)
// Sets the inert bit on an out-of-process iframe.
IPC_MESSAGE_ROUTED1(ViewMsg_SetIsInert, bool /* inert */)
@@ -669,13 +604,6 @@ IPC_MESSAGE_ROUTED1(ViewHostMsg_IntrinsicSizingInfoChanged,
// ViewHostMsg_UnlockMouse).
IPC_MESSAGE_ROUTED0(ViewHostMsg_UnlockMouse)
-// Notifies that multiple touch targets may have been pressed, and to show
-// the disambiguation popup.
-IPC_MESSAGE_ROUTED3(ViewHostMsg_ShowDisambiguationPopup,
- gfx::Rect, /* Border of touched targets */
- gfx::Size, /* Size of zoomed image */
- base::SharedMemoryHandle /* Bitmap pixels */)
-
// Message sent from renderer to the browser when the element that is focused
// has been touched. A bool is passed in this message which indicates if the
// node is editable.
@@ -686,6 +614,9 @@ IPC_MESSAGE_ROUTED1(ViewHostMsg_FocusedNodeTouched,
// after the frame widget has painted something.
IPC_MESSAGE_ROUTED0(ViewHostMsg_DidFirstVisuallyNonEmptyPaint)
+// Sent once the RenderWidgetCompositor issues a draw command.
+IPC_MESSAGE_ROUTED0(ViewHostMsg_DidCommitAndDrawCompositorFrame)
+
// Sent in reply to ViewMsg_WaitForNextFrameForTests.
IPC_MESSAGE_ROUTED0(ViewHostMsg_WaitForNextFrameForTests_ACK)
diff --git a/chromium/content/content_resources.grd b/chromium/content/content_resources.grd
index 5c3268a05c3..b178e346317 100644
--- a/chromium/content/content_resources.grd
+++ b/chromium/content/content_resources.grd
@@ -10,9 +10,6 @@
<translations />
<release seq="1">
<includes>
- <include name="IDR_ACCESSIBILITY_HTML" file="browser/resources/accessibility/accessibility.html" flattenhtml="true" allowexternalscript="true" compress="gzip" type="BINDATA" />
- <include name="IDR_ACCESSIBILITY_CSS" file="browser/resources/accessibility/accessibility.css" compress="gzip" type="BINDATA" />
- <include name="IDR_ACCESSIBILITY_JS" file="browser/resources/accessibility/accessibility.js" flattenhtml="true" compress="gzip" type="BINDATA" />
<include name="IDR_APPCACHE_INTERNALS_HTML" file="browser/resources/appcache/appcache_internals.html" flattenhtml="true" allowexternalscript="true" compress="gzip" type="BINDATA" />
<include name="IDR_APPCACHE_INTERNALS_JS" file="browser/resources/appcache/appcache_internals.js" flattenhtml="false" compress="gzip" type="BINDATA" />
<include name="IDR_APPCACHE_INTERNALS_CSS" file="browser/resources/appcache/appcache_internals.css" flattenhtml="true" compress="gzip" type="BINDATA" />
diff --git a/chromium/content/gpu/BUILD.gn b/chromium/content/gpu/BUILD.gn
index ee2cf00ba9a..8974e441d1b 100644
--- a/chromium/content/gpu/BUILD.gn
+++ b/chromium/content/gpu/BUILD.gn
@@ -77,6 +77,7 @@ target(link_target_type, "gpu_sources") {
"//media/mojo/clients:clients",
"//services/service_manager/public/cpp",
"//services/service_manager/public/mojom",
+ "//services/service_manager/sandbox:chromecast_sandbox_whitelist_buildflags",
"//services/shape_detection:lib",
"//services/shape_detection/public/mojom",
"//services/viz/privileged/interfaces",
diff --git a/chromium/content/gpu/DEPS b/chromium/content/gpu/DEPS
index 084a0645313..48cb1852111 100644
--- a/chromium/content/gpu/DEPS
+++ b/chromium/content/gpu/DEPS
@@ -7,9 +7,9 @@ include_rules = [
"+libGLESv2",
"+services/service_manager",
"+services/shape_detection",
- "+services/ui/common",
"+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 aa8847f9780..fdcef72b1c6 100644
--- a/chromium/content/gpu/gpu_child_thread.cc
+++ b/chromium/content/gpu/gpu_child_thread.cc
@@ -251,9 +251,7 @@ bool GpuChildThread::Send(IPC::Message* msg) {
void GpuChildThread::OnAssociatedInterfaceRequest(
const std::string& name,
mojo::ScopedInterfaceEndpointHandle handle) {
- if (associated_interfaces_.CanBindRequest(name))
- associated_interfaces_.BindRequest(name, std::move(handle));
- else
+ if (!associated_interfaces_.TryBindInterface(name, &handle))
ChildThreadImpl::OnAssociatedInterfaceRequest(name, std::move(handle));
}
diff --git a/chromium/content/gpu/gpu_child_thread.h b/chromium/content/gpu/gpu_child_thread.h
index 6e0481e8ccd..e3b0094a48c 100644
--- a/chromium/content/gpu/gpu_child_thread.h
+++ b/chromium/content/gpu/gpu_child_thread.h
@@ -22,7 +22,6 @@
#include "components/viz/service/gl/gpu_service_impl.h"
#include "components/viz/service/main/viz_main_impl.h"
#include "content/child/child_thread_impl.h"
-#include "content/common/associated_interface_registry_impl.h"
#include "gpu/config/gpu_feature_info.h"
#include "gpu/config/gpu_info.h"
#include "gpu/config/gpu_preferences.h"
@@ -37,6 +36,7 @@
#include "services/service_manager/public/cpp/service_context_ref.h"
#include "services/service_manager/public/mojom/service_factory.mojom.h"
#include "services/viz/privileged/interfaces/viz_main.mojom.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
#include "ui/gfx/native_widget_types.h"
namespace content {
@@ -108,7 +108,7 @@ class GpuChildThread : public ChildThreadImpl,
mojo::BindingSet<service_manager::mojom::ServiceFactory>
service_factory_bindings_;
- AssociatedInterfaceRegistryImpl associated_interfaces_;
+ blink::AssociatedInterfaceRegistry associated_interfaces_;
// Holds a closure that releases pending interface requests on the IO thread.
base::Closure release_pending_requests_closure_;
diff --git a/chromium/content/gpu/gpu_main.cc b/chromium/content/gpu/gpu_main.cc
index f14c045d47a..f589d015d71 100644
--- a/chromium/content/gpu/gpu_main.cc
+++ b/chromium/content/gpu/gpu_main.cc
@@ -16,7 +16,6 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/sys_info.h"
-#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
#include "base/threading/platform_thread.h"
#include "base/timer/hi_res_timer_manager.h"
#include "base/trace_event/trace_event.h"
diff --git a/chromium/content/gpu/gpu_sandbox_hook_linux.cc b/chromium/content/gpu/gpu_sandbox_hook_linux.cc
index cd914e2f992..4806a3f33b7 100644
--- a/chromium/content/gpu/gpu_sandbox_hook_linux.cc
+++ b/chromium/content/gpu/gpu_sandbox_hook_linux.cc
@@ -24,6 +24,7 @@
#include "sandbox/linux/syscall_broker/broker_file_permission.h"
#include "sandbox/linux/syscall_broker/broker_process.h"
#include "services/service_manager/embedder/set_process_title.h"
+#include "services/service_manager/sandbox/chromecast_sandbox_whitelist_buildflags.h"
#include "services/service_manager/sandbox/linux/bpf_cros_amd_gpu_policy_linux.h"
#include "services/service_manager/sandbox/linux/bpf_cros_arm_gpu_policy_linux.h"
#include "services/service_manager/sandbox/linux/bpf_gpu_policy_linux.h"
@@ -44,6 +45,14 @@ inline bool IsChromeOS() {
#endif
}
+inline bool UseChromecastSandboxWhitelist() {
+#if BUILDFLAG(ENABLE_CHROMECAST_GPU_SANDBOX_WHITELIST)
+ return true;
+#else
+ return false;
+#endif
+}
+
inline bool IsArchitectureArm() {
#if defined(ARCH_CPU_ARM_FAMILY)
return true;
@@ -127,8 +136,13 @@ void AddAmdGpuWhitelist(std::vector<BrokerFilePermission>* permissions) {
for (const char* item : kReadWriteList)
permissions->push_back(BrokerFilePermission::ReadWrite(item));
- static const char kCharDevices[] = "/sys/dev/char/";
- permissions->push_back(BrokerFilePermission::ReadOnlyRecursive(kCharDevices));
+ static const char* kDevices[] = {"/sys/dev/char", "/sys/devices"};
+ for (const char* item : kDevices) {
+ std::string path(item);
+ permissions->push_back(
+ BrokerFilePermission::StatOnlyWithIntermediateDirs(path));
+ permissions->push_back(BrokerFilePermission::ReadOnlyRecursive(path + "/"));
+ }
}
void AddArmGpuWhitelist(std::vector<BrokerFilePermission>* permissions) {
@@ -149,6 +163,31 @@ void AddArmGpuWhitelist(std::vector<BrokerFilePermission>* permissions) {
AddArmMaliGpuWhitelist(permissions);
}
+// Need to look in vendor paths for custom vendor implementations.
+static const char* const kWhitelistedChromecastPaths[] = {
+ "/oem_cast_shlib/", "/system/vendor/lib/", "/system/lib/"};
+
+void AddChromecastArmGpuWhitelist(
+ std::vector<BrokerFilePermission>* permissions) {
+ // Device file needed by the ARM GPU userspace.
+ static const char kMali0Path[] = "/dev/mali0";
+ permissions->push_back(BrokerFilePermission::ReadWrite(kMali0Path));
+
+ // Files needed by the ARM GPU userspace.
+ static const char* const kReadOnlyLibraries[] = {"libGLESv2.so.2",
+ "libEGL.so.1"};
+
+ for (const char* library : kReadOnlyLibraries) {
+ for (const char* path : kWhitelistedChromecastPaths) {
+ const std::string library_path(std::string(path) + std::string(library));
+ permissions->push_back(BrokerFilePermission::ReadOnly(library_path));
+ }
+ }
+
+ static const char kLdSoCache[] = "/etc/ld.so.cache";
+ permissions->push_back(BrokerFilePermission::ReadOnly(kLdSoCache));
+}
+
void AddStandardGpuWhiteList(std::vector<BrokerFilePermission>* permissions) {
static const char kDriCardBasePath[] = "/dev/dri/card";
static const char kNvidiaCtlPath[] = "/dev/nvidiactl";
@@ -197,16 +236,31 @@ std::vector<BrokerFilePermission> FilePermissionsForGpu(
return permissions;
}
}
+
+ if (UseChromecastSandboxWhitelist() && IsArchitectureArm()) {
+ AddChromecastArmGpuWhitelist(&permissions);
+ return permissions;
+ }
+
AddStandardGpuWhiteList(&permissions);
return permissions;
}
void LoadArmGpuLibraries() {
// Preload the Mali library.
- dlopen("/usr/lib/libmali.so", dlopen_flag);
+ if (UseChromecastSandboxWhitelist()) {
+ for (const char* path : kWhitelistedChromecastPaths) {
+ const std::string library_path(std::string(path) +
+ std::string("libMali.so"));
+ if (dlopen(library_path.c_str(), dlopen_flag))
+ break;
+ }
+ } else {
+ dlopen("/usr/lib/libmali.so", dlopen_flag);
- // Preload the Tegra V4L2 (video decode acceleration) library.
- dlopen("/usr/lib/libtegrav4l2.so", dlopen_flag);
+ // Preload the Tegra V4L2 (video decode acceleration) library.
+ dlopen("/usr/lib/libtegrav4l2.so", dlopen_flag);
+ }
}
bool LoadAmdGpuLibraries() {
@@ -256,6 +310,8 @@ bool LoadLibrariesForGpu(
}
if (options.use_amd_specific_policies)
return LoadAmdGpuLibraries();
+ } else if (UseChromecastSandboxWhitelist() && IsArchitectureArm()) {
+ LoadArmGpuLibraries();
}
return true;
}
diff --git a/chromium/content/gpu/gpu_service_factory.cc b/chromium/content/gpu/gpu_service_factory.cc
index 844125a7c6c..1f90da0f591 100644
--- a/chromium/content/gpu/gpu_service_factory.cc
+++ b/chromium/content/gpu/gpu_service_factory.cc
@@ -6,7 +6,7 @@
#include <memory>
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "services/shape_detection/public/mojom/constants.mojom.h"
diff --git a/chromium/content/ppapi_plugin/DEPS b/chromium/content/ppapi_plugin/DEPS
index fc443d2e7ad..3bcfb601048 100644
--- a/chromium/content/ppapi_plugin/DEPS
+++ b/chromium/content/ppapi_plugin/DEPS
@@ -7,5 +7,5 @@ include_rules = [
"+ppapi/proxy",
"+services/service_manager/public/cpp",
"+services/service_manager/sandbox",
- "+services/ui/public/interfaces",
+ "+services/ws/public/mojom",
]
diff --git a/chromium/content/ppapi_plugin/ppapi_blink_platform_impl.cc b/chromium/content/ppapi_plugin/ppapi_blink_platform_impl.cc
index 25ca97ea4b8..c88de7f36b3 100644
--- a/chromium/content/ppapi_plugin/ppapi_blink_platform_impl.cc
+++ b/chromium/content/ppapi_plugin/ppapi_blink_platform_impl.cc
@@ -181,19 +181,6 @@ bool PpapiBlinkPlatformImpl::IsLinkVisited(unsigned long long link_hash) {
return false;
}
-void PpapiBlinkPlatformImpl::setCookies(const blink::WebURL& url,
- const blink::WebURL& site_for_cookies,
- const blink::WebString& value) {
- NOTREACHED();
-}
-
-blink::WebString PpapiBlinkPlatformImpl::cookies(
- const blink::WebURL& url,
- const blink::WebURL& site_for_cookies) {
- NOTREACHED();
- return blink::WebString();
-}
-
blink::WebString PpapiBlinkPlatformImpl::DefaultLocale() {
return blink::WebString::FromUTF8("en");
}
@@ -214,16 +201,6 @@ PpapiBlinkPlatformImpl::CreateLocalStorageNamespace() {
return nullptr;
}
-void PpapiBlinkPlatformImpl::dispatchStorageEvent(
- const blink::WebString& key,
- const blink::WebString& old_value,
- const blink::WebString& new_value,
- const blink::WebString& origin,
- const blink::WebURL& url,
- bool is_local_storage) {
- NOTREACHED();
-}
-
int PpapiBlinkPlatformImpl::DatabaseDeleteFile(
const blink::WebString& vfs_file_name,
bool sync_dir) {
diff --git a/chromium/content/ppapi_plugin/ppapi_blink_platform_impl.h b/chromium/content/ppapi_plugin/ppapi_blink_platform_impl.h
index aea9579c6f8..6e96a9571a7 100644
--- a/chromium/content/ppapi_plugin/ppapi_blink_platform_impl.h
+++ b/chromium/content/ppapi_plugin/ppapi_blink_platform_impl.h
@@ -32,23 +32,14 @@ class PpapiBlinkPlatformImpl : public BlinkPlatformImpl {
blink::WebThread* CurrentThread() override;
blink::WebSandboxSupport* GetSandboxSupport() override;
virtual bool sandboxEnabled();
- unsigned long long VisitedLinkHash(const char* canonicalURL,
+ unsigned long long VisitedLinkHash(const char* canonical_url,
size_t length) override;
- bool IsLinkVisited(unsigned long long linkHash) override;
- virtual void setCookies(const blink::WebURL& url,
- const blink::WebURL& site_for_cookies,
- const blink::WebString& value);
- virtual blink::WebString cookies(const blink::WebURL& url,
- const blink::WebURL& site_for_cookies);
+ bool IsLinkVisited(unsigned long long link_hash) override;
blink::WebString DefaultLocale() override;
blink::WebThemeEngine* ThemeEngine() override;
blink::WebData GetDataResource(const char* name) override;
std::unique_ptr<blink::WebStorageNamespace> CreateLocalStorageNamespace()
override;
- virtual void dispatchStorageEvent(const blink::WebString& key,
- const blink::WebString& oldValue, const blink::WebString& newValue,
- const blink::WebString& origin, const blink::WebURL& url,
- bool isLocalStorage);
int DatabaseDeleteFile(const blink::WebString& vfs_file_name,
bool sync_dir) override;
diff --git a/chromium/content/ppapi_plugin/ppapi_thread.cc b/chromium/content/ppapi_plugin/ppapi_thread.cc
index 82b1ebfdd54..7e496c5710d 100644
--- a/chromium/content/ppapi_plugin/ppapi_thread.cc
+++ b/chromium/content/ppapi_plugin/ppapi_thread.cc
@@ -51,7 +51,7 @@
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/proxy/resource_reply_thread_registrar.h"
#include "services/service_manager/public/cpp/connector.h"
-#include "services/ui/public/interfaces/constants.mojom.h"
+#include "services/ws/public/mojom/constants.mojom.h"
#include "third_party/blink/public/web/blink.h"
#include "ui/base/ui_base_features.h"
#include "ui/base/ui_base_switches.h"
@@ -105,7 +105,8 @@ PpapiThread::PpapiThread(const base::CommandLine& command_line, bool is_broker)
command_line.GetSwitchValueASCII(switches::kPpapiFlashArgs));
blink_platform_impl_.reset(new PpapiBlinkPlatformImpl);
- blink::Platform::Initialize(blink_platform_impl_.get());
+ blink::Platform::Initialize(blink_platform_impl_.get(),
+ blink_platform_impl_->CurrentThread());
if (!is_broker_) {
scoped_refptr<ppapi::proxy::PluginMessageFilter> plugin_filter(
@@ -119,10 +120,10 @@ PpapiThread::PpapiThread(const base::CommandLine& command_line, bool is_broker)
// allocator.
if (!command_line.HasSwitch(switches::kSingleProcess)) {
discardable_memory::mojom::DiscardableSharedMemoryManagerPtr manager_ptr;
- if (!features::IsAshInBrowserProcess()) {
+ if (features::IsUsingWindowService()) {
#if defined(USE_AURA)
GetServiceManagerConnection()->GetConnector()->BindInterface(
- ui::mojom::kServiceName, &manager_ptr);
+ ws::mojom::kServiceName, &manager_ptr);
#else
NOTREACHED();
#endif
@@ -296,16 +297,17 @@ void PpapiThread::OnLoadPlugin(const base::FilePath& path,
// client) then fetch the entry points from the embedder, rather than a DLL.
std::vector<PepperPluginInfo> plugins;
GetContentClient()->AddPepperPlugins(&plugins);
- for (size_t i = 0; i < plugins.size(); ++i) {
- if (plugins[i].is_internal && plugins[i].path == path) {
+ for (const auto& plugin : plugins) {
+ if (plugin.is_internal && plugin.path == path) {
// An internal plugin is being loaded, so fetch the entry points.
- plugin_entry_points_ = plugins[i].internal_entry_points;
+ plugin_entry_points_ = plugin.internal_entry_points;
+ break;
}
}
// If the plugin isn't internal then load it from |path|.
base::ScopedNativeLibrary library;
- if (plugin_entry_points_.initialize_module == nullptr) {
+ if (!plugin_entry_points_.initialize_module) {
// Load the plugin from the specified library.
base::NativeLibraryLoadError error;
base::TimeDelta load_time;
diff --git a/chromium/content/public/android/BUILD.gn b/chromium/content/public/android/BUILD.gn
index 7c89dce2968..8135b931c14 100644
--- a/chromium/content/public/android/BUILD.gn
+++ b/chromium/content/public/android/BUILD.gn
@@ -133,13 +133,11 @@ android_library("content_java") {
"java/src/org/chromium/content/browser/MotionEventSynthesizerImpl.java",
"java/src/org/chromium/content/browser/NfcHost.java",
"java/src/org/chromium/content/browser/PopupController.java",
- "java/src/org/chromium/content/browser/PopupZoomer.java",
"java/src/org/chromium/content/browser/RenderCoordinatesImpl.java",
"java/src/org/chromium/content/browser/ScreenOrientationProviderImpl.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",
- "java/src/org/chromium/content/browser/TapDisambiguator.java",
"java/src/org/chromium/content/browser/TracingControllerAndroid.java",
"java/src/org/chromium/content/browser/ViewEventSinkImpl.java",
"java/src/org/chromium/content/browser/WindowEventObserver.java",
@@ -374,7 +372,6 @@ generate_jni("content_jni_headers") {
"java/src/org/chromium/content/browser/ScreenOrientationProviderImpl.java",
"java/src/org/chromium/content/browser/SpeechRecognitionImpl.java",
"java/src/org/chromium/content/browser/SyntheticGestureTarget.java",
- "java/src/org/chromium/content/browser/TapDisambiguator.java",
"java/src/org/chromium/content/browser/TracingControllerAndroid.java",
"java/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityImpl.java",
"java/src/org/chromium/content/browser/accessibility/captioning/CaptioningController.java",
@@ -456,10 +453,9 @@ android_library("content_javatests") {
"javatests/src/org/chromium/content/browser/ChildProcessLauncherHelperTest.java",
"javatests/src/org/chromium/content/browser/ClipboardTest.java",
"javatests/src/org/chromium/content/browser/ContentCommandLineTest.java",
- "javatests/src/org/chromium/content/browser/ContentViewCoreSelectionTest.java",
+ "javatests/src/org/chromium/content/browser/ContentTextSelectionTest.java",
"javatests/src/org/chromium/content/browser/ContentViewLocationTest.java",
"javatests/src/org/chromium/content/browser/ContentViewPointerTypeTest.java",
- "javatests/src/org/chromium/content/browser/ContentViewPopupZoomerTest.java",
"javatests/src/org/chromium/content/browser/ContentViewScrollingTest.java",
"javatests/src/org/chromium/content/browser/EncodeHtmlDataUriTest.java",
"javatests/src/org/chromium/content/browser/GestureDetectorResetTest.java",
@@ -476,7 +472,6 @@ android_library("content_javatests") {
"javatests/src/org/chromium/content/browser/JavaBridgeReturnValuesTest.java",
"javatests/src/org/chromium/content/browser/MediaSessionTest.java",
"javatests/src/org/chromium/content/browser/NavigationTest.java",
- "javatests/src/org/chromium/content/browser/PopupZoomerTest.java",
"javatests/src/org/chromium/content/browser/ScreenOrientationListenerTest.java",
"javatests/src/org/chromium/content/browser/TestsJavaScriptEvalTest.java",
"javatests/src/org/chromium/content/browser/TracingControllerAndroidTest.java",
diff --git a/chromium/content/public/app/BUILD.gn b/chromium/content/public/app/BUILD.gn
index 4bf09585be2..43eab316e9a 100644
--- a/chromium/content/public/app/BUILD.gn
+++ b/chromium/content/public/app/BUILD.gn
@@ -22,6 +22,7 @@
import("//build/config/chrome_build.gni")
import("//build/config/ui.gni")
+import("//chromeos/assistant/assistant.gni")
import("//services/service_manager/public/service_manifest.gni")
import("//tools/v8_context_snapshot/v8_context_snapshot.gni")
import("//ui/base/ui_features.gni")
@@ -201,6 +202,11 @@ service_manifest("packaged_services_manifest") {
if (is_linux) {
packaged_services += [ "//components/services/font:manifest" ]
}
+
+ if (enable_cros_libassistant) {
+ packaged_services +=
+ [ "//chromeos/services/assistant/audio_decoder:manifest" ]
+ }
}
service_manifest("browser_manifest") {
diff --git a/chromium/content/public/app/content_main_delegate.h b/chromium/content/public/app/content_main_delegate.h
index 979e25d1c1b..42310279092 100644
--- a/chromium/content/public/app/content_main_delegate.h
+++ b/chromium/content/public/app/content_main_delegate.h
@@ -125,10 +125,14 @@ class CONTENT_EXPORT ContentMainDelegate {
const base::Closure& quit_closure,
service_manager::BackgroundServiceManager* service_manager);
+ // Allows the embedder to perform platform-specific initializatioion before
+ // creating the main message loop.
+ virtual void PreCreateMainMessageLoop() {}
+
// Allows the embedder to perform platform-specific initializatioion. For
- // example, things that should be done immediately before the creation of the
- // main message loop.
- virtual void PreContentInitialization() {}
+ // example, things that should be done right after TaskScheduler starts and
+ // the main MessageLoop was installed.
+ virtual void PostEarlyInitialization() {}
protected:
friend class ContentClientInitializer;
diff --git a/chromium/content/public/app/mojo/content_browser_manifest.json b/chromium/content/public/app/mojo/content_browser_manifest.json
index 96f8e822a91..c2e72da4f59 100644
--- a/chromium/content/public/app/mojo/content_browser_manifest.json
+++ b/chromium/content/public/app/mojo/content_browser_manifest.json
@@ -27,20 +27,22 @@
"media.mojom.AndroidOverlayProvider"
],
"gpu_client": [
- "ui.mojom.Gpu"
+ "ws.mojom.Gpu"
],
"plugin": [
"discardable_memory.mojom.DiscardableSharedMemoryManager",
- "ui.mojom.Gpu"
+ "ws.mojom.Gpu"
],
"renderer": [
"blink.mojom.BackgroundSyncService",
"blink.mojom.BlobRegistry",
"blink.mojom.BroadcastChannelProvider",
"blink.mojom.ClipboardHost",
+ "blink.mojom.FontUniqueNameLookup",
"blink.mojom.EmbeddedFrameSinkProvider",
"blink.mojom.FileUtilitiesHost",
- "blink.mojom.LockManager",
+ "blink.mojom.FileSystemManager",
+ "blink.mojom.IDBFactory",
"blink.mojom.Hyphenation",
"blink.mojom.MimeRegistry",
"blink.mojom.PluginRegistry",
@@ -66,10 +68,11 @@
"media.mojom.VideoDecodePerfHistory",
"memory_coordinator.mojom.MemoryCoordinatorHandle",
"metrics.mojom.SingleSampleMetricsProvider",
+ "network.mojom.P2PSocketManager",
"network.mojom.URLLoaderFactory",
"resource_coordinator.mojom.ProcessCoordinationUnit",
- "ui.mojom.Gpu",
- "viz.mojom.CompositingModeReporter"
+ "viz.mojom.CompositingModeReporter",
+ "ws.mojom.Gpu"
],
"service_manager:service_factory": [
"service_manager.mojom.ServiceFactory"
@@ -134,7 +137,7 @@
"tracing": [
"tracing"
],
- "ui": [ "arc_manager", "display_output_protection", "video_detector" ],
+ "ui": [ "arc_manager" ],
"unzip_service": [ "unzip_file" ],
"video_capture": [ "capture", "tests" ]
}
@@ -148,9 +151,9 @@
"autofill.mojom.AutofillDriver",
"autofill.mojom.PasswordManagerDriver",
"blink.mojom.AnchorElementMetricsHost",
+ "blink.mojom.AudioContextManager",
"blink.mojom.Authenticator",
"blink.mojom.BackgroundFetchService",
- "blink.mojom.BudgetService",
"blink.mojom.CacheStorage",
"blink.mojom.ColorChooserFactory",
"blink.mojom.CredentialManager",
@@ -164,6 +167,7 @@
"blink.mojom.MediaSessionService",
"blink.mojom.NotificationService",
"blink.mojom.PermissionService",
+ "blink.mojom.Portal",
"blink.mojom.PrefetchURLLoaderService",
"blink.mojom.PresentationService",
"blink.mojom.QuotaDispatcherHost",
@@ -171,6 +175,7 @@
"blink.mojom.TextSuggestionHost",
"blink.mojom.UnhandledTapNotifier",
"blink.mojom.WebBluetoothService",
+ "blink.mojom.WebUsbService",
"blink.test.mojom.VirtualAuthenticatorManager",
@@ -189,10 +194,7 @@
"device.mojom.NFC",
"device.mojom.SensorProvider",
"device.mojom.UsbChooserService",
- "device.mojom.UsbDeviceManager",
"device.mojom.VibrationManager",
- "device.mojom.UsbDeviceManager",
- "device.mojom.VRService",
"device.mojom.VRService",
"device.mojom.WakeLock",
"discardable_memory.mojom.DiscardableSharedMemoryManager",
@@ -210,7 +212,7 @@
"shape_detection.mojom.BarcodeDetectionProvider",
"shape_detection.mojom.FaceDetectionProvider",
"shape_detection.mojom.TextDetection",
- "ui.mojom.Gpu"
+ "ws.mojom.Gpu"
]
},
"requires": {
@@ -220,14 +222,13 @@
"navigation:dedicated_worker": {
"provides": {
"renderer": [
- "blink.mojom.BudgetService",
"blink.mojom.CacheStorage",
"blink.mojom.DedicatedWorkerFactory",
"blink.mojom.LockManager",
"blink.mojom.NotificationService",
"blink.mojom.PermissionService",
"blink.mojom.QuotaDispatcherHost",
- "device.mojom.UsbDeviceManager",
+ "blink.mojom.WebUsbService",
"network.mojom.WebSocket",
"payments.mojom.PaymentManager",
"shape_detection.mojom.BarcodeDetectionProvider",
@@ -240,7 +241,6 @@
"provides": {
"renderer": [
"blink.mojom.BackgroundFetchService",
- "blink.mojom.BudgetService",
"blink.mojom.CacheStorage",
"blink.mojom.CookieStore",
"blink.mojom.LockManager",
@@ -259,7 +259,6 @@
"navigation:shared_worker": {
"provides": {
"renderer": [
- "blink.mojom.BudgetService",
"blink.mojom.CacheStorage",
"blink.mojom.LockManager",
"blink.mojom.NotificationService",
diff --git a/chromium/content/public/app/mojo/content_gpu_manifest.json b/chromium/content/public/app/mojo/content_gpu_manifest.json
index 1335cff15ee..f56ca6cc0d1 100644
--- a/chromium/content/public/app/mojo/content_gpu_manifest.json
+++ b/chromium/content/public/app/mojo/content_gpu_manifest.json
@@ -14,6 +14,7 @@
"service_manager.mojom.ServiceFactory",
"ui.ozone.mojom.DeviceCursor",
"ui.ozone.mojom.DrmDevice",
+ "ui.ozone.mojom.WaylandConnectionClient",
"viz.mojom.CompositingModeReporter",
"viz.mojom.VizMain"
],
diff --git a/chromium/content/public/app/mojo/content_packaged_services_manifest.json b/chromium/content/public/app/mojo/content_packaged_services_manifest.json
index 7bee3760674..eee8e3b2072 100644
--- a/chromium/content/public/app/mojo/content_packaged_services_manifest.json
+++ b/chromium/content/public/app/mojo/content_packaged_services_manifest.json
@@ -8,6 +8,9 @@
{
"name": "content_packaged_services",
"display_name": "Content Packaged Services",
+ "options" : {
+ "instance_sharing" : "singleton"
+ },
"interface_provider_specs": {
"service_manager:connector": {
"provides": {
@@ -20,7 +23,6 @@
"content_browser": [],
"service_manager": [
"service_manager:client_process",
- "service_manager:singleton",
"service_manager:user_id"
]
}
diff --git a/chromium/content/public/app/mojo/content_renderer_manifest.json b/chromium/content/public/app/mojo/content_renderer_manifest.json
index 70c678203f2..4ae4abecffb 100644
--- a/chromium/content/public/app/mojo/content_renderer_manifest.json
+++ b/chromium/content/public/app/mojo/content_renderer_manifest.json
@@ -5,6 +5,7 @@
"service_manager:connector": {
"provides": {
"browser": [
+ "blink.mojom.CrashMemoryMetricsReporter",
"blink.mojom.LeakDetector",
"blink.mojom.OomIntervention",
"blink.mojom.WebDatabase",
diff --git a/chromium/content/public/browser/BUILD.gn b/chromium/content/public/browser/BUILD.gn
index cb9b7ba284b..ed1ba21b7b7 100644
--- a/chromium/content/public/browser/BUILD.gn
+++ b/chromium/content/public/browser/BUILD.gn
@@ -36,6 +36,8 @@ jumbo_source_set("browser_sources") {
"android/synchronous_compositor.h",
"android/synchronous_compositor_client.h",
"appcache_service.h",
+ "audio_loopback_stream_creator.cc",
+ "audio_loopback_stream_creator.h",
"audio_service_info.cc",
"audio_service_info.h",
"authenticator_request_client_delegate.cc",
@@ -77,6 +79,8 @@ jumbo_source_set("browser_sources") {
"browser_plugin_guest_manager.cc",
"browser_plugin_guest_manager.h",
"browser_ppapi_host.h",
+ "browser_task_traits.cc",
+ "browser_task_traits.h",
"browser_thread.h",
"browser_thread_delegate.h",
"browser_url_handler.h",
@@ -87,6 +91,7 @@ jumbo_source_set("browser_sources") {
"cache_storage_usage_info.h",
"cdm_registry.h",
"certificate_request_result_type.h",
+ "child_process_data.cc",
"child_process_data.h",
"child_process_launcher_utils.h",
"child_process_security_policy.h",
@@ -101,6 +106,7 @@ jumbo_source_set("browser_sources") {
"desktop_capture.h",
"desktop_media_id.cc",
"desktop_media_id.h",
+ "desktop_streams_registry.h",
"devtools_agent_host.h",
"devtools_agent_host_client.cc",
"devtools_agent_host_client.h",
@@ -129,6 +135,7 @@ jumbo_source_set("browser_sources") {
"font_list_async.h",
"frame_service_base.h",
"global_request_id.h",
+ "global_routing_id.h",
"gpu_client.h",
"gpu_data_manager.h",
"gpu_data_manager_observer.h",
@@ -166,6 +173,9 @@ jumbo_source_set("browser_sources") {
"memory_coordinator_delegate.h",
"message_port_provider.h",
"mhtml_extra_parts.h",
+ "native_event_processor_mac.h",
+ "native_event_processor_observer_mac.h",
+ "native_event_processor_observer_mac.mm",
"native_web_keyboard_event.h",
"navigation_controller.cc",
"navigation_controller.h",
@@ -179,8 +189,6 @@ jumbo_source_set("browser_sources") {
"navigation_throttle.h",
"navigation_type.h",
"navigation_ui_data.h",
- "network_connection_tracker.cc",
- "network_connection_tracker.h",
"network_quality_observer_factory.h",
"network_service_instance.h",
"notification_database_data.cc",
@@ -329,13 +337,16 @@ jumbo_source_set("browser_sources") {
"//content/public/common:common_sources",
"//device/usb/public/mojom",
"//ipc",
+ "//media/mojo/interfaces:remoting",
"//mojo/public/cpp/bindings",
"//mojo/public/cpp/system",
+ "//services/media_session/public/cpp",
+ "//services/media_session/public/mojom",
"//services/network/public/mojom",
"//services/resource_coordinator/public/cpp:resource_coordinator_cpp",
"//services/service_manager/public/cpp",
"//services/tracing/public/cpp",
- "//services/ui/public/interfaces",
+ "//services/ws/public/mojom",
"//third_party/webrtc/modules/desktop_capture",
# We expose skia headers in the public API.
@@ -347,7 +358,9 @@ jumbo_source_set("browser_sources") {
]
deps = [
"//cc",
+ "//components/viz/host",
"//content/browser", # Must not be public_deps!
+ "//device/fido",
"//gpu",
"//gpu/command_buffer/service:gles2",
"//media",
diff --git a/chromium/content/public/browser/DEPS b/chromium/content/public/browser/DEPS
index 3b73764c818..40897244c89 100644
--- a/chromium/content/public/browser/DEPS
+++ b/chromium/content/public/browser/DEPS
@@ -3,12 +3,15 @@ include_rules = [
# TODO(qinmin): move it to services/download when download becomes a service.
"+components/download/public/common",
"+components/viz/common",
+ "+components/viz/host",
"+device/usb/public/mojom",
+ "+device/fido",
"+services/device/public",
+ "+services/media_session/public",
"+services/network/public/cpp",
"+services/service_manager/sandbox",
"+services/resource_coordinator/public",
- "+services/ui/public/interfaces",
+ "+services/ws/public/mojom",
]
specific_include_rules = {
diff --git a/chromium/content/public/browser/android/synchronous_compositor.h b/chromium/content/public/browser/android/synchronous_compositor.h
index a086271d7fa..7d679567508 100644
--- a/chromium/content/public/browser/android/synchronous_compositor.h
+++ b/chromium/content/public/browser/android/synchronous_compositor.h
@@ -97,6 +97,10 @@ class CONTENT_EXPORT SynchronousCompositor {
// Set the memory limit policy of this compositor.
virtual void SetMemoryPolicy(size_t bytes_limit) = 0;
+ // Called during renderer swap. Should push any relevant up to
+ // SynchronousCompositorClient.
+ virtual void DidBecomeActive() = 0;
+
// Should be called by the embedder after the embedder had modified the
// scroll offset of the root layer. |root_offset| must be in physical pixel
// scale if --use-zoom-for-dsf is enabled. Otherwise, it must be in DIP scale.
diff --git a/chromium/content/public/browser/appcache_service.h b/chromium/content/public/browser/appcache_service.h
index a6b83ee3ca8..0e140ae0e9c 100644
--- a/chromium/content/public/browser/appcache_service.h
+++ b/chromium/content/public/browser/appcache_service.h
@@ -12,7 +12,7 @@
#include "base/memory/ref_counted.h"
#include "content/common/content_export.h"
#include "content/public/common/appcache_info.h"
-#include "net/base/completion_callback.h"
+#include "net/base/completion_once_callback.h"
#include "url/origin.h"
namespace content {
@@ -46,7 +46,7 @@ class CONTENT_EXPORT AppCacheService {
// subresource loads for pages associated with a deleted group
// will fail. This method always completes asynchronously.
virtual void DeleteAppCacheGroup(const GURL& manifest_url,
- const net::CompletionCallback& callback) = 0;
+ net::CompletionOnceCallback callback) = 0;
protected:
virtual ~AppCacheService() {}
diff --git a/chromium/content/public/browser/audio_loopback_stream_creator.cc b/chromium/content/public/browser/audio_loopback_stream_creator.cc
new file mode 100644
index 00000000000..cf1f4c5a1e2
--- /dev/null
+++ b/chromium/content/public/browser/audio_loopback_stream_creator.cc
@@ -0,0 +1,19 @@
+// 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/audio_loopback_stream_creator.h"
+
+#include "content/browser/media/in_process_audio_loopback_stream_creator.h"
+
+namespace content {
+
+// static
+std::unique_ptr<AudioLoopbackStreamCreator>
+AudioLoopbackStreamCreator::CreateInProcessAudioLoopbackStreamCreator() {
+ return std::make_unique<InProcessAudioLoopbackStreamCreator>();
+}
+
+AudioLoopbackStreamCreator::~AudioLoopbackStreamCreator() = default;
+
+} // namespace content
diff --git a/chromium/content/public/browser/audio_loopback_stream_creator.h b/chromium/content/public/browser/audio_loopback_stream_creator.h
new file mode 100644
index 00000000000..f6fbb2eff71
--- /dev/null
+++ b/chromium/content/public/browser/audio_loopback_stream_creator.h
@@ -0,0 +1,53 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_PUBLIC_BROWSER_AUDIO_LOOPBACK_STREAM_CREATOR_H_
+#define CONTENT_PUBLIC_BROWSER_AUDIO_LOOPBACK_STREAM_CREATOR_H_
+
+#include "base/callback.h"
+#include "content/common/content_export.h"
+#include "media/mojo/interfaces/audio_data_pipe.mojom.h"
+#include "media/mojo/interfaces/audio_input_stream.mojom.h"
+
+namespace media {
+class AudioParameters;
+}
+
+namespace content {
+
+class WebContents;
+
+// This interface is used by the embedder to ask the Audio Service to create a
+// loopback stream that either captures audio from a tab or the system-wide
+// loopback.
+// Note: Use this to request loopback audio for a privileged embedder feature,
+// and not for consumption by a renderer. For renderers, use the
+// mojom::RendererAudioInputStreamFactory interface instead.
+class CONTENT_EXPORT AudioLoopbackStreamCreator {
+ public:
+ virtual ~AudioLoopbackStreamCreator();
+
+ // The callback that is called when the requested stream is created.
+ using StreamCreatedCallback = base::RepeatingCallback<void(
+ media::mojom::AudioInputStreamPtr stream,
+ media::mojom::AudioInputStreamClientRequest client_request,
+ media::mojom::ReadOnlyAudioDataPipePtr data_pipe)>;
+
+ // Creates an InProcessAudioLoopbackStreamCreator that handles creating audio
+ // loopback stream through the Audio Service.
+ static std::unique_ptr<AudioLoopbackStreamCreator>
+ CreateInProcessAudioLoopbackStreamCreator();
+
+ // Creates a loopback stream that captures the audio from |loopback_source|,
+ // or the default system playback if |loopback_source| is null. Local output
+ // of the source/system audio is muted during capturing.
+ virtual void CreateLoopbackStream(WebContents* loopback_source,
+ const media::AudioParameters& params,
+ uint32_t total_segments,
+ const StreamCreatedCallback& callback) = 0;
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_BROWSER_AUDIO_LOOPBACK_STREAM_CREATOR_H_
diff --git a/chromium/content/public/browser/authenticator_request_client_delegate.cc b/chromium/content/public/browser/authenticator_request_client_delegate.cc
index 2f06e057efa..8d771934560 100644
--- a/chromium/content/public/browser/authenticator_request_client_delegate.cc
+++ b/chromium/content/public/browser/authenticator_request_client_delegate.cc
@@ -4,6 +4,8 @@
#include "content/public/browser/authenticator_request_client_delegate.h"
+#include <utility>
+
#include "base/callback.h"
#include "base/strings/string_piece.h"
@@ -14,7 +16,13 @@ AuthenticatorRequestClientDelegate::AuthenticatorRequestClientDelegate() =
AuthenticatorRequestClientDelegate::~AuthenticatorRequestClientDelegate() =
default;
-void AuthenticatorRequestClientDelegate::DidStartRequest() {}
+void AuthenticatorRequestClientDelegate::DidFailWithInterestingReason(
+ InterestingFailureReason reason) {}
+
+void AuthenticatorRequestClientDelegate::RegisterActionCallbacks(
+ base::OnceClosure cancel_callback,
+ device::FidoRequestHandlerBase::RequestCallback request_callback,
+ base::RepeatingClosure bluetooth_adapter_power_on_callback) {}
bool AuthenticatorRequestClientDelegate::ShouldPermitIndividualAttestation(
const std::string& relying_party_id) {
@@ -38,4 +46,24 @@ AuthenticatorRequestClientDelegate::GetTouchIdAuthenticatorConfig() const {
}
#endif
+void AuthenticatorRequestClientDelegate::UpdateLastTransportUsed(
+ device::FidoTransportProtocol transport) {}
+
+void AuthenticatorRequestClientDelegate::OnTransportAvailabilityEnumerated(
+ device::FidoRequestHandlerBase::TransportAvailabilityInfo data) {}
+
+bool AuthenticatorRequestClientDelegate::EmbedderControlsAuthenticatorDispatch(
+ const device::FidoAuthenticator& authenticator) {
+ return false;
+}
+
+void AuthenticatorRequestClientDelegate::BluetoothAdapterPowerChanged(
+ bool is_powered_on) {}
+
+void AuthenticatorRequestClientDelegate::FidoAuthenticatorAdded(
+ const device::FidoAuthenticator& authenticator) {}
+
+void AuthenticatorRequestClientDelegate::FidoAuthenticatorRemoved(
+ base::StringPiece device_id) {}
+
} // namespace content
diff --git a/chromium/content/public/browser/authenticator_request_client_delegate.h b/chromium/content/public/browser/authenticator_request_client_delegate.h
index 55b41750a5d..4f11a735e1e 100644
--- a/chromium/content/public/browser/authenticator_request_client_delegate.h
+++ b/chromium/content/public/browser/authenticator_request_client_delegate.h
@@ -12,6 +12,12 @@
#include "base/optional.h"
#include "build/build_config.h"
#include "content/common/content_export.h"
+#include "device/fido/fido_request_handler_base.h"
+#include "device/fido/fido_transport_protocol.h"
+
+namespace device {
+class FidoAuthenticator;
+}
namespace content {
@@ -20,13 +26,31 @@ namespace content {
// request serviced in a given RenderFrame.
//
// [1]: See https://www.w3.org/TR/webauthn/.
-class CONTENT_EXPORT AuthenticatorRequestClientDelegate {
+class CONTENT_EXPORT AuthenticatorRequestClientDelegate
+ : public device::FidoRequestHandlerBase::TransportAvailabilityObserver {
public:
+ // Failure reasons that might be of interest to the user, so the embedder may
+ // decide to inform the user.
+ enum class InterestingFailureReason {
+ kTimeout,
+ kKeyNotRegistered,
+ kKeyAlreadyRegistered,
+ };
+
AuthenticatorRequestClientDelegate();
- virtual ~AuthenticatorRequestClientDelegate();
+ ~AuthenticatorRequestClientDelegate() override;
+
+ // Called when the request fails for the given |reason|, just before this
+ // delegate is destroyed.
+ virtual void DidFailWithInterestingReason(InterestingFailureReason reason);
- // Notifies the delegate that the request is actually starting.
- virtual void DidStartRequest();
+ // Supplies callbacks that the embedder can invoke to initiate certain
+ // actions, namely: initiate BLE pairing process, cancel WebAuthN request, and
+ // dispatch request to connected authenticators.
+ virtual void RegisterActionCallbacks(
+ base::OnceClosure cancel_callback,
+ device::FidoRequestHandlerBase::RequestCallback request_callback,
+ base::RepeatingClosure bluetooth_adapter_power_on_callback);
// Returns true if the given relying party ID is permitted to receive
// individual attestation certificates. This:
@@ -76,6 +100,29 @@ class CONTENT_EXPORT AuthenticatorRequestClientDelegate {
GetTouchIdAuthenticatorConfig() const;
#endif
+ // Saves transport type the user used during WebAuthN API so that the
+ // WebAuthN UI will default to the same transport type during next API call.
+ virtual void UpdateLastTransportUsed(device::FidoTransportProtocol transport);
+
+ // device::FidoRequestHandlerBase::TransportAvailabilityObserver:
+ void OnTransportAvailabilityEnumerated(
+ device::FidoRequestHandlerBase::TransportAvailabilityInfo data) override;
+ // If true, the request handler will defer dispatch of its request onto the
+ // given authenticator to the embedder. The embedder needs to call
+ // |StartAuthenticatorRequest| when it wants to initiate request dispatch.
+ //
+ // This method is invoked before |FidoAuthenticatorAdded|, and may be
+ // invoked multiple times for the same authenticator. Depending on the
+ // result, the request handler might decide not to make the authenticator
+ // available, in which case it never gets passed to
+ // |FidoAuthenticatorAdded|.
+ bool EmbedderControlsAuthenticatorDispatch(
+ const device::FidoAuthenticator& authenticator) override;
+ void BluetoothAdapterPowerChanged(bool is_powered_on) override;
+ void FidoAuthenticatorAdded(
+ const device::FidoAuthenticator& authenticator) override;
+ void FidoAuthenticatorRemoved(base::StringPiece device_id) override;
+
private:
DISALLOW_COPY_AND_ASSIGN(AuthenticatorRequestClientDelegate);
};
diff --git a/chromium/content/public/browser/background_fetch_delegate.h b/chromium/content/public/browser/background_fetch_delegate.h
index bf9e3ff76ab..bff9eb68a7d 100644
--- a/chromium/content/public/browser/background_fetch_delegate.h
+++ b/chromium/content/public/browser/background_fetch_delegate.h
@@ -13,7 +13,10 @@
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
+#include "base/optional.h"
#include "content/common/content_export.h"
+#include "content/public/browser/resource_request_info.h"
+#include "third_party/skia/include/core/SkBitmap.h"
class GURL;
@@ -26,6 +29,10 @@ class HttpRequestHeaders;
struct NetworkTrafficAnnotationTag;
} // namespace net
+namespace url {
+class Origin;
+} // namespace url
+
namespace content {
struct BackgroundFetchResponse;
struct BackgroundFetchResult;
@@ -38,6 +45,7 @@ enum class BackgroundFetchReasonToAbort {
ABORTED_BY_DEVELOPER,
TOTAL_DOWNLOAD_SIZE_EXCEEDED,
SERVICE_WORKER_UNAVAILABLE,
+ QUOTA_EXCEEDED,
};
// Interface for launching background fetches. Implementing classes would
@@ -47,6 +55,7 @@ enum class BackgroundFetchReasonToAbort {
class CONTENT_EXPORT BackgroundFetchDelegate {
public:
using GetIconDisplaySizeCallback = base::OnceCallback<void(const gfx::Size&)>;
+ using GetPermissionForOriginCallback = base::OnceCallback<void(bool)>;
// Client interface that a BackgroundFetchDelegate would use to signal the
// progress of a background fetch.
@@ -95,6 +104,13 @@ class CONTENT_EXPORT BackgroundFetchDelegate {
// Gets size of the icon to display with the Background Fetch UI.
virtual void GetIconDisplaySize(GetIconDisplaySizeCallback callback) = 0;
+ // Checks whether |origin| has permission to start a Background Fetch.
+ // |wc_getter| can be null, which means this is running from a worker context.
+ virtual void GetPermissionForOrigin(
+ const url::Origin& origin,
+ const ResourceRequestInfo::WebContentsGetter& wc_getter,
+ GetPermissionForOriginCallback callback) = 0;
+
// Creates a new download grouping identified by |job_unique_id|. Further
// downloads started by DownloadUrl will also use this |job_unique_id| so that
// a notification can be updated with the current status. If the download was
@@ -118,9 +134,10 @@ class CONTENT_EXPORT BackgroundFetchDelegate {
virtual void Abort(const std::string& job_unique_id) = 0;
// Updates the UI shown for the fetch job associated with |job_unique_id| to
- // display a new |title|.
+ // display a new |title| or |icon|.
virtual void UpdateUI(const std::string& job_unique_id,
- const std::string& title) = 0;
+ const base::Optional<std::string>& title,
+ const base::Optional<SkBitmap>& icon) = 0;
// Set the client that the delegate should communicate changes to.
void SetDelegateClient(base::WeakPtr<Client> client) { client_ = client; }
diff --git a/chromium/content/public/browser/background_tracing_manager.h b/chromium/content/public/browser/background_tracing_manager.h
index b4cd53f742d..edfb80c0028 100644
--- a/chromium/content/public/browser/background_tracing_manager.h
+++ b/chromium/content/public/browser/background_tracing_manager.h
@@ -34,7 +34,7 @@ class BackgroundTracingManager {
// void Upload(const scoped_refptr<base::RefCountedString>& data,
// FinishedProcessingCallback done_callback) {
// base::PostTaskWithTraitsAndReply(
- // FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND},
+ // FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
// base::BindOnce(&DoUploadInBackground, data),
// std::move(done_callback));
// }
diff --git a/chromium/content/public/browser/browser_accessibility_state.h b/chromium/content/public/browser/browser_accessibility_state.h
index 6c91e1b7b76..3c969f94b7b 100644
--- a/chromium/content/public/browser/browser_accessibility_state.h
+++ b/chromium/content/public/browser/browser_accessibility_state.h
@@ -8,6 +8,7 @@
#include "base/callback_forward.h"
#include "content/common/content_export.h"
+#include "ui/accessibility/ax_modes.h"
namespace content {
@@ -28,6 +29,18 @@ class CONTENT_EXPORT BrowserAccessibilityState {
// required by a command line flag or by a platform requirement.)
virtual void DisableAccessibility() = 0;
+ virtual bool IsRendererAccessibilityEnabled() = 0;
+
+ virtual ui::AXMode GetAccessibilityMode() const = 0;
+
+ // Adds the given accessibility mode flags to the current accessibility
+ // mode bitmap.
+ virtual void AddAccessibilityModeFlags(ui::AXMode mode) = 0;
+
+ // Remove the given accessibility mode flags from the current accessibility
+ // mode bitmap.
+ virtual void RemoveAccessibilityModeFlags(ui::AXMode mode) = 0;
+
// Resets accessibility to the platform default for all running tabs.
// This is probably off, but may be on, if --force_renderer_accessibility is
// passed, or EditableTextOnly if this is Win7.
diff --git a/chromium/content/public/browser/browser_context.h b/chromium/content/public/browser/browser_context.h
index 4f794e25ac7..e49eaaa04ab 100644
--- a/chromium/content/public/browser/browser_context.h
+++ b/chromium/content/public/browser/browser_context.h
@@ -15,6 +15,7 @@
#include "base/callback_forward.h"
#include "base/containers/hash_tables.h"
+#include "base/optional.h"
#include "base/supports_user_data.h"
#include "content/common/content_export.h"
#include "net/url_request/url_request_interceptor.h"
@@ -32,6 +33,10 @@ namespace base {
class FilePath;
}
+namespace download {
+class InProgressDownloadManager;
+}
+
namespace service_manager {
class Connector;
}
@@ -69,7 +74,6 @@ class DownloadManager;
class DownloadManagerDelegate;
class PermissionController;
class PermissionControllerDelegate;
-struct PushEventPayload;
class PushMessagingService;
class ResourceContext;
class ServiceManagerConnection;
@@ -167,7 +171,7 @@ class CONTENT_EXPORT BrowserContext : public base::SupportsUserData {
BrowserContext* browser_context,
const GURL& origin,
int64_t service_worker_registration_id,
- const PushEventPayload& payload,
+ base::Optional<std::string> payload,
const base::Callback<void(mojom::PushDeliveryStatus)>& callback);
static void NotifyWillBeDestroyed(BrowserContext* browser_context);
@@ -232,6 +236,9 @@ class CONTENT_EXPORT BrowserContext : public base::SupportsUserData {
// Returns the path of the directory where this context's data is stored.
virtual base::FilePath GetPath() const = 0;
+ // Returns the path of the directory where the code is cached.
+ virtual base::FilePath GetCachePath() const = 0;
+
// Return whether this context is incognito. Default is false.
virtual bool IsOffTheRecord() const = 0;
@@ -329,6 +336,11 @@ class CONTENT_EXPORT BrowserContext : public base::SupportsUserData {
// directly, so privacy is not compromised.
virtual media::VideoDecodePerfHistory* GetVideoDecodePerfHistory();
+ // Retrieves the InProgressDownloadManager associated with this object if
+ // available
+ virtual download::InProgressDownloadManager*
+ RetriveInProgressDownloadManager();
+
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.h b/chromium/content/public/browser/browser_plugin_guest_delegate.h
index d05dd542145..bf2226b53dd 100644
--- a/chromium/content/public/browser/browser_plugin_guest_delegate.h
+++ b/chromium/content/public/browser/browser_plugin_guest_delegate.h
@@ -34,7 +34,7 @@ class CONTENT_EXPORT BrowserPluginGuestDelegate {
virtual void WillAttach(content::WebContents* embedder_web_contents,
int element_instance_id,
bool is_full_page_plugin,
- const base::Closure& completion_callback) {}
+ base::OnceClosure completion_callback) {}
virtual WebContents* CreateNewGuestWindow(
const WebContents::CreateParams& create_params);
diff --git a/chromium/content/public/browser/browser_task_traits.cc b/chromium/content/public/browser/browser_task_traits.cc
new file mode 100644
index 00000000000..311902e7ad9
--- /dev/null
+++ b/chromium/content/public/browser/browser_task_traits.cc
@@ -0,0 +1,12 @@
+// 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/browser_task_traits.h"
+
+namespace content {
+
+// static
+constexpr uint8_t BrowserTaskTraitsExtension::kExtensionId;
+
+} // namespace content
diff --git a/chromium/content/public/browser/browser_task_traits.h b/chromium/content/public/browser/browser_task_traits.h
new file mode 100644
index 00000000000..8ccee9d9fe4
--- /dev/null
+++ b/chromium/content/public/browser/browser_task_traits.h
@@ -0,0 +1,102 @@
+// 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_BROWSER_TASK_TRAITS_H_
+#define CONTENT_PUBLIC_BROWSER_BROWSER_TASK_TRAITS_H_
+
+#include "base/task/task_traits.h"
+#include "base/task/task_traits_extension.h"
+#include "content/common/content_export.h"
+#include "content/public/browser/browser_thread.h"
+
+namespace content {
+
+// Tasks with this trait will not be executed inside a nested RunLoop.
+//
+// Note: This should rarely be required. Drivers of nested loops should instead
+// make sure to be reentrant when allowing nested application tasks (also rare).
+//
+// TODO(https://crbug.com/876272): Investigate removing this trait -- and any
+// logic for deferred tasks in MessageLoop.
+struct NonNestable {};
+
+// TaskTraits for running tasks on the browser threads.
+//
+// These traits enable the use of the //base/task/post_task.h APIs to post tasks
+// to a BrowserThread.
+//
+// To post a task to the UI thread (analogous for IO thread):
+// base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, task);
+//
+// To obtain a TaskRunner for the UI thread (analogous for the IO thread):
+// base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI});
+//
+// See //base/task/post_task.h for more detailed documentation.
+//
+// Posting to a BrowserThread must only be done after it was initialized (ref.
+// BrowserMainLoop::CreateThreads() phase).
+class CONTENT_EXPORT BrowserTaskTraitsExtension {
+ public:
+ static constexpr uint8_t kExtensionId =
+ base::TaskTraitsExtensionStorage::kFirstEmbedderExtensionId;
+
+ struct ValidTrait {
+ ValidTrait(BrowserThread::ID) {}
+ ValidTrait(NonNestable) {}
+ };
+
+ template <
+ class... ArgTypes,
+ class CheckArgumentsAreValid = std::enable_if_t<
+ base::trait_helpers::AreValidTraits<ValidTrait, ArgTypes...>::value>>
+ constexpr BrowserTaskTraitsExtension(ArgTypes... args)
+ : browser_thread_(base::trait_helpers::GetValueFromArgList(
+ base::trait_helpers::RequiredEnumArgGetter<BrowserThread::ID>(),
+ args...)),
+ nestable_(!base::trait_helpers::GetValueFromArgList(
+ base::trait_helpers::BooleanArgGetter<NonNestable>(),
+ args...)) {}
+
+ constexpr base::TaskTraitsExtensionStorage Serialize() const {
+ static_assert(8 == sizeof(BrowserTaskTraitsExtension),
+ "Update Serialize() and Parse() when changing "
+ "BrowserTaskTraitsExtension");
+ return {kExtensionId,
+ {static_cast<uint8_t>(browser_thread_),
+ static_cast<uint8_t>(nestable_)}};
+ }
+
+ static const BrowserTaskTraitsExtension Parse(
+ const base::TaskTraitsExtensionStorage& extension) {
+ return BrowserTaskTraitsExtension(
+ static_cast<BrowserThread::ID>(extension.data[0]),
+ static_cast<bool>(extension.data[1]));
+ }
+
+ constexpr BrowserThread::ID browser_thread() const { return browser_thread_; }
+
+ // Returns true if tasks with these traits may run in a nested RunLoop.
+ constexpr bool nestable() const { return nestable_; }
+
+ private:
+ BrowserTaskTraitsExtension(BrowserThread::ID browser_thread, bool nestable)
+ : browser_thread_(browser_thread), nestable_(nestable) {}
+
+ BrowserThread::ID browser_thread_;
+ bool nestable_;
+};
+
+template <class... ArgTypes,
+ class = std::enable_if_t<base::trait_helpers::AreValidTraits<
+ BrowserTaskTraitsExtension::ValidTrait,
+ ArgTypes...>::value>>
+constexpr base::TaskTraitsExtensionStorage MakeTaskTraitsExtension(
+ ArgTypes&&... args) {
+ return BrowserTaskTraitsExtension(std::forward<ArgTypes>(args)...)
+ .Serialize();
+}
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_BROWSER_BROWSER_TASK_TRAITS_H_
diff --git a/chromium/content/public/browser/browser_task_traits_unittest.nc b/chromium/content/public/browser/browser_task_traits_unittest.nc
new file mode 100644
index 00000000000..3fccbebb141
--- /dev/null
+++ b/chromium/content/public/browser/browser_task_traits_unittest.nc
@@ -0,0 +1,20 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This is a "No Compile Test" suite.
+// http://dev.chromium.org/developers/testing/no-compile-tests
+
+#include "base/task/task_traits.h"
+#include "content/public/browser/browser_task_traits.h"
+
+namespace content {
+
+#if defined(NCTEST_BROWSER_TASK_TRAITS_NO_THREAD) // [r"no member named 'GetDefaultValue' in 'base::trait_helpers::RequiredEnumArgGetter<content::BrowserThread::ID>'"]
+constexpr base::TaskTraits traits = {NonNestable()};
+#elif defined(NCTEST_BROWSER_TASK_TRAITS_MULTIPLE_THREADS) // [r"Multiple arguments of the same type were provided to the constructor of TaskTraits."]
+constexpr base::TaskTraits traits = {BrowserThread::UI,
+ BrowserThread::IO};
+#endif
+
+} // namespace content
diff --git a/chromium/content/public/browser/browser_thread.h b/chromium/content/public/browser/browser_thread.h
index 5d439726026..159bc7f1054 100644
--- a/chromium/content/public/browser/browser_thread.h
+++ b/chromium/content/public/browser/browser_thread.h
@@ -18,7 +18,6 @@
#include "base/task_runner_util.h"
#include "base/time/time.h"
#include "content/common/content_export.h"
-#include "content/public/browser/browser_thread.h"
namespace content {
@@ -35,25 +34,17 @@ class BrowserThreadImpl;
///////////////////////////////////////////////////////////////////////////////
// BrowserThread
//
-// Utility functions for threads that are known by a browser-wide
-// name. For example, there is one IO thread for the entire browser
-// process, and various pieces of code find it useful to retrieve a
-// pointer to the IO thread's message loop.
+// Utility functions for threads that are known by a browser-wide name. For
+// example, there is one IO thread for the entire browser process, and various
+// pieces of code find it useful to retrieve a pointer to the IO thread's
+// message loop.
//
-// Invoke a task by thread ID:
+// See browser_task_traits.h for posting Tasks to a BrowserThread.
+// TODO(https://crbug.com/878356): Replace uses with base's post_task.h API.
//
-// BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, task);
-//
-// The return value is false if the task couldn't be posted because the target
-// thread doesn't exist. If this could lead to data loss, you need to check the
-// result and restructure the code to ensure it doesn't occur.
-//
-// This class automatically handles the lifetime of different threads.
-// It's always safe to call PostTask on any thread. If it's not yet created,
-// the task is deleted. There are no race conditions. If the thread that the
-// task is posted to is guaranteed to outlive the current thread, then no locks
-// are used. You should never need to cache pointers to MessageLoops, since
-// they're not thread safe.
+// This class automatically handles the lifetime of different threads. You
+// should never need to cache pointers to MessageLoops, since they're not thread
+// safe.
class CONTENT_EXPORT BrowserThread {
public:
// An enumeration of the well-known threads.
@@ -68,7 +59,7 @@ class CONTENT_EXPORT BrowserThread {
IO,
// NOTE: do not add new threads here. Instead you should just use
- // base::Create*TaskRunnerWithTraits.
+ // base::Create*TaskRunnerWithTraits to run tasks on the TaskScheduler.
// This identifier does not represent a thread. Instead it counts the
// number of well-known threads. Insert new well-known threads before this
@@ -76,6 +67,9 @@ class CONTENT_EXPORT BrowserThread {
ID_COUNT
};
+ // DEPRECATED: Please use the API described in browser_task_traits.h instead.
+ // TODO(https://crbug.com/878356): Replace uses with base::PostTaskWithTraits.
+ //
// These are the same methods in message_loop.h, but are guaranteed to either
// get posted to the MessageLoop if it's still alive, or be deleted otherwise.
// They return true iff the thread existed and the task was posted. Note that
@@ -176,8 +170,12 @@ class CONTENT_EXPORT BrowserThread {
// sets identifier to its ID. Otherwise returns false.
static bool GetCurrentThreadIdentifier(ID* identifier) WARN_UNUSED_RESULT;
- // Callers can hold on to a refcounted task runner beyond the lifetime
- // of the thread.
+ // DEPRECATED: Please use the API described in browser_task_traits.h instead.
+ // TODO(https://crbug.com/878356): Replace uses with
+ // base::Create*TaskRunnerWithTraits.
+ //
+ // Callers can hold on to a refcounted task runner beyond the lifetime of the
+ // thread.
static scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunnerForThread(
ID identifier);
diff --git a/chromium/content/public/browser/browsing_data_filter_builder.h b/chromium/content/public/browser/browsing_data_filter_builder.h
index e99ffc878e7..fc290d18687 100644
--- a/chromium/content/public/browser/browsing_data_filter_builder.h
+++ b/chromium/content/public/browser/browsing_data_filter_builder.h
@@ -69,7 +69,7 @@ class CONTENT_EXPORT BrowsingDataFilterBuilder {
// 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.
+ // network service via IPC. Returns nullptr if |IsEmptyBlacklist()| is true.
virtual network::mojom::ClearDataFilterPtr BuildNetworkServiceFilter()
const = 0;
diff --git a/chromium/content/public/browser/child_process_data.cc b/chromium/content/public/browser/child_process_data.cc
new file mode 100644
index 00000000000..69399bd68da
--- /dev/null
+++ b/chromium/content/public/browser/child_process_data.cc
@@ -0,0 +1,60 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/public/browser/child_process_data.h"
+
+#if defined(OS_WIN)
+#include <Windows.h>
+#endif
+
+namespace content {
+
+#if defined(OS_WIN)
+void ChildProcessData::SetHandle(base::ProcessHandle process) {
+ HANDLE handle_to_set;
+ if (process == base::kNullProcessHandle) {
+ handle_to_set = base::kNullProcessHandle;
+ } else {
+ BOOL result =
+ ::DuplicateHandle(::GetCurrentProcess(), process, ::GetCurrentProcess(),
+ &handle_to_set, 0, FALSE, DUPLICATE_SAME_ACCESS);
+ auto err = GetLastError();
+ CHECK(result) << process << " " << err;
+ }
+ handle_ = base::win::ScopedHandle(handle_to_set);
+}
+#endif
+
+ChildProcessData::ChildProcessData(int process_type)
+ : process_type(process_type), id(0), handle_(base::kNullProcessHandle) {}
+
+ChildProcessData::ChildProcessData(ChildProcessData&& rhs)
+ : process_type(rhs.process_type),
+ name(rhs.name),
+ metrics_name(rhs.metrics_name),
+ id(rhs.id) {
+#if defined(OS_WIN)
+ handle_.Set(rhs.handle_.Take());
+#else
+ handle_ = rhs.handle_;
+ rhs.handle_ = base::kNullProcessHandle;
+#endif
+}
+
+ChildProcessData::~ChildProcessData() {}
+
+ChildProcessData ChildProcessData::Duplicate() const {
+ ChildProcessData result(process_type);
+ result.name = name;
+ result.metrics_name = metrics_name;
+ result.id = id;
+#if defined(OS_WIN)
+ result.SetHandle(handle_.Get());
+#else
+ result.SetHandle(handle_);
+#endif
+ return result;
+}
+
+} // namespace content
diff --git a/chromium/content/public/browser/child_process_data.h b/chromium/content/public/browser/child_process_data.h
index 887d06dd084..3e8d676098b 100644
--- a/chromium/content/public/browser/child_process_data.h
+++ b/chromium/content/public/browser/child_process_data.h
@@ -7,12 +7,17 @@
#include "base/process/process.h"
#include "base/strings/string16.h"
+#include "build/build_config.h"
#include "content/common/content_export.h"
+#if defined(OS_WIN)
+#include "base/win/scoped_handle.h"
+#endif
+
namespace content {
// Holds information about a child process.
-struct ChildProcessData {
+struct CONTENT_EXPORT ChildProcessData {
// The type of the process. See the content::ProcessType enum for the
// well-known process types.
int process_type;
@@ -29,15 +34,37 @@ struct ChildProcessData {
// one run of the browser.
int id;
- // The handle to the process. May have value kNullProcessHandle if no process
- // exists - either because it hasn't been started yet or it's running in the
- // current process.
- base::ProcessHandle handle;
+#if defined(OS_WIN)
+ base::ProcessHandle GetHandle() const { return handle_.Get(); }
+ // Will duplicate the handle and assume ownership of the duplicate.
+ void SetHandle(base::ProcessHandle process);
+#else
+ base::ProcessHandle GetHandle() const { return handle_; }
+ void SetHandle(base::ProcessHandle process) { handle_ = process; }
+#endif
+
+ bool IsHandleValid() const { return GetHandle() != base::kNullProcessHandle; }
+
+ explicit ChildProcessData(int process_type);
+ ~ChildProcessData();
+
+ ChildProcessData(ChildProcessData&& rhs);
+
+ // Copying these objects requires duplicating the handle which is moderately
+ // expensive, so make it an explicit action.
+ ChildProcessData Duplicate() const;
- explicit ChildProcessData(int process_type)
- : process_type(process_type),
- id(0),
- handle(base::kNullProcessHandle) {}
+ private:
+// The handle to the process. May have value kNullProcessHandle if no process
+// exists - either because it hasn't been started yet or it's running in the
+// current process.
+#if defined(OS_WIN)
+ // Must be a scoped handle on Windows holding a duplicated handle or else
+ // there are no guarantees the handle will still be valid when used.
+ base::win::ScopedHandle handle_;
+#else
+ base::ProcessHandle handle_;
+#endif
};
} // namespace content
diff --git a/chromium/content/public/browser/content_browser_client.cc b/chromium/content/public/browser/content_browser_client.cc
index 2a896c7072c..8e652e4b66f 100644
--- a/chromium/content/public/browser/content_browser_client.cc
+++ b/chromium/content/public/browser/content_browser_client.cc
@@ -10,6 +10,7 @@
#include "base/files/file_path.h"
#include "base/guid.h"
#include "base/logging.h"
+#include "base/no_destructor.h"
#include "build/build_config.h"
#include "content/public/browser/authenticator_request_client_delegate.h"
#include "content/public/browser/client_certificate_delegate.h"
@@ -21,6 +22,7 @@
#include "content/public/browser/url_loader_request_interceptor.h"
#include "content/public/browser/vpn_service_proxy.h"
#include "content/public/common/url_loader_throttle.h"
+#include "content/public/common/url_utils.h"
#include "media/audio/audio_manager.h"
#include "media/media_buildflags.h"
#include "mojo/public/cpp/bindings/associated_interface_ptr.h"
@@ -79,6 +81,15 @@ GURL ContentBrowserClient::GetEffectiveURL(BrowserContext* browser_context,
return url;
}
+bool ContentBrowserClient::ShouldCompareEffectiveURLsForSiteInstanceSelection(
+ BrowserContext* browser_context,
+ content::SiteInstance* candidate_site_instance,
+ bool is_main_frame,
+ const GURL& candidate_url,
+ const GURL& destination_url) {
+ return true;
+}
+
bool ContentBrowserClient::ShouldUseMobileFlingCurve() const {
return false;
}
@@ -105,10 +116,16 @@ bool ContentBrowserClient::ShouldLockToOrigin(BrowserContext* browser_context,
return true;
}
-const char* ContentBrowserClient::GetInitatorSchemeBypassingDocumentBlocking() {
+const char*
+ContentBrowserClient::GetInitiatorSchemeBypassingDocumentBlocking() {
return nullptr;
}
+void ContentBrowserClient::LogInitiatorSchemeBypassingDocumentBlocking(
+ const url::Origin& initiator_origin,
+ int render_process_id,
+ ResourceType resource_type) {}
+
void ContentBrowserClient::GetAdditionalViewSourceSchemes(
std::vector<std::string>* additional_schemes) {
GetAdditionalWebUISchemes(additional_schemes);
@@ -178,7 +195,7 @@ bool ContentBrowserClient::ShouldSwapBrowsingInstancesForNavigation(
}
bool ContentBrowserClient::ShouldIsolateErrorPage(bool in_main_frame) {
- return false;
+ return in_main_frame;
}
std::unique_ptr<media::AudioManager> ContentBrowserClient::CreateAudioManager(
@@ -206,10 +223,11 @@ ContentBrowserClient::GetOriginsRequiringDedicatedProcess() {
}
bool ContentBrowserClient::ShouldEnableStrictSiteIsolation() {
- // By default --site-per-process is turned off for //content embedders.
- // This ensures that embedders like ChromeCast and/or Opera are not forced
- // into --site-per-process.
+#if defined(OS_ANDROID)
return false;
+#else
+ return true;
+#endif
}
bool ContentBrowserClient::IsFileAccessAllowed(
@@ -309,7 +327,7 @@ void ContentBrowserClient::OnCookieChange(int process_id,
void ContentBrowserClient::AllowWorkerFileSystem(
const GURL& url,
ResourceContext* context,
- const std::vector<std::pair<int, int> >& render_frames,
+ const std::vector<GlobalFrameRoutingId>& render_frames,
base::Callback<void(bool)> callback) {
std::move(callback).Run(true);
}
@@ -318,7 +336,7 @@ bool ContentBrowserClient::AllowWorkerIndexedDB(
const GURL& url,
const base::string16& name,
ResourceContext* context,
- const std::vector<std::pair<int, int> >& render_frames) {
+ const std::vector<GlobalFrameRoutingId>& render_frames) {
return true;
}
@@ -463,6 +481,10 @@ base::FilePath ContentBrowserClient::GetShaderDiskCacheDirectory() {
return base::FilePath();
}
+base::FilePath ContentBrowserClient::GetGrShaderDiskCacheDirectory() {
+ return base::FilePath();
+}
+
BrowserPpapiHost*
ContentBrowserClient::GetExternalBrowserPpapiHost(int plugin_process_id) {
return nullptr;
@@ -649,6 +671,7 @@ bool ContentBrowserClient::WillCreateURLLoaderFactory(
BrowserContext* browser_context,
RenderFrameHost* frame,
bool is_navigation,
+ const GURL& url,
network::mojom::URLLoaderFactoryRequest* factory_request) {
return false;
}
@@ -712,13 +735,9 @@ bool ContentBrowserClient::ShouldForceDownloadResource(
return false;
}
-void ContentBrowserClient::CreateUsbDeviceManager(
- RenderFrameHost* render_frame_host,
- device::mojom::UsbDeviceManagerRequest request) {}
-
-void ContentBrowserClient::CreateUsbChooserService(
+void ContentBrowserClient::CreateWebUsbService(
RenderFrameHost* render_frame_host,
- device::mojom::UsbChooserServiceRequest request) {}
+ mojo::InterfaceRequest<blink::mojom::WebUsbService> request) {}
bool ContentBrowserClient::ShowPaymentHandlerWindow(
content::BrowserContext* browser_context,
@@ -737,6 +756,12 @@ ContentBrowserClient::GetWebAuthenticationRequestDelegate(
return std::make_unique<AuthenticatorRequestClientDelegate>();
}
+#if defined(OS_MACOSX)
+bool ContentBrowserClient::IsWebAuthenticationTouchIdAuthenticatorSupported() {
+ return false;
+}
+#endif
+
std::unique_ptr<net::ClientCertStore>
ContentBrowserClient::CreateClientCertStore(ResourceContext* resource_context) {
return nullptr;
@@ -771,4 +796,13 @@ ContentBrowserClient::CreateWindowForPictureInPicture(
return nullptr;
}
+bool ContentBrowserClient::IsSafeRedirectTarget(const GURL& url,
+ ResourceContext* context) {
+ return true;
+}
+
+void ContentBrowserClient::RegisterRendererPreferenceWatcherForWorkers(
+ BrowserContext* browser_context,
+ mojom::RendererPreferenceWatcherPtr watcher) {}
+
} // namespace content
diff --git a/chromium/content/public/browser/content_browser_client.h b/chromium/content/public/browser/content_browser_client.h
index fd5d62fee11..bc2b501331e 100644
--- a/chromium/content/public/browser/content_browser_client.h
+++ b/chromium/content/public/browser/content_browser_client.h
@@ -9,6 +9,7 @@
#include <map>
#include <memory>
+#include <set>
#include <string>
#include <utility>
#include <vector>
@@ -16,21 +17,21 @@
#include "base/callback.h"
#include "base/containers/flat_set.h"
#include "base/optional.h"
-#include "base/task_scheduler/task_scheduler.h"
+#include "base/task/task_scheduler/task_scheduler.h"
#include "base/values.h"
#include "build/build_config.h"
#include "content/public/browser/certificate_request_result_type.h"
#include "content/public/browser/global_request_id.h"
+#include "content/public/browser/global_routing_id.h"
#include "content/public/browser/navigation_throttle.h"
#include "content/public/browser/overlay_window.h"
#include "content/public/browser/resource_request_info.h"
#include "content/public/common/content_client.h"
#include "content/public/common/media_stream_request.h"
+#include "content/public/common/renderer_preference_watcher.mojom.h"
#include "content/public/common/resource_type.h"
#include "content/public/common/socket_permission_request.h"
#include "content/public/common/window_container_type.mojom.h"
-#include "device/usb/public/mojom/chooser_service.mojom.h"
-#include "device/usb/public/mojom/device_manager.mojom.h"
#include "media/base/video_codecs.h"
#include "media/cdm/cdm_proxy.h"
#include "media/media_buildflags.h"
@@ -69,6 +70,12 @@ class CommandLine;
class FilePath;
}
+namespace blink {
+namespace mojom {
+class WebUsbService;
+}
+} // namespace blink
+
namespace device {
class LocationProvider;
}
@@ -250,6 +257,16 @@ class CONTENT_EXPORT ContentBrowserClient {
virtual GURL GetEffectiveURL(BrowserContext* browser_context,
const GURL& url);
+ // Returns true if effective URLs should be compared when choosing a
+ // SiteInstance for a navigation to |destination_url|.
+ // |is_main_frame| is true if the navigation will take place in a main frame.
+ virtual bool ShouldCompareEffectiveURLsForSiteInstanceSelection(
+ BrowserContext* browser_context,
+ content::SiteInstance* candidate_site_instance,
+ bool is_main_frame,
+ const GURL& candidate_url,
+ const GURL& destination_url);
+
// Returns whether gesture fling events should use the mobile-behavior gesture
// curve for scrolling.
virtual bool ShouldUseMobileFlingCurve() const;
@@ -292,7 +309,18 @@ class CONTENT_EXPORT ContentBrowserClient {
// Returns the scheme of request initiator that should be ignored by
// cross-origin read blocking. nullptr can be returned to indicate that no
// exceptions should be granted based on initiator's scheme.
- virtual const char* GetInitatorSchemeBypassingDocumentBlocking();
+ virtual const char* GetInitiatorSchemeBypassingDocumentBlocking();
+
+ // Gives the embedder a chance to log that CORB would have blocked a response
+ // if it wasn't for GetInitatorSchemeBypassingDocumentBlocking above. Called
+ // only after all the other CORB checks (potentially including sniffing) have
+ // been already run / right before blocking would have otherwise happened (and
+ // only for non-empty, non-4xx responses).
+ // TODO(lukasza): Remove once we gather enough data.
+ virtual void LogInitiatorSchemeBypassingDocumentBlocking(
+ const url::Origin& initiator_origin,
+ int render_process_id,
+ ResourceType resource_type);
// Returns a list additional WebUI schemes, if any. These additional schemes
// act as aliases to the chrome: scheme. The additional schemes may or may
@@ -402,8 +430,8 @@ class CONTENT_EXPORT ContentBrowserClient {
// opted into --isolate-origins mode of Site Isolation.
virtual std::vector<url::Origin> GetOriginsRequiringDedicatedProcess();
- // Allows the embedder to programmatically opt into --site-per-process mode of
- // Site Isolation.
+ // Allows the embedder to programmatically control whether the
+ // --site-per-process mode of Site Isolation should be used.
//
// Note that for correctness, the same value should be consistently returned.
// See also https://crbug.com/825369
@@ -543,7 +571,7 @@ class CONTENT_EXPORT ContentBrowserClient {
virtual void AllowWorkerFileSystem(
const GURL& url,
ResourceContext* context,
- const std::vector<std::pair<int, int> >& render_frames,
+ const std::vector<GlobalFrameRoutingId>& render_frames,
base::Callback<void(bool)> callback);
// Allow the embedder to control if access to IndexedDB by a shared worker
@@ -553,7 +581,7 @@ class CONTENT_EXPORT ContentBrowserClient {
const GURL& url,
const base::string16& name,
ResourceContext* context,
- const std::vector<std::pair<int, int> >& render_frames);
+ const std::vector<GlobalFrameRoutingId>& render_frames);
// Allow the embedder to control whether we can use Web Bluetooth.
// TODO(crbug.com/589228): Replace this with a use of the permission system.
@@ -743,6 +771,10 @@ class CONTENT_EXPORT ContentBrowserClient {
// Returns the path to the browser shader disk cache root.
virtual base::FilePath GetShaderDiskCacheDirectory();
+ // Returns the path to the shader disk cache root for shaders generated by
+ // skia.
+ virtual base::FilePath GetGrShaderDiskCacheDirectory();
+
// Notification that a pepper plugin has just been spawned. This allows the
// embedder to add filters onto the host to implement interfaces.
// This is called on the IO thread.
@@ -1094,6 +1126,12 @@ class CONTENT_EXPORT ContentBrowserClient {
// or for non-navigation requests initiated by the browser on behalf of a
// BrowserContext.
//
+ // |is_navigation| is true when it's a request used for navigation.
+ // |url| is set when it's a request for navigations or for a renderer fetching
+ // subresources. It's not set in the 3rd case (browser-initiated
+ // non-navigation requests) because in that case the factory is cached and it
+ // can be used for multiple URLs.
+ //
// |*factory_request| is always valid upon entry and MUST be valid upon
// return. The embedder may swap out the value of |*factory_request| for its
// own, in which case it must return |true| to indicate that it's proxying
@@ -1110,6 +1148,7 @@ class CONTENT_EXPORT ContentBrowserClient {
BrowserContext* browser_context,
RenderFrameHost* frame,
bool is_navigation,
+ const GURL& url,
network::mojom::URLLoaderFactoryRequest* factory_request);
// Allows the embedder to intercept a WebSocket connection. |*request|
@@ -1191,13 +1230,9 @@ class CONTENT_EXPORT ContentBrowserClient {
virtual bool ShouldForceDownloadResource(const GURL& url,
const std::string& mime_type);
- virtual void CreateUsbDeviceManager(
- RenderFrameHost* render_frame_host,
- device::mojom::UsbDeviceManagerRequest request);
-
- virtual void CreateUsbChooserService(
+ virtual void CreateWebUsbService(
RenderFrameHost* render_frame_host,
- device::mojom::UsbChooserServiceRequest request);
+ mojo::InterfaceRequest<blink::mojom::WebUsbService> request);
// Attempt to open the Payment Handler window inside its corresponding
// PaymentRequest UI surface. Returns true if the ContentBrowserClient
@@ -1229,6 +1264,13 @@ class CONTENT_EXPORT ContentBrowserClient {
virtual std::unique_ptr<AuthenticatorRequestClientDelegate>
GetWebAuthenticationRequestDelegate(RenderFrameHost* render_frame_host);
+#if defined(OS_MACOSX)
+ // Returns whether WebAuthn supports the built-in Touch ID platform
+ // authenticator. If true, the embedder must supply a configuration in
+ // |AuthenticatorRequestClientDelegate::GetTouchIdAuthenticatorConfig|.
+ virtual bool IsWebAuthenticationTouchIdAuthenticatorSupported();
+#endif
+
// Get platform ClientCertStore. May return nullptr.
virtual std::unique_ptr<net::ClientCertStore> CreateClientCertStore(
ResourceContext* resource_context);
@@ -1274,6 +1316,16 @@ class CONTENT_EXPORT ContentBrowserClient {
// default implementation provides nullptr OverlayWindow.
virtual std::unique_ptr<OverlayWindow> CreateWindowForPictureInPicture(
PictureInPictureWindowController* controller);
+
+ // Returns true if it is safe to redirect to |url|, otherwise returns false.
+ // This is called on the IO thread.
+ virtual bool IsSafeRedirectTarget(const GURL& url, ResourceContext* context);
+
+ // Registers the watcher to observe updates in RendererPreferences. The
+ // watchers are for shared workers and service workers.
+ virtual void RegisterRendererPreferenceWatcherForWorkers(
+ BrowserContext* browser_context,
+ mojom::RendererPreferenceWatcherPtr watcher);
};
} // namespace content
diff --git a/chromium/content/public/browser/cookie_store_factory.h b/chromium/content/public/browser/cookie_store_factory.h
index c5073384d27..c459156bd3b 100644
--- a/chromium/content/public/browser/cookie_store_factory.h
+++ b/chromium/content/public/browser/cookie_store_factory.h
@@ -21,6 +21,7 @@ namespace net {
class ChannelIDService;
class CookieCryptoDelegate;
class CookieStore;
+class NetLog;
}
namespace storage {
@@ -83,7 +84,8 @@ struct CONTENT_EXPORT CookieStoreConfig {
};
CONTENT_EXPORT std::unique_ptr<net::CookieStore> CreateCookieStore(
- const CookieStoreConfig& config);
+ const CookieStoreConfig& config,
+ net::NetLog* net_log);
} // namespace content
diff --git a/chromium/content/public/browser/desktop_capture.h b/chromium/content/public/browser/desktop_capture.h
index 30d7bdbea1b..c90997a8762 100644
--- a/chromium/content/public/browser/desktop_capture.h
+++ b/chromium/content/public/browser/desktop_capture.h
@@ -15,7 +15,7 @@ namespace desktop_capture {
// Creates a DesktopCaptureOptions with required settings.
CONTENT_EXPORT webrtc::DesktopCaptureOptions CreateDesktopCaptureOptions();
-// Creats specific DesktopCapturer with required settings.
+// Creates specific DesktopCapturer with required settings.
CONTENT_EXPORT std::unique_ptr<webrtc::DesktopCapturer> CreateScreenCapturer();
CONTENT_EXPORT std::unique_ptr<webrtc::DesktopCapturer> CreateWindowCapturer();
diff --git a/chromium/content/public/browser/desktop_media_id.cc b/chromium/content/public/browser/desktop_media_id.cc
index affd921c1ff..34f784fcbc1 100644
--- a/chromium/content/public/browser/desktop_media_id.cc
+++ b/chromium/content/public/browser/desktop_media_id.cc
@@ -77,6 +77,11 @@ namespace content {
const char kScreenPrefix[] = "screen";
const char kWindowPrefix[] = "window";
+// static
+const DesktopMediaID::Id DesktopMediaID::kNullId = 0;
+// static
+const DesktopMediaID::Id DesktopMediaID::kFakeId = -3;
+
#if defined(USE_AURA)
// static
diff --git a/chromium/content/public/browser/desktop_media_id.h b/chromium/content/public/browser/desktop_media_id.h
index 7119cdc1bd9..9c970b6fa06 100644
--- a/chromium/content/public/browser/desktop_media_id.h
+++ b/chromium/content/public/browser/desktop_media_id.h
@@ -28,9 +28,9 @@ struct CONTENT_EXPORT DesktopMediaID {
typedef intptr_t Id;
// Represents an "unset" value for either |id| or |aura_id|.
- static const Id kNullId = 0;
+ static const Id kNullId;
// Represents a fake id to create a dummy capturer for autotests.
- static const Id kFakeId = -3;
+ static const Id kFakeId;
#if defined(USE_AURA)
// Assigns integer identifier to the |window| and returns its DesktopMediaID.
diff --git a/chromium/content/public/browser/desktop_streams_registry.h b/chromium/content/public/browser/desktop_streams_registry.h
new file mode 100644
index 00000000000..ed9eb6a76d4
--- /dev/null
+++ b/chromium/content/public/browser/desktop_streams_registry.h
@@ -0,0 +1,58 @@
+// 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_DESKTOP_STREAMS_REGISTRY_H_
+#define CONTENT_PUBLIC_BROWSER_DESKTOP_STREAMS_REGISTRY_H_
+
+#include "content/common/content_export.h"
+
+class GURL;
+
+namespace content {
+
+enum DesktopStreamRegistryType {
+ kRegistryStreamTypeDesktop,
+ kRegistryStreamTypeTab
+};
+
+struct DesktopMediaID;
+
+// Interface to DesktopStreamsRegistry which is used to store accepted desktop
+// media streams for Desktop/Tab Capture API. Single instance of this class is
+// created at first time use. This should be called on UI thread.
+class CONTENT_EXPORT DesktopStreamsRegistry {
+ public:
+ virtual ~DesktopStreamsRegistry() {}
+
+ static DesktopStreamsRegistry* GetInstance();
+
+ // Adds new stream to the registry. Called by the implementation of either
+ // desktopCapture API or tabCapture API, differentiated by |type|, after user
+ // has approved access to |source| for the |origin|. Returns identifier of
+ // the new stream.
+ // |render_frame_id| refers to the RenderFrame requesting the stream.
+ virtual std::string RegisterStream(int render_process_id,
+ int render_frame_id,
+ const GURL& origin,
+ const DesktopMediaID& source,
+ const std::string& extension_name,
+ const DesktopStreamRegistryType type) = 0;
+
+ // Validates stream identifier specified in getUserMedia(). Returns null
+ // DesktopMediaID if the specified |id| is invalid, i.e. wasn't generated
+ // using RegisterStream() or if it was generated for a different
+ // RenderFrame/origin/type. Otherwise returns ID of the source and removes it
+ // from the registry.
+ virtual DesktopMediaID RequestMediaForStreamId(
+ const std::string& id,
+ int render_process_id,
+ int render_frame_id,
+ const GURL& origin,
+ std::string* extension_name,
+ const DesktopStreamRegistryType type) = 0;
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_BROWSER_DESKTOP_STREAMS_REGISTRY_H_
diff --git a/chromium/content/public/browser/devtools_manager_delegate.cc b/chromium/content/public/browser/devtools_manager_delegate.cc
index fb839936bf4..be5ffe26673 100644
--- a/chromium/content/public/browser/devtools_manager_delegate.cc
+++ b/chromium/content/public/browser/devtools_manager_delegate.cc
@@ -2,8 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/devtools_manager_delegate.h"
+#include "base/values.h"
+#include "content/public/browser/devtools_agent_host.h"
namespace content {
@@ -22,7 +23,8 @@ std::string DevToolsManagerDelegate::GetTargetDescription(WebContents* wc) {
return std::string();
}
-bool DevToolsManagerDelegate::AllowInspectingWebContents(WebContents* wc) {
+bool DevToolsManagerDelegate::AllowInspectingRenderFrameHost(
+ RenderFrameHost* rfh) {
return true;
}
@@ -35,15 +37,35 @@ scoped_refptr<DevToolsAgentHost> DevToolsManagerDelegate::CreateNewTarget(
return nullptr;
}
+std::vector<BrowserContext*> DevToolsManagerDelegate::GetBrowserContexts() {
+ return std::vector<BrowserContext*>();
+}
+
+BrowserContext* DevToolsManagerDelegate::GetDefaultBrowserContext() {
+ return nullptr;
+}
+
+BrowserContext* DevToolsManagerDelegate::CreateBrowserContext() {
+ return nullptr;
+}
+
+void DevToolsManagerDelegate::DisposeBrowserContext(BrowserContext*,
+ DisposeCallback callback) {
+ std::move(callback).Run(false, "Browser Context disposal is not supported");
+}
+
void DevToolsManagerDelegate::ClientAttached(DevToolsAgentHost* agent_host,
DevToolsAgentHostClient* client) {}
void DevToolsManagerDelegate::ClientDetached(DevToolsAgentHost* agent_host,
DevToolsAgentHostClient* client) {}
-bool DevToolsManagerDelegate::HandleCommand(DevToolsAgentHost* agent_host,
- DevToolsAgentHostClient* client,
- base::DictionaryValue* command) {
- return false;
+void DevToolsManagerDelegate::HandleCommand(
+ DevToolsAgentHost* agent_host,
+ DevToolsAgentHostClient* client,
+ std::unique_ptr<base::DictionaryValue> command,
+ const std::string& message,
+ NotHandledCallback callback) {
+ std::move(callback).Run(std::move(command), message);
}
std::string DevToolsManagerDelegate::GetDiscoveryPageHTML() {
diff --git a/chromium/content/public/browser/devtools_manager_delegate.h b/chromium/content/public/browser/devtools_manager_delegate.h
index d0fea8b66aa..a31878d1753 100644
--- a/chromium/content/public/browser/devtools_manager_delegate.h
+++ b/chromium/content/public/browser/devtools_manager_delegate.h
@@ -20,6 +20,7 @@ class DictionaryValue;
namespace content {
class DevToolsAgentHostClient;
+class RenderFrameHost;
class WebContents;
class CONTENT_EXPORT DevToolsManagerDelegate {
@@ -36,8 +37,8 @@ class CONTENT_EXPORT DevToolsManagerDelegate {
// Returns DevToolsAgentHost title to use for given |web_contents| target.
virtual std::string GetTargetDescription(WebContents* web_contents);
- // Returns whether embedder allows to inspect given |web_contents|.
- virtual bool AllowInspectingWebContents(WebContents* web_contents);
+ // Returns whether embedder allows to inspect given |rfh|.
+ virtual bool AllowInspectingRenderFrameHost(RenderFrameHost* rfh);
// Returns all targets embedder would like to report as debuggable
// remotely.
@@ -46,16 +47,38 @@ class CONTENT_EXPORT DevToolsManagerDelegate {
// Creates new inspectable target given the |url|.
virtual scoped_refptr<DevToolsAgentHost> CreateNewTarget(const GURL& url);
+ // Get all live browser contexts created by CreateBrowserContext() method.
+ virtual std::vector<BrowserContext*> GetBrowserContexts();
+
+ // Get default browser context. May return null if not supported.
+ virtual BrowserContext* GetDefaultBrowserContext();
+
+ // Create new browser context. May return null if not supported or not
+ // possible. Delegate must take ownership of the created browser context, and
+ // may destroy it at will.
+ virtual BrowserContext* CreateBrowserContext();
+
+ // Dispose browser context that was created with |CreateBrowserContext|
+ // method.
+ using DisposeCallback = base::OnceCallback<void(bool, const std::string&)>;
+ virtual void DisposeBrowserContext(BrowserContext* context,
+ DisposeCallback callback);
+
// Called when a new client is attached/detached.
virtual void ClientAttached(DevToolsAgentHost* agent_host,
DevToolsAgentHostClient* client);
virtual void ClientDetached(DevToolsAgentHost* agent_host,
DevToolsAgentHostClient* client);
- // Returns true if the command has been handled, false otherwise.
- virtual bool HandleCommand(DevToolsAgentHost* agent_host,
+ // Call callback if command was not handled.
+ using NotHandledCallback =
+ base::OnceCallback<void(std::unique_ptr<base::DictionaryValue>,
+ const std::string&)>;
+ virtual void HandleCommand(DevToolsAgentHost* agent_host,
DevToolsAgentHostClient* client,
- base::DictionaryValue* command);
+ std::unique_ptr<base::DictionaryValue> command,
+ const std::string& message,
+ NotHandledCallback callback);
// Should return discovery page HTML that should list available tabs
// and provide attach links.
diff --git a/chromium/content/public/browser/file_url_loader.h b/chromium/content/public/browser/file_url_loader.h
index b6f0f24ec72..1f06a8faf2d 100644
--- a/chromium/content/public/browser/file_url_loader.h
+++ b/chromium/content/public/browser/file_url_loader.h
@@ -13,6 +13,12 @@
#include "net/http/http_response_headers.h"
#include "services/network/public/mojom/url_loader.mojom.h"
+namespace network {
+namespace mojom {
+class URLLoaderFactory;
+}
+} // namespace network
+
namespace content {
class CONTENT_EXPORT FileURLLoaderObserver
@@ -47,6 +53,15 @@ CONTENT_EXPORT void CreateFileURLLoader(
std::unique_ptr<FileURLLoaderObserver> observer,
scoped_refptr<net::HttpResponseHeaders> extra_response_headers = nullptr);
+// Helper to create a FileURLLoaderFactory instance. This exposes the ability
+// to load file:// URLs through SimpleURLLoader to non-content classes.
+//
+// When non-empty, |profile_path| is used to whitelist specific directories on
+// ChromeOS and Android. It is checked by
+// ContentBrowserClient::IsFileAccessAllowed.
+CONTENT_EXPORT std::unique_ptr<network::mojom::URLLoaderFactory>
+CreateFileURLLoaderFactory(const base::FilePath& profile_path);
+
} // namespace content
#endif // CONTENT_PUBLIC_BROWSER_FILE_URL_LOADER_H_
diff --git a/chromium/content/browser/loader/global_routing_id.h b/chromium/content/public/browser/global_routing_id.h
index 3f5aadf94c0..bf6a9d847c1 100644
--- a/chromium/content/browser/loader/global_routing_id.h
+++ b/chromium/content/public/browser/global_routing_id.h
@@ -1,30 +1,29 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright (c) 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_BROWSER_LOADER_GLOBAL_ROUTING_ID_H_
-#define CONTENT_BROWSER_LOADER_GLOBAL_ROUTING_ID_H_
+#ifndef CONTENT_PUBLIC_BROWSER_GLOBAL_ROUTING_ID_H_
+#define CONTENT_PUBLIC_BROWSER_GLOBAL_ROUTING_ID_H_
#include <tuple>
+#include "base/hash.h"
#include "ipc/ipc_message.h"
namespace content {
-// Uniquely identifies the route from which a net::URLRequest comes.
+// Uniquely identifies a target that legacy IPCs can be routed to.
struct GlobalRoutingID {
- GlobalRoutingID() : child_id(-1), route_id(-1) {
- }
+ GlobalRoutingID() : child_id(-1), route_id(-1) {}
GlobalRoutingID(int child_id, int route_id)
- : child_id(child_id),
- route_id(route_id) {
- }
+ : child_id(child_id), route_id(route_id) {}
- // The unique ID of the child process (different from OS's PID).
+ // The unique ID of the child process (this is different from OS's PID / this
+ // should come from RenderProcessHost::GetID()).
int child_id;
- // The route ID (unique for each URLRequest source).
+ // The route ID.
int route_id;
bool operator<(const GlobalRoutingID& other) const {
@@ -32,8 +31,7 @@ struct GlobalRoutingID {
std::tie(other.child_id, other.route_id);
}
bool operator==(const GlobalRoutingID& other) const {
- return child_id == other.child_id &&
- route_id == other.route_id;
+ return child_id == other.child_id && route_id == other.route_id;
}
bool operator!=(const GlobalRoutingID& other) const {
return !(*this == other);
@@ -48,10 +46,16 @@ struct GlobalFrameRoutingId {
GlobalFrameRoutingId(int child_id, int frame_routing_id)
: child_id(child_id), frame_routing_id(frame_routing_id) {}
- // The unique ID of the child process (different from OS's PID).
+ // GlobalFrameRoutingId is copyable.
+ GlobalFrameRoutingId(const GlobalFrameRoutingId&) = default;
+ GlobalFrameRoutingId& operator=(const GlobalFrameRoutingId&) = default;
+
+ // The unique ID of the child process (this is different from OS's PID / this
+ // should come from RenderProcessHost::GetID()).
int child_id;
- // The route ID (unique for each URLRequest source).
+ // The route ID of a RenderFrame - should come from
+ // RenderFrameHost::GetRoutingID().
int frame_routing_id;
bool operator<(const GlobalFrameRoutingId& other) const {
@@ -67,6 +71,12 @@ struct GlobalFrameRoutingId {
}
};
+struct GlobalFrameRoutingIdHasher {
+ std::size_t operator()(const GlobalFrameRoutingId& id) const {
+ return base::HashInts(id.child_id, id.frame_routing_id);
+ }
+};
+
} // namespace content
-#endif // CONTENT_BROWSER_LOADER_GLOBAL_ROUTING_ID_H_
+#endif // CONTENT_PUBLIC_BROWSER_GLOBAL_ROUTING_ID_H_
diff --git a/chromium/content/public/browser/gpu_client.h b/chromium/content/public/browser/gpu_client.h
index d5d249bf4f6..c5616d1aa37 100644
--- a/chromium/content/public/browser/gpu_client.h
+++ b/chromium/content/public/browser/gpu_client.h
@@ -7,24 +7,17 @@
#include <memory>
-#include "base/callback_forward.h"
+#include "components/viz/host/gpu_client.h"
#include "content/common/content_export.h"
-#include "services/ui/public/interfaces/gpu.mojom.h"
+#include "services/ws/public/mojom/gpu.mojom.h"
namespace content {
-// GpuClient provides an implementation of ui::mojom::Gpu.
-class CONTENT_EXPORT GpuClient {
- public:
- virtual ~GpuClient() {}
-
- using ConnectionErrorHandlerClosure =
- base::OnceCallback<void(GpuClient* client)>;
- static std::unique_ptr<GpuClient, base::OnTaskRunnerDeleter> Create(
- ui::mojom::GpuRequest request,
- ConnectionErrorHandlerClosure connection_error_handler,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner);
-};
+CONTENT_EXPORT
+std::unique_ptr<viz::GpuClient, base::OnTaskRunnerDeleter> CreateGpuClient(
+ ws::mojom::GpuRequest request,
+ viz::GpuClient::ConnectionErrorHandlerClosure connection_error_handler,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner);
} // namespace content
diff --git a/chromium/content/public/browser/gpu_utils.cc b/chromium/content/public/browser/gpu_utils.cc
index 78d1c9897aa..fc97755995c 100644
--- a/chromium/content/public/browser/gpu_utils.cc
+++ b/chromium/content/public/browser/gpu_utils.cc
@@ -10,6 +10,7 @@
#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 "content/browser/gpu/gpu_process_host.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
@@ -98,6 +99,9 @@ const gpu::GpuPreferences GetGpuPreferencesFromCommandLine() {
gpu_preferences.enable_vulkan =
command_line->HasSwitch(switches::kEnableVulkan);
+ gpu_preferences.enable_gpu_benchmarking_extension =
+ command_line->HasSwitch(cc::switches::kEnableGpuBenchmarking);
+
// Some of these preferences are set or adjusted in
// GpuDataManagerImplPrivate::AppendGpuCommandLine.
return gpu_preferences;
diff --git a/chromium/content/public/browser/interstitial_page.h b/chromium/content/public/browser/interstitial_page.h
index bdc03b3c7b3..da8437e9460 100644
--- a/chromium/content/public/browser/interstitial_page.h
+++ b/chromium/content/public/browser/interstitial_page.h
@@ -94,8 +94,8 @@ class InterstitialPage {
// DidAttachInterstitialPage or DidDetachInterstitialPage notifications.
virtual WebContents* GetWebContents() const = 0;
- // Gets the RenderFrameHost associated with
- // the interstitial page's main frame.
+ // 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 InterstitialPageDelegate* GetDelegateForTesting() = 0;
diff --git a/chromium/content/public/browser/media_session.h b/chromium/content/public/browser/media_session.h
index 12a6468b47d..43df8b22449 100644
--- a/chromium/content/public/browser/media_session.h
+++ b/chromium/content/public/browser/media_session.h
@@ -8,6 +8,7 @@
#include "base/macros.h"
#include "base/time/time.h"
#include "content/common/content_export.h"
+#include "services/media_session/public/mojom/audio_focus.mojom.h"
namespace blink {
namespace mojom {
@@ -25,7 +26,7 @@ class WebContents;
//
// MediaSession allows clients to observe its changes via MediaSessionObserver,
// and allows clients to resume/suspend/stop the managed players.
-class MediaSession {
+class MediaSession : public media_session::mojom::MediaSession {
public:
enum class SuspendType {
// Suspended by the system because a transient sound needs to be played.
@@ -40,7 +41,7 @@ class MediaSession {
// none is currently available.
CONTENT_EXPORT static MediaSession* Get(WebContents* contents);
- virtual ~MediaSession() = default;
+ ~MediaSession() override = default;
// Resume the media session.
// |type| represents the origin of the request.
diff --git a/chromium/content/public/browser/native_event_processor_mac.h b/chromium/content/public/browser/native_event_processor_mac.h
new file mode 100644
index 00000000000..43eee243b32
--- /dev/null
+++ b/chromium/content/public/browser/native_event_processor_mac.h
@@ -0,0 +1,22 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_PUBLIC_BROWSER_NATIVE_EVENT_PROCESSOR_MAC_H_
+#define CONTENT_PUBLIC_BROWSER_NATIVE_EVENT_PROCESSOR_MAC_H_
+
+namespace content {
+class NativeEventProcessorObserver;
+} // namespace content
+
+// The application's NSApplication subclass should implement this protocol to
+// give observers additional information about the native events being run in
+// -[NSApplication sendEvent:].
+@protocol NativeEventProcessor
+- (void)addNativeEventProcessorObserver:
+ (content::NativeEventProcessorObserver*)observer;
+- (void)removeNativeEventProcessorObserver:
+ (content::NativeEventProcessorObserver*)observer;
+@end
+
+#endif // CONTENT_PUBLIC_BROWSER_NATIVE_EVENT_PROCESSOR_MAC_H_
diff --git a/chromium/content/public/browser/native_event_processor_observer_mac.h b/chromium/content/public/browser/native_event_processor_observer_mac.h
new file mode 100644
index 00000000000..79bbab7320b
--- /dev/null
+++ b/chromium/content/public/browser/native_event_processor_observer_mac.h
@@ -0,0 +1,50 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_PUBLIC_BROWSER_NATIVE_EVENT_PROCESSOR_OBSERVER_MAC_H_
+#define CONTENT_PUBLIC_BROWSER_NATIVE_EVENT_PROCESSOR_OBSERVER_MAC_H_
+
+#include "base/macros.h"
+#include "base/observer_list.h"
+#include "base/time/time.h"
+#include "content/common/content_export.h"
+
+#if defined(__OBJC__)
+@class NSEvent;
+#else // __OBJC__
+class NSEvent;
+#endif // __OBJC__
+
+namespace content {
+
+class NativeEventProcessorObserver {
+ public:
+ // Called right before a native event is run.
+ virtual void WillRunNativeEvent(const void* opaque_identifier) = 0;
+
+ // Called right after a native event is run.
+ // |creation_time| refers to the time at which the native event was created.
+ virtual void DidRunNativeEvent(const void* opaque_identifier,
+ base::TimeTicks creation_time) = 0;
+};
+
+// The constructor sends a WillRunNativeEvent callback to each observer.
+// The destructor sends a DidRunNativeEvent callback to each observer.
+class CONTENT_EXPORT ScopedNotifyNativeEventProcessorObserver {
+ public:
+ ScopedNotifyNativeEventProcessorObserver(
+ base::ObserverList<NativeEventProcessorObserver>::Unchecked*
+ observer_list,
+ NSEvent* event);
+ ~ScopedNotifyNativeEventProcessorObserver();
+
+ private:
+ base::ObserverList<NativeEventProcessorObserver>::Unchecked* observer_list_;
+ NSEvent* event_;
+ DISALLOW_COPY_AND_ASSIGN(ScopedNotifyNativeEventProcessorObserver);
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_BROWSER_NATIVE_EVENT_PROCESSOR_OBSERVER_MAC_H_
diff --git a/chromium/content/public/browser/native_event_processor_observer_mac.mm b/chromium/content/public/browser/native_event_processor_observer_mac.mm
new file mode 100644
index 00000000000..a0e2fcc09bc
--- /dev/null
+++ b/chromium/content/public/browser/native_event_processor_observer_mac.mm
@@ -0,0 +1,57 @@
+// 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/native_event_processor_observer_mac.h"
+
+#import <AppKit/AppKit.h>
+
+#include "base/observer_list.h"
+#include "base/time/time.h"
+
+namespace content {
+
+namespace {
+
+base::TimeTicks TimeTicksForEvent(NSEvent* event) {
+ // NSEvent.timestamp gives the creation time of the event in seconds
+ // since system startup. The baseline it should be compared agaainst is
+ // NSProcessInfo.systemUptime. To convert to base::TimeTicks, we take
+ // the difference and subtract from base::TimeTicks::Now().
+ // Observations:
+ // 1) This implementation is fast, since both systemUptime and
+ // base::TimeTicks::Now() use the commpage [no syscalls].
+ // 2) systemUptime's implementation uses mach_absolute_time() -- see
+ // CoreFoundation.framework. Presumably, so does NSEvent.timestamp.
+ // mach_absolute_time() does not advance while the machine is asleep.
+ NSTimeInterval current_system_uptime =
+ [[NSProcessInfo processInfo] systemUptime];
+ return base::TimeTicks::Now() +
+ base::TimeDelta::FromSecondsD(event.timestamp - current_system_uptime);
+}
+
+} // namespace
+
+ScopedNotifyNativeEventProcessorObserver::
+ ScopedNotifyNativeEventProcessorObserver(
+ base::ObserverList<NativeEventProcessorObserver>::Unchecked*
+ observer_list,
+ NSEvent* event)
+ : observer_list_(observer_list), event_(event) {
+ for (auto& observer : *observer_list_)
+ observer.WillRunNativeEvent(event_);
+}
+
+ScopedNotifyNativeEventProcessorObserver::
+ ~ScopedNotifyNativeEventProcessorObserver() {
+ base::TimeTicks event_creation_time;
+ for (auto& obs : *observer_list_) {
+ // Compute the value in the loop to avoid doing work if there are no
+ // observers.
+ if (event_creation_time.is_null())
+ event_creation_time = TimeTicksForEvent(event_);
+ obs.DidRunNativeEvent(event_, event_creation_time);
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/public/browser/navigation_handle.h b/chromium/content/public/browser/navigation_handle.h
index 2bace920726..62c86a08842 100644
--- a/chromium/content/public/browser/navigation_handle.h
+++ b/chromium/content/public/browser/navigation_handle.h
@@ -106,7 +106,11 @@ class CONTENT_EXPORT NavigationHandle {
// The time the navigation started, recorded either in the renderer or in the
// browser process. Corresponds to Navigation Timing API.
- virtual const base::TimeTicks& NavigationStart() = 0;
+ virtual base::TimeTicks NavigationStart() = 0;
+
+ // The time the input leading to the navigation started. Will not be
+ // set if unknown.
+ virtual base::TimeTicks NavigationInputStart() = 0;
// Whether or not the navigation was started within a context menu.
virtual bool WasStartedFromContextMenu() const = 0;
@@ -319,6 +323,9 @@ class CONTENT_EXPORT NavigationHandle {
// deferring NavigationThrottle do the resuming.
virtual void CallResumeForTesting() = 0;
+ // Returns whether this navigation is currently deferred.
+ virtual bool IsDeferredForTesting() = 0;
+
// The NavigationData that the embedder returned from
// ResourceDispatcherHostDelegate::GetNavigationData during commit. This will
// be a clone of the NavigationData.
diff --git a/chromium/content/public/browser/network_connection_tracker.cc b/chromium/content/public/browser/network_connection_tracker.cc
deleted file mode 100644
index 1b1612e8c6e..00000000000
--- a/chromium/content/public/browser/network_connection_tracker.cc
+++ /dev/null
@@ -1,177 +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/public/browser/network_connection_tracker.h"
-
-#include <utility>
-
-#include "base/task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "services/network/public/mojom/network_change_manager.mojom.h"
-#include "services/network/public/mojom/network_service.mojom.h"
-
-namespace content {
-
-namespace {
-
-// Wraps a |user_callback| when GetConnectionType() is called on a different
-// thread than NetworkConnectionTracker's thread.
-void OnGetConnectionType(
- scoped_refptr<base::TaskRunner> task_runner,
- NetworkConnectionTracker::ConnectionTypeCallback user_callback,
- network::mojom::ConnectionType connection_type) {
- task_runner->PostTask(
- FROM_HERE,
- base::BindOnce(
- [](NetworkConnectionTracker::ConnectionTypeCallback callback,
- network::mojom::ConnectionType type) {
- std::move(callback).Run(type);
- },
- std::move(user_callback), connection_type));
-}
-
-static const int32_t kConnectionTypeInvalid = -1;
-
-} // namespace
-
-NetworkConnectionTracker::NetworkConnectionTracker(
- base::RepeatingCallback<network::mojom::NetworkService*()> callback)
- : get_network_service_callback_(callback),
- task_runner_(base::ThreadTaskRunnerHandle::Get()),
- connection_type_(kConnectionTypeInvalid),
- network_change_observer_list_(
- new base::ObserverListThreadSafe<NetworkConnectionObserver>(
- base::ObserverListPolicy::EXISTING_ONLY)),
- binding_(this) {
- Initialize();
- DCHECK(binding_.is_bound());
-}
-
-NetworkConnectionTracker::~NetworkConnectionTracker() {
- network_change_observer_list_->AssertEmpty();
-}
-
-bool NetworkConnectionTracker::GetConnectionType(
- network::mojom::ConnectionType* type,
- ConnectionTypeCallback callback) {
- // |connection_type_| is initialized when NetworkService starts up. In most
- // cases, it won't be kConnectionTypeInvalid and code will return early.
- base::subtle::Atomic32 type_value =
- base::subtle::NoBarrier_Load(&connection_type_);
- if (type_value != kConnectionTypeInvalid) {
- *type = static_cast<network::mojom::ConnectionType>(type_value);
- return true;
- }
- base::AutoLock lock(lock_);
- // Check again after getting the lock, and return early if
- // OnInitialConnectionType() is called after first NoBarrier_Load.
- type_value = base::subtle::NoBarrier_Load(&connection_type_);
- if (type_value != kConnectionTypeInvalid) {
- *type = static_cast<network::mojom::ConnectionType>(type_value);
- return true;
- }
- if (!task_runner_->RunsTasksInCurrentSequence()) {
- connection_type_callbacks_.push_back(base::BindOnce(
- &OnGetConnectionType, base::SequencedTaskRunnerHandle::Get(),
- std::move(callback)));
- } else {
- connection_type_callbacks_.push_back(std::move(callback));
- }
- return false;
-}
-
-// static
-bool NetworkConnectionTracker::IsConnectionCellular(
- network::mojom::ConnectionType type) {
- bool is_cellular = false;
- switch (type) {
- case network::mojom::ConnectionType::CONNECTION_2G:
- case network::mojom::ConnectionType::CONNECTION_3G:
- case network::mojom::ConnectionType::CONNECTION_4G:
- is_cellular = true;
- break;
- case network::mojom::ConnectionType::CONNECTION_UNKNOWN:
- case network::mojom::ConnectionType::CONNECTION_ETHERNET:
- case network::mojom::ConnectionType::CONNECTION_WIFI:
- case network::mojom::ConnectionType::CONNECTION_NONE:
- case network::mojom::ConnectionType::CONNECTION_BLUETOOTH:
- is_cellular = false;
- break;
- }
- return is_cellular;
-}
-
-void NetworkConnectionTracker::AddNetworkConnectionObserver(
- NetworkConnectionObserver* observer) {
- network_change_observer_list_->AddObserver(observer);
-}
-
-void NetworkConnectionTracker::RemoveNetworkConnectionObserver(
- NetworkConnectionObserver* observer) {
- network_change_observer_list_->RemoveObserver(observer);
-}
-
-NetworkConnectionTracker::NetworkConnectionTracker()
- : connection_type_(kConnectionTypeInvalid),
- network_change_observer_list_(
- new base::ObserverListThreadSafe<NetworkConnectionObserver>(
- base::ObserverListPolicy::EXISTING_ONLY)),
- binding_(this) {}
-
-void NetworkConnectionTracker::OnInitialConnectionType(
- network::mojom::ConnectionType type) {
- base::AutoLock lock(lock_);
- base::subtle::NoBarrier_Store(&connection_type_,
- static_cast<base::subtle::Atomic32>(type));
- while (!connection_type_callbacks_.empty()) {
- std::move(connection_type_callbacks_.front()).Run(type);
- connection_type_callbacks_.pop_front();
- }
-}
-
-void NetworkConnectionTracker::OnNetworkChanged(
- network::mojom::ConnectionType type) {
- base::subtle::NoBarrier_Store(&connection_type_,
- static_cast<base::subtle::Atomic32>(type));
- network_change_observer_list_->Notify(
- FROM_HERE, &NetworkConnectionObserver::OnConnectionChanged, type);
-}
-
-void NetworkConnectionTracker::Initialize() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(!binding_.is_bound());
-
- network::mojom::NetworkService* network_service =
- get_network_service_callback_.Run();
-
- // Get NetworkChangeManagerPtr.
- network::mojom::NetworkChangeManagerPtr manager_ptr;
- network::mojom::NetworkChangeManagerRequest request(
- mojo::MakeRequest(&manager_ptr));
- network_service->GetNetworkChangeManager(std::move(request));
-
- // Request notification from NetworkChangeManagerPtr.
- network::mojom::NetworkChangeManagerClientPtr client_ptr;
- network::mojom::NetworkChangeManagerClientRequest client_request(
- mojo::MakeRequest(&client_ptr));
- binding_.Bind(std::move(client_request));
- manager_ptr->RequestNotifications(std::move(client_ptr));
-
- // base::Unretained is safe as |binding_| is owned by |this|.
- binding_.set_connection_error_handler(base::BindRepeating(
- &NetworkConnectionTracker::HandleNetworkServicePipeBroken,
- base::Unretained(this)));
-}
-
-void NetworkConnectionTracker::HandleNetworkServicePipeBroken() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- binding_.Close();
- // Reset |connection_type_| to invalid, so future GetConnectionType() can be
- // delayed after network service has restarted, and that there isn't an
- // incorrectly cached state.
- base::subtle::NoBarrier_Store(&connection_type_, kConnectionTypeInvalid);
- Initialize();
-}
-
-} // namespace content
diff --git a/chromium/content/public/browser/network_connection_tracker.h b/chromium/content/public/browser/network_connection_tracker.h
deleted file mode 100644
index 1eb2c8eb499..00000000000
--- a/chromium/content/public/browser/network_connection_tracker.h
+++ /dev/null
@@ -1,136 +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_PUBLIC_BROWSER_NETWORK_CONNECTION_TRACKER_H_
-#define CONTENT_PUBLIC_BROWSER_NETWORK_CONNECTION_TRACKER_H_
-
-#include <list>
-#include <memory>
-
-#include "base/atomicops.h"
-#include "base/callback.h"
-#include "base/gtest_prod_util.h"
-#include "base/macros.h"
-#include "base/observer_list_threadsafe.h"
-#include "base/sequence_checker.h"
-#include "base/synchronization/lock.h"
-#include "content/common/content_export.h"
-#include "mojo/public/cpp/bindings/binding.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
-#include "services/network/public/mojom/network_change_manager.mojom.h"
-#include "services/network/public/mojom/network_service.mojom.h"
-
-namespace content {
-
-// This class subscribes to network change events from
-// network::mojom::NetworkChangeManager and propogates these notifications to
-// its NetworkConnectionObservers registered through
-// AddNetworkConnectionObserver()/RemoveNetworkConnectionObserver().
-class CONTENT_EXPORT NetworkConnectionTracker
- : public network::mojom::NetworkChangeManagerClient {
- public:
- using ConnectionTypeCallback =
- base::OnceCallback<void(network::mojom::ConnectionType)>;
-
- class CONTENT_EXPORT NetworkConnectionObserver {
- public:
- // Please refer to NetworkChangeManagerClient::OnNetworkChanged for when
- // this method is invoked.
- virtual void OnConnectionChanged(network::mojom::ConnectionType type) = 0;
-
- protected:
- virtual ~NetworkConnectionObserver() {}
- };
-
- // Constructs a NetworkConnectionTracker. |callback| should return the network
- // service that is in use. NetworkConnectionTracker does not need to be
- // destroyed before the network service.
- explicit NetworkConnectionTracker(
- base::RepeatingCallback<network::mojom::NetworkService*()> callback);
-
- ~NetworkConnectionTracker() override;
-
- // If connection type can be retrieved synchronously, returns true and |type|
- // will contain the current connection type; Otherwise, returns false and
- // does not modify |type|, in which case, |callback| will be called on the
- // calling thread when connection type is ready. This method is thread safe.
- // Please also refer to net::NetworkChangeNotifier::GetConnectionType() for
- // documentation.
- virtual bool GetConnectionType(network::mojom::ConnectionType* type,
- ConnectionTypeCallback callback);
-
- // Returns true if |type| is a cellular connection.
- // Returns false if |type| is CONNECTION_UNKNOWN, and thus, depending on the
- // implementation of GetConnectionType(), it is possible that
- // IsConnectionCellular(GetConnectionType()) returns false even if the
- // current connection is cellular.
- static bool IsConnectionCellular(network::mojom::ConnectionType type);
-
- // Registers |observer| to receive notifications of network changes. The
- // thread on which this is called is the thread on which |observer| will be
- // called back with notifications.
- void AddNetworkConnectionObserver(NetworkConnectionObserver* observer);
-
- // Unregisters |observer| from receiving notifications. This must be called
- // on the same thread on which AddNetworkConnectionObserver() was called.
- // All observers must be unregistered before |this| is destroyed.
- void RemoveNetworkConnectionObserver(NetworkConnectionObserver* observer);
-
- protected:
- // Constructor used in testing to mock out network service.
- NetworkConnectionTracker();
-
- // NetworkChangeManagerClient implementation. Protected for testing.
- void OnInitialConnectionType(network::mojom::ConnectionType type) override;
- void OnNetworkChanged(network::mojom::ConnectionType type) override;
-
- private:
- FRIEND_TEST_ALL_PREFIXES(NetworkGetConnectionTest,
- GetConnectionTypeOnDifferentThread);
-
- // Starts listening for connection change notifications from
- // |network_service|. Observers may be added and GetConnectionType called, but
- // no network information will be provided until this method is called. For
- // unit tests, this class can be subclassed, and OnInitialConnectionType /
- // OnNetworkChanged may be called directly, instead of providing a
- // NetworkService.
- void Initialize();
-
- // Serves as a connection error handler, and is invoked when network service
- // restarts.
- void HandleNetworkServicePipeBroken();
-
- // Callback to get the current network service raw mojo pointer. This is to
- // ensure that |this| can survive crashes and restarts of network service.
- const base::RepeatingCallback<network::mojom::NetworkService*()>
- get_network_service_callback_;
-
- // The task runner that |this| lives on.
- scoped_refptr<base::SequencedTaskRunner> task_runner_;
-
- // Protect access to |connection_type_callbacks_|.
- base::Lock lock_;
-
- // Saves user callback if GetConnectionType() cannot complete synchronously.
- std::list<ConnectionTypeCallback> connection_type_callbacks_;
-
- // |connection_type_| is set on one thread but read on many threads.
- // The default value is -1 before OnInitialConnectionType().
- base::subtle::Atomic32 connection_type_;
-
- const scoped_refptr<base::ObserverListThreadSafe<NetworkConnectionObserver>>
- network_change_observer_list_;
-
- mojo::Binding<network::mojom::NetworkChangeManagerClient> binding_;
-
- // Only the initialization and re-initialization of |this| are required to
- // be bound to the same sequence.
- SEQUENCE_CHECKER(sequence_checker_);
-
- DISALLOW_COPY_AND_ASSIGN(NetworkConnectionTracker);
-};
-
-} // namespace content
-
-#endif // CONTENT_PUBLIC_BROWSER_NETWORK_CONNECTION_TRACKER_H_
diff --git a/chromium/content/public/browser/network_connection_tracker_unittest.cc b/chromium/content/public/browser/network_connection_tracker_unittest.cc
deleted file mode 100644
index 65689197fb1..00000000000
--- a/chromium/content/public/browser/network_connection_tracker_unittest.cc
+++ /dev/null
@@ -1,343 +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/public/browser/network_connection_tracker.h"
-
-#include "base/macros.h"
-#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
-#include "base/threading/thread.h"
-#include "base/threading/thread_checker.h"
-#include "net/base/mock_network_change_notifier.h"
-#include "services/network/network_service.h"
-#include "services/network/public/mojom/network_change_manager.mojom.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-
-namespace {
-
-class TestNetworkConnectionObserver
- : public NetworkConnectionTracker::NetworkConnectionObserver {
- public:
- explicit TestNetworkConnectionObserver(NetworkConnectionTracker* tracker)
- : num_notifications_(0),
- tracker_(tracker),
- run_loop_(std::make_unique<base::RunLoop>()),
- connection_type_(network::mojom::ConnectionType::CONNECTION_UNKNOWN) {
- tracker_->AddNetworkConnectionObserver(this);
- }
-
- ~TestNetworkConnectionObserver() override {
- tracker_->RemoveNetworkConnectionObserver(this);
- }
-
- // Helper to synchronously get connection type from NetworkConnectionTracker.
- network::mojom::ConnectionType GetConnectionTypeSync() {
- network::mojom::ConnectionType type;
- base::RunLoop run_loop;
- bool sync = tracker_->GetConnectionType(
- &type, base::BindOnce(
- &TestNetworkConnectionObserver::GetConnectionTypeCallback,
- &run_loop, &type));
- if (!sync)
- run_loop.Run();
- return type;
- }
-
- // NetworkConnectionObserver implementation:
- void OnConnectionChanged(network::mojom::ConnectionType type) override {
- EXPECT_EQ(type, GetConnectionTypeSync());
-
- num_notifications_++;
- connection_type_ = type;
- run_loop_->Quit();
- }
-
- size_t num_notifications() const { return num_notifications_; }
- void WaitForNotification() {
- run_loop_->Run();
- run_loop_.reset(new base::RunLoop());
- }
-
- network::mojom::ConnectionType connection_type() const {
- return connection_type_;
- }
-
- private:
- static void GetConnectionTypeCallback(base::RunLoop* run_loop,
- network::mojom::ConnectionType* out,
- network::mojom::ConnectionType type) {
- *out = type;
- run_loop->Quit();
- }
-
- size_t num_notifications_;
- NetworkConnectionTracker* tracker_;
- std::unique_ptr<base::RunLoop> run_loop_;
- network::mojom::ConnectionType connection_type_;
-
- DISALLOW_COPY_AND_ASSIGN(TestNetworkConnectionObserver);
-};
-
-// A helper class to call NetworkConnectionTracker::GetConnectionType().
-class ConnectionTypeGetter {
- public:
- explicit ConnectionTypeGetter(NetworkConnectionTracker* tracker)
- : tracker_(tracker),
- connection_type_(network::mojom::ConnectionType::CONNECTION_UNKNOWN) {}
- ~ConnectionTypeGetter() {}
-
- bool GetConnectionType() {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- return tracker_->GetConnectionType(
- &connection_type_,
- base::BindOnce(&ConnectionTypeGetter::OnGetConnectionType,
- base::Unretained(this)));
- }
-
- void WaitForConnectionType(
- network::mojom::ConnectionType expected_connection_type) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- run_loop_.Run();
- EXPECT_EQ(expected_connection_type, connection_type_);
- }
-
- network::mojom::ConnectionType connection_type() const {
- return connection_type_;
- }
-
- private:
- void OnGetConnectionType(network::mojom::ConnectionType type) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- connection_type_ = type;
- run_loop_.Quit();
- }
-
- base::RunLoop run_loop_;
- NetworkConnectionTracker* tracker_;
- network::mojom::ConnectionType connection_type_;
- THREAD_CHECKER(thread_checker_);
-
- DISALLOW_COPY_AND_ASSIGN(ConnectionTypeGetter);
-};
-
-} // namespace
-
-class NetworkConnectionTrackerTest : public testing::Test {
- public:
- NetworkConnectionTrackerTest() {}
-
- ~NetworkConnectionTrackerTest() override {}
-
- void Initialize() {
- network::mojom::NetworkServicePtr network_service_ptr;
- network::mojom::NetworkServiceRequest network_service_request =
- mojo::MakeRequest(&network_service_ptr);
- network_service_ =
- network::NetworkService::Create(std::move(network_service_request),
- /*netlog=*/nullptr);
- tracker_ = std::make_unique<NetworkConnectionTracker>(
- base::BindRepeating(&NetworkConnectionTrackerTest::network_service,
- base::Unretained(this)));
- observer_ = std::make_unique<TestNetworkConnectionObserver>(tracker_.get());
- }
-
- network::mojom::NetworkService* network_service() {
- return network_service_.get();
- }
-
- NetworkConnectionTracker* network_connection_tracker() {
- return tracker_.get();
- }
-
- TestNetworkConnectionObserver* network_connection_observer() {
- return observer_.get();
- }
-
- // Simulates a connection type change and broadcast it to observers.
- void SimulateConnectionTypeChange(
- net::NetworkChangeNotifier::ConnectionType type) {
- mock_network_change_notifier_.NotifyObserversOfNetworkChangeForTests(type);
- }
-
- // Sets the current connection type of the mock network change notifier.
- void SetConnectionType(net::NetworkChangeNotifier::ConnectionType type) {
- mock_network_change_notifier_.SetConnectionType(type);
- }
-
- private:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
- net::test::MockNetworkChangeNotifier mock_network_change_notifier_;
- std::unique_ptr<network::NetworkService> network_service_;
- std::unique_ptr<NetworkConnectionTracker> tracker_;
- std::unique_ptr<TestNetworkConnectionObserver> observer_;
-
- DISALLOW_COPY_AND_ASSIGN(NetworkConnectionTrackerTest);
-};
-
-TEST_F(NetworkConnectionTrackerTest, ObserverNotified) {
- Initialize();
- EXPECT_EQ(network::mojom::ConnectionType::CONNECTION_UNKNOWN,
- network_connection_observer()->connection_type());
-
- // Simulate a network change.
- SimulateConnectionTypeChange(
- net::NetworkChangeNotifier::ConnectionType::CONNECTION_3G);
-
- network_connection_observer()->WaitForNotification();
- EXPECT_EQ(network::mojom::ConnectionType::CONNECTION_3G,
- network_connection_observer()->connection_type());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(1u, network_connection_observer()->num_notifications());
-}
-
-TEST_F(NetworkConnectionTrackerTest, UnregisteredObserverNotNotified) {
- Initialize();
- auto network_connection_observer2 =
- std::make_unique<TestNetworkConnectionObserver>(
- network_connection_tracker());
-
- // Simulate a network change.
- SimulateConnectionTypeChange(
- net::NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI);
-
- network_connection_observer2->WaitForNotification();
- EXPECT_EQ(network::mojom::ConnectionType::CONNECTION_WIFI,
- network_connection_observer2->connection_type());
- network_connection_observer()->WaitForNotification();
- EXPECT_EQ(network::mojom::ConnectionType::CONNECTION_WIFI,
- network_connection_observer()->connection_type());
- base::RunLoop().RunUntilIdle();
-
- network_connection_observer2.reset();
-
- // Simulate an another network change.
- SimulateConnectionTypeChange(
- net::NetworkChangeNotifier::ConnectionType::CONNECTION_2G);
- network_connection_observer()->WaitForNotification();
- EXPECT_EQ(network::mojom::ConnectionType::CONNECTION_2G,
- network_connection_observer()->connection_type());
- EXPECT_EQ(2u, network_connection_observer()->num_notifications());
-}
-
-TEST_F(NetworkConnectionTrackerTest, GetConnectionType) {
- SetConnectionType(net::NetworkChangeNotifier::ConnectionType::CONNECTION_3G);
- // Creates a NetworkService now so it initializes a NetworkChangeManager
- // with initial connection type as CONNECTION_3G.
- Initialize();
-
- ConnectionTypeGetter getter1(network_connection_tracker());
- ConnectionTypeGetter getter2(network_connection_tracker());
- // These two GetConnectionType() will finish asynchonously because network
- // service is not yet set up.
- EXPECT_FALSE(getter1.GetConnectionType());
- EXPECT_FALSE(getter2.GetConnectionType());
-
- getter1.WaitForConnectionType(
- /*expected_connection_type=*/network::mojom::ConnectionType::
- CONNECTION_3G);
- getter2.WaitForConnectionType(
- /*expected_connection_type=*/network::mojom::ConnectionType::
- CONNECTION_3G);
-
- ConnectionTypeGetter getter3(network_connection_tracker());
- // This GetConnectionType() should finish synchronously.
- EXPECT_TRUE(getter3.GetConnectionType());
- EXPECT_EQ(network::mojom::ConnectionType::CONNECTION_3G,
- getter3.connection_type());
-}
-
-// Tests that GetConnectionType returns false and doesn't modify its |type|
-// parameter when the connection type is unavailable.
-TEST_F(NetworkConnectionTrackerTest, GetConnectionTypeUnavailable) {
- // Returns a dummy network service that has not been initialized.
- network::mojom::NetworkServicePtr* network_service_ptr =
- new network::mojom::NetworkServicePtr;
-
- network::mojom::NetworkServiceRequest request =
- mojo::MakeRequest(network_service_ptr);
- base::RepeatingCallback<network::mojom::NetworkService*()> callback =
- base::BindRepeating(
- [](network::mojom::NetworkService* service) { return service; },
- base::Unretained(network_service_ptr->get()));
-
- auto tracker = std::make_unique<NetworkConnectionTracker>(callback);
- auto type = network::mojom::ConnectionType::CONNECTION_3G;
- bool sync = tracker->GetConnectionType(&type, base::DoNothing());
-
- EXPECT_FALSE(sync);
- EXPECT_EQ(type, network::mojom::ConnectionType::CONNECTION_3G);
- delete network_service_ptr;
-}
-
-// Tests GetConnectionType() on a different thread.
-class NetworkGetConnectionTest : public NetworkConnectionTrackerTest {
- public:
- NetworkGetConnectionTest()
- : getter_thread_("NetworkGetConnectionTestThread") {
- getter_thread_.Start();
- Initialize();
- }
-
- ~NetworkGetConnectionTest() override {}
-
- void GetConnectionType() {
- DCHECK(getter_thread_.task_runner()->RunsTasksInCurrentSequence());
- getter_ =
- std::make_unique<ConnectionTypeGetter>(network_connection_tracker());
- EXPECT_FALSE(getter_->GetConnectionType());
- }
-
- void WaitForConnectionType(
- network::mojom::ConnectionType expected_connection_type) {
- DCHECK(getter_thread_.task_runner()->RunsTasksInCurrentSequence());
- getter_->WaitForConnectionType(expected_connection_type);
- }
-
- base::Thread* getter_thread() { return &getter_thread_; }
-
- private:
- base::Thread getter_thread_;
-
- // Accessed on |getter_thread_|.
- std::unique_ptr<ConnectionTypeGetter> getter_;
-
- DISALLOW_COPY_AND_ASSIGN(NetworkGetConnectionTest);
-};
-
-TEST_F(NetworkGetConnectionTest, GetConnectionTypeOnDifferentThread) {
- // Flush pending OnInitialConnectionType() notification and force |tracker| to
- // use async for GetConnectionType() calls.
- base::RunLoop().RunUntilIdle();
- base::subtle::NoBarrier_Store(&network_connection_tracker()->connection_type_,
- -1);
- {
- base::RunLoop run_loop;
- getter_thread()->task_runner()->PostTaskAndReply(
- FROM_HERE,
- base::BindOnce(&NetworkGetConnectionTest::GetConnectionType,
- base::Unretained(this)),
- base::BindOnce([](base::RunLoop* run_loop) { run_loop->Quit(); },
- base::Unretained(&run_loop)));
- run_loop.Run();
- }
-
- network_connection_tracker()->OnInitialConnectionType(
- network::mojom::ConnectionType::CONNECTION_3G);
- {
- base::RunLoop run_loop;
- getter_thread()->task_runner()->PostTaskAndReply(
- FROM_HERE,
- base::BindOnce(&NetworkGetConnectionTest::WaitForConnectionType,
- base::Unretained(this),
- /*expected_connection_type=*/
- network::mojom::ConnectionType::CONNECTION_3G),
- base::BindOnce([](base::RunLoop* run_loop) { run_loop->Quit(); },
- base::Unretained(&run_loop)));
- run_loop.Run();
- }
-}
-
-} // namespace content
diff --git a/chromium/content/public/browser/network_service_instance.h b/chromium/content/public/browser/network_service_instance.h
index 47e20afb942..69678a7abf5 100644
--- a/chromium/content/public/browser/network_service_instance.h
+++ b/chromium/content/public/browser/network_service_instance.h
@@ -8,12 +8,17 @@
#include "content/common/content_export.h"
namespace network {
+class NetworkConnectionTracker;
class NetworkService;
namespace mojom {
class NetworkService;
}
} // namespace network
+namespace service_manager {
+class Connector;
+} // namespace service_manager
+
namespace content {
// Returns a pointer to the NetworkService, creating / re-creating it as needed.
@@ -24,6 +29,14 @@ namespace content {
// This method can only be called on the UI thread.
CONTENT_EXPORT network::mojom::NetworkService* GetNetworkService();
+// Similar to GetNetworkService(), but will create the NetworkService from a
+// service manager connector if needed. If network service is disabled,
+// |connector| will be ignored and this method is identical to
+// GetNetworkService().
+// This method can only be called on the UI thread.
+CONTENT_EXPORT network::mojom::NetworkService* GetNetworkServiceFromConnector(
+ service_manager::Connector* connector);
+
// 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
@@ -34,6 +47,17 @@ CONTENT_EXPORT network::NetworkService* GetNetworkServiceImpl();
// Must only be called on the UI thread.
CONTENT_EXPORT void FlushNetworkServiceInstanceForTesting();
+// Returns a NetworkConnectionTracker that can be used to subscribe for
+// network change events.
+// Must only be called on the UI thread.
+CONTENT_EXPORT network::NetworkConnectionTracker* GetNetworkConnectionTracker();
+
+// Sets the NetworkConnectionTracker instance to use. For testing only.
+// Must be called on the UI thread. Must be called before the first call to
+// GetNetworkConnectionTracker.
+CONTENT_EXPORT void SetNetworkConnectionTrackerForTesting(
+ network::NetworkConnectionTracker* network_connection_tracker);
+
} // namespace content
#endif // CONTENT_PUBLIC_BROWSER_NETWORK_SERVICE_INSTANCE_H_
diff --git a/chromium/content/public/browser/notification_event_dispatcher.h b/chromium/content/public/browser/notification_event_dispatcher.h
index 57afa43cb7a..9015b091ba9 100644
--- a/chromium/content/public/browser/notification_event_dispatcher.h
+++ b/chromium/content/public/browser/notification_event_dispatcher.h
@@ -11,13 +11,13 @@
#include "base/optional.h"
#include "base/strings/string16.h"
#include "content/common/content_export.h"
-#include "content/public/common/persistent_notification_status.h"
class GURL;
namespace content {
class BrowserContext;
+enum class PersistentNotificationStatus;
// This is the dispatcher to be used for firing events related to notifications.
// This class is a singleton, the instance of which can be retrieved using the
diff --git a/chromium/content/public/browser/overlay_window.h b/chromium/content/public/browser/overlay_window.h
index 8f04e7e4e63..04160fd5127 100644
--- a/chromium/content/public/browser/overlay_window.h
+++ b/chromium/content/public/browser/overlay_window.h
@@ -9,6 +9,10 @@
#include "ui/gfx/native_widget_types.h"
+namespace blink {
+struct PictureInPictureControlInfo;
+}
+
namespace gfx {
class Rect;
class Size;
@@ -52,6 +56,8 @@ class OverlayWindow {
virtual gfx::Rect GetBounds() const = 0;
virtual void UpdateVideoSize(const gfx::Size& natural_size) = 0;
virtual void SetPlaybackState(PlaybackState playback_state) = 0;
+ virtual void SetPictureInPictureCustomControls(
+ const std::vector<blink::PictureInPictureControlInfo>& controls) = 0;
// Retrieves the ui::Layers corresponding to the window and video.
virtual ui::Layer* GetWindowBackgroundLayer() = 0;
diff --git a/chromium/content/public/browser/payment_app_provider.h b/chromium/content/public/browser/payment_app_provider.h
index bde13864ff4..4cfb4164ee3 100644
--- a/chromium/content/public/browser/payment_app_provider.h
+++ b/chromium/content/public/browser/payment_app_provider.h
@@ -13,7 +13,7 @@
#include "base/callback_forward.h"
#include "content/common/content_export.h"
#include "content/public/browser/stored_payment_app.h"
-#include "third_party/blink/public/platform/modules/payments/payment_app.mojom.h"
+#include "third_party/blink/public/mojom/payments/payment_app.mojom.h"
class SkBitmap;
diff --git a/chromium/content/public/browser/permission_controller_delegate.h b/chromium/content/public/browser/permission_controller_delegate.h
index 2a81ed3d815..98eb65187d3 100644
--- a/chromium/content/public/browser/permission_controller_delegate.h
+++ b/chromium/content/public/browser/permission_controller_delegate.h
@@ -77,13 +77,13 @@ class CONTENT_EXPORT PermissionControllerDelegate {
const GURL& embedding_origin) = 0;
// Runs the given |callback| whenever the |permission| associated with the
- // pair { requesting_origin, embedding_origin } changes.
- // Returns the subscription_id to be used to unsubscribe. Can be
- // kNoPendingOperation if the subscribe was not successful.
+ // given RenderFrameHost changes. A nullptr should be passed if the request
+ // is from a worker. Returns the subscription_id to be used to unsubscribe.
+ // Can be kNoPendingOperation if the subscribe was not successful.
virtual int SubscribePermissionStatusChange(
- PermissionType permission,
+ content::PermissionType permission,
+ content::RenderFrameHost* render_frame_host,
const GURL& requesting_origin,
- const GURL& embedding_origin,
const base::Callback<void(blink::mojom::PermissionStatus)>& callback) = 0;
// Unregisters from permission status change notifications.
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 6df6f227d86..32d5232f7c5 100644
--- a/chromium/content/public/browser/picture_in_picture_window_controller.h
+++ b/chromium/content/public/browser/picture_in_picture_window_controller.h
@@ -6,8 +6,13 @@
#define CONTENT_PUBLIC_BROWSER_PICTURE_IN_PICTURE_WINDOW_CONTROLLER_H_
#include <string>
+#include <vector>
#include "content/common/content_export.h"
+namespace blink {
+struct PictureInPictureControlInfo;
+} // namespace blink
+
namespace gfx {
class Size;
} // namespace gfx
@@ -40,13 +45,15 @@ 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) = 0;
+ virtual void Close(bool should_pause_video, bool should_reset_pip_player) = 0;
// Called by the window implementation to notify the controller that the
// window was requested to be closed and destroyed by the system.
virtual void OnWindowDestroyed() = 0;
virtual void ClickCustomControl(const std::string& control_id) = 0;
+ virtual void SetPictureInPictureCustomControls(
+ const std::vector<blink::PictureInPictureControlInfo>&) = 0;
virtual void EmbedSurface(const viz::SurfaceId& surface_id,
const gfx::Size& natural_size) = 0;
virtual OverlayWindow* GetWindowForTesting() = 0;
diff --git a/chromium/content/public/browser/platform_notification_context.h b/chromium/content/public/browser/platform_notification_context.h
index 973fbeafe24..c90129d57c2 100644
--- a/chromium/content/public/browser/platform_notification_context.h
+++ b/chromium/content/public/browser/platform_notification_context.h
@@ -78,6 +78,7 @@ class PlatformNotificationContext
// for |database_data| will be generated, and thus must be empty.
virtual void WriteNotificationData(
int64_t persistent_notification_id,
+ int64_t service_worker_registration_id,
const GURL& origin,
const NotificationDatabaseData& database_data,
const WriteResultCallback& callback) = 0;
diff --git a/chromium/content/public/browser/platform_notification_service.h b/chromium/content/public/browser/platform_notification_service.h
index 228fc30240c..0e9ce438308 100644
--- a/chromium/content/public/browser/platform_notification_service.h
+++ b/chromium/content/public/browser/platform_notification_service.h
@@ -14,6 +14,7 @@
#include "base/callback_forward.h"
#include "content/common/content_export.h"
+#include "content/public/browser/notification_database_data.h"
#include "third_party/blink/public/platform/modules/permissions/permission_status.mojom.h"
class GURL;
@@ -75,6 +76,11 @@ class CONTENT_EXPORT PlatformNotificationService {
// increments the value, as it is called once per notification write.
virtual int64_t ReadNextPersistentNotificationId(
BrowserContext* browser_context) = 0;
+
+ // Records a given notification to UKM.
+ virtual void RecordNotificationUkmEvent(
+ BrowserContext* browser_context,
+ const NotificationDatabaseData& data) = 0;
};
} // namespace content
diff --git a/chromium/content/public/browser/plugin_service.h b/chromium/content/public/browser/plugin_service.h
index 27021d64244..aed3085c779 100644
--- a/chromium/content/public/browser/plugin_service.h
+++ b/chromium/content/public/browser/plugin_service.h
@@ -99,7 +99,7 @@ class CONTENT_EXPORT PluginService {
// Returns information about a pepper plugin if it exists, otherwise nullptr.
// The caller does not own the pointer, and it's not guaranteed to live past
// the call stack.
- virtual PepperPluginInfo* GetRegisteredPpapiPluginInfo(
+ virtual const PepperPluginInfo* GetRegisteredPpapiPluginInfo(
const base::FilePath& plugin_path) = 0;
virtual void SetFilter(PluginServiceFilter* filter) = 0;
diff --git a/chromium/content/public/browser/presentation_request.cc b/chromium/content/public/browser/presentation_request.cc
index d3a1dccdc56..b8df3bc21c7 100644
--- a/chromium/content/public/browser/presentation_request.cc
+++ b/chromium/content/public/browser/presentation_request.cc
@@ -7,7 +7,7 @@
namespace content {
PresentationRequest::PresentationRequest(
- const std::pair<int, int>& render_frame_host_id,
+ const GlobalFrameRoutingId& render_frame_host_id,
const std::vector<GURL>& presentation_urls,
const url::Origin& frame_origin)
: render_frame_host_id(render_frame_host_id),
diff --git a/chromium/content/public/browser/presentation_request.h b/chromium/content/public/browser/presentation_request.h
index e2a1a5b1b92..224095a441a 100644
--- a/chromium/content/public/browser/presentation_request.h
+++ b/chromium/content/public/browser/presentation_request.h
@@ -9,6 +9,7 @@
#include <vector>
#include "content/common/content_export.h"
+#include "content/public/browser/global_routing_id.h"
#include "url/gurl.h"
#include "url/origin.h"
@@ -19,7 +20,7 @@ namespace content {
// frame.
struct CONTENT_EXPORT PresentationRequest {
public:
- PresentationRequest(const std::pair<int, int>& render_frame_host_id,
+ PresentationRequest(const GlobalFrameRoutingId& render_frame_host_id,
const std::vector<GURL>& presentation_urls,
const url::Origin& frame_origin);
~PresentationRequest();
@@ -28,7 +29,7 @@ struct CONTENT_EXPORT PresentationRequest {
PresentationRequest& operator=(const PresentationRequest& other);
// ID of RenderFrameHost that initiated the request.
- std::pair<int, int> render_frame_host_id;
+ GlobalFrameRoutingId render_frame_host_id;
// URLs of presentation.
std::vector<GURL> presentation_urls;
diff --git a/chromium/content/public/browser/presentation_screen_availability_listener.h b/chromium/content/public/browser/presentation_screen_availability_listener.h
index 46e2c86ebaf..09ab4736184 100644
--- a/chromium/content/public/browser/presentation_screen_availability_listener.h
+++ b/chromium/content/public/browser/presentation_screen_availability_listener.h
@@ -8,7 +8,7 @@
#include <string>
#include "content/common/content_export.h"
-#include "third_party/blink/public/platform/modules/presentation/presentation.mojom.h"
+#include "third_party/blink/public/mojom/presentation/presentation.mojom.h"
#include "url/gurl.h"
namespace content {
diff --git a/chromium/content/public/browser/presentation_service_delegate.h b/chromium/content/public/browser/presentation_service_delegate.h
index 03202644b97..c16214654e6 100644
--- a/chromium/content/public/browser/presentation_service_delegate.h
+++ b/chromium/content/public/browser/presentation_service_delegate.h
@@ -12,9 +12,8 @@
#include "base/callback.h"
#include "content/common/content_export.h"
-#include "content/public/common/presentation_connection_message.h"
-#include "media/base/media_controller.h"
-#include "third_party/blink/public/platform/modules/presentation/presentation.mojom.h"
+#include "media/base/flinging_controller.h"
+#include "third_party/blink/public/mojom/presentation/presentation.mojom.h"
namespace content {
@@ -22,11 +21,11 @@ struct PresentationRequest;
class PresentationScreenAvailabilityListener;
using PresentationConnectionCallback =
- base::OnceCallback<void(const blink::mojom::PresentationInfo&)>;
+ base::OnceCallback<void(blink::mojom::PresentationConnectionResultPtr)>;
using PresentationConnectionErrorCallback =
base::OnceCallback<void(const blink::mojom::PresentationError&)>;
-using DefaultPresentationConnectionCallback =
- base::RepeatingCallback<void(const blink::mojom::PresentationInfo&)>;
+using DefaultPresentationConnectionCallback = base::RepeatingCallback<void(
+ blink::mojom::PresentationConnectionResultPtr)>;
struct PresentationConnectionStateChangeInfo {
explicit PresentationConnectionStateChangeInfo(
@@ -170,11 +169,11 @@ class CONTENT_EXPORT ControllerPresentationServiceDelegate
int render_frame_id,
const std::string& presentation_id) = 0;
- // Gets a MediaController for a given presentation ID.
+ // Gets a FlingingController for a given presentation ID.
// |render_process_id|, |render_frame_id|: ID of originating frame.
// |presentation_id|: The ID of the presentation for which we want a
// Controller.
- virtual std::unique_ptr<media::MediaController> GetMediaController(
+ virtual std::unique_ptr<media::FlingingController> GetFlingingController(
int render_process_id,
int render_frame_id,
const std::string& presentation_id) = 0;
@@ -190,20 +189,6 @@ class CONTENT_EXPORT ControllerPresentationServiceDelegate
int render_frame_id,
const blink::mojom::PresentationInfo& connection,
const PresentationConnectionStateChangedCallback& state_changed_cb) = 0;
-
- // Connect |controller_connection| owned by the controlling frame to the
- // local presentation represented by |presentation_info|.
- // |render_process_id|, |render_frame_id|: ID of originating frame.
- // |controller_connection|: Pointer to controller's presentation connection,
- // ownership passed from controlling frame to the local presentation.
- // |receiver_connection_request|: Mojo InterfaceRequest to be bind to receiver
- // page's presentation connection.
- virtual void ConnectToPresentation(
- int render_process_id,
- int render_frame_id,
- const blink::mojom::PresentationInfo& presentation_info,
- PresentationConnectionPtr controller_connection_ptr,
- PresentationConnectionRequest receiver_connection_request) = 0;
};
// An interface implemented by embedders to handle
diff --git a/chromium/content/public/browser/render_frame_host.h b/chromium/content/public/browser/render_frame_host.h
index 5a8553521db..eaee051bc83 100644
--- a/chromium/content/public/browser/render_frame_host.h
+++ b/chromium/content/public/browser/render_frame_host.h
@@ -316,7 +316,9 @@ class CONTENT_EXPORT RenderFrameHost : public IPC::Listener,
const blink::WebMediaPlayerAction& action) = 0;
// Creates a Network Service-backed factory from appropriate |NetworkContext|.
- virtual void CreateNetworkServiceDefaultFactory(
+ // If this returns true, any redirect safety checks should be bypassed in
+ // downstream loaders.
+ virtual bool CreateNetworkServiceDefaultFactory(
network::mojom::URLLoaderFactoryRequest default_factory_request) = 0;
private:
diff --git a/chromium/content/public/browser/render_process_host.h b/chromium/content/public/browser/render_process_host.h
index 19d9c106e87..ef2a04280e1 100644
--- a/chromium/content/public/browser/render_process_host.h
+++ b/chromium/content/public/browser/render_process_host.h
@@ -76,6 +76,7 @@ class CONTENT_EXPORT RenderProcessHost : public IPC::Sender,
struct Priority {
bool is_hidden;
unsigned int frame_depth;
+ bool intersects_viewport;
#if defined(OS_ANDROID)
ChildProcessImportance importance;
#endif
@@ -149,6 +150,9 @@ class CONTENT_EXPORT RenderProcessHost : public IPC::Sender,
// Get computed frame depth from PriorityClients.
virtual unsigned int GetFrameDepth() const = 0;
+ // Get computed viewport intersection state from PriorityClients.
+ virtual bool GetIntersectsViewport() const = 0;
+
virtual RendererAudioOutputStreamFactoryContext*
GetRendererAudioOutputStreamFactoryContext() = 0;
@@ -453,6 +457,16 @@ class CONTENT_EXPORT RenderProcessHost : public IPC::Sender,
// be posted back on the UI thread).
void PostTaskWhenProcessIsReady(base::OnceClosure task);
+ // Controls whether the destructor of RenderProcessHost*Impl* will end up
+ // cleaning the memory used by the exception added via
+ // RenderProcessHostImpl::AddCorbExceptionForPlugin.
+ //
+ // TODO(lukasza): https://crbug.com/652474: This method shouldn't be part of
+ // the //content public API, because it shouldn't be called by anyone other
+ // than RenderProcessHostImpl (from underneath
+ // RenderProcessHostImpl::AddCorbExceptionForPlugin).
+ virtual void CleanupCorbExceptionForPluginUponDestruction() = 0;
+
// Static management functions -----------------------------------------------
// Possibly start an unbound, spare RenderProcessHost. A subsequent creation
diff --git a/chromium/content/public/browser/render_process_host_observer.h b/chromium/content/public/browser/render_process_host_observer.h
index fca52416394..60e3668f4ed 100644
--- a/chromium/content/public/browser/render_process_host_observer.h
+++ b/chromium/content/public/browser/render_process_host_observer.h
@@ -23,10 +23,6 @@ class CONTENT_EXPORT RenderProcessHostObserver {
// RenderProcessHost.
virtual void RenderProcessReady(RenderProcessHost* host) {}
- // This method is invoked when the process when the process could shut down
- // but may or may not be allowed.
- virtual void RenderProcessShutdownRequested(RenderProcessHost* host) {}
-
// This method is invoked when the process of the observed RenderProcessHost
// exits (either normally or with a crash). To determine if the process closed
// normally or crashed, examine the |status| parameter.
diff --git a/chromium/content/public/browser/render_widget_host.h b/chromium/content/public/browser/render_widget_host.h
index 29e577f2c4c..514b39fd65c 100644
--- a/chromium/content/public/browser/render_widget_host.h
+++ b/chromium/content/public/browser/render_widget_host.h
@@ -201,8 +201,6 @@ class CONTENT_EXPORT RenderWidgetHost : public IPC::Sender {
// Returns true if the renderer is considered unresponsive.
virtual bool IsCurrentlyUnresponsive() const = 0;
- virtual void SetIgnoreInputEvents(bool ignore_input_events) = 0;
-
// Called to propagate updated visual properties to the renderer. Returns
// whether the renderer has been informed of updated properties.
virtual bool SynchronizeVisualProperties() = 0;
diff --git a/chromium/content/public/browser/render_widget_host_view.h b/chromium/content/public/browser/render_widget_host_view.h
index c4b21150bbc..c662115a717 100644
--- a/chromium/content/public/browser/render_widget_host_view.h
+++ b/chromium/content/public/browser/render_widget_host_view.h
@@ -141,12 +141,16 @@ class CONTENT_EXPORT RenderWidgetHostView {
// Returns the currently selected text.
virtual base::string16 GetSelectedText() = 0;
- // Returns the currently selected text with the text before and after it.
+ // Returns part of the text on the page which includes the selected text plus
+ // possibly several characters before and after it.
virtual base::string16 GetSurroundingText() = 0;
// Returns the range of the selection in the page.
virtual gfx::Range GetSelectedRange() = 0;
+ // The offset of the surrounding text relative to the start of the total text.
+ virtual size_t GetOffsetForSurroundingText() = 0;
+
// This only returns non-null on platforms that implement touch
// selection editing (TSE), currently Aura and (soon) Android.
// TODO(wjmaclean): update this comment when OOPIF TSE is implemented on
diff --git a/chromium/content/public/browser/resource_request_info.h b/chromium/content/public/browser/resource_request_info.h
index c0e13fb0c39..607b807f4bc 100644
--- a/chromium/content/public/browser/resource_request_info.h
+++ b/chromium/content/public/browser/resource_request_info.h
@@ -173,6 +173,9 @@ class ResourceRequestInfo {
// Returns the current state of Previews.
virtual PreviewsState GetPreviewsState() const = 0;
+ // Sets the PreviewsState to |previews_state|.
+ virtual void SetPreviewsState(PreviewsState previews_state) = 0;
+
// PlzNavigate
// Only used for navigations. Returns opaque data set by the embedder on the
// UI thread at the beginning of navigation.
diff --git a/chromium/content/public/browser/service_worker_context.h b/chromium/content/public/browser/service_worker_context.h
index a8c957a414e..f1974cd4c74 100644
--- a/chromium/content/public/browser/service_worker_context.h
+++ b/chromium/content/public/browser/service_worker_context.h
@@ -39,7 +39,7 @@ enum class StartServiceWorkerForNavigationHintResult {
// Something failed.
FAILED = 5,
// Add new result to record here.
- NUM_TYPES
+ kMaxValue = FAILED,
};
// Represents the per-StoragePartition service worker data.
@@ -63,21 +63,20 @@ class ServiceWorkerContext {
using StartServiceWorkerForNavigationHintCallback = base::OnceCallback<void(
StartServiceWorkerForNavigationHintResult result)>;
- using StartWorkerCallback =
- base::OnceCallback<void(int process_id, int thread_id)>;
-
- // Registers the header name which should not be passed to the ServiceWorker.
- // Must be called from the IO thread.
- CONTENT_EXPORT static void AddExcludedHeadersForFetchEvent(
- const std::set<std::string>& header_names);
-
- // Returns true if the header name should not be passed to the ServiceWorker.
- // Must be called from the IO thread.
- static bool IsExcludedHeaderNameForFetchEvent(const std::string& header_name);
+ using StartWorkerCallback = base::OnceCallback<
+ void(int64_t version_id, int process_id, int thread_id)>;
// Returns true if |url| is within the service worker |scope|.
CONTENT_EXPORT static bool ScopeMatches(const GURL& scope, const GURL& url);
+ // Runs a |task| on task |runner| making sure that
+ // |service_worker_context| is alive while the task is being run.
+ CONTENT_EXPORT static void RunTask(
+ scoped_refptr<base::SequencedTaskRunner> runner,
+ const base::Location& from_here,
+ ServiceWorkerContext* service_worker_context,
+ base::OnceClosure task);
+
// Observer methods are always dispatched on the UI thread.
virtual void AddObserver(ServiceWorkerContextObserver* observer) = 0;
virtual void RemoveObserver(ServiceWorkerContextObserver* observer) = 0;
@@ -166,13 +165,28 @@ class ServiceWorkerContext {
// Starts the active worker of the registration whose scope is |pattern|. If
// there is no active worker, starts the installing worker.
- // |info_callback| is passed the worker's render process id and thread id.
+ // |info_callback| is passed information about the started worker.
//
// Must be called on IO thread.
virtual void StartWorkerForPattern(const GURL& pattern,
StartWorkerCallback info_callback,
base::OnceClosure failure_callback) = 0;
+ // Deprecated: DO NOT USE
+ // This is a temporary addition only to be used for the Android Messages
+ // integration with ChromeOS (http://crbug.com/823256). The removal is
+ // tracked at http://crbug.com/869714. Please ask Service Worker OWNERS
+ // (content/browser/service_worker/OWNERS) if you have questions.
+ //
+ // This method MUST be called on the IO thread. It starts the active worker
+ // of the registration whose scope is |pattern|, sets its timeout to 999 days,
+ // and passes in the given |message|. The |result_callback| will be executed
+ // upon success or failure and pass back the boolean result.
+ virtual void StartServiceWorkerAndDispatchLongRunningMessage(
+ const GURL& pattern,
+ blink::TransferableMessage message,
+ ResultCallback result_callback) = 0;
+
// Starts the service worker for |document_url|. Called when a navigation to
// that URL is predicted to occur soon. Must be called from the UI thread. The
// |callback| will always be called on the UI thread.
diff --git a/chromium/content/public/browser/service_worker_context_observer.h b/chromium/content/public/browser/service_worker_context_observer.h
index 1f1b3b8315a..c8e4c8df633 100644
--- a/chromium/content/public/browser/service_worker_context_observer.h
+++ b/chromium/content/public/browser/service_worker_context_observer.h
@@ -11,12 +11,24 @@ namespace content {
class ServiceWorkerContextObserver {
public:
- // Called when a service worker has been registered with scope |pattern|.
+ // Called when a service worker has been registered with scope |scope|.
//
// This is called when the ServiceWorkerContainer.register() promise is
// resolved, which happens before the service worker registration is persisted
// to disk.
- virtual void OnRegistrationCompleted(const GURL& pattern) {}
+ virtual void OnRegistrationCompleted(const GURL& scope) {}
+
+ // Called when the service worker with id |version_id| changes status to
+ // activated.
+ virtual void OnVersionActivated(int64_t version_id, const GURL& scope) {}
+
+ // Called when the service worker with id |version_id| changes status to
+ // redundant.
+ virtual void OnVersionRedundant(int64_t version_id, const GURL& scope) {}
+
+ // Called when there are no more controllees for the service worker with id
+ // |version_id|.
+ virtual void OnNoControllees(int64_t version_id, const GURL& scope) {}
protected:
virtual ~ServiceWorkerContextObserver() {}
diff --git a/chromium/content/public/browser/site_instance.h b/chromium/content/public/browser/site_instance.h
index a0739838640..1bb348216fe 100644
--- a/chromium/content/public/browser/site_instance.h
+++ b/chromium/content/public/browser/site_instance.h
@@ -170,7 +170,9 @@ class CONTENT_EXPORT SiteInstance : public base::RefCounted<SiteInstance> {
const GURL& dest_url);
// 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.
+ // registered domain. Returns an empty GURL if the URL has no host. Prior to
+ // determining the site, |url| is resolved to an effective URL via
+ // ContentBrowserClient::GetEffectiveURL().
static GURL GetSiteForURL(BrowserContext* context, const GURL& url);
protected:
diff --git a/chromium/content/public/browser/site_isolation_policy.cc b/chromium/content/public/browser/site_isolation_policy.cc
index a3df9c3912a..721cc826414 100644
--- a/chromium/content/public/browser/site_isolation_policy.cc
+++ b/chromium/content/public/browser/site_isolation_policy.cc
@@ -94,7 +94,7 @@ void SiteIsolationPolicy::PopulateURLLoaderFactoryParamsPtrForCORB(
const char* initiator_scheme_exception =
GetContentClient()
->browser()
- ->GetInitatorSchemeBypassingDocumentBlocking();
+ ->GetInitiatorSchemeBypassingDocumentBlocking();
if (initiator_scheme_exception)
params->corb_excluded_initiator_scheme = initiator_scheme_exception;
}
diff --git a/chromium/content/public/browser/speech_recognition_session_config.h b/chromium/content/public/browser/speech_recognition_session_config.h
index b42c1cfae8c..2aeff3942ef 100644
--- a/chromium/content/public/browser/speech_recognition_session_config.h
+++ b/chromium/content/public/browser/speech_recognition_session_config.h
@@ -14,7 +14,6 @@
#include "content/common/content_export.h"
#include "content/public/browser/speech_recognition_session_context.h"
#include "content/public/browser/speech_recognition_session_preamble.h"
-#include "net/url_request/url_request_context_getter.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "third_party/blink/public/mojom/speech/speech_recognition_grammar.mojom.h"
#include "url/origin.h"
@@ -30,6 +29,9 @@ struct CONTENT_EXPORT SpeechRecognitionSessionConfig {
~SpeechRecognitionSessionConfig();
std::string language;
+ // Accept language header. If |language| is empty, used to get a language
+ // instead.
+ std::string accept_language;
std::vector<blink::mojom::SpeechRecognitionGrammar> grammars;
url::Origin origin;
bool filter_profanities;
@@ -41,9 +43,6 @@ struct CONTENT_EXPORT SpeechRecognitionSessionConfig {
scoped_refptr<SpeechRecognitionSessionPreamble> preamble;
SpeechRecognitionSessionContext initial_context;
scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory;
- // TODO(mmenke): Remove this dependency.
- scoped_refptr<net::URLRequestContextGetter>
- deprecated_url_request_context_getter;
base::WeakPtr<SpeechRecognitionEventListener> event_listener;
};
diff --git a/chromium/content/public/browser/storage_partition.h b/chromium/content/public/browser/storage_partition.h
index fe4b7cc8d99..f55e28d79cd 100644
--- a/chromium/content/public/browser/storage_partition.h
+++ b/chromium/content/public/browser/storage_partition.h
@@ -54,6 +54,7 @@ class BrowserContext;
class CacheStorageContext;
class DOMStorageContext;
class IndexedDBContext;
+class GeneratedCodeCacheContext;
class PlatformNotificationContext;
class ServiceWorkerContext;
class SharedWorkerService;
@@ -106,6 +107,7 @@ class CONTENT_EXPORT StoragePartition {
virtual ServiceWorkerContext* GetServiceWorkerContext() = 0;
virtual SharedWorkerService* GetSharedWorkerService() = 0;
virtual CacheStorageContext* GetCacheStorageContext() = 0;
+ virtual GeneratedCodeCacheContext* GetGeneratedCodeCacheContext() = 0;
#if !defined(OS_ANDROID)
virtual HostZoomMap* GetHostZoomMap() = 0;
virtual HostZoomLevelContext* GetHostZoomLevelContext() = 0;
@@ -214,6 +216,9 @@ class CONTENT_EXPORT StoragePartition {
// unwritten data has been written out to the filesystem.
virtual void Flush() = 0;
+ // Resets all URLLoaderFactories bound to this partition's network context.
+ virtual void ResetURLLoaderFactories() = 0;
+
// Clear the bluetooth allowed devices map. For test use only.
virtual void ClearBluetoothAllowedDevicesMapForTesting() = 0;
@@ -224,10 +229,6 @@ class CONTENT_EXPORT StoragePartition {
// Wait until all deletions tasks are finished. For test use only.
virtual void WaitForDeletionTasksForTesting() = 0;
- // Used in tests to force the cached SharedURLLoaderFactory to be dropped, as
- // a way to work-around https://crbug.com/857577.
- virtual void ResetURLLoaderFactoryForBrowserProcessForTesting() {}
-
protected:
virtual ~StoragePartition() {}
};
diff --git a/chromium/content/public/browser/tracing_delegate.h b/chromium/content/public/browser/tracing_delegate.h
index 08f6c5b419b..82af20064e3 100644
--- a/chromium/content/public/browser/tracing_delegate.h
+++ b/chromium/content/public/browser/tracing_delegate.h
@@ -15,8 +15,8 @@ namespace base {
class DictionaryValue;
}
-namespace net {
-class URLRequestContextGetter;
+namespace network {
+class SharedURLLoaderFactory;
}
namespace content {
@@ -34,7 +34,7 @@ class CONTENT_EXPORT TracingDelegate {
// Provide trace uploading functionality; see trace_uploader.h.
virtual std::unique_ptr<TraceUploader> GetTraceUploader(
- net::URLRequestContextGetter* request_context) = 0;
+ scoped_refptr<network::SharedURLLoaderFactory>) = 0;
// This can be used to veto a particular background tracing scenario.
virtual bool IsAllowedToBeginBackgroundScenario(
diff --git a/chromium/content/public/browser/url_data_source.cc b/chromium/content/public/browser/url_data_source.cc
index 8161895bd95..2f5c450c634 100644
--- a/chromium/content/public/browser/url_data_source.cc
+++ b/chromium/content/public/browser/url_data_source.cc
@@ -4,6 +4,9 @@
#include "content/public/browser/url_data_source.h"
+#include <utility>
+
+#include "base/memory/ptr_util.h"
#include "content/browser/webui/url_data_manager.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/url_constants.h"
@@ -11,9 +14,16 @@
namespace content {
+// static
void URLDataSource::Add(BrowserContext* browser_context,
URLDataSource* source) {
- URLDataManager::AddDataSource(browser_context, source);
+ Add(browser_context, base::WrapUnique(source));
+}
+
+// static
+void URLDataSource::Add(BrowserContext* browser_context,
+ std::unique_ptr<URLDataSource> source) {
+ URLDataManager::AddDataSource(browser_context, std::move(source));
}
scoped_refptr<base::SingleThreadTaskRunner>
diff --git a/chromium/content/public/browser/url_data_source.h b/chromium/content/public/browser/url_data_source.h
index d6eab3dae07..a636ba6b689 100644
--- a/chromium/content/public/browser/url_data_source.h
+++ b/chromium/content/public/browser/url_data_source.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_PUBLIC_BROWSER_URL_DATA_SOURCE_H_
#define CONTENT_PUBLIC_BROWSER_URL_DATA_SOURCE_H_
+#include <memory>
#include <string>
#include "base/callback.h"
@@ -14,6 +15,7 @@
#include "content/public/browser/resource_request_info.h"
class GURL;
+
namespace base {
class RefCountedMemory;
}
@@ -29,9 +31,13 @@ class ResourceContext;
// notify.
class CONTENT_EXPORT URLDataSource {
public:
- // Adds a URL data source to |browser_context|.
+ // Adds a URL data source to |browser_context|. Deprecated.
static void Add(BrowserContext* browser_context, URLDataSource* source);
+ // Adds a URL data source to |browser_context|.
+ static void Add(BrowserContext* browser_context,
+ std::unique_ptr<URLDataSource> source);
+
virtual ~URLDataSource() {}
// The name of this source.
diff --git a/chromium/content/public/browser/url_loader_request_interceptor.h b/chromium/content/public/browser/url_loader_request_interceptor.h
index 473902d6f07..bcc5278656b 100644
--- a/chromium/content/public/browser/url_loader_request_interceptor.h
+++ b/chromium/content/public/browser/url_loader_request_interceptor.h
@@ -29,7 +29,8 @@ class URLLoaderRequestInterceptor {
virtual ~URLLoaderRequestInterceptor() = default;
using RequestHandler =
- base::OnceCallback<void(network::mojom::URLLoaderRequest,
+ base::OnceCallback<void(const network::ResourceRequest& resource_request,
+ network::mojom::URLLoaderRequest,
network::mojom::URLLoaderClientPtr)>;
using LoaderCallback = base::OnceCallback<void(RequestHandler)>;
@@ -37,8 +38,13 @@ class URLLoaderRequestInterceptor {
// The handler must invoke |callback| eventually with either a non-null
// RequestHandler indicating its willingness to handle the request, or a null
// RequestHandler to indicate that someone else should handle the request.
+ //
+ // The |tentative_resource_request| passed to this function and the resource
+ // request later passed to the RequestHandler given to |callback| may not be
+ // exactly the same. See documentation for
+ // NavigationLoaderInterceptor::MaybeCreateLoader.
virtual void MaybeCreateLoader(
- const network::ResourceRequest& resource_request,
+ const network::ResourceRequest& tentative_resource_request,
ResourceContext* resource_context,
LoaderCallback callback) = 0;
};
diff --git a/chromium/content/public/browser/video_capture_device_launcher.h b/chromium/content/public/browser/video_capture_device_launcher.h
index d2a3f83e9ab..033c1c13eaf 100644
--- a/chromium/content/public/browser/video_capture_device_launcher.h
+++ b/chromium/content/public/browser/video_capture_device_launcher.h
@@ -29,7 +29,7 @@ class CONTENT_EXPORT VideoCaptureDeviceLauncher {
virtual ~Callbacks() {}
virtual void OnDeviceLaunched(
std::unique_ptr<LaunchedVideoCaptureDevice> device) = 0;
- virtual void OnDeviceLaunchFailed() = 0;
+ virtual void OnDeviceLaunchFailed(media::VideoCaptureError error) = 0;
virtual void OnDeviceLaunchAborted() = 0;
};
diff --git a/chromium/content/public/browser/web_contents.h b/chromium/content/public/browser/web_contents.h
index 0f82f91e437..786eecfcb70 100644
--- a/chromium/content/public/browser/web_contents.h
+++ b/chromium/content/public/browser/web_contents.h
@@ -72,6 +72,7 @@ class InterfaceProvider;
namespace content {
class BrowserContext;
+class BrowserPluginGuest;
class BrowserPluginGuestDelegate;
class InterstitialPage;
class RenderFrameHost;
@@ -390,6 +391,12 @@ class WebContents : public PageNavigator,
// both renderer accessibility, and a native browser accessibility tree.
virtual bool IsFullAccessibilityModeForTesting() const = 0;
+ virtual ui::AXMode GetAccessibilityMode() const = 0;
+
+ virtual void SetAccessibilityMode(ui::AXMode mode) = 0;
+
+ virtual base::string16 DumpAccessibilityTree(bool internal) = 0;
+
virtual const PageImportanceSignals& GetPageImportanceSignals() const = 0;
// Tab navigation state ------------------------------------------------------
@@ -527,6 +534,10 @@ class WebContents : public PageNavigator,
// Otherwise, return nullptr.
virtual WebContents* GetOuterWebContents() = 0;
+ // Returns the root WebContents of the WebContents tree. Always returns
+ // non-null value.
+ virtual WebContents* GetOutermostWebContents() = 0;
+
// Invoked when visible security state changes.
virtual void DidChangeVisibleSecurityState() = 0;
@@ -905,10 +916,11 @@ class WebContents : public PageNavigator,
// Returns true if other views are allowed, false otherwise.
virtual bool GetAllowOtherViews() = 0;
+#endif // OS_ANDROID
- // Returns true if the WebContents has completed its first meaningful paint.
+ // Returns true if the WebContents has completed its first meaningful paint
+ // since the last navigation.
virtual bool CompletedFirstVisuallyNonEmptyPaint() const = 0;
-#endif // OS_ANDROID
// TODO(https://crbug.com/826293): This is a simple mitigation to validate
// that an action that requires a user gesture actually has one in the
@@ -917,6 +929,13 @@ class WebContents : public PageNavigator,
// user activation work.
virtual bool HasRecentInteractiveInputEvent() const = 0;
+ // Sets a flag that causes the WebContents to ignore input events.
+ virtual void SetIgnoreInputEvents(bool ignore_input_events) = 0;
+
+ // Returns guest browser plugin object, or NULL if this WebContents is not a
+ // guest.
+ virtual BrowserPluginGuest* GetBrowserPluginGuest() const = 0;
+
private:
// This interface should only be implemented inside content.
friend class WebContentsImpl;
diff --git a/chromium/content/public/browser/web_contents_observer.h b/chromium/content/public/browser/web_contents_observer.h
index 35dab314009..458b71354dd 100644
--- a/chromium/content/public/browser/web_contents_observer.h
+++ b/chromium/content/public/browser/web_contents_observer.h
@@ -264,9 +264,11 @@ class CONTENT_EXPORT WebContentsObserver : public IPC::Listener {
ResourceType resource_type) {}
// This method is invoked when a resource associate with the frame
- // |render_frame_host| has been loaded, successfully or not.
+ // |render_frame_host| has been loaded, successfully or not. |request_id| will
+ // only be populated for main frame resources.
virtual void ResourceLoadComplete(
RenderFrameHost* render_frame_host,
+ const GlobalRequestID& request_id,
const mojom::ResourceLoadInfo& resource_load_info) {}
// This method is invoked when a new non-pending navigation entry is created.
@@ -447,7 +449,8 @@ class CONTENT_EXPORT WebContentsObserver : public IPC::Listener {
// Invoked when text selection is changed.
virtual void DidChangeTextSelection(const base::string16& text,
- const gfx::Range& range) {}
+ const gfx::Range& range,
+ size_t offset) {}
// Invoked when media is playing or paused. |id| is unique per player and per
// RenderFrameHost. There may be multiple players within a RenderFrameHost
@@ -500,6 +503,7 @@ class CONTENT_EXPORT WebContentsObserver : public IPC::Listener {
// There is a slight delay between media entering or exiting fullscreen
// and it being detected.
virtual void MediaEffectivelyFullscreenChanged(bool is_fullscreen) {}
+ virtual void MediaPictureInPictureChanged(bool is_picture_in_picture) {}
virtual void MediaMutedStatusChanged(const MediaPlayerId& id, bool muted) {}
// Invoked when the renderer process changes the page scale factor.
@@ -517,9 +521,6 @@ class CONTENT_EXPORT WebContentsObserver : public IPC::Listener {
// focus.
virtual void OnWebContentsLostFocus(RenderWidgetHost* render_widget_host) {}
- // Notifes that a CompositorFrame was received from the renderer.
- virtual void DidReceiveCompositorFrame() {}
-
// Notifies that the manifest URL for the main frame changed to
// |manifest_url|. This will be invoked when a document with a manifest loads
// or when the manifest URL changes (possibly to nothing). It is not invoked
@@ -536,6 +537,18 @@ class CONTENT_EXPORT WebContentsObserver : public IPC::Listener {
const std::string& interface_name,
mojo::ScopedMessagePipeHandle* interface_pipe) {}
+ // Notifies that the RenderWidgetCompositor has issued a draw command. An
+ // observer can use this method to detect when Chrome visually updated a
+ // tab.
+ virtual void DidCommitAndDrawCompositorFrame() {}
+
+ // Called when "audible" playback starts or stops on a WebAudio AudioContext.
+ using AudioContextId = std::pair<RenderFrameHost*, int>;
+ virtual void AudioContextPlaybackStarted(
+ const AudioContextId& audio_context_id) {}
+ virtual void AudioContextPlaybackStopped(
+ const AudioContextId& audio_context_id) {}
+
// IPC::Listener implementation.
// DEPRECATED: Use (i.e. override) the other overload instead:
// virtual bool OnMessageReceived(const IPC::Message& message,
diff --git a/chromium/content/public/browser/web_contents_user_data.h b/chromium/content/public/browser/web_contents_user_data.h
index d9a776f53b3..8523f47a268 100644
--- a/chromium/content/public/browser/web_contents_user_data.h
+++ b/chromium/content/public/browser/web_contents_user_data.h
@@ -25,9 +25,6 @@ namespace content {
// friend class content::WebContentsUserData<FooTabHelper>;
// // ... more private stuff here ...
// }
-// --- in foo_tab_helper.cc ---
-// DEFINE_WEB_CONTENTS_USER_DATA_KEY(FooTabHelper);
-//
template <typename T>
class WebContentsUserData : public base::SupportsUserData::Data {
public:
@@ -58,10 +55,6 @@ class WebContentsUserData : public base::SupportsUserData::Data {
}
};
-// Macro previously used to define the UserDataKey().
-// TODO(fdoray): Remove this. https://crbug.com/589840
-#define DEFINE_WEB_CONTENTS_USER_DATA_KEY(TYPE)
-
} // namespace content
#endif // CONTENT_PUBLIC_BROWSER_WEB_CONTENTS_USER_DATA_H_
diff --git a/chromium/content/public/browser/webrtc_event_logger.cc b/chromium/content/public/browser/webrtc_event_logger.cc
index e61c7b20c4e..b4de604d672 100644
--- a/chromium/content/public/browser/webrtc_event_logger.cc
+++ b/chromium/content/public/browser/webrtc_event_logger.cc
@@ -5,6 +5,7 @@
#include "content/public/browser/webrtc_event_logger.h"
#include "base/logging.h"
+#include "content/public/browser/browser_thread.h"
namespace content {
@@ -15,6 +16,7 @@ WebRtcEventLogger* WebRtcEventLogger::Get() {
}
WebRtcEventLogger::WebRtcEventLogger() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(!g_webrtc_event_logger);
g_webrtc_event_logger = this;
// Checking that g_webrtc_event_logger was never set before, in a way that
@@ -22,6 +24,7 @@ WebRtcEventLogger::WebRtcEventLogger() {
}
WebRtcEventLogger::~WebRtcEventLogger() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK_EQ(g_webrtc_event_logger, this);
g_webrtc_event_logger = nullptr;
}
diff --git a/chromium/content/public/browser/webrtc_event_logger.h b/chromium/content/public/browser/webrtc_event_logger.h
index e7f29eae618..664e6598d1e 100644
--- a/chromium/content/public/browser/webrtc_event_logger.h
+++ b/chromium/content/public/browser/webrtc_event_logger.h
@@ -11,12 +11,8 @@
#include "base/files/file_path.h"
#include "content/common/content_export.h"
-class WebRTCInternalsIntegrationBrowserTest;
-
namespace content {
-class BrowserContext;
-
// Interface for a logger of WebRTC events, which the embedding application may
// subclass and instantiate. Only one instance may ever be created, and it must
// live until the embedding application terminates.
@@ -33,30 +29,6 @@ class CONTENT_EXPORT WebRtcEventLogger {
// not execute.
virtual ~WebRtcEventLogger();
- // TODO(eladalon): Change from using BrowserContext to using Profile.
- // https://crbug.com/775415
-
- // Enables WebRTC event logging for a given BrowserContext:
- // * Pending logs from previous sessions become eligible to be uploaded.
- // * New logs for active peer connections *may* be recorded. (This does *not*
- // start logging; it just makes it possible.)
- // This function would typically be called during a BrowserContext's
- // initialization.
- // This function must not be called for an off-the-records BrowserContext.
- // Local-logging is not associated with BrowserContexts, and is allowed even
- // if EnableForBrowserContext is not called. That is, even for incognito mode.
- virtual void EnableForBrowserContext(const BrowserContext* browser_context,
- base::OnceClosure reply) = 0;
-
- // Disables WebRTC event logging for a given BrowserContext. New remote-bound
- // WebRTC event logs will no longer be created for this BrowserContext.
- // This would typically be called when a BrowserContext is destroyed. One must
- // therefore be careful note to call any of BrowserContext's virtual methods.
- // TODO(eladalon): After changing to a Profile-centered interface, change this
- // to not even receive a pointer. https://crbug.com/775415
- virtual void DisableForBrowserContext(const BrowserContext* browser_context,
- base::OnceClosure reply) = 0;
-
// Call this to let the logger know when a PeerConnection was created.
// |peer_connection_id| should be a non-empty, relatively short (i.e.
// inexpensive to store) identifier, by which the peer connection may later
@@ -127,15 +99,7 @@ class CONTENT_EXPORT WebRtcEventLogger {
base::OnceCallback<void(std::pair<bool, bool>)> reply) = 0;
protected:
- friend WebRTCInternalsIntegrationBrowserTest; // (PostNullTaskForTesting)
-
WebRtcEventLogger();
-
- // Allows tests to synchronize with internal task queues (if such exist in
- // the subclass). This allows tests to only examine products (such as log
- // files) at a time when, if the program is behaving as expected, they would
- // be guaranteed to be ready.
- virtual void PostNullTaskForTesting(base::OnceClosure reply) = 0;
};
} // namespace content
diff --git a/chromium/content/public/common/BUILD.gn b/chromium/content/public/common/BUILD.gn
index f0cad2ddd4c..c94dc1a1fc8 100644
--- a/chromium/content/public/common/BUILD.gn
+++ b/chromium/content/public/common/BUILD.gn
@@ -171,6 +171,8 @@ jumbo_source_set("common_sources") {
"menu_item.h",
"mhtml_generation_params.cc",
"mhtml_generation_params.h",
+ "mime_handler_view_mode.cc",
+ "mime_handler_view_mode.h",
"notification_resources.cc",
"notification_resources.h",
"origin_util.h",
@@ -184,11 +186,8 @@ jumbo_source_set("common_sources") {
"persistent_notification_status.h",
"platform_notification_data.cc",
"platform_notification_data.h",
- "presentation_connection_message.cc",
- "presentation_connection_message.h",
"previews_state.h",
"process_type.h",
- "push_event_payload.h",
"push_subscription_options.h",
"referrer.cc",
"referrer.h",
@@ -334,6 +333,9 @@ source_set("feature_h264_with_openh264_ffmpeg") {
}
mojom("interfaces") {
+ # We don't want Blink variants of these bindings to be generated.
+ disable_variants = true
+
# Must depend on //content/public/common/ instead, for component build.
visibility = [
":common_sources",
@@ -354,6 +356,8 @@ mojom("interfaces") {
"fullscreen_video_element.mojom",
"load_timing_info.mojom",
"push_messaging_status.mojom",
+ "renderer_preference_watcher.mojom",
+ "renderer_preferences.mojom",
"resource_load_info.mojom",
"resource_usage_reporter.mojom",
"transferrable_url_loader.mojom",
@@ -368,6 +372,7 @@ mojom("interfaces") {
public_deps = [
":resource_type_bindings",
"//services/network/public/mojom",
+ "//third_party/blink/public:mojo_bindings",
"//url/mojom:url_mojom_gurl",
"//url/mojom:url_mojom_origin",
]
diff --git a/chromium/content/public/common/DEPS b/chromium/content/public/common/DEPS
index 817d7a21698..b84338ed9c3 100644
--- a/chromium/content/public/common/DEPS
+++ b/chromium/content/public/common/DEPS
@@ -19,7 +19,4 @@ specific_include_rules = {
"simple_url_loader_unittest\.cc": [
"+content/public/network",
],
- "network_connection_tracker_unittest\.cc": [
- "+content/public/network",
- ],
}
diff --git a/chromium/content/public/common/common_param_traits.cc b/chromium/content/public/common/common_param_traits.cc
index d4862b7cdda..539c53ed326 100644
--- a/chromium/content/public/common/common_param_traits.cc
+++ b/chromium/content/public/common/common_param_traits.cc
@@ -10,60 +10,10 @@
#include "content/public/common/content_constants.h"
#include "content/public/common/page_state.h"
#include "content/public/common/referrer.h"
-#include "net/base/ip_address.h"
-#include "net/base/ip_endpoint.h"
#include "net/http/http_util.h"
namespace IPC {
-void ParamTraits<net::IPEndPoint>::Write(base::Pickle* m, const param_type& p) {
- WriteParam(m, p.address());
- WriteParam(m, p.port());
-}
-
-bool ParamTraits<net::IPEndPoint>::Read(const base::Pickle* m,
- base::PickleIterator* iter,
- param_type* p) {
- net::IPAddress address;
- uint16_t port;
- if (!ReadParam(m, iter, &address) || !ReadParam(m, iter, &port))
- return false;
- if (!address.empty() && !address.IsValid())
- return false;
-
- *p = net::IPEndPoint(address, port);
- return true;
-}
-
-void ParamTraits<net::IPEndPoint>::Log(const param_type& p, std::string* l) {
- LogParam("IPEndPoint:" + p.ToString(), l);
-}
-
-void ParamTraits<net::IPAddress>::Write(base::Pickle* m, const param_type& p) {
- base::StackVector<uint8_t, 16> bytes;
- for (uint8_t byte : p.bytes())
- bytes->push_back(byte);
- WriteParam(m, bytes);
-}
-
-bool ParamTraits<net::IPAddress>::Read(const base::Pickle* m,
- base::PickleIterator* iter,
- param_type* p) {
- base::StackVector<uint8_t, 16> bytes;
- if (!ReadParam(m, iter, &bytes))
- return false;
- if (bytes->size() && bytes->size() != net::IPAddress::kIPv4AddressSize &&
- bytes->size() != net::IPAddress::kIPv6AddressSize) {
- return false;
- }
- *p = net::IPAddress(bytes->data(), bytes->size());
- return true;
-}
-
-void ParamTraits<net::IPAddress>::Log(const param_type& p, std::string* l) {
- LogParam("IPAddress:" + (p.empty() ? "(empty)" : p.ToString()), l);
-}
-
void ParamTraits<content::PageState>::Write(base::Pickle* m,
const param_type& p) {
WriteParam(m, p.ToEncodedData());
diff --git a/chromium/content/public/common/common_param_traits.h b/chromium/content/public/common/common_param_traits.h
index 89e503702dc..366da86000b 100644
--- a/chromium/content/public/common/common_param_traits.h
+++ b/chromium/content/public/common/common_param_traits.h
@@ -35,34 +35,9 @@ namespace content {
class PageState;
}
-namespace net {
-class IPAddress;
-class IPEndPoint;
-}
-
namespace IPC {
template <>
-struct CONTENT_EXPORT ParamTraits<net::IPEndPoint> {
- typedef net::IPEndPoint param_type;
- static void Write(base::Pickle* m, const param_type& p);
- static bool Read(const base::Pickle* m,
- base::PickleIterator* iter,
- param_type* p);
- static void Log(const param_type& p, std::string* l);
-};
-
-template <>
-struct CONTENT_EXPORT ParamTraits<net::IPAddress> {
- typedef net::IPAddress param_type;
- static void Write(base::Pickle* m, const param_type& p);
- static bool Read(const base::Pickle* m,
- base::PickleIterator* iter,
- param_type* p);
- static void Log(const param_type& p, std::string* l);
-};
-
-template <>
struct CONTENT_EXPORT ParamTraits<content::PageState> {
typedef content::PageState param_type;
static void Write(base::Pickle* m, const param_type& p);
diff --git a/chromium/content/public/common/common_param_traits_macros.h b/chromium/content/public/common/common_param_traits_macros.h
index 57f03dc1ed3..64de36aa745 100644
--- a/chromium/content/public/common/common_param_traits_macros.h
+++ b/chromium/content/public/common/common_param_traits_macros.h
@@ -12,10 +12,10 @@
#include "cc/input/touch_action.h"
#include "content/public/common/console_message_level.h"
#include "content/public/common/referrer.h"
+#include "content/public/common/renderer_preferences.h"
#include "content/public/common/web_preferences.h"
#include "content/public/common/webplugininfo_param_traits.h"
#include "ipc/ipc_message_macros.h"
-#include "net/base/network_change_notifier.h"
#include "services/network/public/cpp/network_ipc_param_traits.h"
#include "third_party/blink/public/platform/modules/permissions/permission_status.mojom.h"
#include "third_party/blink/public/platform/web_history_scroll_restoration_type.h"
@@ -44,8 +44,6 @@ IPC_ENUM_TRAITS_VALIDATE(ui::PageTransition,
((value &
ui::PageTransition::PAGE_TRANSITION_CORE_MASK) <=
ui::PageTransition::PAGE_TRANSITION_LAST_CORE))
-IPC_ENUM_TRAITS_MAX_VALUE(net::NetworkChangeNotifier::ConnectionType,
- net::NetworkChangeNotifier::CONNECTION_LAST)
IPC_ENUM_TRAITS_MAX_VALUE(content::ConsoleMessageLevel,
content::CONSOLE_MESSAGE_LEVEL_LAST)
IPC_ENUM_TRAITS_MAX_VALUE(blink::WebFrameSerializerCacheControlPolicy,
@@ -241,6 +239,7 @@ IPC_STRUCT_TRAITS_BEGIN(content::WebPreferences)
IPC_STRUCT_TRAITS_MEMBER(autoplay_policy)
IPC_STRUCT_TRAITS_MEMBER(low_priority_iframes_threshold)
IPC_STRUCT_TRAITS_MEMBER(picture_in_picture_enabled)
+ IPC_STRUCT_TRAITS_MEMBER(translate_service_available)
IPC_STRUCT_TRAITS_MEMBER(lazy_frame_loading_distance_thresholds_px)
IPC_STRUCT_TRAITS_END()
@@ -290,4 +289,60 @@ IPC_STRUCT_TRAITS_BEGIN(ui::AXEvent)
IPC_STRUCT_TRAITS_MEMBER(action_request_id)
IPC_STRUCT_TRAITS_END()
+IPC_ENUM_TRAITS_MAX_VALUE(gfx::FontRenderParams::Hinting,
+ gfx::FontRenderParams::HINTING_MAX)
+IPC_ENUM_TRAITS_MAX_VALUE(gfx::FontRenderParams::SubpixelRendering,
+ gfx::FontRenderParams::SUBPIXEL_RENDERING_MAX)
+
+IPC_STRUCT_TRAITS_BEGIN(content::RendererPreferences)
+ IPC_STRUCT_TRAITS_MEMBER(can_accept_load_drops)
+ IPC_STRUCT_TRAITS_MEMBER(should_antialias_text)
+ IPC_STRUCT_TRAITS_MEMBER(hinting)
+ IPC_STRUCT_TRAITS_MEMBER(use_autohinter)
+ IPC_STRUCT_TRAITS_MEMBER(use_bitmaps)
+ IPC_STRUCT_TRAITS_MEMBER(subpixel_rendering)
+ IPC_STRUCT_TRAITS_MEMBER(use_subpixel_positioning)
+ IPC_STRUCT_TRAITS_MEMBER(focus_ring_color)
+ IPC_STRUCT_TRAITS_MEMBER(thumb_active_color)
+ IPC_STRUCT_TRAITS_MEMBER(thumb_inactive_color)
+ IPC_STRUCT_TRAITS_MEMBER(track_color)
+ IPC_STRUCT_TRAITS_MEMBER(active_selection_bg_color)
+ IPC_STRUCT_TRAITS_MEMBER(active_selection_fg_color)
+ IPC_STRUCT_TRAITS_MEMBER(inactive_selection_bg_color)
+ IPC_STRUCT_TRAITS_MEMBER(inactive_selection_fg_color)
+ IPC_STRUCT_TRAITS_MEMBER(browser_handles_all_top_level_requests)
+ IPC_STRUCT_TRAITS_MEMBER(caret_blink_interval)
+ IPC_STRUCT_TRAITS_MEMBER(use_custom_colors)
+ IPC_STRUCT_TRAITS_MEMBER(enable_referrers)
+ IPC_STRUCT_TRAITS_MEMBER(enable_do_not_track)
+ IPC_STRUCT_TRAITS_MEMBER(enable_encrypted_media)
+ IPC_STRUCT_TRAITS_MEMBER(webrtc_ip_handling_policy)
+ IPC_STRUCT_TRAITS_MEMBER(webrtc_udp_min_port)
+ IPC_STRUCT_TRAITS_MEMBER(webrtc_udp_max_port)
+ IPC_STRUCT_TRAITS_MEMBER(user_agent_override)
+ IPC_STRUCT_TRAITS_MEMBER(accept_languages)
+ IPC_STRUCT_TRAITS_MEMBER(disable_client_blocked_error_page)
+ IPC_STRUCT_TRAITS_MEMBER(plugin_fullscreen_allowed)
+ IPC_STRUCT_TRAITS_MEMBER(network_contry_iso)
+#if defined(OS_LINUX)
+ IPC_STRUCT_TRAITS_MEMBER(system_font_family_name)
+#endif
+#if defined(OS_WIN)
+ IPC_STRUCT_TRAITS_MEMBER(caption_font_family_name)
+ IPC_STRUCT_TRAITS_MEMBER(caption_font_height)
+ IPC_STRUCT_TRAITS_MEMBER(small_caption_font_family_name)
+ IPC_STRUCT_TRAITS_MEMBER(small_caption_font_height)
+ IPC_STRUCT_TRAITS_MEMBER(menu_font_family_name)
+ IPC_STRUCT_TRAITS_MEMBER(menu_font_height)
+ IPC_STRUCT_TRAITS_MEMBER(status_font_family_name)
+ IPC_STRUCT_TRAITS_MEMBER(status_font_height)
+ IPC_STRUCT_TRAITS_MEMBER(message_font_family_name)
+ IPC_STRUCT_TRAITS_MEMBER(message_font_height)
+ IPC_STRUCT_TRAITS_MEMBER(vertical_scroll_bar_width_in_dips)
+ IPC_STRUCT_TRAITS_MEMBER(horizontal_scroll_bar_height_in_dips)
+ IPC_STRUCT_TRAITS_MEMBER(arrow_bitmap_height_vertical_scroll_bar_in_dips)
+ IPC_STRUCT_TRAITS_MEMBER(arrow_bitmap_width_horizontal_scroll_bar_in_dips)
+#endif
+IPC_STRUCT_TRAITS_END()
+
#endif // CONTENT_PUBLIC_COMMON_COMMON_PARAM_TRAITS_MACROS_H_
diff --git a/chromium/content/public/common/content_client.cc b/chromium/content/public/common/content_client.cc
index 24932438c9f..998defab191 100644
--- a/chromium/content/public/common/content_client.cc
+++ b/chromium/content/public/common/content_client.cc
@@ -6,6 +6,7 @@
#include "base/logging.h"
#include "base/strings/string_piece.h"
+#include "base/values.h"
#include "build/build_config.h"
#include "content/public/common/origin_util.h"
#include "content/public/common/user_agent.h"
@@ -102,6 +103,10 @@ std::string ContentClient::GetProcessTypeNameInEnglish(int type) {
return std::string();
}
+base::DictionaryValue ContentClient::GetNetLogConstants() const {
+ return base::DictionaryValue();
+}
+
blink::OriginTrialPolicy* ContentClient::GetOriginTrialPolicy() {
return nullptr;
}
diff --git a/chromium/content/public/common/content_client.h b/chromium/content/public/common/content_client.h
index 528fd6abf6a..b939bc2a9ed 100644
--- a/chromium/content/public/common/content_client.h
+++ b/chromium/content/public/common/content_client.h
@@ -20,6 +20,7 @@
namespace base {
class RefCountedMemory;
+class DictionaryValue;
}
namespace blink {
@@ -173,6 +174,14 @@ class CONTENT_EXPORT ContentClient {
// doesn't know about because they're from the embedder.
virtual std::string GetProcessTypeNameInEnglish(int type);
+ // Called once during initialization of NetworkService to provide constants
+ // to NetLog. (Though it may be called multiples times if NetworkService
+ // crashes and needs to be reinitialized). The return value is merged with
+ // |GetNetConstants()| and passed to FileNetLogObserver - see documentation
+ // of |FileNetLogObserver::CreateBounded()| for more information. The
+ // convention is to put new constants under a subdict at the key "clientInfo".
+ virtual base::DictionaryValue GetNetLogConstants() const;
+
// Returns whether or not V8 script extensions should be allowed for a
// service worker.
virtual bool AllowScriptExtensionForServiceWorker(const GURL& script_url);
diff --git a/chromium/content/public/common/content_features.cc b/chromium/content/public/common/content_features.cc
index 9ac4e9d631b..eaa31fc6cdb 100644
--- a/chromium/content/public/common/content_features.cc
+++ b/chromium/content/public/common/content_features.cc
@@ -144,6 +144,12 @@ const base::Feature kExtendedMouseButtons{"ExtendedMouseButtons",
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 a security restriction on iframes navigating their top frame.
// When enabled, the navigation will only be permitted if the iframe is
// same-origin to the top frame, or if a user gesture is being processed.
@@ -178,6 +184,11 @@ const base::Feature kHeapCompaction{"HeapCompaction",
const base::Feature kImageCaptureAPI{"ImageCaptureAPI",
base::FEATURE_ENABLED_BY_DEFAULT};
+// Use the requester origin as a second key to enfore site isolation policy for
+// code caches.
+const base::Feature kIsolatedCodeCache{"IsolatedCodeCache",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
// Alternative to switches::kIsolateOrigins, for turning on origin isolation.
// List of origins to isolate has to be specified via
// kIsolateOriginsFieldTrialParamName.
@@ -197,6 +208,10 @@ const base::Feature kLazyFrameLoading{"LazyFrameLoading",
base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kLazyFrameVisibleLoadTimeMetrics{
"LazyFrameVisibleLoadTimeMetrics", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kLazyImageLoading{"LazyImageLoading",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kLazyImageVisibleLoadTimeMetrics{
+ "LazyImageVisibleLoadTimeMetrics", base::FEATURE_DISABLED_BY_DEFAULT};
// Enable lazy initialization of the media controls.
const base::Feature kLazyInitializeMediaControls{
@@ -229,6 +244,11 @@ const base::Feature kMediaDevicesSystemMonitorCache {
const base::Feature kMemoryCoordinator{"MemoryCoordinator",
base::FEATURE_DISABLED_BY_DEFAULT};
+// Instead of BrowserPlugin or GuestViews, MimeHandlerView will use a cross
+// process frame to render its handler.
+const base::Feature kMimeHandlerViewInCrossProcessFrame{
+ "MimeHandlerViewInCrossProcessFrame", base::FEATURE_DISABLED_BY_DEFAULT};
+
// ES6 Modules dynamic imports.
const base::Feature kModuleScriptsDynamicImport{
"ModuleScriptsDynamicImport", base::FEATURE_ENABLED_BY_DEFAULT};
@@ -266,10 +286,6 @@ const base::Feature kNetworkServiceInProcess{"NetworkServiceInProcess",
const base::Feature kNotificationContentImage{"NotificationContentImage",
base::FEATURE_ENABLED_BY_DEFAULT};
-// Off-main-thread WebSocket. See https://crbug.com/825740
-const base::Feature kOffMainThreadWebSocket{"OffMainThreadWebSocket",
- base::FEATURE_ENABLED_BY_DEFAULT};
-
// Origin Policy. See https://crbug.com/751996
const base::Feature kOriginPolicy{"OriginPolicy",
base::FEATURE_DISABLED_BY_DEFAULT};
@@ -286,6 +302,11 @@ const base::Feature kPageLifecycle{"PageLifecycle",
const base::Feature kPassiveDocumentEventListeners{
"PassiveDocumentEventListeners", base::FEATURE_ENABLED_BY_DEFAULT};
+// Whether document level wheel and mousewheel event listeners should default
+// 'passive' to true.
+const base::Feature kPassiveDocumentWheelEventListeners{
+ "PassiveDocumentWheelEventListeners", base::FEATURE_DISABLED_BY_DEFAULT};
+
// Whether we should force a touchstart and first touchmove per scroll event
// listeners to be non-blocking during fling.
const base::Feature kPassiveEventListenersDueToFling{
@@ -366,18 +387,30 @@ const base::Feature kSendBeaconThrowForBlobWithNonSimpleType{
const base::Feature kSecMetadata{"SecMetadata",
base::FEATURE_DISABLED_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).
+const base::Feature kServiceWorkerLongRunningMessage{
+ "ServiceWorkerLongRunningMessage", base::FEATURE_ENABLED_BY_DEFAULT};
+
// Service worker based payment apps as defined by w3c here:
// https://w3c.github.io/webpayments-payment-apps-api/
-const base::Feature kServiceWorkerPaymentApps{
- "ServiceWorkerPaymentApps", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kServiceWorkerPaymentApps{"ServiceWorkerPaymentApps",
+ base::FEATURE_ENABLED_BY_DEFAULT};
// Generate V8 full code cache of service worker scripts.
const base::Feature kServiceWorkerScriptFullCodeCache{
"ServiceWorkerScriptFullCodeCache", base::FEATURE_ENABLED_BY_DEFAULT};
// http://tc39.github.io/ecmascript_sharedmem/shmem.html
-const base::Feature kSharedArrayBuffer{"SharedArrayBuffer",
- base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kSharedArrayBuffer {
+ "SharedArrayBuffer",
+#if defined(OS_ANDROID)
+ base::FEATURE_DISABLED_BY_DEFAULT
+#else
+ base::FEATURE_ENABLED_BY_DEFAULT
+#endif
+};
// Origin-Signed HTTP Exchanges (for WebPackage Loading)
// https://www.chromestatus.com/features/5745285984681984
@@ -394,21 +427,6 @@ const base::Feature kSignedHTTPExchangeOriginTrial{
const base::Feature kSpareRendererForSitePerProcess{
"SpareRendererForSitePerProcess", base::FEATURE_ENABLED_BY_DEFAULT};
-// Stop scheduler task queues in background after allowed grace time.
-const base::Feature kStopInBackground {
- "stop-in-background",
-#if defined(OS_ANDROID)
- base::FEATURE_ENABLED_BY_DEFAULT
-#else
- base::FEATURE_DISABLED_BY_DEFAULT
-#endif
-};
-
-// Stop non-timer task queues in background, on Android,
-// after allowed grace time. Launch bug: https://crbug.com/822954.
-const base::Feature kStopNonTimersInBackground{
- "stop-non-timers-in-background", base::FEATURE_DISABLED_BY_DEFAULT};
-
// Throttle Blink timers in out-of-view cross origin frames.
const base::Feature kTimerThrottlingForHiddenFrames{
"TimerThrottlingForHiddenFrames", base::FEATURE_ENABLED_BY_DEFAULT};
@@ -419,10 +437,12 @@ const base::Feature kTimerThrottlingForHiddenFrames{
const base::Feature kTopDocumentIsolation{"top-document-isolation",
base::FEATURE_DISABLED_BY_DEFAULT};
-// Use Feature Policy to gate the use of permission features like midi,
-// geolocation, camera, microphone, etc.
-const base::Feature kUseFeaturePolicyForPermissions{
- "UseFeaturePolicyForPermissions", base::FEATURE_ENABLED_BY_DEFAULT};
+// Enables async touchpad pinch zoom events. We check the ACK of the first
+// synthetic wheel event in a pinch sequence, then send the rest of the
+// synthetic wheel events of the pinch sequence as non-blocking if the first
+// event’s ACK is not canceled.
+const base::Feature kTouchpadAsyncPinchEvents{
+ "TouchpadAsyncPinchEvents", base::FEATURE_DISABLED_BY_DEFAULT};
// An experimental simple user-activation model where the user gesture state is
// tracked through a frame-based state instead of the gesture tokens we use
@@ -430,13 +450,6 @@ const base::Feature kUseFeaturePolicyForPermissions{
const base::Feature kUserActivationV2{"UserActivationV2",
base::FEATURE_DISABLED_BY_DEFAULT};
-// Use RenderWidgetHostView::CreateVideoCapturer instead of
-// RenderWidgetHostView::CopyFromSurface to obtain a stream of snapshots
-// captured from the renderer for DevTools performance timeline and eyedropper
-// tool.
-const base::Feature kUseVideoCaptureApiForDevToolsSnapshots{
- "UseVideoCaptureApiForDevToolsSnapshots", base::FEATURE_ENABLED_BY_DEFAULT};
-
// Enables to use a snapshot file in creating V8 contexts.
const base::Feature kV8ContextSnapshot{"V8ContextSnapshot",
base::FEATURE_ENABLED_BY_DEFAULT};
@@ -453,6 +466,13 @@ const base::Feature kV8Orinoco{"V8Orinoco", base::FEATURE_ENABLED_BY_DEFAULT};
const base::Feature kV8VmFuture{"V8VmFuture",
base::FEATURE_DISABLED_BY_DEFAULT};
+// Controls the decode acceleration of JPEG images (as opposed to camera
+// captures) in Chrome OS using the VA-API.
+// TODO(andrescj): remove or enable by default in Chrome OS once
+// https://crbug.com/868400 is resolved.
+const base::Feature kVaapiJpegImageDecodeAcceleration{
+ "VaapiJpegImageDecodeAcceleration", base::FEATURE_DISABLED_BY_DEFAULT};
+
// Enable WebAssembly structured cloning.
// http://webassembly.org/
const base::Feature kWebAssembly{"WebAssembly",
@@ -464,7 +484,7 @@ const base::Feature kWebAssemblyStreaming{"WebAssemblyStreaming",
// Enable WebAssembly baseline compilation and tier up.
const base::Feature kWebAssemblyBaseline{"WebAssemblyBaseline",
- base::FEATURE_DISABLED_BY_DEFAULT};
+ base::FEATURE_ENABLED_BY_DEFAULT};
// Enable WebAssembly threads.
// https://github.com/WebAssembly/threads
@@ -490,11 +510,7 @@ const base::Feature kWebContentsOcclusion {
// https://w3c.github.io/webauthn
const base::Feature kWebAuth {
"WebAuthentication",
-#if defined(OS_ANDROID)
- base::FEATURE_DISABLED_BY_DEFAULT
-#else
base::FEATURE_ENABLED_BY_DEFAULT
-#endif
};
// Controls whether BLE authenticators can be used via the WebAuthentication
@@ -506,7 +522,13 @@ const base::Feature kWebAuthBle{"WebAuthenticationBle",
// using pairingless BLE protocol.
// https://w3c.github.io/webauthn
const base::Feature kWebAuthCable{"WebAuthenticationCable",
- base::FEATURE_DISABLED_BY_DEFAULT};
+ base::FEATURE_ENABLED_BY_DEFAULT};
+
+// Controls whether CTAP2 devices can communicate via the WebAuthentication API
+// using pairingless BLE protocol on Windows.
+// https://w3c.github.io/webauthn
+const base::Feature kWebAuthCableWin{"WebAuthenticationCableWin",
+ base::FEATURE_DISABLED_BY_DEFAULT};
// If WebGL Image Chromium is allowed, this feature controls whether it is
// enabled.
@@ -521,21 +543,6 @@ const base::Feature kExperimentalProductivityFeatures{
const base::Feature kWebPayments{"WebPayments",
base::FEATURE_ENABLED_BY_DEFAULT};
-// Informs the WebRTC Acoustic Echo Canceler (AEC) that echo path loss is
-// bounded.
-const base::Feature kWebRtcAecBoundedErlSetup{
- "WebRtcAecBoundedErlSetup", base::FEATURE_DISABLED_BY_DEFAULT};
-
-// Informs the WebRTC Acoustic Echo Canceler (AEC) that the playout and
-// capture is done using different clocks.
-const base::Feature kWebRtcAecClockDriftSetup{
- "WebRtcAecClockDriftSetup", base::FEATURE_DISABLED_BY_DEFAULT};
-
-// Informs the WebRTC Acoustic Echo Canceler (AEC) that the feature providing
-// echo canceller transparency to render noise should be used.
-const base::Feature kWebRtcAecNoiseTransparency{
- "WebRtcAecNoiseTransparency", base::FEATURE_DISABLED_BY_DEFAULT};
-
// Makes WebRTC use ECDSA certs by default (i.e., when no cert type was
// specified in JS).
const base::Feature kWebRtcEcdsaDefault{"WebRTC-EnableWebRtcEcdsa",
@@ -570,6 +577,11 @@ const base::Feature kWebRtcScreenshareSwEncoding{
const base::Feature kWebRtcUseEchoCanceller3{"WebRtcUseEchoCanceller3",
base::FEATURE_DISABLED_BY_DEFAULT};
+// Enables the WebRTC Agc2 digital adaptation with WebRTC Agc1 analog
+// adaptation. Feature for http://crbug.com/873650. Is sent to WebRTC.
+const base::Feature kWebRtcHybridAgc{"WebRtcHybridAgc",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
// Use GpuMemoryBuffer backed VideoFrames in media streams.
const base::Feature kWebRtcUseGpuMemoryBufferVideoFrames{
"WebRTC-UseGpuMemoryBufferVideoFrames", base::FEATURE_ENABLED_BY_DEFAULT};
@@ -601,6 +613,10 @@ const base::Feature kWipeCorruptV2IDBDatabases{
const base::Feature kWorkStealingInScriptRunner{
"WorkStealingInScriptRunner", base::FEATURE_DISABLED_BY_DEFAULT};
+// Enabled scheduler use for script streaming.
+const base::Feature kScheduledScriptStreaming{
+ "ScheduledScriptStreaming", base::FEATURE_DISABLED_BY_DEFAULT};
+
#if defined(OS_ANDROID)
// Autofill Accessibility in Android.
// crbug.com/627860
@@ -653,7 +669,7 @@ const base::Feature kDeviceMonitorMac{"DeviceMonitorMac",
// Enable IOSurface based screen capturer.
const base::Feature kIOSurfaceCapturer{"IOSurfaceCapturer",
- base::FEATURE_DISABLED_BY_DEFAULT};
+ base::FEATURE_ENABLED_BY_DEFAULT};
// The V2 sandbox on MacOS removes the unsandboed warmup phase and sandboxes the
// entire life of the process.
@@ -661,12 +677,6 @@ const base::Feature kMacV2Sandbox{"MacV2Sandbox",
base::FEATURE_ENABLED_BY_DEFAULT};
#endif // defined(OS_MACOSX)
-#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
-// Always set the UI thread's priority to DISPLAY.
-const base::Feature kOverrideUIThreadPriority{
- "OverrideUIThreadPriority", base::FEATURE_DISABLED_BY_DEFAULT};
-#endif // defined(OS_ANDROID) || defined(OS_CHROMEOS)
-
enum class VideoCaptureServiceConfiguration {
kEnabledForOutOfProcess,
kEnabledForBrowserProcess,
diff --git a/chromium/content/public/common/content_features.h b/chromium/content/public/common/content_features.h
index 33ff8d509de..764b0685ab7 100644
--- a/chromium/content/public/common/content_features.h
+++ b/chromium/content/public/common/content_features.h
@@ -30,6 +30,7 @@ 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 kCacheInlineScriptCode;
+CONTENT_EXPORT extern const base::Feature kIsolatedCodeCache;
CONTENT_EXPORT extern const base::Feature kCanvas2DImageChromium;
CONTENT_EXPORT extern const base::Feature kCompositeOpaqueFixedPosition;
CONTENT_EXPORT extern const base::Feature kCompositeOpaqueScrollers;
@@ -42,6 +43,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 kFontCacheScaling;
+CONTENT_EXPORT extern const base::Feature kFontSrcLocalMatching;
CONTENT_EXPORT extern const base::Feature
kFramebustingNeedsSameOriginOrUserGesture;
CONTENT_EXPORT extern const base::Feature kGamepadExtensions;
@@ -55,11 +57,14 @@ CONTENT_EXPORT extern const base::Feature kKeyboardLockAPI;
CONTENT_EXPORT extern const base::Feature kLayeredAPI;
CONTENT_EXPORT extern const base::Feature kLazyFrameLoading;
CONTENT_EXPORT extern const base::Feature kLazyFrameVisibleLoadTimeMetrics;
+CONTENT_EXPORT extern const base::Feature kLazyImageLoading;
+CONTENT_EXPORT extern const base::Feature kLazyImageVisibleLoadTimeMetrics;
CONTENT_EXPORT extern const base::Feature kLazyInitializeMediaControls;
CONTENT_EXPORT extern const base::Feature kLazyParseCSS;
CONTENT_EXPORT extern const base::Feature kLowPriorityIframes;
CONTENT_EXPORT extern const base::Feature kMediaDevicesSystemMonitorCache;
CONTENT_EXPORT extern const base::Feature kMemoryCoordinator;
+CONTENT_EXPORT extern const base::Feature kMimeHandlerViewInCrossProcessFrame;
CONTENT_EXPORT extern const base::Feature kModuleScriptsDynamicImport;
CONTENT_EXPORT extern const base::Feature kModuleScriptsImportMetaUrl;
CONTENT_EXPORT extern const base::Feature kMojoSessionStorage;
@@ -67,11 +72,11 @@ CONTENT_EXPORT extern const base::Feature kMojoVideoCapture;
CONTENT_EXPORT extern const base::Feature kMojoVideoCaptureSecondary;
CONTENT_EXPORT extern const base::Feature kNetworkServiceInProcess;
CONTENT_EXPORT extern const base::Feature kNotificationContentImage;
-CONTENT_EXPORT extern const base::Feature kOffMainThreadWebSocket;
CONTENT_EXPORT extern const base::Feature kOriginPolicy;
CONTENT_EXPORT extern const base::Feature kOriginTrials;
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 kPdfIsolation;
CONTENT_EXPORT extern const base::Feature kPerNavigationMojoInterface;
@@ -89,25 +94,23 @@ CONTENT_EXPORT extern const base::Feature kScrollAnchorSerialization;
CONTENT_EXPORT extern const base::Feature
kSendBeaconThrowForBlobWithNonSimpleType;
CONTENT_EXPORT extern const base::Feature kSecMetadata;
+CONTENT_EXPORT extern const base::Feature kServiceWorkerLongRunningMessage;
CONTENT_EXPORT extern const base::Feature kServiceWorkerPaymentApps;
CONTENT_EXPORT extern const base::Feature kServiceWorkerScriptFullCodeCache;
CONTENT_EXPORT extern const base::Feature kSharedArrayBuffer;
CONTENT_EXPORT extern const base::Feature kSignedHTTPExchange;
CONTENT_EXPORT extern const base::Feature kSignedHTTPExchangeOriginTrial;
CONTENT_EXPORT extern const base::Feature kSpareRendererForSitePerProcess;
-CONTENT_EXPORT extern const base::Feature kStopInBackground;
-CONTENT_EXPORT extern const base::Feature kStopNonTimersInBackground;
CONTENT_EXPORT extern const base::Feature kTimerThrottlingForHiddenFrames;
CONTENT_EXPORT extern const base::Feature kTopDocumentIsolation;
+CONTENT_EXPORT extern const base::Feature kTouchpadAsyncPinchEvents;
CONTENT_EXPORT extern const base::Feature kTouchpadOverscrollHistoryNavigation;
-CONTENT_EXPORT extern const base::Feature kUseFeaturePolicyForPermissions;
CONTENT_EXPORT extern const base::Feature kUserActivationV2;
-CONTENT_EXPORT extern const base::Feature
- kUseVideoCaptureApiForDevToolsSnapshots;
CONTENT_EXPORT extern const base::Feature kV8ContextSnapshot;
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 kVaapiJpegImageDecodeAcceleration;
CONTENT_EXPORT extern const base::Feature kWebAssembly;
CONTENT_EXPORT extern const base::Feature kWebAssemblyStreaming;
CONTENT_EXPORT extern const base::Feature kWebAssemblyBaseline;
@@ -116,18 +119,17 @@ CONTENT_EXPORT extern const base::Feature kWebAssemblyTrapHandler;
CONTENT_EXPORT extern const base::Feature kWebAuth;
CONTENT_EXPORT extern const base::Feature kWebAuthBle;
CONTENT_EXPORT extern const base::Feature kWebAuthCable;
+CONTENT_EXPORT extern const base::Feature kWebAuthCableWin;
CONTENT_EXPORT extern const base::Feature kWebContentsOcclusion;
CONTENT_EXPORT extern const base::Feature kWebGLImageChromium;
CONTENT_EXPORT extern const base::Feature kWebPayments;
-CONTENT_EXPORT extern const base::Feature kWebRtcAecBoundedErlSetup;
-CONTENT_EXPORT extern const base::Feature kWebRtcAecClockDriftSetup;
-CONTENT_EXPORT extern const base::Feature kWebRtcAecNoiseTransparency;
CONTENT_EXPORT extern const base::Feature kWebRtcEcdsaDefault;
CONTENT_EXPORT extern const base::Feature kWebRtcHWH264Encoding;
CONTENT_EXPORT extern const base::Feature kWebRtcHWVP8Encoding;
CONTENT_EXPORT extern const base::Feature kWebRtcMultiplexCodec;
CONTENT_EXPORT extern const base::Feature kWebRtcScreenshareSwEncoding;
CONTENT_EXPORT extern const base::Feature kWebRtcUseEchoCanceller3;
+CONTENT_EXPORT extern const base::Feature kWebRtcHybridAgc;
CONTENT_EXPORT extern const base::Feature kWebRtcUseGpuMemoryBufferVideoFrames;
CONTENT_EXPORT extern const base::Feature kWebUsb;
CONTENT_EXPORT extern const base::Feature kWebVrVsyncAlign;
@@ -137,6 +139,7 @@ CONTENT_EXPORT extern const base::Feature kWebXrHitTest;
CONTENT_EXPORT extern const base::Feature kWebXrOrientationSensorDevice;
CONTENT_EXPORT extern const base::Feature kWipeCorruptV2IDBDatabases;
CONTENT_EXPORT extern const base::Feature kWorkStealingInScriptRunner;
+CONTENT_EXPORT extern const base::Feature kScheduledScriptStreaming;
#if defined(OS_ANDROID)
CONTENT_EXPORT extern const base::Feature kAndroidAutofillAccessibility;
@@ -156,10 +159,6 @@ CONTENT_EXPORT extern const char kWebXrRenderPathParamValueSharedBuffer[];
CONTENT_EXPORT extern const base::Feature kWebUIPolymer2;
#endif // !defined(OS_ANDROID)
-#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
-CONTENT_EXPORT extern const base::Feature kOverrideUIThreadPriority;
-#endif // defined(OS_ANDROID) || defined(OS_CHROMEOS)
-
#if defined(OS_MACOSX)
CONTENT_EXPORT extern const base::Feature kDeviceMonitorMac;
CONTENT_EXPORT extern const base::Feature kIOSurfaceCapturer;
diff --git a/chromium/content/public/common/content_switches.cc b/chromium/content/public/common/content_switches.cc
index 19c2246a3bd..049f139bc7f 100644
--- a/chromium/content/public/common/content_switches.cc
+++ b/chromium/content/public/common/content_switches.cc
@@ -13,21 +13,6 @@ namespace switches {
// have an effect. 0 disables MSAA.
const char kAcceleratedCanvas2dMSAASampleCount[] = "canvas-msaa-sample-count";
-// Enables a new tuning of the WebRTC Acoustic Echo Canceler (AEC). The new
-// tuning aims at resolving two issues with the AEC:
-// https://bugs.chromium.org/p/webrtc/issues/detail?id=5777
-// https://bugs.chromium.org/p/webrtc/issues/detail?id=5778
-// TODO(hlundin): Remove this switch when experimentation is over;
-// crbug.com/603821.
-const char kAecRefinedAdaptiveFilter[] = "aec-refined-adaptive-filter";
-
-// Override the default minimum starting volume of the Automatic Gain Control
-// algorithm in WebRTC used with audio tracks from getUserMedia.
-// The valid range is 12-255. Values outside that range will be clamped
-// to the lowest or highest valid value inside WebRTC.
-// TODO(tommi): Remove this switch when crbug.com/555577 is fixed.
-const char kAgcStartupMinVolume[] = "agc-startup-min-volume";
-
// By default, file:// URIs cannot read other file:// URIs. This is an
// override for developers who need the old behavior for testing.
const char kAllowFileAccessFromFiles[] = "allow-file-access-from-files";
@@ -429,9 +414,6 @@ const char kEnableTracing[] = "enable-tracing";
// The filename to write the output of the test tracing to.
const char kEnableTracingOutput[] = "enable-tracing-output";
-// Enables unsafe WebGPU support.
-const char kEnableUnsafeWebGPU[] = "enable-unsafe-webgpu";
-
// Enable screen capturing support for MediaStream API.
const char kEnableUserMediaScreenCapturing[] =
"enable-usermedia-screen-capturing";
@@ -516,13 +498,6 @@ const char kForcePresentationReceiverForTesting[] =
// overrides this if present.
const char kForceRendererAccessibility[] = "force-renderer-accessibility";
-// Sets the timeout seconds of NetworkQuietTimers in
-// FirstMeaningfulPainterDectector. Used by embedders who want to change the
-// timeout time in order to run web contents on various embedded devices and
-// changeable network bandwidths in different regions. For example, it's useful
-// when using FMP signal to dismiss a splash screen.
-const char kFMPNetworkQuietTimeout[] = "fmp-network-quiet-timeout";
-
// For development / testing only. When running content_browsertests,
// saves output of failing accessibility tests to their expectations files in
// content/test/data/accessibility/, overwriting existing file content.
@@ -618,12 +593,22 @@ const char kMHTMLSkipNostoreAll[] = "skip-nostore-all";
// Use a Mojo-based LocalStorage implementation.
const char kMojoLocalStorage[] = "mojo-local-storage";
+// Sets the timeout seconds of the network-quiet timers in IdlenessDetector.
+// Used by embedders who want to change the timeout time in order to run web
+// contents on various embedded devices and changeable network bandwidths in
+// different regions. For example, it's useful when using FirstMeaningfulPaint
+// signal to dismiss a splash screen.
+const char kNetworkQuietTimeout[] = "network-quiet-timeout";
+
// Disables the use of a zygote process for forking child processes. Instead,
// child processes will be forked and exec'd directly. Note that --no-sandbox
// should also be used together with this flag because the sandbox needs the
// zygote to work.
const char kNoZygote[] = "no-zygote";
+// Disables V8 mitigations for executing untrusted code.
+const char kNoV8UntrustedCodeMitigations[] = "no-v8-untrusted-code-mitigations";
+
// Number of worker threads used to rasterize content.
const char kNumRasterThreads[] = "num-raster-threads";
diff --git a/chromium/content/public/common/content_switches.h b/chromium/content/public/common/content_switches.h
index 2c795e814b1..081af901e81 100644
--- a/chromium/content/public/common/content_switches.h
+++ b/chromium/content/public/common/content_switches.h
@@ -16,8 +16,6 @@ namespace switches {
// All switches in alphabetical order. The switches should be documented
// alongside the definition of their values in the .cc file.
CONTENT_EXPORT extern const char kAcceleratedCanvas2dMSAASampleCount[];
-CONTENT_EXPORT extern const char kAecRefinedAdaptiveFilter[];
-CONTENT_EXPORT extern const char kAgcStartupMinVolume[];
CONTENT_EXPORT extern const char kAllowFileAccessFromFiles[];
CONTENT_EXPORT extern const char kAllowInsecureLocalhost[];
CONTENT_EXPORT extern const char kAllowLoopbackInPeerConnection[];
@@ -135,7 +133,6 @@ CONTENT_EXPORT extern const char kEnableStrictPowerfulFeatureRestrictions[];
CONTENT_EXPORT extern const char kEnableThreadedCompositing[];
CONTENT_EXPORT extern const char kEnableTracing[];
CONTENT_EXPORT extern const char kEnableTracingOutput[];
-CONTENT_EXPORT extern const char kEnableUnsafeWebGPU[];
CONTENT_EXPORT extern const char kEnableUserMediaScreenCapturing[];
CONTENT_EXPORT extern const char kEnableUseZoomForDSF[];
CONTENT_EXPORT extern const char kEnableViewport[];
@@ -157,7 +154,6 @@ CONTENT_EXPORT extern const char kEnableOopRasterization[];
CONTENT_EXPORT extern const char kForceOverlayFullscreenVideo[];
CONTENT_EXPORT extern const char kForcePresentationReceiverForTesting[];
CONTENT_EXPORT extern const char kForceRendererAccessibility[];
-CONTENT_EXPORT extern const char kFMPNetworkQuietTimeout[];
CONTENT_EXPORT extern const char kGenerateAccessibilityTestExpectations[];
extern const char kGpuLauncher[];
CONTENT_EXPORT extern const char kGpuProcess[];
@@ -185,7 +181,9 @@ CONTENT_EXPORT extern const char kMHTMLGeneratorOption[];
CONTENT_EXPORT extern const char kMHTMLSkipNostoreMain[];
CONTENT_EXPORT extern const char kMHTMLSkipNostoreAll[];
CONTENT_EXPORT extern const char kMojoLocalStorage[];
+CONTENT_EXPORT extern const char kNetworkQuietTimeout[];
CONTENT_EXPORT extern const char kNoZygote[];
+extern const char kNoV8UntrustedCodeMitigations[];
CONTENT_EXPORT extern const char kEnableAppContainer[];
CONTENT_EXPORT extern const char kDisableAppContainer[];
CONTENT_EXPORT extern const char kNumRasterThreads[];
diff --git a/chromium/content/public/common/media_stream_request.cc b/chromium/content/public/common/media_stream_request.cc
index d2e688e67d3..1f18ec8a0c4 100644
--- a/chromium/content/public/common/media_stream_request.cc
+++ b/chromium/content/public/common/media_stream_request.cc
@@ -11,20 +11,28 @@ namespace content {
bool IsAudioInputMediaType(MediaStreamType type) {
return (type == MEDIA_DEVICE_AUDIO_CAPTURE ||
- type == MEDIA_TAB_AUDIO_CAPTURE ||
- type == MEDIA_DESKTOP_AUDIO_CAPTURE);
+ type == MEDIA_GUM_TAB_AUDIO_CAPTURE ||
+ type == MEDIA_GUM_DESKTOP_AUDIO_CAPTURE);
}
-bool IsVideoMediaType(MediaStreamType type) {
+bool IsVideoInputMediaType(MediaStreamType type) {
return (type == MEDIA_DEVICE_VIDEO_CAPTURE ||
- type == MEDIA_TAB_VIDEO_CAPTURE ||
- type == MEDIA_DESKTOP_VIDEO_CAPTURE);
+ type == MEDIA_GUM_TAB_VIDEO_CAPTURE ||
+ type == MEDIA_GUM_DESKTOP_VIDEO_CAPTURE ||
+ type == MEDIA_DISPLAY_VIDEO_CAPTURE);
}
bool IsScreenCaptureMediaType(MediaStreamType type) {
- return (type == MEDIA_TAB_AUDIO_CAPTURE || type == MEDIA_TAB_VIDEO_CAPTURE ||
- type == MEDIA_DESKTOP_AUDIO_CAPTURE ||
- type == MEDIA_DESKTOP_VIDEO_CAPTURE);
+ return (type == MEDIA_DISPLAY_VIDEO_CAPTURE ||
+ type == MEDIA_GUM_TAB_AUDIO_CAPTURE ||
+ type == MEDIA_GUM_TAB_VIDEO_CAPTURE ||
+ type == MEDIA_GUM_DESKTOP_AUDIO_CAPTURE ||
+ type == MEDIA_GUM_DESKTOP_VIDEO_CAPTURE);
+}
+
+bool IsDeviceMediaType(MediaStreamType type) {
+ return (type == MEDIA_DEVICE_AUDIO_CAPTURE ||
+ type == MEDIA_DEVICE_VIDEO_CAPTURE);
}
// static
diff --git a/chromium/content/public/common/media_stream_request.h b/chromium/content/public/common/media_stream_request.h
index 946502b28db..66e13851784 100644
--- a/chromium/content/public/common/media_stream_request.h
+++ b/chromium/content/public/common/media_stream_request.h
@@ -30,15 +30,20 @@ enum MediaStreamType {
MEDIA_DEVICE_AUDIO_CAPTURE,
MEDIA_DEVICE_VIDEO_CAPTURE,
+ // Below MEDIA_GUM_* types represent the streams generated by
+ // getUserMedia() calls with constraints that are collected with legacy
+ // APIs for desktop and tab capture.
// Mirroring of a browser tab.
- MEDIA_TAB_AUDIO_CAPTURE,
- MEDIA_TAB_VIDEO_CAPTURE,
-
+ MEDIA_GUM_TAB_AUDIO_CAPTURE,
+ MEDIA_GUM_TAB_VIDEO_CAPTURE,
// Desktop media sources.
- MEDIA_DESKTOP_VIDEO_CAPTURE,
-
+ MEDIA_GUM_DESKTOP_VIDEO_CAPTURE,
// Capture system audio (post-mix loopback stream).
- MEDIA_DESKTOP_AUDIO_CAPTURE,
+ MEDIA_GUM_DESKTOP_AUDIO_CAPTURE,
+
+ // Enables the capture of a user's display, generated by getDisplayMedia()
+ // call.
+ MEDIA_DISPLAY_VIDEO_CAPTURE,
NUM_MEDIA_TYPES
};
@@ -77,8 +82,9 @@ using CameraCalibration =
// Convenience predicates to determine whether the given type represents some
// audio or some video device.
CONTENT_EXPORT bool IsAudioInputMediaType(MediaStreamType type);
-CONTENT_EXPORT bool IsVideoMediaType(MediaStreamType type);
+CONTENT_EXPORT bool IsVideoInputMediaType(MediaStreamType type);
CONTENT_EXPORT bool IsScreenCaptureMediaType(MediaStreamType type);
+CONTENT_EXPORT bool IsDeviceMediaType(MediaStreamType type);
// TODO(xians): Change the structs to classes.
// Represents one device in a request for media stream(s).
diff --git a/chromium/content/public/common/mime_handler_view_mode.cc b/chromium/content/public/common/mime_handler_view_mode.cc
new file mode 100644
index 00000000000..e235c623d86
--- /dev/null
+++ b/chromium/content/public/common/mime_handler_view_mode.cc
@@ -0,0 +1,17 @@
+// 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/common/mime_handler_view_mode.h"
+
+#include "content/public/common/content_features.h"
+
+namespace content {
+
+// static
+bool MimeHandlerViewMode::UsesCrossProcessFrame() {
+ return base::FeatureList::IsEnabled(
+ features::kMimeHandlerViewInCrossProcessFrame);
+}
+
+} // namespace content
diff --git a/chromium/content/public/common/mime_handler_view_mode.h b/chromium/content/public/common/mime_handler_view_mode.h
new file mode 100644
index 00000000000..12cd4c436cb
--- /dev/null
+++ b/chromium/content/public/common/mime_handler_view_mode.h
@@ -0,0 +1,25 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_PUBLIC_COMMON_MIME_HANDLER_VIEW_MODE_H_
+#define CONTENT_PUBLIC_COMMON_MIME_HANDLER_VIEW_MODE_H_
+
+#include "base/macros.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+class CONTENT_EXPORT MimeHandlerViewMode {
+ public:
+ // Returns true if MimeHandlerViewGuest uses cross-process frames instead of
+ // BrowserPlugin.
+ static bool UsesCrossProcessFrame();
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(MimeHandlerViewMode);
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_COMMON_MIME_HANDLER_VIEW_MODE_H_
diff --git a/chromium/content/public/common/persistent_notification_status.h b/chromium/content/public/common/persistent_notification_status.h
index 38d1dab4f2a..235f9ea6c06 100644
--- a/chromium/content/public/common/persistent_notification_status.h
+++ b/chromium/content/public/common/persistent_notification_status.h
@@ -9,26 +9,29 @@ namespace content {
// Delivery status for persistent notification clicks to a Service Worker.
// PersistentNotificationStatus entries should not be reordered or removed.
-enum PersistentNotificationStatus {
+enum class PersistentNotificationStatus {
// The notificationclick event has been delivered successfully.
- PERSISTENT_NOTIFICATION_STATUS_SUCCESS = 0,
+ kSuccess = 0,
// The event could not be delivered because the Service Worker is unavailable.
- PERSISTENT_NOTIFICATION_STATUS_NO_SERVICE_WORKER,
+ kServiceWorkerMissing = 1,
// The event could not be delivered because of a Service Worker error.
- PERSISTENT_NOTIFICATION_STATUS_SERVICE_WORKER_ERROR,
+ kServiceWorkerError = 2,
// The event has been delivered, but the developer extended the event with a
// promise that has been rejected.
- PERSISTENT_NOTIFICATION_STATUS_EVENT_WAITUNTIL_REJECTED,
+ kWaitUntilRejected = 3,
// The event could not be delivered because the data associated with the
// notification could not be read from the database.
- PERSISTENT_NOTIFICATION_STATUS_DATABASE_ERROR,
+ kDatabaseError = 4,
- // Only add new entries above this line.
- PERSISTENT_NOTIFICATION_STATUS_MAX
+ // The event could not be delivered because no permission had been granted to
+ // the origin.
+ kPermissionMissing = 5,
+
+ kMaxValue = kPermissionMissing
};
} // content
diff --git a/chromium/content/public/common/presentation_connection_message.cc b/chromium/content/public/common/presentation_connection_message.cc
deleted file mode 100644
index d8c0e583f8b..00000000000
--- a/chromium/content/public/common/presentation_connection_message.cc
+++ /dev/null
@@ -1,44 +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/common/presentation_connection_message.h"
-
-#include <utility>
-
-namespace content {
-
-PresentationConnectionMessage::PresentationConnectionMessage() = default;
-
-PresentationConnectionMessage::PresentationConnectionMessage(
- std::string message)
- : message(std::move(message)) {}
-
-PresentationConnectionMessage::PresentationConnectionMessage(
- std::vector<uint8_t> data)
- : data(std::move(data)) {}
-
-PresentationConnectionMessage::PresentationConnectionMessage(
- const PresentationConnectionMessage& other) = default;
-
-PresentationConnectionMessage::PresentationConnectionMessage(
- PresentationConnectionMessage&& other) noexcept = default;
-
-PresentationConnectionMessage::~PresentationConnectionMessage() {}
-
-bool PresentationConnectionMessage::operator==(
- const PresentationConnectionMessage& other) const {
- return this->data == other.data && this->message == other.message;
-}
-
-PresentationConnectionMessage& PresentationConnectionMessage::operator=(
- const PresentationConnectionMessage& other) = default;
-
-PresentationConnectionMessage& PresentationConnectionMessage::operator=(
- PresentationConnectionMessage&& other) = default;
-
-bool PresentationConnectionMessage::is_binary() const {
- return data.has_value();
-}
-
-} // namespace content
diff --git a/chromium/content/public/common/presentation_connection_message.h b/chromium/content/public/common/presentation_connection_message.h
deleted file mode 100644
index 3beccc9994e..00000000000
--- a/chromium/content/public/common/presentation_connection_message.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_PUBLIC_COMMON_PRESENTATION_CONNECTION_MESSAGE_H_
-#define CONTENT_PUBLIC_COMMON_PRESENTATION_CONNECTION_MESSAGE_H_
-
-#include <stddef.h> // For size_t
-#include <stdint.h>
-
-#include <string>
-#include <vector>
-
-#include "base/optional.h"
-#include "content/common/content_export.h"
-
-namespace content {
-
-// Represents a presentation connection message. If this is a text message,
-// |data| is null; otherwise, |message| is null. Empty messages are allowed.
-struct CONTENT_EXPORT PresentationConnectionMessage {
- public:
- // Constructs a new, untyped message (for Mojo). These messages are not valid
- // and exactly one of |message| or |data| must be set.
- PresentationConnectionMessage();
- // Copy constructor / assignment are necessary due to MediaRouter allowing
- // multiple RouteMessageObserver instances per MediaRoute.
- PresentationConnectionMessage(const PresentationConnectionMessage& other);
- PresentationConnectionMessage(PresentationConnectionMessage&& other) noexcept;
- // Constructs a text message from |message|.
- explicit PresentationConnectionMessage(std::string message);
- // Constructs a binary message from |data|.
- explicit PresentationConnectionMessage(std::vector<uint8_t> data);
-
- ~PresentationConnectionMessage();
-
- bool is_binary() const;
-
- bool operator==(const PresentationConnectionMessage& other) const;
- PresentationConnectionMessage& operator=(
- const PresentationConnectionMessage& other);
- PresentationConnectionMessage& operator=(
- PresentationConnectionMessage&& other);
-
- base::Optional<std::string> message;
- base::Optional<std::vector<uint8_t>> data;
-};
-
-} // namespace content
-
-#endif // CONTENT_PUBLIC_COMMON_PRESENTATION_CONNECTION_MESSAGE_H_
diff --git a/chromium/content/public/common/previews_state.h b/chromium/content/public/common/previews_state.h
index e5ab4b75df4..e87edd62d3f 100644
--- a/chromium/content/public/common/previews_state.h
+++ b/chromium/content/public/common/previews_state.h
@@ -42,7 +42,9 @@ enum PreviewsTypes {
1 << 7, // Request that resource loading hints be used during pageload.
OFFLINE_PAGE_ON =
1 << 8, // Request that an offline page be used if one is stored.
- PREVIEWS_STATE_LAST = OFFLINE_PAGE_ON
+ LITE_PAGE_REDIRECT_ON = 1 << 9, // Allow the browser to redirect the resource
+ // to a Lite Page server.
+ PREVIEWS_STATE_LAST = LITE_PAGE_REDIRECT_ON
};
// Combination of all previews that are guaranteed not to provide partial
@@ -69,6 +71,8 @@ STATIC_ASSERT_PREVIEWS_ENUM(RESOURCE_LOADING_HINTS_ON,
blink::WebURLRequest::kResourceLoadingHintsOn);
STATIC_ASSERT_PREVIEWS_ENUM(OFFLINE_PAGE_ON,
blink::WebURLRequest::kOfflinePageOn);
+STATIC_ASSERT_PREVIEWS_ENUM(LITE_PAGE_REDIRECT_ON,
+ blink::WebURLRequest::kLitePageRedirectOn);
STATIC_ASSERT_PREVIEWS_ENUM(PREVIEWS_STATE_LAST,
blink::WebURLRequest::kPreviewsStateLast);
diff --git a/chromium/content/public/common/push_event_payload.h b/chromium/content/public/common/push_event_payload.h
deleted file mode 100644
index a560cdac69b..00000000000
--- a/chromium/content/public/common/push_event_payload.h
+++ /dev/null
@@ -1,37 +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_EVENT_PAYLOAD_H_
-#define CONTENT_PUBLIC_COMMON_PUSH_EVENT_PAYLOAD_H_
-
-#include <string>
-
-#include "content/common/content_export.h"
-
-namespace content {
-
-// Structure representing the payload delivered as part of a push message.
-// This struct contains the decrypted information sent from the push
-// service as part of a PushEvent as well as metadata about the information.
-struct CONTENT_EXPORT PushEventPayload {
- PushEventPayload() : is_null(true) {}
- ~PushEventPayload() {}
-
- // Method to both set the data string and update the null status.
- void setData(const std::string& data_in) {
- data = data_in;
- is_null = false;
- }
-
- // Data contained in the payload.
- std::string data;
-
- // Whether the payload is null or not. Payloads can be valid with non-empty
- // content, valid with empty content, or null.
- bool is_null;
-};
-
-} // namespace content
-
-#endif // CONTENT_PUBLIC_COMMON_PUSH_EVENT_PAYLOAD_H_
diff --git a/chromium/content/public/common/renderer_preference_watcher.mojom b/chromium/content/public/common/renderer_preference_watcher.mojom
new file mode 100644
index 00000000000..997831e445e
--- /dev/null
+++ b/chromium/content/public/common/renderer_preference_watcher.mojom
@@ -0,0 +1,14 @@
+// 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/renderer_preferences.mojom";
+
+// Implementation of this interface usually lives in the renderer process and
+// the browser process calls NotifyUpdate() whenever preferences are updated.
+interface RendererPreferenceWatcher {
+ // Send the new preference to the receiver.
+ NotifyUpdate(RendererPreferences new_prefs);
+}; \ No newline at end of file
diff --git a/chromium/content/public/common/renderer_preferences.cc b/chromium/content/public/common/renderer_preferences.cc
index 3e4683a0b25..2f5c823d475 100644
--- a/chromium/content/public/common/renderer_preferences.cc
+++ b/chromium/content/public/common/renderer_preferences.cc
@@ -34,7 +34,6 @@ RendererPreferences::RendererPreferences()
enable_encrypted_media(true),
webrtc_udp_min_port(0),
webrtc_udp_max_port(0),
- tap_multiple_targets_strategy(TAP_MULTIPLE_TARGETS_STRATEGY_POPUP),
disable_client_blocked_error_page(false),
plugin_fullscreen_allowed(true)
#if defined(OS_WIN)
diff --git a/chromium/content/public/common/renderer_preferences.h b/chromium/content/public/common/renderer_preferences.h
index dd45021de12..fa8c2cd5869 100644
--- a/chromium/content/public/common/renderer_preferences.h
+++ b/chromium/content/public/common/renderer_preferences.h
@@ -25,14 +25,6 @@
namespace content {
-enum TapMultipleTargetsStrategy {
- TAP_MULTIPLE_TARGETS_STRATEGY_ZOOM = 0,
- TAP_MULTIPLE_TARGETS_STRATEGY_POPUP,
- TAP_MULTIPLE_TARGETS_STRATEGY_NONE,
-
- TAP_MULTIPLE_TARGETS_STRATEGY_MAX = TAP_MULTIPLE_TARGETS_STRATEGY_NONE,
-};
-
// User preferences needed to be passed to the renderer process.
// TODO(crbug.com/869748): Move the preferences into
// third_party/blink/public/mojom as a mojom struct.
@@ -124,9 +116,6 @@ struct CONTENT_EXPORT RendererPreferences {
// The accept-languages of the browser, comma-separated.
std::string accept_languages;
- // How to handle a tap gesture touching multiple targets
- TapMultipleTargetsStrategy tap_multiple_targets_strategy;
-
// Disables rendering default error page when client choses to block a page.
// Corresponds to net::ERR_BLOCKED_BY_CLIENT.
bool disable_client_blocked_error_page;
diff --git a/chromium/content/public/common/renderer_preferences.mojom b/chromium/content/public/common/renderer_preferences.mojom
new file mode 100644
index 00000000000..2331553f55f
--- /dev/null
+++ b/chromium/content/public/common/renderer_preferences.mojom
@@ -0,0 +1,8 @@
+// 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;
+
+[Native]
+struct RendererPreferences;
diff --git a/chromium/content/public/common/renderer_preferences.typemap b/chromium/content/public/common/renderer_preferences.typemap
new file mode 100644
index 00000000000..01fdfc4d867
--- /dev/null
+++ b/chromium/content/public/common/renderer_preferences.typemap
@@ -0,0 +1,9 @@
+# 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.
+
+mojom = "//content/public/common/renderer_preferences.mojom"
+public_headers = [ "//content/public/common/renderer_preferences.h" ]
+traits_headers = [ "//content/public/common/common_param_traits_macros.h" ]
+type_mappings =
+ [ "content.mojom.RendererPreferences=content::RendererPreferences" ]
diff --git a/chromium/content/public/common/typemaps.gni b/chromium/content/public/common/typemaps.gni
index 4e0d0c3d3c6..8dd9f6b2f8a 100644
--- a/chromium/content/public/common/typemaps.gni
+++ b/chromium/content/public/common/typemaps.gni
@@ -5,6 +5,7 @@
typemaps = [
"//content/public/common/load_timing_info.typemap",
"//content/public/common/referrer.typemap",
+ "//content/public/common/renderer_preferences.typemap",
"//content/public/common/resource_type.typemap",
"//content/public/common/webplugininfo.typemap",
]
diff --git a/chromium/content/public/common/url_constants.cc b/chromium/content/public/common/url_constants.cc
index e85d54e2990..e4f7d81d65f 100644
--- a/chromium/content/public/common/url_constants.cc
+++ b/chromium/content/public/common/url_constants.cc
@@ -22,7 +22,6 @@ const char kAboutSrcDocURL[] = "about:srcdoc";
const char kChromeUIAppCacheInternalsHost[] = "appcache-internals";
const char kChromeUIIndexedDBInternalsHost[] = "indexeddb-internals";
-const char kChromeUIAccessibilityHost[] = "accessibility";
const char kChromeUIBlobInternalsHost[] = "blob-internals";
const char kChromeUIBrowserCrashHost[] = "inducebrowsercrashforrealz";
const char kChromeUIDinoHost[] = "dino";
@@ -59,6 +58,11 @@ const char kChromeUIProcessInternalsURL[] = "chrome://process-internals";
#if defined(OS_ANDROID)
const char kChromeUIGpuJavaCrashURL[] = "chrome://gpu-java-crash/";
#endif
+#if defined(OS_WIN)
+const char kChromeUIBrowserHeapCorruptionURL[] =
+ "chrome://inducebrowserheapcorruption/";
+const char kChromeUIHeapCorruptionCrashURL[] = "chrome://heapcorruptioncrash/";
+#endif
#if defined(ADDRESS_SANITIZER)
const char kChromeUICrashHeapOverflowURL[] = "chrome://crash/heap-overflow";
const char kChromeUICrashHeapUnderflowURL[] = "chrome://crash/heap-underflow";
diff --git a/chromium/content/public/common/url_constants.h b/chromium/content/public/common/url_constants.h
index 0da500fb484..d134378340f 100644
--- a/chromium/content/public/common/url_constants.h
+++ b/chromium/content/public/common/url_constants.h
@@ -69,6 +69,10 @@ CONTENT_EXPORT extern const char kChromeUIProcessInternalsURL[];
#if defined(OS_ANDROID)
CONTENT_EXPORT extern const char kChromeUIGpuJavaCrashURL[];
#endif
+#if defined(OS_WIN)
+CONTENT_EXPORT extern const char kChromeUIBrowserHeapCorruptionURL[];
+CONTENT_EXPORT extern const char kChromeUIHeapCorruptionCrashURL[];
+#endif
#if defined(ADDRESS_SANITIZER)
CONTENT_EXPORT extern const char kChromeUICrashHeapOverflowURL[];
CONTENT_EXPORT extern const char kChromeUICrashHeapUnderflowURL[];
diff --git a/chromium/content/public/common/url_loader_throttle.cc b/chromium/content/public/common/url_loader_throttle.cc
index a919a363a9f..2ddff46b734 100644
--- a/chromium/content/public/common/url_loader_throttle.cc
+++ b/chromium/content/public/common/url_loader_throttle.cc
@@ -9,6 +9,8 @@
namespace content {
void URLLoaderThrottle::Delegate::SetPriority(net::RequestPriority priority) {}
+void URLLoaderThrottle::Delegate::UpdateDeferredResponseHead(
+ const network::ResourceResponseHead& new_response_head) {}
void URLLoaderThrottle::Delegate::PauseReadingBodyFromNet() {}
void URLLoaderThrottle::Delegate::ResumeReadingBodyFromNet() {}
@@ -35,11 +37,12 @@ void URLLoaderThrottle::WillRedirectRequest(
const net::RedirectInfo& redirect_info,
const network::ResourceResponseHead& response_head,
bool* defer,
- std::vector<std::string>* to_be_removed_request_headers) {}
+ std::vector<std::string>* to_be_removed_request_headers,
+ net::HttpRequestHeaders* modified_request_headers) {}
void URLLoaderThrottle::WillProcessResponse(
const GURL& response_url,
- const network::ResourceResponseHead& response_head,
+ network::ResourceResponseHead* response_head,
bool* defer) {}
URLLoaderThrottle::URLLoaderThrottle() {}
diff --git a/chromium/content/public/common/url_loader_throttle.h b/chromium/content/public/common/url_loader_throttle.h
index 37faba04144..1f9fe093134 100644
--- a/chromium/content/public/common/url_loader_throttle.h
+++ b/chromium/content/public/common/url_loader_throttle.h
@@ -57,6 +57,13 @@ class CONTENT_EXPORT URLLoaderThrottle {
virtual void SetPriority(net::RequestPriority priority);
+ // Updates the response head which is deferred to be sent. This method needs
+ // to be called when the response is deferred on
+ // URLLoaderThrottle::WillProcessResponse() and before calling
+ // Delegate::Resume().
+ virtual void UpdateDeferredResponseHead(
+ const network::ResourceResponseHead& new_response_head);
+
// Pauses/resumes reading response body if the resource is fetched from
// network.
virtual void PauseReadingBodyFromNet();
@@ -82,24 +89,42 @@ class CONTENT_EXPORT URLLoaderThrottle {
virtual void DetachFromCurrentSequence();
// Called before the resource request is started.
+ // |request| needs to be modified before the callback return (i.e.
+ // 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).
+ //
+ // Implementations should be aware that throttling can happen multiple times
+ // for the same |request|, even after one instance of the same throttle
+ // subclass already modified the request. This happens, e.g., when a service
+ // worker initially elects to handle a request but then later falls back to
+ // network, so new throttles are created for another URLLoaderFactory to
+ // handle the request.
virtual void WillStartRequest(network::ResourceRequest* request, bool* defer);
// Called when the request was redirected. |redirect_info| contains the
// redirect responses's HTTP status code and some information about the new
// request that will be sent if the redirect is followed, including the new
// URL and new method.
+ //
+ // Request headers added to |to_be_removed_request_headers| will be removed
+ // before the redirect is followed. Headers added to
+ // |modified_request_headers| will be merged into the existing request headers
+ // before the redirect is followed.
virtual void WillRedirectRequest(
const net::RedirectInfo& redirect_info,
const network::ResourceResponseHead& response_head,
bool* defer,
- std::vector<std::string>* to_be_removed_request_headers);
+ std::vector<std::string>* to_be_removed_request_headers,
+ net::HttpRequestHeaders* modified_request_headers);
// Called when the response headers and meta data are available.
// TODO(776312): Migrate this URL to ResourceResponseHead.
- virtual void WillProcessResponse(
- const GURL& response_url,
- const network::ResourceResponseHead& response_head,
- bool* defer);
+ virtual void WillProcessResponse(const GURL& response_url,
+ network::ResourceResponseHead* response_head,
+ bool* defer);
void set_delegate(Delegate* delegate) { delegate_ = delegate; }
diff --git a/chromium/content/public/common/url_utils.cc b/chromium/content/public/common/url_utils.cc
index e14b5d9c7d6..fc44c56135a 100644
--- a/chromium/content/public/common/url_utils.cc
+++ b/chromium/content/public/common/url_utils.cc
@@ -4,7 +4,11 @@
#include "content/public/common/url_utils.h"
+#include <set>
+#include <string>
+
#include "base/logging.h"
+#include "base/no_destructor.h"
#include "build/build_config.h"
#include "content/common/url_schemes.h"
#include "content/public/common/browser_side_navigation_policy.h"
@@ -90,6 +94,11 @@ bool IsRendererDebugURL(const GURL& url) {
}
#endif
+#if defined(OS_WIN)
+ if (url == kChromeUIHeapCorruptionCrashURL)
+ return true;
+#endif
+
#if DCHECK_IS_ON()
if (url == kChromeUICrashDcheckURL)
return true;
@@ -105,4 +114,23 @@ bool IsRendererDebugURL(const GURL& url) {
return false;
}
+bool IsSafeRedirectTarget(const GURL& from_url, const GURL& to_url) {
+ static base::NoDestructor<std::set<std::string>> kUnsafeSchemes(
+ std::set<std::string>({
+ url::kAboutScheme, url::kDataScheme, url::kFileScheme,
+ url::kFileSystemScheme,
+ }));
+ if (HasWebUIScheme(to_url))
+ return false;
+ if (kUnsafeSchemes->find(to_url.scheme()) == kUnsafeSchemes->end())
+ return true;
+ if (from_url.is_empty())
+ return false;
+ if (from_url.SchemeIsFile() && to_url.SchemeIsFile())
+ return true;
+ if (from_url.SchemeIsFileSystem() && to_url.SchemeIsFileSystem())
+ return true;
+ return false;
+}
+
} // namespace content
diff --git a/chromium/content/public/common/url_utils.h b/chromium/content/public/common/url_utils.h
index 7161cbd9688..a5b4e58f7ce 100644
--- a/chromium/content/public/common/url_utils.h
+++ b/chromium/content/public/common/url_utils.h
@@ -39,6 +39,10 @@ CONTENT_EXPORT bool IsRendererDebugURL(const GURL& url);
// is disabled.
bool CONTENT_EXPORT IsURLHandledByNetworkService(const GURL& url);
+// Determines whether it is safe to redirect from |from_url| to |to_url|.
+CONTENT_EXPORT bool IsSafeRedirectTarget(const GURL& from_url,
+ const GURL& to_url);
+
} // namespace content
#endif // CONTENT_PUBLIC_COMMON_URL_UTILS_H_
diff --git a/chromium/content/public/common/url_utils_unittest.cc b/chromium/content/public/common/url_utils_unittest.cc
index 198a4c4cde8..c7081cf0a13 100644
--- a/chromium/content/public/common/url_utils_unittest.cc
+++ b/chromium/content/public/common/url_utils_unittest.cc
@@ -22,4 +22,23 @@ TEST(UrlUtilsTest, IsURLHandledByNetworkStack) {
EXPECT_FALSE(IsURLHandledByNetworkStack(GURL()));
}
+TEST(UrlUtilsTest, IsSafeRedirectTarget) {
+ EXPECT_FALSE(IsSafeRedirectTarget(GURL(), GURL("chrome://foo/bar.html")));
+ EXPECT_TRUE(IsSafeRedirectTarget(GURL(), GURL("http://foo/bar.html")));
+ EXPECT_FALSE(IsSafeRedirectTarget(GURL(), GURL("file:///foo/bar/")));
+ EXPECT_TRUE(
+ IsSafeRedirectTarget(GURL("file:///foo/bar"), GURL("file:///foo/bar/")));
+ EXPECT_TRUE(IsSafeRedirectTarget(GURL("filesystem://foo/bar"),
+ GURL("filesystem://foo/bar/")));
+ EXPECT_TRUE(IsSafeRedirectTarget(GURL(), GURL("unknown://foo/bar/")));
+ EXPECT_FALSE(IsSafeRedirectTarget(GURL("http://foo/bar.html"),
+ GURL("file:///foo/bar/")));
+ EXPECT_TRUE(IsSafeRedirectTarget(GURL("file:///foo/bar/"),
+ GURL("http://foo/bar.html")));
+
+ // TODO(cmumford): Capturing current behavior, but should probably prevent
+ // redirect to invalid URL.
+ EXPECT_TRUE(IsSafeRedirectTarget(GURL(), GURL()));
+}
+
} // namespace content
diff --git a/chromium/content/public/common/use_zoom_for_dsf_policy.cc b/chromium/content/public/common/use_zoom_for_dsf_policy.cc
index 2b8d484dbca..05be9f23b85 100644
--- a/chromium/content/public/common/use_zoom_for_dsf_policy.cc
+++ b/chromium/content/public/common/use_zoom_for_dsf_policy.cc
@@ -8,7 +8,7 @@
#include "build/build_config.h"
#include "content/public/common/content_switches.h"
-#if defined(OS_WIN)
+#if defined(OS_WIN) || defined(OS_ANDROID)
#include "base/feature_list.h"
#endif
@@ -19,10 +19,15 @@ const base::Feature kUseZoomForDsfEnabledByDefault{
"use-zoom-for-dsf enabled by default", base::FEATURE_ENABLED_BY_DEFAULT};
#endif
+#if defined(OS_ANDROID)
+const base::Feature kUseZoomForDsfEnabledByDefault{
+ "use-zoom-for-dsf enabled by default", base::FEATURE_DISABLED_BY_DEFAULT};
+#endif
+
bool IsUseZoomForDSFEnabledByDefault() {
#if defined(OS_LINUX) || defined(OS_FUCHSIA)
return true;
-#elif defined(OS_WIN)
+#elif defined(OS_WIN) || defined(OS_ANDROID)
return base::FeatureList::IsEnabled(kUseZoomForDsfEnabledByDefault);
#else
return false;
diff --git a/chromium/content/public/common/user_agent.h b/chromium/content/public/common/user_agent.h
index 8a095a81c92..fbd7f9f346c 100644
--- a/chromium/content/public/common/user_agent.h
+++ b/chromium/content/public/common/user_agent.h
@@ -7,6 +7,7 @@
#include <string>
+#include "build/build_config.h"
#include "content/common/content_export.h"
namespace content {
@@ -17,18 +18,24 @@ CONTENT_EXPORT std::string GetWebKitVersion();
CONTENT_EXPORT std::string GetWebKitRevision();
// Builds a User-agent compatible string that describes the OS and CPU type.
-CONTENT_EXPORT std::string BuildOSCpuInfo();
+// On Android, the string will only include the build number if true is passed
+// as an argument.
+CONTENT_EXPORT std::string BuildOSCpuInfo(bool include_android_build_number);
// Helper function to generate a full user agent string from a short
// product name.
CONTENT_EXPORT std::string BuildUserAgentFromProduct(
const std::string& product);
+#if defined(OS_ANDROID)
// Helper function to generate a full user agent string given a short
// product name and some extra text to be added to the OS info.
+// This is currently only used for Android Web View.
CONTENT_EXPORT std::string BuildUserAgentFromProductAndExtraOSInfo(
- const std::string& product,
- const std::string& extra_os_info);
+ const std::string& product,
+ const std::string& extra_os_info,
+ const bool include_android_build_number);
+#endif
// Builds a full user agent string given a string describing the OS and a
// product name.
diff --git a/chromium/content/public/common/web_preferences.cc b/chromium/content/public/common/web_preferences.cc
index 8378aefaf81..bd8facb2d85 100644
--- a/chromium/content/public/common/web_preferences.cc
+++ b/chromium/content/public/common/web_preferences.cc
@@ -236,7 +236,8 @@ WebPreferences::WebPreferences()
do_not_update_selection_on_mutating_selection_range(false),
autoplay_policy(AutoplayPolicy::kDocumentUserActivationRequired),
low_priority_iframes_threshold(net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN),
- picture_in_picture_enabled(true) {
+ picture_in_picture_enabled(true),
+ translate_service_available(false) {
standard_font_family_map[kCommonScript] =
base::ASCIIToUTF16("Times New Roman");
fixed_font_family_map[kCommonScript] = base::ASCIIToUTF16("Courier New");
diff --git a/chromium/content/public/common/web_preferences.h b/chromium/content/public/common/web_preferences.h
index 78cbf5f3db8..eba70c162af 100644
--- a/chromium/content/public/common/web_preferences.h
+++ b/chromium/content/public/common/web_preferences.h
@@ -188,7 +188,12 @@ struct CONTENT_EXPORT WebPreferences {
bool supports_multiple_windows;
bool viewport_enabled;
bool viewport_meta_enabled;
+
+ // If true - Blink will clamp the minimum scale factor to the content width,
+ // preventing zoom beyond the visible content. This is really only needed if
+ // viewport_enabled is on.
bool shrinks_viewport_contents_to_fit;
+
ViewportStyle viewport_style;
bool always_show_context_menu_on_touch;
bool smooth_scroll_for_find_enabled;
@@ -306,12 +311,19 @@ struct CONTENT_EXPORT WebPreferences {
// Whether Picture-in-Picture is enabled.
bool picture_in_picture_enabled;
- // Specifies how close a lazily loaded iframe should be from the viewport
- // before it should start being loaded in, depending on the effective
+ // Whether a translate service is available.
+ // blink's hrefTranslate attribute existence relies on the result.
+ // See https://github.com/dtapuska/html-translate
+ bool translate_service_available;
+
+ // Specifies how close a lazily loaded iframe or image should be from the
+ // viewport before it should start being loaded in, depending on the effective
// connection type of the current network. Blink will use the default distance
// threshold for effective connection types that aren't specified here.
std::map<net::EffectiveConnectionType, int>
lazy_frame_loading_distance_thresholds_px;
+ std::map<net::EffectiveConnectionType, int>
+ lazy_image_loading_distance_thresholds_px;
// We try to keep the default values the same as the default values in
// chrome, except for the cases where it would require lots of extra work for
diff --git a/chromium/content/public/renderer/BUILD.gn b/chromium/content/public/renderer/BUILD.gn
index ea773ce6f24..eb312e8c256 100644
--- a/chromium/content/public/renderer/BUILD.gn
+++ b/chromium/content/public/renderer/BUILD.gn
@@ -55,7 +55,6 @@ target(link_target_type, "renderer_sources") {
"navigation_state.cc",
"navigation_state.h",
"pepper_plugin_instance.h",
- "platform_event_observer.h",
"plugin_instance_throttler.h",
"render_accessibility.h",
"render_frame.h",
@@ -72,7 +71,6 @@ target(link_target_type, "renderer_sources") {
"render_view_observer.h",
"render_view_observer_tracker.h",
"render_view_visitor.h",
- "renderer_gamepad_provider.h",
"renderer_ppapi_host.h",
"request_peer.h",
"resource_dispatcher_delegate.h",
diff --git a/chromium/content/public/renderer/content_renderer_client.cc b/chromium/content/public/renderer/content_renderer_client.cc
index 5d904190947..84f90fab895 100644
--- a/chromium/content/public/renderer/content_renderer_client.cc
+++ b/chromium/content/public/renderer/content_renderer_client.cc
@@ -11,7 +11,6 @@
#include "third_party/blink/public/platform/web_media_stream_center.h"
#include "third_party/blink/public/platform/web_rtc_peer_connection_handler.h"
#include "third_party/blink/public/platform/web_speech_synthesizer.h"
-#include "third_party/blink/public/platform/websocket_handshake_throttle.h"
#include "ui/gfx/icc_profile.h"
#include "url/gurl.h"
@@ -25,6 +24,15 @@ SkBitmap* ContentRendererClient::GetSadWebViewBitmap() {
return nullptr;
}
+bool ContentRendererClient::IsPluginHandledByMimeHandlerView(
+ RenderFrame* embedder_frame,
+ const blink::WebElement& owner_element,
+ const GURL& original_url,
+ const std::string& original_mime_type,
+ int32_t instance_id_to_use) {
+ return false;
+}
+
bool ContentRendererClient::OverrideCreatePlugin(
RenderFrame* render_frame,
const blink::WebPluginParams& params,
@@ -68,11 +76,6 @@ blink::WebThemeEngine* ContentRendererClient::OverrideThemeEngine() {
return nullptr;
}
-std::unique_ptr<blink::WebSocketHandshakeThrottle>
-ContentRendererClient::CreateWebSocketHandshakeThrottle() {
- return nullptr;
-}
-
std::unique_ptr<WebSocketHandshakeThrottleProvider>
ContentRendererClient::CreateWebSocketHandshakeThrottleProvider() {
return nullptr;
@@ -120,8 +123,7 @@ bool ContentRendererClient::ShouldFork(blink::WebLocalFrame* frame,
const GURL& url,
const std::string& http_method,
bool is_initial_navigation,
- bool is_server_redirect,
- bool* send_referrer) {
+ bool is_server_redirect) {
return false;
}
@@ -233,6 +235,11 @@ BrowserPluginDelegate* ContentRendererClient::CreateBrowserPluginDelegate(
return nullptr;
}
+bool ContentRendererClient::IsExcludedHeaderForServiceWorkerFetchEvent(
+ const std::string& header_name) {
+ return false;
+}
+
bool ContentRendererClient::ShouldEnforceWebRTCRoutingPreferences() {
return true;
}
@@ -246,10 +253,19 @@ ContentRendererClient::GetTaskSchedulerInitParams() {
return nullptr;
}
-bool ContentRendererClient::AllowIdleMediaSuspend() {
+bool ContentRendererClient::IsIdleMediaSuspendEnabled() {
return true;
}
+bool ContentRendererClient::IsBackgroundMediaSuspendEnabled(
+ RenderFrame* render_frame) {
+#if defined(OS_ANDROID)
+ return true;
+#else
+ return false;
+#endif
+}
+
bool ContentRendererClient::OverrideLegacySymantecCertConsoleMessage(
const GURL& url,
std::string* console_messsage) {
@@ -268,4 +284,8 @@ blink::WebFrame* ContentRendererClient::FindFrame(
return nullptr;
}
+bool ContentRendererClient::IsSafeRedirectTarget(const GURL& url) {
+ return true;
+}
+
} // namespace content
diff --git a/chromium/content/public/renderer/content_renderer_client.h b/chromium/content/public/renderer/content_renderer_client.h
index a2dc7a811e7..f1c9cc5997c 100644
--- a/chromium/content/public/renderer/content_renderer_client.h
+++ b/chromium/content/public/renderer/content_renderer_client.h
@@ -16,7 +16,7 @@
#include "base/files/file_path.h"
#include "base/memory/ref_counted.h"
#include "base/strings/string16.h"
-#include "base/task_scheduler/task_scheduler.h"
+#include "base/task/task_scheduler/task_scheduler.h"
#include "build/build_config.h"
#include "content/public/common/content_client.h"
#include "content/public/renderer/url_loader_throttle_provider.h"
@@ -39,6 +39,7 @@ class SingleThreadTaskRunner;
}
namespace blink {
+class WebElement;
class WebFrame;
class WebLocalFrame;
class WebMIDIAccessor;
@@ -87,6 +88,15 @@ 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 IsPluginHandledByMimeHandlerView(
+ RenderFrame* embedder_frame,
+ const blink::WebElement& plugin_element,
+ const GURL& original_url,
+ const std::string& original_mime_type,
+ int32_t instance_id_to_use);
+
// Allows the embedder to override creating a plugin. If it returns true, then
// |plugin| will contain the created plugin, although it could be NULL. If it
// returns false, the content layer will create the plugin.
@@ -169,13 +179,6 @@ class CONTENT_EXPORT ContentRendererClient {
// the content layer will provide an engine.
virtual blink::WebThemeEngine* OverrideThemeEngine();
- // Allows the embedder to provide a WebSocketHandshakeThrottle. If it returns
- // NULL then none will be used.
- // TODO(nhiroki): Remove this once the off-main-thread WebSocket is enabled by
- // default (https://crbug.com/825740).
- virtual std::unique_ptr<blink::WebSocketHandshakeThrottle>
- CreateWebSocketHandshakeThrottle();
-
// Allows the embedder to provide a WebSocketHandshakeThrottleProvider. If it
// returns NULL then none will be used.
virtual std::unique_ptr<WebSocketHandshakeThrottleProvider>
@@ -225,15 +228,11 @@ class CONTENT_EXPORT ContentRendererClient {
#endif
// Returns true if we should fork a new process for the given navigation.
- // If |send_referrer| is set to false (which is the default), no referrer
- // header will be send for the navigation. Otherwise, the referrer header is
- // set according to the frame's referrer policy.
virtual bool ShouldFork(blink::WebLocalFrame* frame,
const GURL& url,
const std::string& http_method,
bool is_initial_navigation,
- bool is_server_redirect,
- bool* send_referrer);
+ bool is_server_redirect);
// Notifies the embedder that the given frame is requesting the resource at
// |url|. If the function returns a valid |new_url|, the request must be
@@ -368,6 +367,13 @@ class CONTENT_EXPORT ContentRendererClient {
const GURL& service_worker_scope,
const GURL& script_url) {}
+ // Asks the embedder whether to exclude the given header from service worker
+ // fetch events. This is useful if the embedder injects headers that it wants
+ // to go to network but not to the service worker. This function is called
+ // from the worker thread.
+ virtual bool IsExcludedHeaderForServiceWorkerFetchEvent(
+ const std::string& header_name);
+
// Whether this renderer should enforce preferences related to the WebRTC
// routing logic, i.e. allowing multiple routes and non-proxied UDP.
virtual bool ShouldEnforceWebRTCRoutingPreferences();
@@ -388,7 +394,11 @@ class CONTENT_EXPORT ContentRendererClient {
// Whether the renderer allows idle media players to be automatically
// suspended after a period of inactivity.
- virtual bool AllowIdleMediaSuspend();
+ virtual bool IsIdleMediaSuspendEnabled();
+
+ // Whether the renderer should automatically suspend media playback on
+ // background tabs for given |render_frame|.
+ virtual bool IsBackgroundMediaSuspendEnabled(RenderFrame* render_frame);
// Called when a resource at |url| is loaded using an otherwise-valid legacy
// Symantec certificate that will be distrusted in future. Allows the embedder
@@ -413,6 +423,9 @@ class CONTENT_EXPORT ContentRendererClient {
// from outside of the browsing instance.
virtual blink::WebFrame* FindFrame(blink::WebLocalFrame* relative_to_frame,
const std::string& name);
+
+ // Returns true if it is safe to redirect to |url|, otherwise returns false.
+ virtual bool IsSafeRedirectTarget(const GURL& url);
};
} // namespace content
diff --git a/chromium/content/public/renderer/platform_event_observer.h b/chromium/content/public/renderer/platform_event_observer.h
deleted file mode 100644
index ab8008544b5..00000000000
--- a/chromium/content/public/renderer/platform_event_observer.h
+++ /dev/null
@@ -1,133 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_PUBLIC_RENDERER_PLATFORM_EVENT_OBSERVER_H_
-#define CONTENT_PUBLIC_RENDERER_PLATFORM_EVENT_OBSERVER_H_
-
-#include "base/logging.h"
-#include "base/macros.h"
-#include "content/public/renderer/render_thread.h"
-#include "content/public/renderer/render_thread_observer.h"
-
-namespace blink {
-class WebPlatformEventListener;
-}
-
-namespace content {
-
-// This class is used as a base class for PlatformEventObserver<ListenerType> to
-// allow storing PlatformEventObserver<> with different typename in the same
-// place.
-class PlatformEventObserverBase {
- public:
- virtual ~PlatformEventObserverBase() { }
-
- // Methods that need to be exposed in PlatformEventObserverBase. Their purpose
- // is described in PlatformEventObserver<>.
-
- virtual void Start(blink::WebPlatformEventListener* listener) = 0;
- virtual void Stop() = 0;
-};
-
-// PlatformEventObserver<> defines the basic skeleton for an object requesting
-// the browser process to start/stop listening to some platform/hardware events
-// and observe the result.
-// The results are received via IPC, assuming that the object was correctly
-// registered as an observer via the constructor taking a RenderThread.
-template <typename ListenerType>
-class PlatformEventObserver : public PlatformEventObserverBase,
- public RenderThreadObserver {
- public:
- // Creates a PlatformEventObserver that doesn't listen to responses from the
- // browser process. Can be used for testing purposes or for observers that
- // have other means to get their results.
- PlatformEventObserver()
- : is_observing_(false),
- listener_(0) {
- }
-
- // Creates a PlatformEventObserver that registers to the RenderThread in order
- // to intercept the received IPC messages (via OnControlMessageReceived). If
- // |thread| is null, it will not register.
- explicit PlatformEventObserver(RenderThread* thread)
- : is_observing_(false),
- listener_(0) {
- if (thread)
- thread->AddObserver(this);
- }
-
- // The observer must automatically stop observing when destroyed in case it
- // did not stop before. Implementations of PlatformEventObserver must do
- // so by calling StopIfObserving() from their destructors.
- ~PlatformEventObserver() override {
- // If this assert fails, the derived destructor failed to invoke
- // StopIfObserving().
- DCHECK(!is_observing());
- }
-
- // Called when a new IPC message is received. Must be used to listen to the
- // responses from the browser process if any expected.
- bool OnControlMessageReceived(const IPC::Message& msg) override {
- return false;
- }
-
- // Start observing. Will request the browser process to start listening to the
- // events. |listener| will receive any response from the browser process.
- // Note: should not be called if already observing.
- void Start(blink::WebPlatformEventListener* listener) override {
- DCHECK(!is_observing());
- listener_ = static_cast<ListenerType*>(listener);
- is_observing_ = true;
-
- SendStartMessage();
- }
-
- // Stop observing. Will let the browser know that it doesn't need to observe
- // anymore.
- void Stop() override {
- DCHECK(is_observing());
- listener_ = 0;
- is_observing_ = false;
-
- SendStopMessage();
- }
-
- protected:
- // This method is expected to send an IPC to the browser process to let it
- // know that it should start observing.
- // It is expected for subclasses to override it.
- virtual void SendStartMessage() = 0;
-
- // This method is expected to send an IPC to the browser process to let it
- // know that it should start observing.
- // It is expected for subclasses to override it.
- virtual void SendStopMessage() = 0;
-
- // Implementations of PlatformEventObserver must call StopIfObserving()
- // from their destructor to shutdown in an orderly manner.
- // (As Stop() calls a virtual method, it cannot be handled by
- // ~PlatformEventObserver.)
- void StopIfObserving() {
- if (is_observing())
- Stop();
- }
-
- bool is_observing() const {
- return is_observing_;
- }
-
- ListenerType* listener() {
- return listener_;
- }
-
- private:
- bool is_observing_;
- ListenerType* listener_;
-
- DISALLOW_COPY_AND_ASSIGN(PlatformEventObserver);
-};
-
-} // namespace content
-
-#endif // CONTENT_PUBLIC_RENDERER_PLATFORM_EVENT_OBSERVER_H_
diff --git a/chromium/content/public/renderer/render_frame_observer.cc b/chromium/content/public/renderer/render_frame_observer.cc
index 6b7909b41b0..556e5ee9330 100644
--- a/chromium/content/public/renderer/render_frame_observer.cc
+++ b/chromium/content/public/renderer/render_frame_observer.cc
@@ -29,6 +29,12 @@ RenderFrameObserver::~RenderFrameObserver() {
}
}
+bool RenderFrameObserver::OnAssociatedInterfaceRequestForFrame(
+ const std::string& interface_name,
+ mojo::ScopedInterfaceEndpointHandle* handle) {
+ return false;
+}
+
bool RenderFrameObserver::OnMessageReceived(const IPC::Message& message) {
return false;
}
diff --git a/chromium/content/public/renderer/render_frame_observer.h b/chromium/content/public/renderer/render_frame_observer.h
index 2f1f46075b2..88efca34d57 100644
--- a/chromium/content/public/renderer/render_frame_observer.h
+++ b/chromium/content/public/renderer/render_frame_observer.h
@@ -14,6 +14,7 @@
#include "content/public/common/resource_type.h"
#include "ipc/ipc_listener.h"
#include "ipc/ipc_sender.h"
+#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
#include "mojo/public/cpp/system/message_pipe.h"
#include "third_party/blink/public/platform/web_client_hints_types.mojom.h"
#include "third_party/blink/public/platform/web_feature.mojom.h"
@@ -169,6 +170,14 @@ class CONTENT_EXPORT RenderFrameObserver : public IPC::Listener,
const std::string& interface_name,
mojo::ScopedMessagePipeHandle* interface_pipe) {}
+ // Similar to above but for handling Channel-associated interface requests.
+ // Returns |true| if the request is handled by the implementation (taking
+ // ownership of |*handle|) and |false| otherwise (leaving |*handle|
+ // unmodified).
+ virtual bool OnAssociatedInterfaceRequestForFrame(
+ const std::string& interface_name,
+ mojo::ScopedInterfaceEndpointHandle* handle);
+
// IPC::Listener implementation.
bool OnMessageReceived(const IPC::Message& message) override;
diff --git a/chromium/content/public/renderer/render_thread_observer.h b/chromium/content/public/renderer/render_thread_observer.h
index 35b708e7a26..137e1800297 100644
--- a/chromium/content/public/renderer/render_thread_observer.h
+++ b/chromium/content/public/renderer/render_thread_observer.h
@@ -37,8 +37,6 @@ class CONTENT_EXPORT RenderThreadObserver {
// Called when the renderer cache of the plugin list has changed.
virtual void PluginListChanged() {}
- virtual void IdleNotification() {}
-
// Called when the network state changes.
virtual void NetworkStateChanged(bool online) {}
diff --git a/chromium/content/public/renderer/render_view_observer.h b/chromium/content/public/renderer/render_view_observer.h
index c879f8be873..4c54de570b8 100644
--- a/chromium/content/public/renderer/render_view_observer.h
+++ b/chromium/content/public/renderer/render_view_observer.h
@@ -43,7 +43,7 @@ class CONTENT_EXPORT RenderViewObserver : public IPC::Listener,
bool is_new_navigation) {}
virtual void DidClearWindowObject(blink::WebLocalFrame* frame) {}
virtual void DidCommitCompositorFrame() {}
- virtual void DidUpdateLayout() {}
+ virtual void DidUpdateMainFrameLayout() {}
// These match the RenderView methods.
virtual void DidHandleGestureEvent(const blink::WebGestureEvent& event) {}
diff --git a/chromium/content/public/renderer/renderer_gamepad_provider.h b/chromium/content/public/renderer/renderer_gamepad_provider.h
deleted file mode 100644
index fe5e69ec08d..00000000000
--- a/chromium/content/public/renderer/renderer_gamepad_provider.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_PUBLIC_RENDERER_RENDERER_GAMEPAD_PROVIDER_H_
-#define CONTENT_PUBLIC_RENDERER_RENDERER_GAMEPAD_PROVIDER_H_
-
-#include "base/macros.h"
-#include "content/public/renderer/platform_event_observer.h"
-
-namespace blink {
-class WebGamepadListener;
-}
-
-namespace device {
-class Gamepads;
-}
-
-namespace content {
-
-// Provides gamepad data and events for blink.
-class RendererGamepadProvider
- : public PlatformEventObserver<blink::WebGamepadListener> {
- public:
- RendererGamepadProvider() {}
- ~RendererGamepadProvider() override {}
-
- // Provides latest snapshot of gamepads.
- virtual void SampleGamepads(device::Gamepads& gamepads) = 0;
-
- protected:
- DISALLOW_COPY_AND_ASSIGN(RendererGamepadProvider);
-};
-
-} // namespace content
-
-#endif // CONTENT_PUBLIC_RENDERER_RENDERER_GAMEPAD_PROVIDER_H_
diff --git a/chromium/content/public/renderer/url_loader_throttle_provider.h b/chromium/content/public/renderer/url_loader_throttle_provider.h
index 2d1aca8d6e4..d0ead39a3d0 100644
--- a/chromium/content/public/renderer/url_loader_throttle_provider.h
+++ b/chromium/content/public/renderer/url_loader_throttle_provider.h
@@ -38,6 +38,9 @@ class CONTENT_EXPORT URLLoaderThrottleProvider {
int render_frame_id,
const blink::WebURLRequest& request,
ResourceType resource_type) = 0;
+
+ // Set the network status online state as specified in |is_online|.
+ virtual void SetOnline(bool is_online) = 0;
};
} // namespace content
diff --git a/chromium/content/public/test/android/BUILD.gn b/chromium/content/public/test/android/BUILD.gn
index 956c87c17d5..baae99c22c0 100644
--- a/chromium/content/public/test/android/BUILD.gn
+++ b/chromium/content/public/test/android/BUILD.gn
@@ -34,6 +34,7 @@ android_library("content_java_test_support") {
"javatests/src/org/chromium/content/browser/test/ContentJUnit4ClassRunner.java",
"javatests/src/org/chromium/content/browser/test/InterstitialPageDelegateAndroid.java",
"javatests/src/org/chromium/content/browser/test/NativeLibraryTestRule.java",
+ "javatests/src/org/chromium/content/browser/test/RenderFrameHostTestExt.java",
"javatests/src/org/chromium/content/browser/test/mock/MockRenderFrameHost.java",
"javatests/src/org/chromium/content/browser/test/mock/MockWebContents.java",
"javatests/src/org/chromium/content/browser/test/util/ClickUtils.java",
@@ -53,6 +54,7 @@ android_library("content_java_test_support") {
"javatests/src/org/chromium/content/browser/test/util/TestWebContentsObserver.java",
"javatests/src/org/chromium/content/browser/test/util/TouchCommon.java",
"javatests/src/org/chromium/content/browser/test/util/UiUtils.java",
+ "javatests/src/org/chromium/content/browser/test/util/WebContentsUtils.java",
]
}
@@ -61,20 +63,36 @@ generate_jni("content_test_jni") {
jni_package = "content/public/test"
sources = [
"javatests/src/org/chromium/content/browser/test/InterstitialPageDelegateAndroid.java",
+ "javatests/src/org/chromium/content/browser/test/RenderFrameHostTestExt.java",
+ "javatests/src/org/chromium/content/browser/test/util/DOMUtils.java",
+ "javatests/src/org/chromium/content/browser/test/util/WebContentsUtils.java",
]
}
static_library("content_native_test_support") {
testonly = true
+
+ # See comment at the top of //content/BUILD.gn for why this is disabled in
+ # component builds.
+ if (is_component_build) {
+ check_includes = false
+ }
+
sources = [
+ "dom_utils.cc",
"interstitial_page_delegate_android.cc",
"interstitial_page_delegate_android.h",
+ "render_frame_host_test_ext.cc",
+ "render_frame_host_test_ext.h",
+ "web_contents_utils.cc",
]
deps = [
":content_test_jni",
"//base",
+ "//content/browser:for_content_tests",
"//content/public/browser",
"//device/gamepad",
"//media/midi",
+ "//ui/android",
]
}
diff --git a/chromium/content/renderer/BUILD.gn b/chromium/content/renderer/BUILD.gn
index d97b7082177..0efc1738743 100644
--- a/chromium/content/renderer/BUILD.gn
+++ b/chromium/content/renderer/BUILD.gn
@@ -39,8 +39,6 @@ target(link_target_type, "renderer") {
"accessibility/blink_ax_tree_source.h",
"accessibility/render_accessibility_impl.cc",
"accessibility/render_accessibility_impl.h",
- "android/disambiguation_popup_helper.cc",
- "android/disambiguation_popup_helper.h",
"android/renderer_date_time_picker.cc",
"android/renderer_date_time_picker.h",
"android/synchronous_compositor_proxy.cc",
@@ -207,6 +205,10 @@ target(link_target_type, "renderer") {
"layout_test_dependencies.h",
"loader/child_url_loader_factory_bundle.cc",
"loader/child_url_loader_factory_bundle.h",
+ "loader/code_cache_loader_impl.cc",
+ "loader/code_cache_loader_impl.h",
+ "loader/frame_request_blocker.cc",
+ "loader/frame_request_blocker.h",
"loader/ftp_directory_listing_response_delegate.cc",
"loader/ftp_directory_listing_response_delegate.h",
"loader/navigation_response_override_parameters.cc",
@@ -296,6 +298,8 @@ target(link_target_type, "renderer") {
"media/stream/aec_dump_message_filter.h",
"media/stream/apply_constraints_processor.cc",
"media/stream/apply_constraints_processor.h",
+ "media/stream/audio_service_audio_processor_proxy.cc",
+ "media/stream/audio_service_audio_processor_proxy.h",
"media/stream/external_media_stream_audio_source.cc",
"media/stream/external_media_stream_audio_source.h",
"media/stream/local_media_stream_audio_source.cc",
@@ -382,8 +386,6 @@ target(link_target_type, "renderer") {
"media/webrtc/peer_connection_remote_audio_source.h",
"media/webrtc/peer_connection_tracker.cc",
"media/webrtc/peer_connection_tracker.h",
- "media/webrtc/rtc_certificate.cc",
- "media/webrtc/rtc_certificate.h",
"media/webrtc/rtc_certificate_generator.cc",
"media/webrtc/rtc_certificate_generator.h",
"media/webrtc/rtc_data_channel_handler.cc",
@@ -407,6 +409,8 @@ target(link_target_type, "renderer") {
"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",
"media/webrtc/rtc_video_decoder_factory.h",
"media/webrtc/rtc_video_encoder.cc",
@@ -441,6 +445,8 @@ target(link_target_type, "renderer") {
"media/webrtc/webrtc_video_capturer_adapter.h",
"media/webrtc/webrtc_video_frame_adapter.cc",
"media/webrtc/webrtc_video_frame_adapter.h",
+ "media/webrtc/webrtc_video_utils.cc",
+ "media/webrtc/webrtc_video_utils.h",
"media/webrtc_local_audio_source_provider.cc",
"media/webrtc_local_audio_source_provider.h",
"media/webrtc_logging.cc",
@@ -469,7 +475,6 @@ target(link_target_type, "renderer") {
"media_recorder/vpx_encoder.h",
"menu_item_builder.cc",
"menu_item_builder.h",
- "message_delivery_policy.h",
"mojo/blink_interface_provider_impl.cc",
"mojo/blink_interface_provider_impl.h",
"mojo/blink_interface_registry_impl.cc",
@@ -571,6 +576,8 @@ target(link_target_type, "renderer") {
"service_worker/service_worker_network_provider.h",
"service_worker/service_worker_provider_context.cc",
"service_worker/service_worker_provider_context.h",
+ "service_worker/service_worker_provider_state_for_client.cc",
+ "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",
@@ -641,6 +648,7 @@ target(link_target_type, "renderer") {
defines = []
public_deps = [
+ "//content/common:mojo_bindings",
"//content/public/common:common_sources",
"//ipc",
]
@@ -678,6 +686,7 @@ target(link_target_type, "renderer") {
"//gpu",
"//gpu/command_buffer/client:gles2_interface",
"//gpu/command_buffer/client:raster_interface",
+ "//gpu/command_buffer/client:webgpu_interface",
"//jingle:jingle_glue",
"//media",
"//media:media_buildflags",
@@ -692,11 +701,13 @@ target(link_target_type, "renderer") {
"//media/mojo/clients",
"//media/mojo/interfaces",
"//media/mojo/interfaces:remoting",
+ "//media/webrtc",
"//mojo/public/cpp/bindings",
"//net",
"//ppapi/buildflags",
"//printing/buildflags",
"//sandbox",
+ "//services/audio/public/mojom",
"//services/device/public/cpp/generic_sensor",
"//services/device/public/mojom",
"//services/device/public/mojom:constants",
@@ -704,7 +715,7 @@ target(link_target_type, "renderer") {
"//services/network:network_service",
"//services/service_manager/public/cpp",
"//services/service_manager/public/mojom",
- "//services/ui/public/cpp/gpu",
+ "//services/ws/public/cpp/gpu",
"//skia",
"//storage/common",
"//third_party/blink/public:blink",
@@ -717,6 +728,7 @@ target(link_target_type, "renderer") {
"//third_party/libvpx",
"//third_party/libyuv",
"//third_party/opus",
+ "//third_party/sqlite",
"//third_party/webrtc/api:libjingle_logging_api",
"//third_party/webrtc/api:libjingle_peerconnection_api",
"//third_party/webrtc/api:rtc_stats_api",
@@ -754,6 +766,9 @@ target(link_target_type, "renderer") {
"//third_party/webrtc/pc:rtc_pc_base",
"//third_party/webrtc/rtc_base:rtc_base",
"//third_party/webrtc/rtc_base:rtc_task_queue",
+
+ # TODO(titovartem) remove dependency on WebRTC internals.
+ "//third_party/webrtc/rtc_base/third_party/sigslot:sigslot",
"//third_party/webrtc/stats",
"//third_party/webrtc/system_wrappers",
"//third_party/webrtc_overrides:init_webrtc",
@@ -777,7 +792,7 @@ target(link_target_type, "renderer") {
if (use_aura) {
public_deps += [ "//content/renderer/mus" ]
allow_circular_includes_from += [ "//content/renderer/mus" ]
- deps += [ "//services/ui/public/cpp" ]
+ deps += [ "//services/ws/public/cpp" ]
}
if (use_external_popup_menu) {
@@ -1033,7 +1048,10 @@ target(link_target_type, "renderer") {
# See comment at the top of //content/BUILD.gn for how this works.
group("for_content_tests") {
- visibility = [ "//content/test/*" ]
+ visibility = [
+ "//content/shell/test_runner",
+ "//content/test/*",
+ ]
if (!is_component_build) {
public_deps = [
diff --git a/chromium/content/renderer/OWNERS b/chromium/content/renderer/OWNERS
index d646d43c6cc..13765f89ba8 100644
--- a/chromium/content/renderer/OWNERS
+++ b/chromium/content/renderer/OWNERS
@@ -1,17 +1,21 @@
haraken@chromium.org
+# These are for the common case of adding or renaming files. If you're doing
+# structural changes, please get a review from a reviewer in this file.
+per-file BUILD.gn=*
+
# Mac Sandbox profiles.
per-file *.sb=set noparent
per-file *.sb=rsesek@chromium.org
# DirectWrite specific changes.
-per-file renderer_font_platform_win.*=scottmg@chromium.org
-per-file renderer_font_platform_win.*=cpu@chromium.org
+per-file renderer_font_platform_win*=scottmg@chromium.org
+per-file renderer_font_platform_win*=cpu@chromium.org
# For surface ID propagation and synchronization
-per-file render_frame_proxy.*=fsamuel@chromium.org
-per-file render_view_impl.*=fsamuel@chromium.org
-per-file render_widget.*=fsamuel@chromium.org
-per-file child_frame_compositor.*=fsamuel@chromium.org
-per-file child_frame_compositing_helper.*=fsamuel@chromium.org
+per-file render_frame_proxy*=fsamuel@chromium.org
+per-file render_view_impl*=fsamuel@chromium.org
+per-file render_widget*=fsamuel@chromium.org
+per-file child_frame_compositor*=fsamuel@chromium.org
+per-file child_frame_compositing_helper*=fsamuel@chromium.org
per-file render_frame_metadata*=fsamuel@chromium.org
diff --git a/chromium/content/renderer/PRESUBMIT.py b/chromium/content/renderer/PRESUBMIT.py
index 7fecab9b13a..eb6734d6064 100644
--- a/chromium/content/renderer/PRESUBMIT.py
+++ b/chromium/content/renderer/PRESUBMIT.py
@@ -28,7 +28,7 @@ def _CheckForUseOfGlobalTaskRunnerGetter(input_api, output_api):
problems.append('%s:%d' % (f, line_number))
if problems:
- return [output_api.PresubmitError(
+ return [output_api.PresubmitPromptWarning(
'base::ThreadTaskRunnerHandle::Get() and'
' base::SequencedTaskRunnerHandle::Get() are deprecated in renderer;'
' please use RenderFrame::GetTaskRunner for production code and'
diff --git a/chromium/content/renderer/accessibility/blink_ax_enum_conversion.cc b/chromium/content/renderer/accessibility/blink_ax_enum_conversion.cc
index 3b504e29872..d51402b4d1a 100644
--- a/chromium/content/renderer/accessibility/blink_ax_enum_conversion.cc
+++ b/chromium/content/renderer/accessibility/blink_ax_enum_conversion.cc
@@ -25,6 +25,9 @@ void AXStateFromBlink(const blink::WebAXObject& o, ui::AXNodeData* dst) {
else if (o.Role() == blink::kWebAXRolePopUpButton)
dst->SetHasPopup(ax::mojom::HasPopup::kMenu);
+ if (o.IsAutofillAvailable())
+ dst->AddState(ax::mojom::State::kAutofillAvailable);
+
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 f43d7214fd2..6a5030c35d3 100644
--- a/chromium/content/renderer/accessibility/blink_ax_tree_source.cc
+++ b/chromium/content/renderer/accessibility/blink_ax_tree_source.cc
@@ -903,7 +903,7 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src,
// TODO(nektar): Turn off kHTMLAccessibilityMode for automation and Mac
// and remove ifdef.
-#if defined(OS_WIN)
+#if defined(OS_WIN) || defined(OS_CHROMEOS)
if (dst->role == ax::mojom::Role::kMath && element.InnerHTML().length()) {
TruncateAndAddStringAttribute(dst,
ax::mojom::StringAttribute::kInnerHtml,
diff --git a/chromium/content/renderer/accessibility/render_accessibility_impl.cc b/chromium/content/renderer/accessibility/render_accessibility_impl.cc
index 05fbd8de672..31ec8b96133 100644
--- a/chromium/content/renderer/accessibility/render_accessibility_impl.cc
+++ b/chromium/content/renderer/accessibility/render_accessibility_impl.cc
@@ -33,6 +33,7 @@
#include "ui/accessibility/ax_node.h"
#include "ui/accessibility/ax_role_properties.h"
+using blink::WebAXContext;
using blink::WebAXObject;
using blink::WebDocument;
using blink::WebElement;
@@ -41,7 +42,6 @@ using blink::WebLocalFrame;
using blink::WebNode;
using blink::WebPoint;
using blink::WebRect;
-using blink::WebScopedAXContext;
using blink::WebSettings;
using blink::WebView;
@@ -72,7 +72,7 @@ void RenderAccessibilityImpl::SnapshotAccessibilityTree(
return;
WebDocument document = render_frame->GetWebFrame()->GetDocument();
- WebScopedAXContext context(document);
+ WebAXContext context(document);
WebAXObject root = context.Root();
if (!root.UpdateLayoutAndCheckValidity())
return;
@@ -112,7 +112,6 @@ RenderAccessibilityImpl::RenderAccessibilityImpl(RenderFrameImpl* render_frame,
ack_token_ = g_next_ack_token++;
WebView* web_view = render_frame_->GetRenderView()->GetWebView();
WebSettings* settings = web_view->GetSettings();
- settings->SetAccessibilityEnabled(true);
#if defined(OS_ANDROID)
// Password values are only passed through on Android.
@@ -128,6 +127,8 @@ RenderAccessibilityImpl::RenderAccessibilityImpl(RenderFrameImpl* render_frame,
const WebDocument& document = GetMainDocument();
if (!document.IsNull()) {
+ ax_context_.reset(new blink::WebAXContext(document));
+
// It's possible that the webview has already loaded a webpage without
// accessibility being enabled. Initialize the browser's cached
// accessibility tree by sending it a notification.
@@ -139,6 +140,10 @@ RenderAccessibilityImpl::RenderAccessibilityImpl(RenderFrameImpl* render_frame,
RenderAccessibilityImpl::~RenderAccessibilityImpl() {
}
+void RenderAccessibilityImpl::DidCreateNewDocument() {
+ ax_context_.reset(new blink::WebAXContext(GetMainDocument()));
+}
+
void RenderAccessibilityImpl::AccessibilityModeChanged() {
ui::AXMode new_mode = render_frame_->accessibility_mode();
if (tree_source_.accessibility_mode() == new_mode)
@@ -231,22 +236,6 @@ void RenderAccessibilityImpl::AccessibilityFocusedNodeChanged(
}
}
-void RenderAccessibilityImpl::DisableAccessibility() {
- RenderView* render_view = render_frame_->GetRenderView();
- if (!render_view)
- return;
-
- WebView* web_view = render_view->GetWebView();
- if (!web_view)
- return;
-
- WebSettings* settings = web_view->GetSettings();
- if (!settings)
- return;
-
- settings->SetAccessibilityEnabled(false);
-}
-
void RenderAccessibilityImpl::HandleAXEvent(const blink::WebAXObject& obj,
ax::mojom::Event event,
int action_request_id) {
diff --git a/chromium/content/renderer/accessibility/render_accessibility_impl.h b/chromium/content/renderer/accessibility/render_accessibility_impl.h
index f2c5d3fb805..240a0ff6086 100644
--- a/chromium/content/renderer/accessibility/render_accessibility_impl.h
+++ b/chromium/content/renderer/accessibility/render_accessibility_impl.h
@@ -14,6 +14,7 @@
#include "content/public/renderer/render_accessibility.h"
#include "content/public/renderer/render_frame_observer.h"
#include "content/renderer/accessibility/blink_ax_tree_source.h"
+#include "third_party/blink/public/web/web_ax_context.h"
#include "third_party/blink/public/web/web_ax_object.h"
#include "ui/accessibility/ax_relative_bounds.h"
#include "ui/accessibility/ax_tree.h"
@@ -73,6 +74,7 @@ class CONTENT_EXPORT RenderAccessibilityImpl
void OnPluginRootNodeUpdated() override;
// RenderFrameObserver implementation.
+ void DidCreateNewDocument() override;
void AccessibilityModeChanged() override;
bool OnMessageReceived(const IPC::Message& message) override;
@@ -91,11 +93,6 @@ class CONTENT_EXPORT RenderAccessibilityImpl
void AccessibilityFocusedNodeChanged(const blink::WebNode& node);
- // This can be called before deleting a RenderAccessibilityImpl instance due
- // to the accessibility mode changing, as opposed to during frame destruction
- // (when there'd be no point).
- void DisableAccessibility();
-
void HandleAXEvent(const blink::WebAXObject& obj,
ax::mojom::Event event,
int action_request_id = -1);
@@ -139,6 +136,9 @@ class CONTENT_EXPORT RenderAccessibilityImpl
// The RenderFrameImpl that owns us.
RenderFrameImpl* render_frame_;
+ // This keeps accessibility enabled as long as it lives.
+ std::unique_ptr<blink::WebAXContext> ax_context_;
+
// Events from Blink are collected until they are ready to be
// sent to the browser.
std::vector<ui::AXEvent> pending_events_;
diff --git a/chromium/content/renderer/android/disambiguation_popup_helper.cc b/chromium/content/renderer/android/disambiguation_popup_helper.cc
deleted file mode 100644
index 485732fda5c..00000000000
--- a/chromium/content/renderer/android/disambiguation_popup_helper.cc
+++ /dev/null
@@ -1,119 +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/android/disambiguation_popup_helper.h"
-
-#include <stddef.h>
-
-#include <algorithm>
-
-#include "third_party/blink/public/platform/web_rect.h"
-#include "ui/gfx/geometry/size_conversions.h"
-
-using blink::WebRect;
-using blink::WebVector;
-
-namespace {
-
-// The amount of padding to add to the disambiguation popup to show
-// content around the possible elements, adding some context.
-const int kDisambiguationPopupPadding = 8;
-
-// Constants used for fitting the disambiguation popup inside the bounds of
-// the view. Note that there are mirror constants in PopupZoomer.java.
-const int kDisambiguationPopupBoundsMargin = 25;
-
-// The smallest allowable touch target used for disambiguation popup.
-// This value is used to determine the minimum amount we need to scale to
-// make all targets touchable.
-const int kDisambiguationPopupMinimumTouchSize = 40;
-const float kDisambiguationPopupMaxScale = 5.0;
-const float kDisambiguationPopupMinScale = 2.0;
-
-// Compute the scaling factor to ensure the smallest touch candidate reaches
-// a certain clickable size after zooming
-float FindOptimalScaleFactor(const WebVector<WebRect>& target_rects,
- float total_scale) {
- DCHECK_GT(total_scale, 0.0f);
- if (!target_rects.size()) {
- NOTREACHED();
- return kDisambiguationPopupMinScale;
- }
- int smallest_target = std::min(target_rects[0].width, target_rects[0].height);
- for (size_t i = 1; i < target_rects.size(); i++) {
- smallest_target = std::min(
- {smallest_target, target_rects[i].width, target_rects[i].height});
- }
- const float smallest_target_f = std::max(smallest_target * total_scale, 1.0f);
- return std::min(kDisambiguationPopupMaxScale,
- std::max(kDisambiguationPopupMinScale,
- kDisambiguationPopupMinimumTouchSize /
- smallest_target_f)) *
- total_scale;
-}
-
-void TrimEdges(int* e1, int* e2, int max_combined) {
- if (*e1 + *e2 <= max_combined)
- return;
-
- if (std::min(*e1, *e2) * 2 >= max_combined)
- *e1 = *e2 = max_combined / 2;
- else if (*e1 > *e2)
- *e1 = max_combined - *e2;
- else
- *e2 = max_combined - *e1;
-}
-
-// Ensure the disambiguation popup fits inside the screen,
-// clip the edges farthest to the touch point if needed.
-gfx::Rect CropZoomArea(const gfx::Rect& zoom_rect,
- const gfx::Size& viewport_size,
- const gfx::Point& touch_point,
- float scale) {
- gfx::Size max_size = viewport_size;
- max_size.Enlarge(-2 * kDisambiguationPopupBoundsMargin,
- -2 * kDisambiguationPopupBoundsMargin);
- max_size = gfx::ScaleToCeiledSize(max_size, 1.0 / scale);
-
- int left = touch_point.x() - zoom_rect.x();
- int right = zoom_rect.right() - touch_point.x();
- int top = touch_point.y() - zoom_rect.y();
- int bottom = zoom_rect.bottom() - touch_point.y();
- TrimEdges(&left, &right, max_size.width());
- TrimEdges(&top, &bottom, max_size.height());
-
- return gfx::Rect(touch_point.x() - left,
- touch_point.y() - top,
- left + right,
- top + bottom);
-}
-
-} // namespace
-
-namespace content {
-
-// static
-float DisambiguationPopupHelper::ComputeZoomAreaAndScaleFactor(
- const gfx::Rect& tap_rect,
- const WebVector<WebRect>& target_rects,
- const gfx::Size& screen_size,
- const gfx::Size& visible_content_size,
- float total_scale,
- gfx::Rect* zoom_rect) {
- *zoom_rect = tap_rect;
- for (size_t i = 0; i < target_rects.size(); i++)
- zoom_rect->Union(gfx::Rect(target_rects[i]));
- zoom_rect->Inset(-kDisambiguationPopupPadding, -kDisambiguationPopupPadding);
-
- zoom_rect->Intersect(gfx::Rect(visible_content_size));
-
- float new_total_scale =
- FindOptimalScaleFactor(target_rects, total_scale);
- *zoom_rect = CropZoomArea(
- *zoom_rect, screen_size, tap_rect.CenterPoint(), new_total_scale);
-
- return new_total_scale;
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/android/disambiguation_popup_helper.h b/chromium/content/renderer/android/disambiguation_popup_helper.h
deleted file mode 100644
index e2824bd4cba..00000000000
--- a/chromium/content/renderer/android/disambiguation_popup_helper.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_ANDROID_DISAMBIGUATION_POPUP_HELPER_H_
-#define CONTENT_RENDERER_ANDROID_DISAMBIGUATION_POPUP_HELPER_H_
-
-#include "content/common/content_export.h"
-#include "third_party/blink/public/platform/web_vector.h"
-
-namespace gfx {
-class Rect;
-class Size;
-}
-
-namespace blink {
-struct WebRect;
-}
-
-namespace content {
-
-// Contains functions to calculate proper scaling factor and popup size
-class DisambiguationPopupHelper {
- public:
- CONTENT_EXPORT static float ComputeZoomAreaAndScaleFactor(
- const gfx::Rect& tap_rect,
- const blink::WebVector<blink::WebRect>& target_rects,
- const gfx::Size& screen_size,
- const gfx::Size& visible_content_size,
- float total_scale,
- gfx::Rect* zoom_rect);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_ANDROID_DISAMBIGUATION_POPUP_HELPER_H_
diff --git a/chromium/content/renderer/android/disambiguation_popup_helper_unittest.cc b/chromium/content/renderer/android/disambiguation_popup_helper_unittest.cc
deleted file mode 100644
index 679a8e26543..00000000000
--- a/chromium/content/renderer/android/disambiguation_popup_helper_unittest.cc
+++ /dev/null
@@ -1,90 +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/android/disambiguation_popup_helper.h"
-
-#include <stddef.h>
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/web_rect.h"
-#include "third_party/blink/public/platform/web_vector.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/geometry/size.h"
-#include "ui/gfx/geometry/size_conversions.h"
-
-// these constants are copied from the implementation class
-namespace {
-const float kDisambiguationPopupMaxScale = 5.0;
-const float kDisambiguationPopupMinScale = 2.0;
-} // unnamed namespace
-
-namespace content {
-
-class DisambiguationPopupHelperUnittest : public testing::Test {
- public:
- DisambiguationPopupHelperUnittest()
- : kScreenSize_(640, 480)
- , kVisibleContentSize_(640, 480)
- , kImplScale_(1) { }
- protected:
- const gfx::Size kScreenSize_;
- const gfx::Size kVisibleContentSize_;
- const float kImplScale_;
-};
-
-TEST_F(DisambiguationPopupHelperUnittest, ClipByViewport) {
- gfx::Rect tap_rect(1000, 1000, 10, 10);
- blink::WebVector<blink::WebRect> target_rects(static_cast<size_t>(1));
- target_rects[0] = gfx::Rect(-20, -20, 10, 10);
-
- gfx::Rect zoom_rect;
- float scale = DisambiguationPopupHelper::ComputeZoomAreaAndScaleFactor(
- tap_rect, target_rects, kScreenSize_, kVisibleContentSize_, kImplScale_,
- &zoom_rect);
-
- EXPECT_TRUE(gfx::Rect(kVisibleContentSize_).Contains(zoom_rect));
- EXPECT_LE(kDisambiguationPopupMinScale, scale);
-
- gfx::Size scaled_size = gfx::ScaleToCeiledSize(zoom_rect.size(), scale);
- EXPECT_TRUE(gfx::Rect(kScreenSize_).Contains(gfx::Rect(scaled_size)));
-}
-
-TEST_F(DisambiguationPopupHelperUnittest, MiniTarget) {
- gfx::Rect tap_rect(-5, -5, 20, 20);
- blink::WebVector<blink::WebRect> target_rects(static_cast<size_t>(1));
- target_rects[0] = gfx::Rect(10, 10, 1, 1);
-
- gfx::Rect zoom_rect;
- float scale = DisambiguationPopupHelper::ComputeZoomAreaAndScaleFactor(
- tap_rect, target_rects, kScreenSize_, kVisibleContentSize_, kImplScale_,
- &zoom_rect);
-
- EXPECT_TRUE(gfx::Rect(kVisibleContentSize_).Contains(zoom_rect));
- EXPECT_EQ(kDisambiguationPopupMaxScale, scale);
- EXPECT_TRUE(zoom_rect.Contains(target_rects[0]));
-
- gfx::Size scaled_size = gfx::ScaleToCeiledSize(zoom_rect.size(), scale);
- EXPECT_TRUE(gfx::Rect(kScreenSize_).Contains(gfx::Rect(scaled_size)));
-}
-
-TEST_F(DisambiguationPopupHelperUnittest, LongLinks) {
- gfx::Rect tap_rect(10, 10, 20, 20);
- blink::WebVector<blink::WebRect> target_rects(static_cast<size_t>(2));
- target_rects[0] = gfx::Rect(15, 15, 1000, 5);
- target_rects[1] = gfx::Rect(15, 25, 1000, 5);
-
- gfx::Rect zoom_rect;
- float scale = DisambiguationPopupHelper::ComputeZoomAreaAndScaleFactor(
- tap_rect, target_rects, kScreenSize_, kVisibleContentSize_, kImplScale_,
- &zoom_rect);
-
- EXPECT_TRUE(gfx::Rect(kVisibleContentSize_).Contains(zoom_rect));
- EXPECT_EQ(kDisambiguationPopupMaxScale, scale);
- EXPECT_TRUE(zoom_rect.Contains(tap_rect));
-
- gfx::Size scaled_size = gfx::ScaleToCeiledSize(zoom_rect.size(), scale);
- EXPECT_TRUE(gfx::Rect(kScreenSize_).Contains(gfx::Rect(scaled_size)));
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/android/synchronous_compositor_proxy.h b/chromium/content/renderer/android/synchronous_compositor_proxy.h
index 8319840a6d4..9615426f888 100644
--- a/chromium/content/renderer/android/synchronous_compositor_proxy.h
+++ b/chromium/content/renderer/android/synchronous_compositor_proxy.h
@@ -130,6 +130,8 @@ class SynchronousCompositorProxy : public ui::SynchronousInputHandler,
// To browser.
uint32_t version_ = 0;
+ // |total_scroll_offset_| and |max_scroll_offset_| are in physical pixel when
+ // use-zoom-for-dsf is enabled, otherwise in dip.
gfx::ScrollOffset total_scroll_offset_; // Modified by both.
gfx::ScrollOffset max_scroll_offset_;
gfx::SizeF scrollable_size_;
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 24c569eea65..558e0ff4fd3 100644
--- a/chromium/content/renderer/android/synchronous_layer_tree_frame_sink.cc
+++ b/chromium/content/renderer/android/synchronous_layer_tree_frame_sink.cc
@@ -313,8 +313,10 @@ void SynchronousLayerTreeFrameSink::SubmitCompositorFrame(
SkBlendMode::kSrcOver, 0 /* sorting_context_id */);
surface_quad->SetNew(
shared_quad_state, gfx::Rect(child_size), gfx::Rect(child_size),
- viz::SurfaceId(kChildFrameSinkId, child_local_surface_id_),
- base::nullopt, SK_ColorWHITE, false);
+ viz::SurfaceRange(
+ base::nullopt,
+ viz::SurfaceId(kChildFrameSinkId, child_local_surface_id_)),
+ SK_ColorWHITE, false);
child_support_->SubmitCompositorFrame(child_local_surface_id_,
std::move(frame));
diff --git a/chromium/content/renderer/appcache/OWNERS b/chromium/content/renderer/appcache/OWNERS
index db1043cbffe..ad46687e8ae 100644
--- a/chromium/content/renderer/appcache/OWNERS
+++ b/chromium/content/renderer/appcache/OWNERS
@@ -1,5 +1,4 @@
-pwnall@chromium.org
-jsbell@chromium.org
+file://content/browser/appcache/OWNERS
# TEAM: storage-dev@chromium.org
# COMPONENT: Blink>Storage>AppCache
diff --git a/chromium/content/renderer/blob_storage/OWNERS b/chromium/content/renderer/blob_storage/OWNERS
index d04a7d57277..2c35e9492cd 100644
--- a/chromium/content/renderer/blob_storage/OWNERS
+++ b/chromium/content/renderer/blob_storage/OWNERS
@@ -1,4 +1,4 @@
-dmurph@chromium.org
+file://content/browser/blob_storage/OWNERS
# TEAM: storage-dev@chromium.org
# COMPONENT: Blink>Storage>FileAPI
diff --git a/chromium/content/renderer/browser_plugin/browser_plugin.cc b/chromium/content/renderer/browser_plugin/browser_plugin.cc
index 4d8251069ae..95a4d2f30c4 100644
--- a/chromium/content/renderer/browser_plugin/browser_plugin.cc
+++ b/chromium/content/renderer/browser_plugin/browser_plugin.cc
@@ -72,7 +72,7 @@ static base::LazyInstance<PluginContainerMap>::DestructorAtExit
namespace content {
// static
-BrowserPlugin* BrowserPlugin::GetFromNode(blink::WebNode& node) {
+BrowserPlugin* BrowserPlugin::GetFromNode(const blink::WebNode& node) {
blink::WebPluginContainer* container = node.PluginContainer();
if (!container)
return nullptr;
@@ -145,7 +145,7 @@ bool BrowserPlugin::OnMessageReceived(const IPC::Message& message) {
void BrowserPlugin::OnFirstSurfaceActivation(
int browser_plugin_instance_id,
const viz::SurfaceInfo& surface_info) {
- if (!attached() || !features::IsAshInBrowserProcess())
+ if (!attached() || features::IsUsingWindowService())
return;
if (!enable_surface_synchronization_) {
@@ -320,7 +320,7 @@ void BrowserPlugin::SynchronizeVisualProperties() {
sent_visual_properties_ = pending_visual_properties_;
#if defined(USE_AURA)
- if (!features::IsAshInBrowserProcess() && mus_embedded_frame_) {
+ if (features::IsUsingWindowService() && mus_embedded_frame_) {
mus_embedded_frame_->SetWindowBounds(GetLocalSurfaceId(),
FrameRectInPixels());
}
@@ -414,7 +414,7 @@ void BrowserPlugin::OnSetMouseLock(int browser_plugin_instance_id,
void BrowserPlugin::OnSetMusEmbedToken(
int instance_id,
const base::UnguessableToken& embed_token) {
- DCHECK(!features::IsAshInBrowserProcess());
+ DCHECK(features::IsUsingWindowService());
if (!attached_) {
pending_embed_token_ = embed_token;
} else {
@@ -861,7 +861,7 @@ void BrowserPlugin::OnMusEmbeddedFrameSurfaceChanged(
void BrowserPlugin::OnMusEmbeddedFrameSinkIdAllocated(
const viz::FrameSinkId& frame_sink_id) {
// RendererWindowTreeClient should only call this when mus is hosting viz.
- DCHECK(!features::IsAshInBrowserProcess());
+ DCHECK(features::IsUsingWindowService());
OnGuestReady(browser_plugin_instance_id_, frame_sink_id);
}
#endif
diff --git a/chromium/content/renderer/browser_plugin/browser_plugin.h b/chromium/content/renderer/browser_plugin/browser_plugin.h
index b3091678c58..9ef2eb19f8a 100644
--- a/chromium/content/renderer/browser_plugin/browser_plugin.h
+++ b/chromium/content/renderer/browser_plugin/browser_plugin.h
@@ -60,7 +60,7 @@ class CONTENT_EXPORT BrowserPlugin : public blink::WebPlugin,
public ChildFrameCompositor,
public MouseLockDispatcher::LockTarget {
public:
- static BrowserPlugin* GetFromNode(blink::WebNode& node);
+ static BrowserPlugin* GetFromNode(const blink::WebNode& node);
int render_frame_routing_id() const { return render_frame_routing_id_; }
int browser_plugin_instance_id() const { return browser_plugin_instance_id_; }
@@ -99,6 +99,8 @@ class CONTENT_EXPORT BrowserPlugin : public blink::WebPlugin,
// Returns the last allocated LocalSurfaceId.
const viz::LocalSurfaceId& GetLocalSurfaceId() const;
+ const viz::FrameSinkId& frame_sink_id() const { return frame_sink_id_; }
+
void SynchronizeVisualProperties();
// Returns whether a message should be forwarded to BrowserPlugin.
diff --git a/chromium/content/renderer/dom_serializer_browsertest.cc b/chromium/content/renderer/dom_serializer_browsertest.cc
index 2b188608b53..8dfad4b4b2f 100644
--- a/chromium/content/renderer/dom_serializer_browsertest.cc
+++ b/chromium/content/renderer/dom_serializer_browsertest.cc
@@ -142,7 +142,7 @@ class MAYBE_DomSerializerTests : public ContentBrowserTest,
data, "text/html", encoding_info, base_url, WebURL(),
false /* replace */, blink::WebFrameLoadType::kStandard,
blink::WebHistoryItem(), false /* is_client_redirect */,
- nullptr /* navigation_data */, blink::WebNavigationTimings());
+ nullptr /* navigation_params */, nullptr /* navigation_data */);
}
base::MessageLoopCurrent::ScopedNestableTaskAllower allow;
waiter.Wait();
@@ -677,7 +677,7 @@ IN_PROC_BROWSER_TEST_F(MAYBE_DomSerializerTests,
std::string original_contents;
{
// Read original contents for later comparison.
- base::ThreadRestrictions::ScopedAllowIO allow_io_for_test_verifications;
+ base::ScopedAllowBlockingForTesting allow_blocking;
ASSERT_TRUE(base::ReadFileToString(xml_file_path, &original_contents));
}
@@ -703,7 +703,7 @@ IN_PROC_BROWSER_TEST_F(MAYBE_DomSerializerTests,
std::string original_contents;
{
// Read original contents for later comparison .
- base::ThreadRestrictions::ScopedAllowIO allow_io_for_test_verifications;
+ base::ScopedAllowBlockingForTesting allow_blocking;
ASSERT_TRUE(base::ReadFileToString(page_file_path, &original_contents));
}
diff --git a/chromium/content/renderer/dom_storage/OWNERS b/chromium/content/renderer/dom_storage/OWNERS
index c41905dac40..aeb1ffd2213 100644
--- a/chromium/content/renderer/dom_storage/OWNERS
+++ b/chromium/content/renderer/dom_storage/OWNERS
@@ -1,5 +1,4 @@
-mek@chromium.org
-dmurph@chromium.org
+file://content/browser/dom_storage/OWNERS
# TEAM: storage-dev@chromium.org
# COMPONENT: Blink>Storage>DOMStorage
diff --git a/chromium/content/renderer/dom_storage/local_storage_cached_area.cc b/chromium/content/renderer/dom_storage/local_storage_cached_area.cc
index ffa21c9200d..c04e0e8bff1 100644
--- a/chromium/content/renderer/dom_storage/local_storage_cached_area.cc
+++ b/chromium/content/renderer/dom_storage/local_storage_cached_area.cc
@@ -22,6 +22,7 @@
#include "mojo/public/cpp/bindings/strong_associated_binding.h"
#include "third_party/blink/public/mojom/dom_storage/session_storage_namespace.mojom.h"
#include "third_party/blink/public/mojom/dom_storage/storage_partition_service.mojom.h"
+#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
#include "third_party/blink/public/platform/web_url.h"
#include "third_party/blink/public/web/web_storage_event_dispatcher.h"
diff --git a/chromium/content/renderer/dom_storage/local_storage_cached_areas.cc b/chromium/content/renderer/dom_storage/local_storage_cached_areas.cc
index 7c2327ac3df..6ecf2ca4e75 100644
--- a/chromium/content/renderer/dom_storage/local_storage_cached_areas.cc
+++ b/chromium/content/renderer/dom_storage/local_storage_cached_areas.cc
@@ -181,7 +181,7 @@ size_t LocalStorageCachedAreas::DOMStorageNamespace::TotalCacheSize() const {
bool LocalStorageCachedAreas::DOMStorageNamespace::CleanUpUnusedAreas() {
CheckPrefixes();
base::EraseIf(cached_areas,
- [](auto& pair) { return pair.second->HasOneRef(); });
+ [](const auto& pair) { return pair.second->HasOneRef(); });
return cached_areas.empty();
}
diff --git a/chromium/content/renderer/fileapi/OWNERS b/chromium/content/renderer/fileapi/OWNERS
index df298d5781b..6269c8b39df 100644
--- a/chromium/content/renderer/fileapi/OWNERS
+++ b/chromium/content/renderer/fileapi/OWNERS
@@ -1,8 +1,4 @@
-jsbell@chromium.org
-pwnall@chromium.org
-jianli@chromium.org
-tzik@chromium.org
-nhiroki@chromium.org
+file://content/browser/fileapi/OWNERS
# TEAM: storage-dev@chromium.org
# COMPONENT: Blink>Storage>FileSystem
diff --git a/chromium/content/renderer/fileapi/file_system_dispatcher.cc b/chromium/content/renderer/fileapi/file_system_dispatcher.cc
index 77d8e5b82d7..2d5f84f7378 100644
--- a/chromium/content/renderer/fileapi/file_system_dispatcher.cc
+++ b/chromium/content/renderer/fileapi/file_system_dispatcher.cc
@@ -11,11 +11,15 @@
#include "base/files/file_util.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
+#include "base/no_destructor.h"
#include "base/process/process.h"
#include "components/services/filesystem/public/interfaces/types.mojom.h"
#include "content/child/child_thread_impl.h"
-#include "content/common/fileapi/file_system_messages.h"
+#include "content/public/common/service_names.mojom.h"
+#include "content/public/renderer/worker_thread.h"
+#include "services/service_manager/public/cpp/connector.h"
#include "storage/common/fileapi/file_system_info.h"
+#include "storage/common/fileapi/file_system_type_converters.h"
namespace content {
@@ -85,16 +89,17 @@ class FileSystemDispatcher::CallbackDispatcher {
error_callback_.Run(error_code);
}
- void DidReadMetadata(
- const base::File::Info& file_info) {
+ void DidReadMetadata(const base::File::Info& file_info) {
metadata_callback_.Run(file_info);
}
void DidCreateSnapshotFile(
const base::File::Info& file_info,
const base::FilePath& platform_path,
+ base::Optional<blink::mojom::ReceivedSnapshotListenerPtr> opt_listener,
int request_id) {
- snapshot_callback_.Run(file_info, platform_path, request_id);
+ snapshot_callback_.Run(file_info, platform_path, std::move(opt_listener),
+ request_id);
}
void DidReadDirectory(
@@ -103,8 +108,7 @@ class FileSystemDispatcher::CallbackDispatcher {
directory_callback_.Run(entries, has_more);
}
- void DidOpenFileSystem(const std::string& name,
- const GURL& root) {
+ void DidOpenFileSystem(const std::string& name, const GURL& root) {
filesystem_callback_.Run(name, root);
}
@@ -134,8 +138,28 @@ class FileSystemDispatcher::CallbackDispatcher {
DISALLOW_COPY_AND_ASSIGN(CallbackDispatcher);
};
-FileSystemDispatcher::FileSystemDispatcher() {
-}
+class FileSystemDispatcher::FileSystemOperationListenerImpl
+ : public blink::mojom::FileSystemOperationListener {
+ public:
+ FileSystemOperationListenerImpl(int request_id,
+ FileSystemDispatcher* dispatcher)
+ : request_id_(request_id), dispatcher_(dispatcher) {}
+
+ private:
+ // blink::mojom::FileSystemOperationListener
+ void ResultsRetrieved(
+ std::vector<filesystem::mojom::DirectoryEntryPtr> entries,
+ bool has_more) override;
+ void ErrorOccurred(base::File::Error error_code) override;
+ void DidWrite(int64_t byte_count, bool complete) override;
+
+ const int request_id_;
+ FileSystemDispatcher* const dispatcher_;
+};
+
+FileSystemDispatcher::FileSystemDispatcher(
+ scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner)
+ : main_thread_task_runner_(std::move(main_thread_task_runner)) {}
FileSystemDispatcher::~FileSystemDispatcher() {
// Make sure we fire all the remaining callbacks.
@@ -150,21 +174,25 @@ FileSystemDispatcher::~FileSystemDispatcher() {
}
}
-bool FileSystemDispatcher::OnMessageReceived(const IPC::Message& msg) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(FileSystemDispatcher, msg)
- IPC_MESSAGE_HANDLER(FileSystemMsg_DidOpenFileSystem, OnDidOpenFileSystem)
- IPC_MESSAGE_HANDLER(FileSystemMsg_DidResolveURL, OnDidResolveURL)
- IPC_MESSAGE_HANDLER(FileSystemMsg_DidSucceed, OnDidSucceed)
- IPC_MESSAGE_HANDLER(FileSystemMsg_DidReadDirectory, OnDidReadDirectory)
- IPC_MESSAGE_HANDLER(FileSystemMsg_DidReadMetadata, OnDidReadMetadata)
- IPC_MESSAGE_HANDLER(FileSystemMsg_DidCreateSnapshotFile,
- OnDidCreateSnapshotFile)
- IPC_MESSAGE_HANDLER(FileSystemMsg_DidFail, OnDidFail)
- IPC_MESSAGE_HANDLER(FileSystemMsg_DidWrite, OnDidWrite)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
+blink::mojom::FileSystemManager& FileSystemDispatcher::GetFileSystemManager() {
+ auto BindInterfaceOnMainThread =
+ [](blink::mojom::FileSystemManagerRequest request) {
+ DCHECK(ChildThreadImpl::current());
+ ChildThreadImpl::current()->GetConnector()->BindInterface(
+ mojom::kBrowserServiceName, std::move(request));
+ };
+ if (!file_system_manager_ptr_) {
+ if (WorkerThread::GetCurrentId()) {
+ blink::mojom::FileSystemManagerRequest request =
+ mojo::MakeRequest(&file_system_manager_ptr_);
+ main_thread_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(BindInterfaceOnMainThread, std::move(request)));
+ } else {
+ BindInterfaceOnMainThread(mojo::MakeRequest(&file_system_manager_ptr_));
+ }
+ }
+ return *file_system_manager_ptr_;
}
void FileSystemDispatcher::OpenFileSystem(
@@ -174,8 +202,26 @@ void FileSystemDispatcher::OpenFileSystem(
const StatusCallback& error_callback) {
int request_id = dispatchers_.Add(
CallbackDispatcher::Create(success_callback, error_callback));
- ChildThreadImpl::current()->Send(new FileSystemHostMsg_OpenFileSystem(
- request_id, origin_url, type));
+ GetFileSystemManager().Open(
+ origin_url, mojo::ConvertTo<blink::mojom::FileSystemType>(type),
+ base::BindOnce(&FileSystemDispatcher::DidOpenFileSystem,
+ base::Unretained(this), request_id));
+}
+
+void FileSystemDispatcher::OpenFileSystemSync(
+ const GURL& origin_url,
+ storage::FileSystemType type,
+ const OpenFileSystemCallback& success_callback,
+ const StatusCallback& error_callback) {
+ int request_id = dispatchers_.Add(
+ CallbackDispatcher::Create(success_callback, error_callback));
+ std::string name;
+ GURL root_url;
+ base::File::Error error_code = base::File::FILE_ERROR_FAILED;
+ GetFileSystemManager().Open(
+ origin_url, mojo::ConvertTo<blink::mojom::FileSystemType>(type), &name,
+ &root_url, &error_code);
+ DidOpenFileSystem(request_id, std::move(name), root_url, error_code);
}
void FileSystemDispatcher::ResolveURL(
@@ -184,35 +230,82 @@ void FileSystemDispatcher::ResolveURL(
const StatusCallback& error_callback) {
int request_id = dispatchers_.Add(
CallbackDispatcher::Create(success_callback, error_callback));
- ChildThreadImpl::current()->Send(new FileSystemHostMsg_ResolveURL(
- request_id, filesystem_url));
+ GetFileSystemManager().ResolveURL(
+ filesystem_url, base::BindOnce(&FileSystemDispatcher::DidResolveURL,
+ base::Unretained(this), request_id));
}
-void FileSystemDispatcher::Move(
- const GURL& src_path,
- const GURL& dest_path,
- const StatusCallback& callback) {
+void FileSystemDispatcher::ResolveURLSync(
+ const GURL& filesystem_url,
+ const ResolveURLCallback& success_callback,
+ const StatusCallback& error_callback) {
+ int request_id = dispatchers_.Add(
+ CallbackDispatcher::Create(success_callback, error_callback));
+ blink::mojom::FileSystemInfoPtr info;
+ base::FilePath file_path;
+ bool is_directory;
+ base::File::Error error_code = base::File::FILE_ERROR_FAILED;
+ GetFileSystemManager().ResolveURL(filesystem_url, &info, &file_path,
+ &is_directory, &error_code);
+ DidResolveURL(request_id, std::move(info), std::move(file_path), is_directory,
+ error_code);
+}
+
+void FileSystemDispatcher::Move(const GURL& src_path,
+ const GURL& dest_path,
+ const StatusCallback& callback) {
int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
- ChildThreadImpl::current()->Send(new FileSystemHostMsg_Move(
- request_id, src_path, dest_path));
+ GetFileSystemManager().Move(
+ src_path, dest_path,
+ base::BindOnce(&FileSystemDispatcher::DidFinish, base::Unretained(this),
+ request_id));
}
-void FileSystemDispatcher::Copy(
- const GURL& src_path,
- const GURL& dest_path,
- const StatusCallback& callback) {
+void FileSystemDispatcher::MoveSync(const GURL& src_path,
+ const GURL& dest_path,
+ const StatusCallback& callback) {
int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
- ChildThreadImpl::current()->Send(new FileSystemHostMsg_Copy(
- request_id, src_path, dest_path));
+ base::File::Error error_code = base::File::FILE_ERROR_FAILED;
+ GetFileSystemManager().Move(src_path, dest_path, &error_code);
+ DidFinish(request_id, error_code);
}
-void FileSystemDispatcher::Remove(
- const GURL& path,
- bool recursive,
- const StatusCallback& callback) {
+void FileSystemDispatcher::Copy(const GURL& src_path,
+ const GURL& dest_path,
+ const StatusCallback& callback) {
+ int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
+ GetFileSystemManager().Copy(
+ src_path, dest_path,
+ base::BindOnce(&FileSystemDispatcher::DidFinish, base::Unretained(this),
+ request_id));
+}
+
+void FileSystemDispatcher::CopySync(const GURL& src_path,
+ const GURL& dest_path,
+ const StatusCallback& callback) {
+ int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
+ base::File::Error error_code = base::File::FILE_ERROR_FAILED;
+ GetFileSystemManager().Copy(src_path, dest_path, &error_code);
+ DidFinish(request_id, error_code);
+}
+
+void FileSystemDispatcher::Remove(const GURL& path,
+ bool recursive,
+ const StatusCallback& callback) {
int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
- ChildThreadImpl::current()->Send(
- new FileSystemHostMsg_Remove(request_id, path, recursive));
+ GetFileSystemManager().Remove(
+ path, recursive,
+ base::BindOnce(&FileSystemDispatcher::DidFinish, base::Unretained(this),
+ request_id));
+}
+
+void FileSystemDispatcher::RemoveSync(const GURL& path,
+ bool recursive,
+ const StatusCallback& callback) {
+ int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
+ base::File::Error error_code = base::File::FILE_ERROR_FAILED;
+ GetFileSystemManager().Remove(path, recursive, &error_code);
+ DidFinish(request_id, error_code);
}
void FileSystemDispatcher::ReadMetadata(
@@ -221,37 +314,81 @@ void FileSystemDispatcher::ReadMetadata(
const StatusCallback& error_callback) {
int request_id = dispatchers_.Add(
CallbackDispatcher::Create(success_callback, error_callback));
- ChildThreadImpl::current()->Send(
- new FileSystemHostMsg_ReadMetadata(request_id, path));
+ GetFileSystemManager().ReadMetadata(
+ path, base::BindOnce(&FileSystemDispatcher::DidReadMetadata,
+ base::Unretained(this), request_id));
}
-void FileSystemDispatcher::CreateFile(
+void FileSystemDispatcher::ReadMetadataSync(
const GURL& path,
- bool exclusive,
- const StatusCallback& callback) {
+ const MetadataCallback& success_callback,
+ const StatusCallback& error_callback) {
+ int request_id = dispatchers_.Add(
+ CallbackDispatcher::Create(success_callback, error_callback));
+ base::File::Info file_info;
+ base::File::Error error_code = base::File::FILE_ERROR_FAILED;
+ GetFileSystemManager().ReadMetadata(path, &file_info, &error_code);
+ DidReadMetadata(request_id, std::move(file_info), error_code);
+}
+
+void FileSystemDispatcher::CreateFile(const GURL& path,
+ bool exclusive,
+ const StatusCallback& callback) {
int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
- ChildThreadImpl::current()->Send(new FileSystemHostMsg_Create(
- request_id, path, exclusive,
- false /* is_directory */, false /* recursive */));
+ GetFileSystemManager().Create(
+ path, exclusive, /*is_directory=*/false, /*is_recursive=*/false,
+ base::BindOnce(&FileSystemDispatcher::DidFinish, base::Unretained(this),
+ request_id));
}
-void FileSystemDispatcher::CreateDirectory(
- const GURL& path,
- bool exclusive,
- bool recursive,
- const StatusCallback& callback) {
+void FileSystemDispatcher::CreateFileSync(const GURL& path,
+ bool exclusive,
+ const StatusCallback& callback) {
int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
- ChildThreadImpl::current()->Send(new FileSystemHostMsg_Create(
- request_id, path, exclusive, true /* is_directory */, recursive));
+ base::File::Error error_code = base::File::FILE_ERROR_FAILED;
+ GetFileSystemManager().Create(path, exclusive, /*is_directory=*/false,
+ /*is_recursive=*/false, &error_code);
+ DidFinish(request_id, error_code);
}
-void FileSystemDispatcher::Exists(
- const GURL& path,
- bool is_directory,
- const StatusCallback& callback) {
+void FileSystemDispatcher::CreateDirectory(const GURL& path,
+ bool exclusive,
+ bool recursive,
+ const StatusCallback& callback) {
+ int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
+ GetFileSystemManager().Create(
+ path, exclusive, true, recursive,
+ base::BindOnce(&FileSystemDispatcher::DidFinish, base::Unretained(this),
+ request_id));
+}
+
+void FileSystemDispatcher::CreateDirectorySync(const GURL& path,
+ bool exclusive,
+ bool recursive,
+ const StatusCallback& callback) {
int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
- ChildThreadImpl::current()->Send(
- new FileSystemHostMsg_Exists(request_id, path, is_directory));
+ base::File::Error error_code = base::File::FILE_ERROR_FAILED;
+ GetFileSystemManager().Create(path, exclusive, true, recursive, &error_code);
+ DidFinish(request_id, error_code);
+}
+
+void FileSystemDispatcher::Exists(const GURL& path,
+ bool is_directory,
+ const StatusCallback& callback) {
+ int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
+ GetFileSystemManager().Exists(
+ path, is_directory,
+ base::BindOnce(&FileSystemDispatcher::DidFinish, base::Unretained(this),
+ request_id));
+}
+
+void FileSystemDispatcher::ExistsSync(const GURL& path,
+ bool is_directory,
+ const StatusCallback& callback) {
+ int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
+ base::File::Error error_code = base::File::FILE_ERROR_FAILED;
+ GetFileSystemManager().Exists(path, is_directory, &error_code);
+ DidFinish(request_id, error_code);
}
void FileSystemDispatcher::ReadDirectory(
@@ -260,8 +397,28 @@ void FileSystemDispatcher::ReadDirectory(
const StatusCallback& error_callback) {
int request_id = dispatchers_.Add(
CallbackDispatcher::Create(success_callback, error_callback));
- ChildThreadImpl::current()->Send(
- new FileSystemHostMsg_ReadDirectory(request_id, path));
+ blink::mojom::FileSystemOperationListenerPtr ptr;
+ blink::mojom::FileSystemOperationListenerRequest request =
+ mojo::MakeRequest(&ptr);
+ op_listeners_.AddBinding(
+ std::make_unique<FileSystemOperationListenerImpl>(request_id, this),
+ std::move(request));
+ GetFileSystemManager().ReadDirectory(path, std::move(ptr));
+}
+
+void FileSystemDispatcher::ReadDirectorySync(
+ const GURL& path,
+ const ReadDirectoryCallback& success_callback,
+ const StatusCallback& error_callback) {
+ int request_id = dispatchers_.Add(
+ CallbackDispatcher::Create(success_callback, error_callback));
+ std::vector<filesystem::mojom::DirectoryEntryPtr> entries;
+ base::File::Error result = base::File::FILE_ERROR_FAILED;
+ GetFileSystemManager().ReadDirectorySync(path, &entries, &result);
+ if (result == base::File::FILE_OK)
+ DidReadDirectory(request_id, std::move(entries), /*has_more=*/false);
+ else
+ DidFail(request_id, result);
}
void FileSystemDispatcher::Truncate(const GURL& path,
@@ -269,13 +426,30 @@ void FileSystemDispatcher::Truncate(const GURL& path,
int* request_id_out,
const StatusCallback& callback) {
int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
- ChildThreadImpl::current()->Send(
- new FileSystemHostMsg_Truncate(request_id, path, offset));
+ blink::mojom::FileSystemCancellableOperationPtr op_ptr;
+ blink::mojom::FileSystemCancellableOperationRequest op_request =
+ mojo::MakeRequest(&op_ptr);
+ op_ptr.set_connection_error_handler(
+ base::BindOnce(&FileSystemDispatcher::RemoveOperationPtr,
+ base::Unretained(this), request_id));
+ cancellable_operations_[request_id] = std::move(op_ptr);
+ GetFileSystemManager().Truncate(
+ path, offset, std::move(op_request),
+ base::BindOnce(&FileSystemDispatcher::DidTruncate, base::Unretained(this),
+ request_id));
if (request_id_out)
*request_id_out = request_id;
}
+void FileSystemDispatcher::TruncateSync(const GURL& path,
+ int64_t offset,
+ const StatusCallback& callback) {
+ base::File::Error error_code = base::File::FILE_ERROR_FAILED;
+ GetFileSystemManager().TruncateSync(path, offset, &error_code);
+ std::move(callback).Run(error_code);
+}
+
void FileSystemDispatcher::Write(const GURL& path,
const std::string& blob_id,
int64_t offset,
@@ -284,30 +458,66 @@ void FileSystemDispatcher::Write(const GURL& path,
const StatusCallback& error_callback) {
int request_id = dispatchers_.Add(
CallbackDispatcher::Create(success_callback, error_callback));
- ChildThreadImpl::current()->Send(
- new FileSystemHostMsg_Write(request_id, path, blob_id, offset));
+
+ blink::mojom::FileSystemCancellableOperationPtr op_ptr;
+ blink::mojom::FileSystemCancellableOperationRequest op_request =
+ mojo::MakeRequest(&op_ptr);
+ op_ptr.set_connection_error_handler(
+ base::BindOnce(&FileSystemDispatcher::RemoveOperationPtr,
+ base::Unretained(this), request_id));
+ cancellable_operations_[request_id] = std::move(op_ptr);
+
+ blink::mojom::FileSystemOperationListenerPtr listener_ptr;
+ blink::mojom::FileSystemOperationListenerRequest request =
+ mojo::MakeRequest(&listener_ptr);
+ op_listeners_.AddBinding(
+ std::make_unique<FileSystemOperationListenerImpl>(request_id, this),
+ std::move(request));
+
+ GetFileSystemManager().Write(path, blob_id, offset, std::move(op_request),
+ std::move(listener_ptr));
if (request_id_out)
*request_id_out = request_id;
}
-void FileSystemDispatcher::Cancel(
- int request_id_to_cancel,
- const StatusCallback& callback) {
+void FileSystemDispatcher::WriteSync(const GURL& path,
+ const std::string& blob_id,
+ int64_t offset,
+ const WriteCallback& success_callback,
+ const StatusCallback& error_callback) {
+ int64_t byte_count;
+ base::File::Error error_code = base::File::FILE_ERROR_FAILED;
+ GetFileSystemManager().WriteSync(path, blob_id, offset, &byte_count,
+ &error_code);
+ if (error_code == base::File::FILE_OK)
+ std::move(success_callback).Run(byte_count, /*complete=*/true);
+ else
+ std::move(error_callback).Run(error_code);
+}
+
+void FileSystemDispatcher::Cancel(int request_id_to_cancel,
+ const StatusCallback& callback) {
int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
- ChildThreadImpl::current()->Send(new FileSystemHostMsg_CancelWrite(
- request_id, request_id_to_cancel));
+ if (cancellable_operations_.find(request_id_to_cancel) ==
+ cancellable_operations_.end()) {
+ DidFail(request_id, base::File::FILE_ERROR_INVALID_OPERATION);
+ return;
+ }
+ cancellable_operations_[request_id_to_cancel]->Cancel(
+ base::BindOnce(&FileSystemDispatcher::DidCancel, base::Unretained(this),
+ request_id, request_id_to_cancel));
}
-void FileSystemDispatcher::TouchFile(
- const GURL& path,
- const base::Time& last_access_time,
- const base::Time& last_modified_time,
- const StatusCallback& callback) {
+void FileSystemDispatcher::TouchFile(const GURL& path,
+ const base::Time& last_access_time,
+ const base::Time& last_modified_time,
+ const StatusCallback& callback) {
int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
- ChildThreadImpl::current()->Send(
- new FileSystemHostMsg_TouchFile(
- request_id, path, last_access_time, last_modified_time));
+ GetFileSystemManager().TouchFile(
+ path, last_access_time, last_modified_time,
+ base::BindOnce(&FileSystemDispatcher::DidFinish, base::Unretained(this),
+ request_id));
}
void FileSystemDispatcher::CreateSnapshotFile(
@@ -316,83 +526,214 @@ void FileSystemDispatcher::CreateSnapshotFile(
const StatusCallback& error_callback) {
int request_id = dispatchers_.Add(
CallbackDispatcher::Create(success_callback, error_callback));
- ChildThreadImpl::current()->Send(
- new FileSystemHostMsg_CreateSnapshotFile(
- request_id, file_path));
+ GetFileSystemManager().CreateSnapshotFile(
+ file_path, base::BindOnce(&FileSystemDispatcher::DidCreateSnapshotFile,
+ base::Unretained(this), request_id));
}
-void FileSystemDispatcher::OnDidOpenFileSystem(int request_id,
- const std::string& name,
- const GURL& root) {
- DCHECK(root.is_valid());
- CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
- DCHECK(dispatcher);
- dispatcher->DidOpenFileSystem(name, root);
- dispatchers_.Remove(request_id);
+void FileSystemDispatcher::CreateSnapshotFileSync(
+ const GURL& file_path,
+ const CreateSnapshotFileCallback& success_callback,
+ const StatusCallback& error_callback) {
+ int request_id = dispatchers_.Add(
+ CallbackDispatcher::Create(success_callback, error_callback));
+ base::File::Info file_info;
+ base::FilePath platform_path;
+ base::File::Error error_code = base::File::FILE_ERROR_FAILED;
+ blink::mojom::ReceivedSnapshotListenerPtr listener;
+ GetFileSystemManager().CreateSnapshotFile(
+ file_path, &file_info, &platform_path, &error_code, &listener);
+ DidCreateSnapshotFile(request_id, std::move(file_info),
+ std::move(platform_path), error_code,
+ std::move(listener));
}
-void FileSystemDispatcher::OnDidResolveURL(int request_id,
- const storage::FileSystemInfo& info,
- const base::FilePath& file_path,
- bool is_directory) {
- DCHECK(info.root_url.is_valid());
- CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
- DCHECK(dispatcher);
- dispatcher->DidResolveURL(info, file_path, is_directory);
- dispatchers_.Remove(request_id);
+void FileSystemDispatcher::CreateFileWriter(
+ const GURL& file_path,
+ std::unique_ptr<CreateFileWriterCallbacks> callbacks) {
+ GetFileSystemManager().CreateWriter(
+ file_path,
+ base::BindOnce(
+ [](std::unique_ptr<CreateFileWriterCallbacks> callbacks,
+ base::File::Error result, blink::mojom::FileWriterPtr writer) {
+ if (result != base::File::FILE_OK) {
+ callbacks->OnError(result);
+ } else {
+ callbacks->OnSuccess(writer.PassInterface().PassHandle());
+ }
+ },
+ std::move(callbacks)));
}
-void FileSystemDispatcher::OnDidSucceed(int request_id) {
- CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
- DCHECK(dispatcher);
- dispatcher->DidSucceed();
- dispatchers_.Remove(request_id);
+void FileSystemDispatcher::ChooseEntry(
+ int render_frame_id,
+ std::unique_ptr<ChooseEntryCallbacks> callbacks) {
+ GetFileSystemManager().ChooseEntry(
+ render_frame_id,
+ base::BindOnce(
+ [](std::unique_ptr<ChooseEntryCallbacks> callbacks,
+ base::File::Error result,
+ std::vector<blink::mojom::FileSystemEntryPtr> entries) {
+ if (result != base::File::FILE_OK) {
+ callbacks->OnError(result);
+ } else {
+ blink::WebVector<blink::WebFileSystem::FileSystemEntry>
+ web_entries(entries.size());
+ for (size_t i = 0; i < entries.size(); ++i) {
+ web_entries[i].file_system_id =
+ blink::WebString::FromASCII(entries[i]->file_system_id);
+ web_entries[i].base_name =
+ blink::WebString::FromASCII(entries[i]->base_name);
+ }
+ callbacks->OnSuccess(std::move(web_entries));
+ }
+ },
+ std::move(callbacks)));
}
-void FileSystemDispatcher::OnDidReadMetadata(
- int request_id, const base::File::Info& file_info) {
- CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
- DCHECK(dispatcher);
- dispatcher->DidReadMetadata(file_info);
- dispatchers_.Remove(request_id);
+void FileSystemDispatcher::DidOpenFileSystem(int request_id,
+ const std::string& name,
+ const GURL& root,
+ base::File::Error error_code) {
+ if (error_code == base::File::Error::FILE_OK) {
+ CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
+ DCHECK(dispatcher);
+ dispatcher->DidOpenFileSystem(name, root);
+ dispatchers_.Remove(request_id);
+ } else {
+ DidFail(request_id, error_code);
+ }
}
-void FileSystemDispatcher::OnDidCreateSnapshotFile(
- int request_id, const base::File::Info& file_info,
- const base::FilePath& platform_path) {
- CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
- DCHECK(dispatcher);
- dispatcher->DidCreateSnapshotFile(file_info, platform_path, request_id);
- dispatchers_.Remove(request_id);
+void FileSystemDispatcher::DidResolveURL(int request_id,
+ blink::mojom::FileSystemInfoPtr info,
+ const base::FilePath& file_path,
+ bool is_directory,
+ base::File::Error error_code) {
+ if (error_code == base::File::Error::FILE_OK) {
+ DCHECK(info->root_url.is_valid());
+ CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
+ DCHECK(dispatcher);
+ dispatcher->DidResolveURL(mojo::ConvertTo<storage::FileSystemInfo>(info),
+ file_path, is_directory);
+ dispatchers_.Remove(request_id);
+ } else {
+ DidFail(request_id, error_code);
+ }
+}
+
+void FileSystemDispatcher::DidFinish(int request_id,
+ base::File::Error error_code) {
+ if (error_code == base::File::Error::FILE_OK) {
+ CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
+ DCHECK(dispatcher);
+ dispatcher->DidSucceed();
+ dispatchers_.Remove(request_id);
+ } else {
+ DidFail(request_id, error_code);
+ }
+}
+
+void FileSystemDispatcher::DidReadMetadata(int request_id,
+ const base::File::Info& file_info,
+ base::File::Error error_code) {
+ if (error_code == base::File::FILE_OK) {
+ CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
+ DCHECK(dispatcher);
+ dispatcher->DidReadMetadata(file_info);
+ dispatchers_.Remove(request_id);
+ } else {
+ DidFail(request_id, error_code);
+ }
+}
+
+void FileSystemDispatcher::DidCreateSnapshotFile(
+ int request_id,
+ const base::File::Info& file_info,
+ const base::FilePath& platform_path,
+ base::File::Error error_code,
+ blink::mojom::ReceivedSnapshotListenerPtr listener) {
+ base::Optional<blink::mojom::ReceivedSnapshotListenerPtr> opt_listener;
+ if (listener)
+ opt_listener = std::move(listener);
+ if (error_code == base::File::FILE_OK) {
+ CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
+ DCHECK(dispatcher);
+ dispatcher->DidCreateSnapshotFile(file_info, platform_path,
+ std::move(opt_listener), request_id);
+ dispatchers_.Remove(request_id);
+ } else {
+ DidFail(request_id, error_code);
+ }
}
-void FileSystemDispatcher::OnDidReadDirectory(
+void FileSystemDispatcher::DidReadDirectory(
int request_id,
- const std::vector<filesystem::mojom::DirectoryEntry>& entries,
+ std::vector<filesystem::mojom::DirectoryEntryPtr> entries,
bool has_more) {
CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
DCHECK(dispatcher);
- dispatcher->DidReadDirectory(entries, has_more);
+ std::vector<filesystem::mojom::DirectoryEntry> entries_copy;
+ for (const auto& entry : entries) {
+ entries_copy.push_back(*entry);
+ }
+ dispatcher->DidReadDirectory(std::move(entries_copy), has_more);
if (!has_more)
dispatchers_.Remove(request_id);
}
-void FileSystemDispatcher::OnDidFail(
- int request_id, base::File::Error error_code) {
+void FileSystemDispatcher::DidFail(int request_id,
+ base::File::Error error_code) {
CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
DCHECK(dispatcher);
dispatcher->DidFail(error_code);
dispatchers_.Remove(request_id);
}
-void FileSystemDispatcher::OnDidWrite(int request_id,
- int64_t bytes,
- bool complete) {
+void FileSystemDispatcher::DidWrite(int request_id,
+ int64_t bytes,
+ bool complete) {
CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
DCHECK(dispatcher);
dispatcher->DidWrite(bytes, complete);
- if (complete)
+ if (complete) {
dispatchers_.Remove(request_id);
+ RemoveOperationPtr(request_id);
+ }
+}
+
+void FileSystemDispatcher::DidTruncate(int request_id,
+ base::File::Error error_code) {
+ // If |error_code| is ABORT, it means the operation was cancelled,
+ // so we let DidCancel clean up the interface pointer.
+ if (error_code != base::File::FILE_ERROR_ABORT)
+ RemoveOperationPtr(request_id);
+ DidFinish(request_id, error_code);
+}
+
+void FileSystemDispatcher::DidCancel(int request_id,
+ int cancelled_request_id,
+ base::File::Error error_code) {
+ if (error_code == base::File::FILE_OK)
+ RemoveOperationPtr(cancelled_request_id);
+ DidFinish(request_id, error_code);
+}
+
+void FileSystemDispatcher::FileSystemOperationListenerImpl::ResultsRetrieved(
+ std::vector<filesystem::mojom::DirectoryEntryPtr> entries,
+ bool has_more) {
+ dispatcher_->DidReadDirectory(request_id_, std::move(entries), has_more);
+}
+
+void FileSystemDispatcher::FileSystemOperationListenerImpl::ErrorOccurred(
+ base::File::Error error_code) {
+ dispatcher_->DidFail(request_id_, error_code);
+}
+
+void FileSystemDispatcher::FileSystemOperationListenerImpl::DidWrite(
+ int64_t byte_count,
+ bool complete) {
+ dispatcher_->DidWrite(request_id_, byte_count, complete);
}
} // namespace content
diff --git a/chromium/content/renderer/fileapi/file_system_dispatcher.h b/chromium/content/renderer/fileapi/file_system_dispatcher.h
index 676e471113c..ff90f64008d 100644
--- a/chromium/content/renderer/fileapi/file_system_dispatcher.h
+++ b/chromium/content/renderer/fileapi/file_system_dispatcher.h
@@ -18,8 +18,13 @@
#include "components/services/filesystem/public/interfaces/types.mojom.h"
#include "ipc/ipc_listener.h"
#include "ipc/ipc_platform_file.h"
+#include "mojo/public/cpp/bindings/strong_binding_set.h"
#include "storage/common/fileapi/file_system_types.h"
#include "storage/common/quota/quota_limit_type.h"
+#include "third_party/blink/public/mojom/filesystem/file_system.mojom.h"
+#include "third_party/blink/public/platform/web_callbacks.h"
+#include "third_party/blink/public/platform/web_file_system.h"
+#include "third_party/blink/public/platform/web_url.h"
namespace base {
class FilePath;
@@ -32,18 +37,21 @@ struct FileSystemInfo;
class GURL;
namespace content {
+class FileSystemOperationListenerImpl;
// Dispatches and sends file system related messages sent to/from a child
-// process from/to the main browser process. There is one instance
-// per child process. Messages are dispatched on the main child thread.
-class FileSystemDispatcher : public IPC::Listener {
+// process from/to the main browser process. There is an instance held by
+// each WebFileSystemImpl and WebFileWriterImpl object.
+class FileSystemDispatcher {
public:
typedef base::Callback<void(base::File::Error error)> StatusCallback;
typedef base::Callback<void(const base::File::Info& file_info)>
MetadataCallback;
- typedef base::Callback<void(const base::File::Info& file_info,
- const base::FilePath& platform_path,
- int request_id)>
+ typedef base::Callback<void(
+ const base::File::Info& file_info,
+ const base::FilePath& platform_path,
+ base::Optional<blink::mojom::ReceivedSnapshotListenerPtr> opt_listener,
+ int request_id)>
CreateSnapshotFileCallback;
typedef base::Callback<void(
@@ -63,91 +71,180 @@ class FileSystemDispatcher : public IPC::Listener {
storage::QuotaLimitType quota_policy)>
OpenFileCallback;
- FileSystemDispatcher();
- ~FileSystemDispatcher() override;
-
- // IPC::Listener implementation.
- bool OnMessageReceived(const IPC::Message& msg) override;
+ explicit FileSystemDispatcher(
+ scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner);
+ ~FileSystemDispatcher();
void OpenFileSystem(const GURL& origin_url,
storage::FileSystemType type,
const OpenFileSystemCallback& success_callback,
const StatusCallback& error_callback);
+ void OpenFileSystemSync(const GURL& origin_url,
+ storage::FileSystemType type,
+ const OpenFileSystemCallback& success_callback,
+ const StatusCallback& error_callback);
+
void ResolveURL(const GURL& filesystem_url,
const ResolveURLCallback& success_callback,
const StatusCallback& error_callback);
+ void ResolveURLSync(const GURL& filesystem_url,
+ const ResolveURLCallback& success_callback,
+ const StatusCallback& error_callback);
+
void Move(const GURL& src_path,
const GURL& dest_path,
const StatusCallback& callback);
+ void MoveSync(const GURL& src_path,
+ const GURL& dest_path,
+ const StatusCallback& callback);
+
void Copy(const GURL& src_path,
const GURL& dest_path,
const StatusCallback& callback);
+ void CopySync(const GURL& src_path,
+ const GURL& dest_path,
+ const StatusCallback& callback);
+
void Remove(const GURL& path, bool recursive, const StatusCallback& callback);
+ void RemoveSync(const GURL& path,
+ bool recursive,
+ const StatusCallback& callback);
+
void ReadMetadata(const GURL& path,
const MetadataCallback& success_callback,
const StatusCallback& error_callback);
+ void ReadMetadataSync(const GURL& path,
+ const MetadataCallback& success_callback,
+ const StatusCallback& error_callback);
+
void CreateFile(const GURL& path,
bool exclusive,
const StatusCallback& callback);
+ void CreateFileSync(const GURL& path,
+ bool exclusive,
+ const StatusCallback& callback);
+
void CreateDirectory(const GURL& path,
bool exclusive,
bool recursive,
const StatusCallback& callback);
+ void CreateDirectorySync(const GURL& path,
+ bool exclusive,
+ bool recursive,
+ const StatusCallback& callback);
+
void Exists(const GURL& path,
bool for_directory,
const StatusCallback& callback);
+ void ExistsSync(const GURL& path,
+ bool for_directory,
+ const StatusCallback& callback);
+
void ReadDirectory(const GURL& path,
const ReadDirectoryCallback& success_callback,
const StatusCallback& error_callback);
+ void ReadDirectorySync(const GURL& path,
+ const ReadDirectoryCallback& success_callback,
+ const StatusCallback& error_callback);
+
void Truncate(const GURL& path,
int64_t offset,
int* request_id_out,
const StatusCallback& callback);
+ void TruncateSync(const GURL& path,
+ int64_t offset,
+ const StatusCallback& callback);
+
void Write(const GURL& path,
const std::string& blob_id,
int64_t offset,
int* request_id_out,
const WriteCallback& success_callback,
const StatusCallback& error_callback);
+ void WriteSync(const GURL& path,
+ const std::string& blob_id,
+ int64_t offset,
+ const WriteCallback& success_callback,
+ const StatusCallback& error_callback);
+
void Cancel(int request_id_to_cancel, const StatusCallback& callback);
void TouchFile(const GURL& file_path,
const base::Time& last_access_time,
const base::Time& last_modified_time,
const StatusCallback& callback);
- // The caller must send FileSystemHostMsg_DidReceiveSnapshot message
- // with |request_id| passed to |success_callback| after the snapshot file
- // is successfully received.
void CreateSnapshotFile(const GURL& file_path,
const CreateSnapshotFileCallback& success_callback,
const StatusCallback& error_callback);
+ void CreateSnapshotFileSync(
+ const GURL& file_path,
+ const CreateSnapshotFileCallback& success_callback,
+ const StatusCallback& error_callback);
+
+ using CreateFileWriterCallbacks =
+ blink::WebFileSystem::CreateFileWriterCallbacks;
+ void CreateFileWriter(const GURL& file_path,
+ std::unique_ptr<CreateFileWriterCallbacks> callbacks);
+
+ using ChooseEntryCallbacks = blink::WebFileSystem::ChooseEntryCallbacks;
+ void ChooseEntry(int render_frame_id,
+ std::unique_ptr<ChooseEntryCallbacks> callbacks);
private:
class CallbackDispatcher;
-
- // Message handlers.
- void OnDidOpenFileSystem(int request_id,
- const std::string& name,
- const GURL& root);
- void OnDidResolveURL(int request_id,
- const storage::FileSystemInfo& info,
- const base::FilePath& file_path,
- bool is_directory);
- void OnDidSucceed(int request_id);
- void OnDidReadMetadata(int request_id,
- const base::File::Info& file_info);
- void OnDidCreateSnapshotFile(int request_id,
- const base::File::Info& file_info,
- const base::FilePath& platform_path);
- void OnDidReadDirectory(
+ class FileSystemOperationListenerImpl;
+
+ void DidOpenFileSystem(int request_id,
+ const std::string& name,
+ const GURL& root,
+ base::File::Error error_code);
+ void DidResolveURL(int request_id,
+ blink::mojom::FileSystemInfoPtr info,
+ const base::FilePath& file_path,
+ bool is_directory,
+ base::File::Error error_code);
+ void DidFinish(int request_id, base::File::Error error_code);
+ void DidReadMetadata(int request_id,
+ const base::File::Info& file_info,
+ base::File::Error error);
+ void DidCreateSnapshotFile(
int request_id,
- const std::vector<filesystem::mojom::DirectoryEntry>& entries,
+ const base::File::Info& file_info,
+ const base::FilePath& platform_path,
+ base::File::Error error_code,
+ blink::mojom::ReceivedSnapshotListenerPtr listener);
+ void DidReadDirectory(
+ int request_id,
+ std::vector<filesystem::mojom::DirectoryEntryPtr> entries,
bool has_more);
- void OnDidFail(int request_id, base::File::Error error_code);
- void OnDidWrite(int request_id, int64_t bytes, bool complete);
+ void DidFail(int request_id, base::File::Error error_code);
+ void DidWrite(int request_id, int64_t bytes, bool complete);
+ void DidTruncate(int request_id, base::File::Error error_code);
+ void DidCancel(int request_id,
+ int cancelled_request_id,
+ base::File::Error error_code);
+
+ void RemoveOperationPtr(int request_id) {
+ DCHECK(cancellable_operations_.find(request_id) !=
+ cancellable_operations_.end());
+ cancellable_operations_.erase(request_id);
+ }
+
+ blink::mojom::FileSystemManager& GetFileSystemManager();
+
+ blink::mojom::FileSystemManagerPtr file_system_manager_ptr_;
base::IDMap<std::unique_ptr<CallbackDispatcher>> dispatchers_;
+ mojo::StrongBindingSet<blink::mojom::FileSystemOperationListener>
+ op_listeners_;
+
+ using OperationsMap =
+ std::unordered_map<int, blink::mojom::FileSystemCancellableOperationPtr>;
+ OperationsMap cancellable_operations_;
+
+ scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
+
DISALLOW_COPY_AND_ASSIGN(FileSystemDispatcher);
};
diff --git a/chromium/content/renderer/fileapi/webfilesystem_impl.cc b/chromium/content/renderer/fileapi/webfilesystem_impl.cc
index f5969dc7f1d..b58fac0c441 100644
--- a/chromium/content/renderer/fileapi/webfilesystem_impl.cc
+++ b/chromium/content/renderer/fileapi/webfilesystem_impl.cc
@@ -18,7 +18,7 @@
#include "base/threading/thread_local.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/services/filesystem/public/interfaces/types.mojom.h"
-#include "content/common/fileapi/file_system_messages.h"
+#include "content/public/renderer/render_frame.h"
#include "content/renderer/file_info_util.h"
#include "content/renderer/fileapi/file_system_dispatcher.h"
#include "content/renderer/fileapi/webfilewriter_impl.h"
@@ -29,6 +29,7 @@
#include "third_party/blink/public/platform/web_file_system_callbacks.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_url.h"
+#include "third_party/blink/public/web/web_local_frame.h"
#include "url/gurl.h"
using blink::WebFileInfo;
@@ -40,94 +41,31 @@ using blink::WebVector;
namespace content {
-class WebFileSystemImpl::WaitableCallbackResults
- : public base::RefCountedThreadSafe<WaitableCallbackResults> {
- public:
- WaitableCallbackResults()
- : results_available_event_(
- base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED) {}
-
- void AddResultsAndSignal(const base::Closure& results_closure) {
- base::AutoLock lock(lock_);
- results_closures_.push_back(results_closure);
- results_available_event_.Signal();
- }
-
- void WaitAndRun() {
- results_available_event_.Wait();
- Run();
- }
-
- void Run() {
- std::vector<base::Closure> closures;
- {
- base::AutoLock lock(lock_);
- results_closures_.swap(closures);
- results_available_event_.Reset();
- }
- for (size_t i = 0; i < closures.size(); ++i)
- closures[i].Run();
- }
-
- private:
- friend class base::RefCountedThreadSafe<WaitableCallbackResults>;
-
- ~WaitableCallbackResults() {}
-
- base::Lock lock_;
- base::WaitableEvent results_available_event_;
- std::vector<base::Closure> results_closures_;
- DISALLOW_COPY_AND_ASSIGN(WaitableCallbackResults);
-};
-
namespace {
-typedef WebFileSystemImpl::WaitableCallbackResults WaitableCallbackResults;
-
base::LazyInstance<base::ThreadLocalPointer<WebFileSystemImpl>>::Leaky
g_webfilesystem_tls = LAZY_INSTANCE_INITIALIZER;
-void DidReceiveSnapshotFile(int request_id) {
- if (ChildThreadImpl::current())
- ChildThreadImpl::current()->Send(
- new FileSystemHostMsg_DidReceiveSnapshotFile(request_id));
-}
-
-template <typename Method, typename Params>
-void CallDispatcherOnMainThread(
- const scoped_refptr<base::SingleThreadTaskRunner>& main_thread_task_runner,
- Method method, const Params& params,
- WaitableCallbackResults* waitable_results) {
- if (!main_thread_task_runner->BelongsToCurrentThread()) {
- main_thread_task_runner->PostTask(
- FROM_HERE,
- base::BindOnce(&CallDispatcherOnMainThread<Method, Params>,
- main_thread_task_runner, method, params, nullptr));
- if (!waitable_results)
- return;
- waitable_results->WaitAndRun();
- }
- if (!RenderThreadImpl::current() ||
- !RenderThreadImpl::current()->file_system_dispatcher())
- return;
-
- DCHECK(!waitable_results);
- DispatchToMethod(RenderThreadImpl::current()->file_system_dispatcher(),
- method, params);
-}
-
enum CallbacksUnregisterMode {
UNREGISTER_CALLBACKS,
DO_NOT_UNREGISTER_CALLBACKS,
};
+template <typename Method, typename Params>
+void CallDispatcher(const WebFileSystemCallbacks& callbacks,
+ Method async_method,
+ Method sync_method,
+ FileSystemDispatcher* dispatcher,
+ Params&& params) {
+ if (callbacks.ShouldBlockUntilCompletion())
+ DispatchToMethod(dispatcher, sync_method, params);
+ else
+ DispatchToMethod(dispatcher, async_method, params);
+}
+
// Bridging functions that convert the arguments into Blink objects
// (e.g. WebFileInfo, WebString, WebVector<WebFileSystemEntry>)
// and call WebFileSystemCallbacks's methods.
-// These are called by RunCallbacks after crossing threads to ensure
-// thread safety, because the Blink objects cannot be passed across
-// threads by base::Bind().
void DidSucceed(WebFileSystemCallbacks* callbacks) {
callbacks->DidSucceed();
}
@@ -174,11 +112,9 @@ void DidFail(base::File::Error error, WebFileSystemCallbacks* callbacks) {
callbacks->DidFail(storage::FileErrorToWebFileError(error));
}
-// Run WebFileSystemCallbacks's |method| with |params|.
-void RunCallbacks(
- int callbacks_id,
- const base::Callback<void(WebFileSystemCallbacks*)>& callback,
- CallbacksUnregisterMode callbacks_unregister_mode) {
+void RunCallbacks(int callbacks_id,
+ base::OnceCallback<void(WebFileSystemCallbacks*)> callback,
+ CallbacksUnregisterMode callbacks_unregister_mode) {
WebFileSystemImpl* filesystem =
WebFileSystemImpl::ThreadSpecificInstance(nullptr);
if (!filesystem)
@@ -186,117 +122,61 @@ void RunCallbacks(
WebFileSystemCallbacks callbacks = filesystem->GetCallbacks(callbacks_id);
if (callbacks_unregister_mode == UNREGISTER_CALLBACKS)
filesystem->UnregisterCallbacks(callbacks_id);
- callback.Run(&callbacks);
-}
-
-void DispatchResultsClosure(
- const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
- int callbacks_id,
- WaitableCallbackResults* waitable_results,
- const base::Closure& results_closure) {
- if (task_runner->BelongsToCurrentThread()) {
- results_closure.Run();
- return;
- }
-
- if (waitable_results) {
- // If someone is waiting, this should result in running the closure.
- waitable_results->AddResultsAndSignal(results_closure);
- // In case no one is waiting, post a task to run the closure.
- task_runner->PostTask(
- FROM_HERE, base::BindOnce(&WaitableCallbackResults::Run,
- base::WrapRefCounted(waitable_results)));
- return;
- }
- task_runner->PostTask(FROM_HERE, results_closure);
-}
-
-void CallbackFileSystemCallbacks(
- const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
- int callbacks_id,
- WaitableCallbackResults* waitable_results,
- const base::Callback<void(WebFileSystemCallbacks*)>& callback,
- CallbacksUnregisterMode callbacksunregister_mode) {
- DispatchResultsClosure(task_runner, callbacks_id, waitable_results,
- base::Bind(&RunCallbacks, callbacks_id, callback,
- callbacksunregister_mode));
+ std::move(callback).Run(&callbacks);
}
//-----------------------------------------------------------------------------
-// Callback adapters. Callbacks must be called on the original calling thread,
-// so these callback adapters relay back the results to the calling thread
-// if necessary.
+// Callback adapters.
-void OpenFileSystemCallbackAdapter(
- const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
- int callbacks_id,
- WaitableCallbackResults* waitable_results,
- const std::string& name,
- const GURL& root) {
- CallbackFileSystemCallbacks(task_runner, callbacks_id, waitable_results,
- base::Bind(&DidOpenFileSystem, name, root),
- UNREGISTER_CALLBACKS);
+void OpenFileSystemCallbackAdapter(int callbacks_id,
+ const std::string& name,
+ const GURL& root) {
+ RunCallbacks(callbacks_id, base::BindOnce(&DidOpenFileSystem, name, root),
+ UNREGISTER_CALLBACKS);
}
-void ResolveURLCallbackAdapter(
- const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
- int callbacks_id,
- WaitableCallbackResults* waitable_results,
- const storage::FileSystemInfo& info,
- const base::FilePath& file_path,
- bool is_directory) {
+void ResolveURLCallbackAdapter(int callbacks_id,
+ const storage::FileSystemInfo& info,
+ const base::FilePath& file_path,
+ bool is_directory) {
base::FilePath normalized_path(
storage::VirtualPath::GetNormalizedFilePath(file_path));
- CallbackFileSystemCallbacks(
- task_runner, callbacks_id, waitable_results,
- base::Bind(&DidResolveURL, info.name, info.root_url, info.mount_type,
- normalized_path, is_directory),
- UNREGISTER_CALLBACKS);
+ RunCallbacks(callbacks_id,
+ base::BindOnce(&DidResolveURL, info.name, info.root_url,
+ info.mount_type, normalized_path, is_directory),
+ UNREGISTER_CALLBACKS);
}
-void StatusCallbackAdapter(
- const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
- int callbacks_id,
- WaitableCallbackResults* waitable_results,
- base::File::Error error) {
+void StatusCallbackAdapter(int callbacks_id, base::File::Error error) {
if (error == base::File::FILE_OK) {
- CallbackFileSystemCallbacks(task_runner, callbacks_id, waitable_results,
- base::Bind(&DidSucceed), UNREGISTER_CALLBACKS);
+ RunCallbacks(callbacks_id, base::BindOnce(&DidSucceed),
+ UNREGISTER_CALLBACKS);
} else {
- CallbackFileSystemCallbacks(task_runner, callbacks_id, waitable_results,
- base::Bind(&DidFail, error),
- UNREGISTER_CALLBACKS);
+ RunCallbacks(callbacks_id, base::BindOnce(&DidFail, error),
+ UNREGISTER_CALLBACKS);
}
}
-void ReadMetadataCallbackAdapter(
- const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
- int callbacks_id,
- WaitableCallbackResults* waitable_results,
- const base::File::Info& file_info) {
- CallbackFileSystemCallbacks(task_runner, callbacks_id, waitable_results,
- base::Bind(&DidReadMetadata, file_info),
- UNREGISTER_CALLBACKS);
+void ReadMetadataCallbackAdapter(int callbacks_id,
+ const base::File::Info& file_info) {
+ RunCallbacks(callbacks_id, base::BindOnce(&DidReadMetadata, file_info),
+ UNREGISTER_CALLBACKS);
}
void ReadDirectoryCallbackAdapter(
- const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
int callbacks_id,
- WaitableCallbackResults* waitable_results,
const std::vector<filesystem::mojom::DirectoryEntry>& entries,
bool has_more) {
- CallbackFileSystemCallbacks(
- task_runner, callbacks_id, waitable_results,
- base::Bind(&DidReadDirectory, entries, has_more),
- has_more ? DO_NOT_UNREGISTER_CALLBACKS : UNREGISTER_CALLBACKS);
+ RunCallbacks(callbacks_id,
+ base::BindOnce(&DidReadDirectory, entries, has_more),
+ has_more ? DO_NOT_UNREGISTER_CALLBACKS : UNREGISTER_CALLBACKS);
}
-void DidCreateFileWriter(
- int callbacks_id,
- const GURL& path,
- blink::WebFileWriterClient* client,
- const scoped_refptr<base::SingleThreadTaskRunner>& main_thread_task_runner,
- const base::File::Info& file_info) {
+void DidCreateFileWriter(int callbacks_id,
+ const GURL& path,
+ blink::WebFileWriterClient* client,
+ base::SingleThreadTaskRunner* main_thread_task_runner,
+ const base::File::Info& file_info) {
WebFileSystemImpl* filesystem =
WebFileSystemImpl::ThreadSpecificInstance(nullptr);
if (!filesystem)
@@ -318,24 +198,20 @@ void DidCreateFileWriter(
}
void CreateFileWriterCallbackAdapter(
- const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
int callbacks_id,
- WaitableCallbackResults* waitable_results,
- const scoped_refptr<base::SingleThreadTaskRunner>& main_thread_task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner,
const GURL& path,
blink::WebFileWriterClient* client,
const base::File::Info& file_info) {
- DispatchResultsClosure(
- task_runner, callbacks_id, waitable_results,
- base::Bind(&DidCreateFileWriter, callbacks_id, path, client,
- main_thread_task_runner, file_info));
+ DidCreateFileWriter(callbacks_id, path, client, main_thread_task_runner.get(),
+ file_info);
}
void DidCreateSnapshotFile(
int callbacks_id,
- const scoped_refptr<base::SingleThreadTaskRunner>& main_thread_task_runner,
const base::File::Info& file_info,
const base::FilePath& platform_path,
+ base::Optional<blink::mojom::ReceivedSnapshotListenerPtr> opt_listener,
int request_id) {
WebFileSystemImpl* filesystem =
WebFileSystemImpl::ThreadSpecificInstance(nullptr);
@@ -352,22 +228,19 @@ void DidCreateSnapshotFile(
// TODO(michaeln,kinuko): Use ThreadSafeSender when Blob becomes
// non-bridge model.
- main_thread_task_runner->PostTask(
- FROM_HERE, base::BindOnce(&DidReceiveSnapshotFile, request_id));
+ if (opt_listener) {
+ opt_listener.value()->DidReceiveSnapshotFile();
+ }
}
void CreateSnapshotFileCallbackAdapter(
- const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
int callbacks_id,
- WaitableCallbackResults* waitable_results,
- const scoped_refptr<base::SingleThreadTaskRunner>& main_thread_task_runner,
const base::File::Info& file_info,
const base::FilePath& platform_path,
+ base::Optional<blink::mojom::ReceivedSnapshotListenerPtr> opt_listener,
int request_id) {
- DispatchResultsClosure(
- task_runner, callbacks_id, waitable_results,
- base::Bind(&DidCreateSnapshotFile, callbacks_id, main_thread_task_runner,
- file_info, platform_path, request_id));
+ DidCreateSnapshotFile(callbacks_id, file_info, platform_path,
+ std::move(opt_listener), request_id);
}
} // namespace
@@ -376,12 +249,11 @@ void CreateSnapshotFileCallbackAdapter(
// WebFileSystemImpl
WebFileSystemImpl* WebFileSystemImpl::ThreadSpecificInstance(
- const scoped_refptr<base::SingleThreadTaskRunner>&
- main_thread_task_runner) {
- if (g_webfilesystem_tls.Pointer()->Get() || !main_thread_task_runner.get())
+ scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner) {
+ if (g_webfilesystem_tls.Pointer()->Get() || !main_thread_task_runner)
return g_webfilesystem_tls.Pointer()->Get();
WebFileSystemImpl* filesystem =
- new WebFileSystemImpl(main_thread_task_runner);
+ new WebFileSystemImpl(std::move(main_thread_task_runner));
if (WorkerThread::GetCurrentId())
WorkerThread::AddObserver(filesystem);
return filesystem;
@@ -394,9 +266,10 @@ void WebFileSystemImpl::DeleteThreadSpecificInstance() {
}
WebFileSystemImpl::WebFileSystemImpl(
- const scoped_refptr<base::SingleThreadTaskRunner>& main_thread_task_runner)
+ scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner)
: main_thread_task_runner_(main_thread_task_runner),
- next_callbacks_id_(1) {
+ next_callbacks_id_(1),
+ file_system_dispatcher_(std::move(main_thread_task_runner)) {
g_webfilesystem_tls.Pointer()->Set(this);
}
@@ -413,197 +286,135 @@ void WebFileSystemImpl::OpenFileSystem(const blink::WebURL& storage_partition,
blink::WebFileSystemType type,
WebFileSystemCallbacks callbacks) {
int callbacks_id = RegisterCallbacks(callbacks);
- scoped_refptr<WaitableCallbackResults> waitable_results =
- MaybeCreateWaitableResults(callbacks, callbacks_id);
- CallDispatcherOnMainThread(
- main_thread_task_runner_, &FileSystemDispatcher::OpenFileSystem,
+ CallDispatcher(
+ callbacks, &FileSystemDispatcher::OpenFileSystem,
+ &FileSystemDispatcher::OpenFileSystemSync, &file_system_dispatcher_,
std::make_tuple(
GURL(storage_partition), static_cast<storage::FileSystemType>(type),
- base::Bind(&OpenFileSystemCallbackAdapter,
- base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- base::RetainedRef(waitable_results)),
- base::Bind(&StatusCallbackAdapter,
- base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- base::RetainedRef(waitable_results))),
- waitable_results.get());
+ base::BindRepeating(&OpenFileSystemCallbackAdapter, callbacks_id),
+ base::BindRepeating(&StatusCallbackAdapter, callbacks_id)));
}
void WebFileSystemImpl::ResolveURL(const blink::WebURL& filesystem_url,
WebFileSystemCallbacks callbacks) {
int callbacks_id = RegisterCallbacks(callbacks);
- scoped_refptr<WaitableCallbackResults> waitable_results =
- MaybeCreateWaitableResults(callbacks, callbacks_id);
- CallDispatcherOnMainThread(
- main_thread_task_runner_, &FileSystemDispatcher::ResolveURL,
+ CallDispatcher(
+ callbacks, &FileSystemDispatcher::ResolveURL,
+ &FileSystemDispatcher::ResolveURLSync, &file_system_dispatcher_,
std::make_tuple(
GURL(filesystem_url),
- base::Bind(&ResolveURLCallbackAdapter,
- base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- base::RetainedRef(waitable_results)),
- base::Bind(&StatusCallbackAdapter,
- base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- base::RetainedRef(waitable_results))),
- waitable_results.get());
+ base::BindRepeating(&ResolveURLCallbackAdapter, callbacks_id),
+ base::BindRepeating(&StatusCallbackAdapter, callbacks_id)));
}
void WebFileSystemImpl::Move(const blink::WebURL& src_path,
const blink::WebURL& dest_path,
WebFileSystemCallbacks callbacks) {
int callbacks_id = RegisterCallbacks(callbacks);
- scoped_refptr<WaitableCallbackResults> waitable_results =
- MaybeCreateWaitableResults(callbacks, callbacks_id);
- CallDispatcherOnMainThread(
- main_thread_task_runner_, &FileSystemDispatcher::Move,
- std::make_tuple(
- GURL(src_path), GURL(dest_path),
- base::Bind(&StatusCallbackAdapter,
- base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- base::RetainedRef(waitable_results))),
- waitable_results.get());
+ CallDispatcher(callbacks, &FileSystemDispatcher::Move,
+ &FileSystemDispatcher::MoveSync, &file_system_dispatcher_,
+ std::make_tuple(GURL(src_path), GURL(dest_path),
+ base::BindRepeating(&StatusCallbackAdapter,
+ callbacks_id)));
}
void WebFileSystemImpl::Copy(const blink::WebURL& src_path,
const blink::WebURL& dest_path,
WebFileSystemCallbacks callbacks) {
int callbacks_id = RegisterCallbacks(callbacks);
- scoped_refptr<WaitableCallbackResults> waitable_results =
- MaybeCreateWaitableResults(callbacks, callbacks_id);
- CallDispatcherOnMainThread(
- main_thread_task_runner_, &FileSystemDispatcher::Copy,
- std::make_tuple(
- GURL(src_path), GURL(dest_path),
- base::Bind(&StatusCallbackAdapter,
- base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- base::RetainedRef(waitable_results))),
- waitable_results.get());
+ CallDispatcher(callbacks, &FileSystemDispatcher::Copy,
+ &FileSystemDispatcher::CopySync, &file_system_dispatcher_,
+ std::make_tuple(GURL(src_path), GURL(dest_path),
+ base::BindRepeating(&StatusCallbackAdapter,
+ callbacks_id)));
}
void WebFileSystemImpl::Remove(const blink::WebURL& path,
WebFileSystemCallbacks callbacks) {
int callbacks_id = RegisterCallbacks(callbacks);
- scoped_refptr<WaitableCallbackResults> waitable_results =
- MaybeCreateWaitableResults(callbacks, callbacks_id);
- CallDispatcherOnMainThread(
- main_thread_task_runner_, &FileSystemDispatcher::Remove,
- std::make_tuple(
- GURL(path), false /* recursive */,
- base::Bind(&StatusCallbackAdapter,
- base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- base::RetainedRef(waitable_results))),
- waitable_results.get());
+ CallDispatcher(callbacks, &FileSystemDispatcher::Remove,
+ &FileSystemDispatcher::RemoveSync, &file_system_dispatcher_,
+ std::make_tuple(GURL(path), /*recursive=*/false,
+ base::BindRepeating(&StatusCallbackAdapter,
+ callbacks_id)));
}
void WebFileSystemImpl::RemoveRecursively(const blink::WebURL& path,
WebFileSystemCallbacks callbacks) {
int callbacks_id = RegisterCallbacks(callbacks);
- scoped_refptr<WaitableCallbackResults> waitable_results =
- MaybeCreateWaitableResults(callbacks, callbacks_id);
- CallDispatcherOnMainThread(
- main_thread_task_runner_, &FileSystemDispatcher::Remove,
- std::make_tuple(
- GURL(path), true /* recursive */,
- base::Bind(&StatusCallbackAdapter,
- base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- base::RetainedRef(waitable_results))),
- waitable_results.get());
+ CallDispatcher(callbacks, &FileSystemDispatcher::Remove,
+ &FileSystemDispatcher::RemoveSync, &file_system_dispatcher_,
+ std::make_tuple(GURL(path), /*recursive=*/true,
+ base::BindRepeating(&StatusCallbackAdapter,
+ callbacks_id)));
}
void WebFileSystemImpl::ReadMetadata(const blink::WebURL& path,
WebFileSystemCallbacks callbacks) {
int callbacks_id = RegisterCallbacks(callbacks);
- scoped_refptr<WaitableCallbackResults> waitable_results =
- MaybeCreateWaitableResults(callbacks, callbacks_id);
- CallDispatcherOnMainThread(
- main_thread_task_runner_, &FileSystemDispatcher::ReadMetadata,
+ CallDispatcher(
+ callbacks, &FileSystemDispatcher::ReadMetadata,
+ &FileSystemDispatcher::ReadMetadataSync, &file_system_dispatcher_,
std::make_tuple(
GURL(path),
- base::Bind(&ReadMetadataCallbackAdapter,
- base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- base::RetainedRef(waitable_results)),
- base::Bind(&StatusCallbackAdapter,
- base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- base::RetainedRef(waitable_results))),
- waitable_results.get());
+ base::BindRepeating(&ReadMetadataCallbackAdapter, callbacks_id),
+ base::BindRepeating(&StatusCallbackAdapter, callbacks_id)));
}
void WebFileSystemImpl::CreateFile(const blink::WebURL& path,
bool exclusive,
WebFileSystemCallbacks callbacks) {
int callbacks_id = RegisterCallbacks(callbacks);
- scoped_refptr<WaitableCallbackResults> waitable_results =
- MaybeCreateWaitableResults(callbacks, callbacks_id);
- CallDispatcherOnMainThread(
- main_thread_task_runner_, &FileSystemDispatcher::CreateFile,
+ CallDispatcher(
+ callbacks, &FileSystemDispatcher::CreateFile,
+ &FileSystemDispatcher::CreateFileSync, &file_system_dispatcher_,
std::make_tuple(
GURL(path), exclusive,
- base::Bind(&StatusCallbackAdapter,
- base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- base::RetainedRef(waitable_results))),
- waitable_results.get());
+ base::BindRepeating(&StatusCallbackAdapter, callbacks_id)));
}
void WebFileSystemImpl::CreateDirectory(const blink::WebURL& path,
bool exclusive,
WebFileSystemCallbacks callbacks) {
int callbacks_id = RegisterCallbacks(callbacks);
- scoped_refptr<WaitableCallbackResults> waitable_results =
- MaybeCreateWaitableResults(callbacks, callbacks_id);
- CallDispatcherOnMainThread(
- main_thread_task_runner_, &FileSystemDispatcher::CreateDirectory,
+ CallDispatcher(
+ callbacks, &FileSystemDispatcher::CreateDirectory,
+ &FileSystemDispatcher::CreateDirectorySync, &file_system_dispatcher_,
std::make_tuple(
- GURL(path), exclusive, false /* recursive */,
- base::Bind(&StatusCallbackAdapter,
- base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- base::RetainedRef(waitable_results))),
- waitable_results.get());
+ GURL(path), exclusive, /*recursive=*/false,
+ base::BindRepeating(&StatusCallbackAdapter, callbacks_id)));
}
void WebFileSystemImpl::FileExists(const blink::WebURL& path,
WebFileSystemCallbacks callbacks) {
int callbacks_id = RegisterCallbacks(callbacks);
- scoped_refptr<WaitableCallbackResults> waitable_results =
- MaybeCreateWaitableResults(callbacks, callbacks_id);
- CallDispatcherOnMainThread(
- main_thread_task_runner_, &FileSystemDispatcher::Exists,
- std::make_tuple(
- GURL(path), false /* directory */,
- base::Bind(&StatusCallbackAdapter,
- base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- base::RetainedRef(waitable_results))),
- waitable_results.get());
+ CallDispatcher(callbacks, &FileSystemDispatcher::Exists,
+ &FileSystemDispatcher::ExistsSync, &file_system_dispatcher_,
+ std::make_tuple(GURL(path), /*directory=*/false,
+ base::BindRepeating(&StatusCallbackAdapter,
+ callbacks_id)));
}
void WebFileSystemImpl::DirectoryExists(const blink::WebURL& path,
WebFileSystemCallbacks callbacks) {
int callbacks_id = RegisterCallbacks(callbacks);
- scoped_refptr<WaitableCallbackResults> waitable_results =
- MaybeCreateWaitableResults(callbacks, callbacks_id);
- CallDispatcherOnMainThread(
- main_thread_task_runner_, &FileSystemDispatcher::Exists,
- std::make_tuple(
- GURL(path), true /* directory */,
- base::Bind(&StatusCallbackAdapter,
- base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- base::RetainedRef(waitable_results))),
- waitable_results.get());
+ CallDispatcher(callbacks, &FileSystemDispatcher::Exists,
+ &FileSystemDispatcher::ExistsSync, &file_system_dispatcher_,
+ std::make_tuple(GURL(path), /*directory=*/true,
+ base::BindRepeating(&StatusCallbackAdapter,
+ callbacks_id)));
}
int WebFileSystemImpl::ReadDirectory(const blink::WebURL& path,
WebFileSystemCallbacks callbacks) {
int callbacks_id = RegisterCallbacks(callbacks);
- scoped_refptr<WaitableCallbackResults> waitable_results =
- MaybeCreateWaitableResults(callbacks, callbacks_id);
- CallDispatcherOnMainThread(
- main_thread_task_runner_, &FileSystemDispatcher::ReadDirectory,
+ CallDispatcher(
+ callbacks, &FileSystemDispatcher::ReadDirectory,
+ &FileSystemDispatcher::ReadDirectorySync, &file_system_dispatcher_,
std::make_tuple(
GURL(path),
- base::Bind(&ReadDirectoryCallbackAdapter,
- base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- base::RetainedRef(waitable_results)),
- base::Bind(&StatusCallbackAdapter,
- base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- base::RetainedRef(waitable_results))),
- waitable_results.get());
+ base::BindRepeating(&ReadDirectoryCallbackAdapter, callbacks_id),
+ base::BindRepeating(&StatusCallbackAdapter, callbacks_id)));
return callbacks_id;
}
@@ -611,50 +422,40 @@ void WebFileSystemImpl::CreateFileWriter(const WebURL& path,
blink::WebFileWriterClient* client,
WebFileSystemCallbacks callbacks) {
int callbacks_id = RegisterCallbacks(callbacks);
- scoped_refptr<WaitableCallbackResults> waitable_results =
- MaybeCreateWaitableResults(callbacks, callbacks_id);
- CallDispatcherOnMainThread(
- main_thread_task_runner_, &FileSystemDispatcher::ReadMetadata,
+ CallDispatcher(
+ callbacks, &FileSystemDispatcher::ReadMetadata,
+ &FileSystemDispatcher::ReadMetadataSync, &file_system_dispatcher_,
std::make_tuple(
GURL(path),
- base::Bind(&CreateFileWriterCallbackAdapter,
- base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- base::RetainedRef(waitable_results),
- main_thread_task_runner_, GURL(path), client),
- base::Bind(&StatusCallbackAdapter,
- base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- base::RetainedRef(waitable_results))),
- waitable_results.get());
+ base::BindRepeating(&CreateFileWriterCallbackAdapter, callbacks_id,
+ main_thread_task_runner_, GURL(path), client),
+ base::BindRepeating(&StatusCallbackAdapter, callbacks_id)));
+}
+
+void WebFileSystemImpl::CreateFileWriter(
+ const blink::WebURL& path,
+ std::unique_ptr<CreateFileWriterCallbacks> callbacks) {
+ file_system_dispatcher_.CreateFileWriter(path, std::move(callbacks));
}
void WebFileSystemImpl::CreateSnapshotFileAndReadMetadata(
const blink::WebURL& path,
WebFileSystemCallbacks callbacks) {
int callbacks_id = RegisterCallbacks(callbacks);
- scoped_refptr<WaitableCallbackResults> waitable_results =
- MaybeCreateWaitableResults(callbacks, callbacks_id);
- CallDispatcherOnMainThread(
- main_thread_task_runner_, &FileSystemDispatcher::CreateSnapshotFile,
+ CallDispatcher(
+ callbacks, &FileSystemDispatcher::CreateSnapshotFile,
+ &FileSystemDispatcher::CreateSnapshotFileSync, &file_system_dispatcher_,
std::make_tuple(
GURL(path),
- base::Bind(&CreateSnapshotFileCallbackAdapter,
- base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- base::RetainedRef(waitable_results),
- main_thread_task_runner_),
- base::Bind(&StatusCallbackAdapter,
- base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- base::RetainedRef(waitable_results))),
- waitable_results.get());
+ base::BindRepeating(&CreateSnapshotFileCallbackAdapter, callbacks_id),
+ base::BindRepeating(&StatusCallbackAdapter, callbacks_id)));
}
-bool WebFileSystemImpl::WaitForAdditionalResult(int callbacksId) {
- WaitableCallbackResultsMap::iterator found =
- waitable_results_.find(callbacksId);
- if (found == waitable_results_.end())
- return false;
-
- found->second->WaitAndRun();
- return true;
+void WebFileSystemImpl::ChooseEntry(
+ blink::WebFrame* frame,
+ std::unique_ptr<ChooseEntryCallbacks> callbacks) {
+ file_system_dispatcher_.ChooseEntry(
+ RenderFrame::GetRoutingIdForWebFrame(frame), std::move(callbacks));
}
int WebFileSystemImpl::RegisterCallbacks(
@@ -677,17 +478,6 @@ void WebFileSystemImpl::UnregisterCallbacks(int callbacks_id) {
CallbacksMap::iterator found = callbacks_.find(callbacks_id);
DCHECK(found != callbacks_.end());
callbacks_.erase(found);
-
- waitable_results_.erase(callbacks_id);
-}
-
-WaitableCallbackResults* WebFileSystemImpl::MaybeCreateWaitableResults(
- const WebFileSystemCallbacks& callbacks, int callbacks_id) {
- if (!callbacks.ShouldBlockUntilCompletion())
- return nullptr;
- WaitableCallbackResults* results = new WaitableCallbackResults();
- waitable_results_[callbacks_id] = results;
- return results;
}
} // namespace content
diff --git a/chromium/content/renderer/fileapi/webfilesystem_impl.h b/chromium/content/renderer/fileapi/webfilesystem_impl.h
index 97f92a5d70d..eeb7145f71c 100644
--- a/chromium/content/renderer/fileapi/webfilesystem_impl.h
+++ b/chromium/content/renderer/fileapi/webfilesystem_impl.h
@@ -12,6 +12,7 @@
#include "base/memory/ref_counted.h"
#include "base/threading/thread_checker.h"
#include "content/public/renderer/worker_thread.h"
+#include "content/renderer/fileapi/file_system_dispatcher.h"
#include "third_party/blink/public/platform/web_file_system.h"
namespace base {
@@ -28,14 +29,11 @@ namespace content {
class WebFileSystemImpl : public blink::WebFileSystem,
public WorkerThread::Observer {
public:
- class WaitableCallbackResults;
-
// Returns thread-specific instance. If non-null |main_thread_loop|
// is given and no thread-specific instance has been created it may
// create a new instance.
static WebFileSystemImpl* ThreadSpecificInstance(
- const scoped_refptr<base::SingleThreadTaskRunner>&
- main_thread_task_runner);
+ scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner);
// Deletes thread-specific instance (if exists). For workers it deletes
// itself in WillStopCurrentWorkerThread(), but for an instance created on the
@@ -43,8 +41,7 @@ class WebFileSystemImpl : public blink::WebFileSystem,
static void DeleteThreadSpecificInstance();
explicit WebFileSystemImpl(
- const scoped_refptr<base::SingleThreadTaskRunner>&
- main_thread_task_runner);
+ scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner);
~WebFileSystemImpl() override;
// WorkerThread::Observer implementation.
@@ -83,10 +80,15 @@ class WebFileSystemImpl : public blink::WebFileSystem,
void CreateFileWriter(const blink::WebURL& path,
blink::WebFileWriterClient*,
blink::WebFileSystemCallbacks) override;
+ void CreateFileWriter(
+ const blink::WebURL& path,
+ std::unique_ptr<CreateFileWriterCallbacks> callbacks) override;
void CreateSnapshotFileAndReadMetadata(
const blink::WebURL& path,
blink::WebFileSystemCallbacks) override;
- bool WaitForAdditionalResult(int callbacksId) override;
+
+ void ChooseEntry(blink::WebFrame* frame,
+ std::unique_ptr<ChooseEntryCallbacks>) override;
int RegisterCallbacks(const blink::WebFileSystemCallbacks& callbacks);
blink::WebFileSystemCallbacks GetCallbacks(int callbacks_id);
@@ -94,17 +96,12 @@ class WebFileSystemImpl : public blink::WebFileSystem,
private:
typedef std::map<int, blink::WebFileSystemCallbacks> CallbacksMap;
- typedef std::map<int, scoped_refptr<WaitableCallbackResults> >
- WaitableCallbackResultsMap;
-
- WaitableCallbackResults* MaybeCreateWaitableResults(
- const blink::WebFileSystemCallbacks& callbacks, int callbacks_id);
scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
CallbacksMap callbacks_;
int next_callbacks_id_;
- WaitableCallbackResultsMap waitable_results_;
+ FileSystemDispatcher file_system_dispatcher_;
// Thread-affine per use of TLS in impl.
THREAD_CHECKER(thread_checker_);
diff --git a/chromium/content/renderer/fileapi/webfilewriter_impl.cc b/chromium/content/renderer/fileapi/webfilewriter_impl.cc
index 61c646a4e1d..9502920bd98 100644
--- a/chromium/content/renderer/fileapi/webfilewriter_impl.cc
+++ b/chromium/content/renderer/fileapi/webfilewriter_impl.cc
@@ -13,164 +13,55 @@
namespace content {
-namespace {
-
-FileSystemDispatcher* GetFileSystemDispatcher() {
- return RenderThreadImpl::current()
- ? RenderThreadImpl::current()->file_system_dispatcher()
- : nullptr;
-}
-
-} // namespace
-
typedef FileSystemDispatcher::StatusCallback StatusCallback;
typedef FileSystemDispatcher::WriteCallback WriteCallback;
-// This instance may be created outside main thread but runs mainly
-// on main thread.
-class WebFileWriterImpl::WriterBridge
- : public base::RefCountedThreadSafe<WriterBridge> {
- public:
- WriterBridge(WebFileWriterImpl::Type type)
- : request_id_(0),
- running_on_worker_(WorkerThread::GetCurrentId() > 0),
- task_runner_(running_on_worker_ ? base::ThreadTaskRunnerHandle::Get()
- : nullptr),
- written_bytes_(0) {
- if (type == WebFileWriterImpl::TYPE_SYNC) {
- waitable_event_.reset(new base::WaitableEvent(
- base::WaitableEvent::ResetPolicy::AUTOMATIC,
- base::WaitableEvent::InitialState::NOT_SIGNALED));
- }
- }
-
- void Truncate(const GURL& path,
- int64_t offset,
- const StatusCallback& status_callback) {
- status_callback_ = status_callback;
- if (!GetFileSystemDispatcher())
- return;
- RenderThreadImpl::current()->file_system_dispatcher()->Truncate(
- path, offset, &request_id_,
- base::Bind(&WriterBridge::DidFinish, this));
- }
-
- void Write(const GURL& path,
- const std::string& id,
- int64_t offset,
- const WriteCallback& write_callback,
- const StatusCallback& error_callback) {
- write_callback_ = write_callback;
- status_callback_ = error_callback;
- if (!GetFileSystemDispatcher())
- return;
- RenderThreadImpl::current()->file_system_dispatcher()->Write(
- path, id, offset, &request_id_,
- base::Bind(&WriterBridge::DidWrite, this),
- base::Bind(&WriterBridge::DidFinish, this));
- }
-
- void Cancel(const StatusCallback& status_callback) {
- status_callback_ = status_callback;
- if (!GetFileSystemDispatcher())
- return;
- RenderThreadImpl::current()->file_system_dispatcher()->Cancel(
- request_id_,
- base::Bind(&WriterBridge::DidFinish, this));
- }
-
- base::WaitableEvent* waitable_event() {
- return waitable_event_.get();
- }
-
- void WaitAndRun() {
- waitable_event_->Wait();
- DCHECK(!results_closure_.is_null());
- results_closure_.Run();
- }
-
- private:
- friend class base::RefCountedThreadSafe<WriterBridge>;
- virtual ~WriterBridge() {}
-
- void DidWrite(int64_t bytes, bool complete) {
- written_bytes_ += bytes;
- if (waitable_event_ && !complete)
- return;
- PostTaskToWorker(base::Bind(write_callback_, written_bytes_, complete));
- }
-
- void DidFinish(base::File::Error status) {
- PostTaskToWorker(base::Bind(status_callback_, status));
- }
-
- void PostTaskToWorker(const base::Closure& closure) {
- written_bytes_ = 0;
- if (!running_on_worker_) {
- DCHECK(!waitable_event_);
- closure.Run();
- return;
- }
- DCHECK(task_runner_);
- if (waitable_event_) {
- results_closure_ = closure;
- waitable_event_->Signal();
- return;
- }
- task_runner_->PostTask(FROM_HERE, closure);
- }
-
- StatusCallback status_callback_;
- WriteCallback write_callback_;
- int request_id_;
- const bool running_on_worker_;
- scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
- int written_bytes_;
- std::unique_ptr<base::WaitableEvent> waitable_event_;
- base::Closure results_closure_;
-};
-
WebFileWriterImpl::WebFileWriterImpl(
- const GURL& path, blink::WebFileWriterClient* client,
- Type type,
- const scoped_refptr<base::SingleThreadTaskRunner>& main_thread_task_runner)
- : WebFileWriterBase(path, client),
- main_thread_task_runner_(main_thread_task_runner),
- bridge_(new WriterBridge(type)) {
-}
-
-WebFileWriterImpl::~WebFileWriterImpl() {
-}
+ const GURL& path,
+ blink::WebFileWriterClient* client,
+ Type type,
+ scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner)
+ : WebFileWriterBase(path, client),
+ request_id_(0),
+ type_(type),
+ file_system_dispatcher_(std::make_unique<FileSystemDispatcher>(
+ std::move(main_thread_task_runner))) {}
+
+WebFileWriterImpl::~WebFileWriterImpl() {}
void WebFileWriterImpl::DoTruncate(const GURL& path, int64_t offset) {
- RunOnMainThread(base::Bind(&WriterBridge::Truncate, bridge_,
- path, offset,
- base::Bind(&WebFileWriterImpl::DidFinish, AsWeakPtr())));
+ if (type_ == TYPE_SYNC) {
+ file_system_dispatcher_->TruncateSync(
+ path, offset,
+ base::Bind(&WebFileWriterImpl::DidFinish, base::Unretained(this)));
+ } else {
+ file_system_dispatcher_->Truncate(
+ path, offset, &request_id_,
+ base::Bind(&WebFileWriterImpl::DidFinish, base::Unretained(this)));
+ }
}
void WebFileWriterImpl::DoWrite(const GURL& path,
const std::string& blob_id,
int64_t offset) {
- RunOnMainThread(base::Bind(&WriterBridge::Write, bridge_,
- path, blob_id, offset,
- base::Bind(&WebFileWriterImpl::DidWrite, AsWeakPtr()),
- base::Bind(&WebFileWriterImpl::DidFinish, AsWeakPtr())));
+ if (type_ == TYPE_SYNC) {
+ file_system_dispatcher_->WriteSync(
+ path, blob_id, offset,
+ base::Bind(&WebFileWriterImpl::DidWrite, base::Unretained(this)),
+ base::Bind(&WebFileWriterImpl::DidFinish, base::Unretained(this)));
+ } else {
+ file_system_dispatcher_->Write(
+ path, blob_id, offset, &request_id_,
+ base::Bind(&WebFileWriterImpl::DidWrite, base::Unretained(this)),
+ base::Bind(&WebFileWriterImpl::DidFinish, base::Unretained(this)));
+ }
}
void WebFileWriterImpl::DoCancel() {
- RunOnMainThread(base::Bind(&WriterBridge::Cancel, bridge_,
- base::Bind(&WebFileWriterImpl::DidFinish, AsWeakPtr())));
-}
-
-void WebFileWriterImpl::RunOnMainThread(const base::Closure& closure) {
- if (main_thread_task_runner_->RunsTasksInCurrentSequence()) {
- DCHECK(!bridge_->waitable_event());
- closure.Run();
- return;
- }
- main_thread_task_runner_->PostTask(FROM_HERE, closure);
- if (bridge_->waitable_event())
- bridge_->WaitAndRun();
+ DCHECK_EQ(type_, TYPE_ASYNC);
+ file_system_dispatcher_->Cancel(
+ request_id_,
+ base::Bind(&WebFileWriterImpl::DidFinish, base::Unretained(this)));
}
} // namespace content
diff --git a/chromium/content/renderer/fileapi/webfilewriter_impl.h b/chromium/content/renderer/fileapi/webfilewriter_impl.h
index 2737ea76fe6..cddc24df921 100644
--- a/chromium/content/renderer/fileapi/webfilewriter_impl.h
+++ b/chromium/content/renderer/fileapi/webfilewriter_impl.h
@@ -10,8 +10,6 @@
#include <string>
#include "base/callback_forward.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
#include "content/renderer/fileapi/webfilewriter_base.h"
namespace base {
@@ -20,20 +18,21 @@ class SingleThreadTaskRunner;
namespace content {
+class FileSystemDispatcher;
+
// An implementation of WebFileWriter for use in chrome renderers and workers.
-class WebFileWriterImpl : public WebFileWriterBase,
- public base::SupportsWeakPtr<WebFileWriterImpl> {
+class WebFileWriterImpl : public WebFileWriterBase {
public:
enum Type {
TYPE_SYNC,
TYPE_ASYNC,
};
- WebFileWriterImpl(const GURL& path,
- blink::WebFileWriterClient* client,
- Type type,
- const scoped_refptr<base::SingleThreadTaskRunner>&
- main_thread_task_runner);
+ WebFileWriterImpl(
+ const GURL& path,
+ blink::WebFileWriterClient* client,
+ Type type,
+ scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner);
~WebFileWriterImpl() override;
protected:
@@ -45,12 +44,9 @@ class WebFileWriterImpl : public WebFileWriterBase,
void DoCancel() override;
private:
- class WriterBridge;
-
- void RunOnMainThread(const base::Closure& closure);
-
- scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
- scoped_refptr<WriterBridge> bridge_;
+ int request_id_;
+ Type type_;
+ std::unique_ptr<FileSystemDispatcher> file_system_dispatcher_;
};
} // namespace content
diff --git a/chromium/content/renderer/gpu/actions_parser.cc b/chromium/content/renderer/gpu/actions_parser.cc
index fe0b34ab0c2..d65cfa3e748 100644
--- a/chromium/content/renderer/gpu/actions_parser.cc
+++ b/chromium/content/renderer/gpu/actions_parser.cc
@@ -21,6 +21,8 @@ SyntheticPointerActionParams::PointerActionType ToSyntheticPointerActionType(
return SyntheticPointerActionParams::PointerActionType::MOVE;
if (action_type == "pointerUp")
return SyntheticPointerActionParams::PointerActionType::RELEASE;
+ if (action_type == "pointerLeave")
+ return SyntheticPointerActionParams::PointerActionType::LEAVE;
if (action_type == "pause")
return SyntheticPointerActionParams::PointerActionType::IDLE;
return SyntheticPointerActionParams::PointerActionType::NOT_INITIALIZED;
@@ -245,6 +247,7 @@ bool ActionsParser::ParseAction(
case SyntheticPointerActionParams::PointerActionType::RELEASE:
action_param.set_button(button);
break;
+ case SyntheticPointerActionParams::PointerActionType::LEAVE:
case SyntheticPointerActionParams::PointerActionType::IDLE:
case SyntheticPointerActionParams::PointerActionType::NOT_INITIALIZED:
break;
diff --git a/chromium/content/renderer/gpu/frame_swap_message_queue.cc b/chromium/content/renderer/gpu/frame_swap_message_queue.cc
index 1d4e9746815..f1803681f13 100644
--- a/chromium/content/renderer/gpu/frame_swap_message_queue.cc
+++ b/chromium/content/renderer/gpu/frame_swap_message_queue.cc
@@ -15,8 +15,6 @@
#include "base/stl_util.h"
#include "ipc/ipc_message.h"
-using std::vector;
-
namespace content {
class FrameSwapMessageSubQueue {
@@ -37,7 +35,6 @@ class FrameSwapMessageSubQueue {
namespace {
-// Queue specific to MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE.
class SendMessageScopeImpl : public FrameSwapMessageQueue::SendMessageScope {
public:
SendMessageScopeImpl(base::Lock* lock) : auto_lock_(*lock) {}
@@ -82,38 +79,10 @@ class VisualStateQueue : public FrameSwapMessageSubQueue {
DISALLOW_COPY_AND_ASSIGN(VisualStateQueue);
};
-// Queue specific to MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP.
-class SwapQueue : public FrameSwapMessageSubQueue {
- public:
- SwapQueue() {}
- bool Empty() const override { return queue_.empty(); }
-
- void QueueMessage(int source_frame_number,
- std::unique_ptr<IPC::Message> msg,
- bool* is_first) override {
- if (is_first)
- *is_first = Empty();
- queue_.push_back(std::move(msg));
- }
-
- void DrainMessages(
- int source_frame_number,
- std::vector<std::unique_ptr<IPC::Message>>* messages) override {
- std::move(queue_.begin(), queue_.end(), std::back_inserter(*messages));
- queue_.clear();
- }
-
- private:
- std::vector<std::unique_ptr<IPC::Message>> queue_;
-
- DISALLOW_COPY_AND_ASSIGN(SwapQueue);
-};
-
} // namespace
FrameSwapMessageQueue::FrameSwapMessageQueue(int32_t routing_id)
: visual_state_queue_(new VisualStateQueue()),
- swap_queue_(new SwapQueue()),
routing_id_(routing_id) {
DETACH_FROM_THREAD(impl_thread_checker_);
}
@@ -123,32 +92,16 @@ FrameSwapMessageQueue::~FrameSwapMessageQueue() {
bool FrameSwapMessageQueue::Empty() const {
base::AutoLock lock(lock_);
- return next_drain_messages_.empty() && visual_state_queue_->Empty() &&
- swap_queue_->Empty();
-}
-
-FrameSwapMessageSubQueue* FrameSwapMessageQueue::GetSubQueue(
- MessageDeliveryPolicy policy) {
- switch (policy) {
- case MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP:
- return swap_queue_.get();
- break;
- case MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE:
- return visual_state_queue_.get();
- break;
- }
- NOTREACHED();
- return nullptr;
+ return next_drain_messages_.empty() && visual_state_queue_->Empty();
}
void FrameSwapMessageQueue::QueueMessageForFrame(
- MessageDeliveryPolicy policy,
int source_frame_number,
std::unique_ptr<IPC::Message> msg,
bool* is_first) {
base::AutoLock lock(lock_);
- GetSubQueue(policy)
- ->QueueMessage(source_frame_number, std::move(msg), is_first);
+ visual_state_queue_->QueueMessage(source_frame_number, std::move(msg),
+ is_first);
}
void FrameSwapMessageQueue::DidActivate(int source_frame_number) {
@@ -158,8 +111,6 @@ void FrameSwapMessageQueue::DidActivate(int source_frame_number) {
}
void FrameSwapMessageQueue::DidSwap(int source_frame_number) {
- base::AutoLock lock(lock_);
- swap_queue_->DrainMessages(0, &next_drain_messages_);
}
void FrameSwapMessageQueue::DidNotSwap(
@@ -171,7 +122,6 @@ void FrameSwapMessageQueue::DidNotSwap(
case cc::SwapPromise::SWAP_FAILS:
case cc::SwapPromise::COMMIT_NO_UPDATE:
DrainMessages(messages);
- swap_queue_->DrainMessages(source_frame_number, messages);
visual_state_queue_->DrainMessages(source_frame_number, messages);
break;
case cc::SwapPromise::COMMIT_FAILS:
@@ -200,7 +150,7 @@ FrameSwapMessageQueue::AcquireSendMessageScope() {
// static
void FrameSwapMessageQueue::TransferMessages(
std::vector<std::unique_ptr<IPC::Message>>* source,
- vector<IPC::Message>* dest) {
+ std::vector<IPC::Message>* dest) {
for (const auto& msg : *source) {
dest->push_back(*msg.get());
}
diff --git a/chromium/content/renderer/gpu/frame_swap_message_queue.h b/chromium/content/renderer/gpu/frame_swap_message_queue.h
index 54ad846aa3b..a1e1de850ea 100644
--- a/chromium/content/renderer/gpu/frame_swap_message_queue.h
+++ b/chromium/content/renderer/gpu/frame_swap_message_queue.h
@@ -16,7 +16,6 @@
#include "base/threading/thread_checker.h"
#include "cc/trees/swap_promise.h"
#include "content/common/content_export.h"
-#include "content/renderer/message_delivery_policy.h"
namespace IPC {
class Message;
@@ -42,13 +41,11 @@ class CONTENT_EXPORT FrameSwapMessageQueue
// Queues message to be returned on a matching DrainMessages call.
//
- // |policy| determines how messages are matched with DrainMessages calls.
// |source_frame_number| frame number to queue |msg| for.
// |msg| - message to queue. The method takes ownership of |msg|.
// |is_first| - output parameter. Set to true if this was the first message
// enqueued for the given source_frame_number.
- void QueueMessageForFrame(MessageDeliveryPolicy policy,
- int source_frame_number,
+ void QueueMessageForFrame(int source_frame_number,
std::unique_ptr<IPC::Message> msg,
bool* is_first);
@@ -105,13 +102,10 @@ class CONTENT_EXPORT FrameSwapMessageQueue
private:
friend class base::RefCountedThreadSafe<FrameSwapMessageQueue>;
- FrameSwapMessageSubQueue* GetSubQueue(MessageDeliveryPolicy policy);
-
~FrameSwapMessageQueue();
mutable base::Lock lock_;
std::unique_ptr<FrameSwapMessageSubQueue> visual_state_queue_;
- std::unique_ptr<FrameSwapMessageSubQueue> swap_queue_;
std::vector<std::unique_ptr<IPC::Message>> next_drain_messages_;
int32_t routing_id_ = 0;
bool frames_are_discarded_ = false;
diff --git a/chromium/content/renderer/gpu/frame_swap_message_queue_unittest.cc b/chromium/content/renderer/gpu/frame_swap_message_queue_unittest.cc
index ce18fba26b2..7c3c95f7008 100644
--- a/chromium/content/renderer/gpu/frame_swap_message_queue_unittest.cc
+++ b/chromium/content/renderer/gpu/frame_swap_message_queue_unittest.cc
@@ -21,26 +21,22 @@ class FrameSwapMessageQueueTest : public testing::Test {
protected:
void QueueNextSwapMessage(std::unique_ptr<IPC::Message> msg) {
- queue_->QueueMessageForFrame(MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP, 0,
- std::move(msg), nullptr);
+ queue_->QueueMessageForFrame(0, std::move(msg), nullptr);
}
void QueueNextSwapMessage(std::unique_ptr<IPC::Message> msg, bool* first) {
- queue_->QueueMessageForFrame(MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP, 0,
- std::move(msg), first);
+ queue_->QueueMessageForFrame(0, std::move(msg), first);
}
void QueueVisualStateMessage(int source_frame_number,
std::unique_ptr<IPC::Message> msg) {
- queue_->QueueMessageForFrame(MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE,
- source_frame_number, std::move(msg), nullptr);
+ queue_->QueueMessageForFrame(source_frame_number, std::move(msg), nullptr);
}
void QueueVisualStateMessage(int source_frame_number,
std::unique_ptr<IPC::Message> msg,
bool* first) {
- queue_->QueueMessageForFrame(MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE,
- source_frame_number, std::move(msg), first);
+ queue_->QueueMessageForFrame(source_frame_number, std::move(msg), first);
}
void DrainMessages(int source_frame_number,
diff --git a/chromium/content/renderer/gpu/gpu_benchmarking_extension.cc b/chromium/content/renderer/gpu/gpu_benchmarking_extension.cc
index 0b2b903d230..bef6372a97b 100644
--- a/chromium/content/renderer/gpu/gpu_benchmarking_extension.cc
+++ b/chromium/content/renderer/gpu/gpu_benchmarking_extension.cc
@@ -287,7 +287,10 @@ bool BeginSmoothScroll(GpuBenchmarkingContext* context,
float speed_in_pixels_s,
bool prevent_fling,
float start_x,
- float start_y) {
+ float start_y,
+ float fling_velocity,
+ bool precise_scrolling_deltas,
+ bool scroll_by_page) {
gfx::Rect rect = context->render_view_impl()->GetWidget()->ViewRect();
rect -= rect.OffsetFromOrigin();
if (!rect.Contains(start_x, start_y)) {
@@ -324,31 +327,47 @@ bool BeginSmoothScroll(GpuBenchmarkingContext* context,
gesture_params.speed_in_pixels_s = speed_in_pixels_s;
gesture_params.prevent_fling = prevent_fling;
+ gesture_params.precise_scrolling_deltas = precise_scrolling_deltas;
+ gesture_params.scroll_by_page = scroll_by_page;
gesture_params.anchor.SetPoint(start_x, start_y);
+ DCHECK(gesture_source_type != SyntheticGestureParams::TOUCH_INPUT ||
+ fling_velocity == 0);
float distance_length = pixels_to_scroll;
gfx::Vector2dF distance;
- if (direction == "down")
+ if (direction == "down") {
distance.set_y(-distance_length);
- else if (direction == "up")
+ gesture_params.fling_velocity_y = fling_velocity;
+ } else if (direction == "up") {
distance.set_y(distance_length);
- else if (direction == "right")
+ gesture_params.fling_velocity_y = -fling_velocity;
+ } else if (direction == "right") {
distance.set_x(-distance_length);
- else if (direction == "left")
+ gesture_params.fling_velocity_x = fling_velocity;
+ } else if (direction == "left") {
distance.set_x(distance_length);
- else if (direction == "upleft") {
+ gesture_params.fling_velocity_x = -fling_velocity;
+ } else if (direction == "upleft") {
distance.set_y(distance_length);
distance.set_x(distance_length);
+ gesture_params.fling_velocity_x = -fling_velocity;
+ gesture_params.fling_velocity_y = -fling_velocity;
} else if (direction == "upright") {
distance.set_y(distance_length);
distance.set_x(-distance_length);
+ gesture_params.fling_velocity_x = fling_velocity;
+ gesture_params.fling_velocity_y = -fling_velocity;
} else if (direction == "downleft") {
distance.set_y(-distance_length);
distance.set_x(distance_length);
+ gesture_params.fling_velocity_x = -fling_velocity;
+ gesture_params.fling_velocity_y = fling_velocity;
} else if (direction == "downright") {
distance.set_y(-distance_length);
distance.set_x(-distance_length);
+ gesture_params.fling_velocity_x = fling_velocity;
+ gesture_params.fling_velocity_y = fling_velocity;
} else {
return false;
}
@@ -547,6 +566,7 @@ gin::ObjectTemplateBuilder GpuBenchmarking::GetObjectTemplateBuilder(
&GpuBenchmarking::SendMessageToMicroBenchmark)
.SetMethod("hasGpuChannel", &GpuBenchmarking::HasGpuChannel)
.SetMethod("hasGpuProcess", &GpuBenchmarking::HasGpuProcess)
+ .SetMethod("crashGpuProcess", &GpuBenchmarking::CrashGpuProcess)
.SetMethod("getGpuDriverBugWorkarounds",
&GpuBenchmarking::GetGpuDriverBugWorkarounds)
.SetMethod("startProfiling", &GpuBenchmarking::StartProfiling)
@@ -640,21 +660,32 @@ bool GpuBenchmarking::SmoothScrollBy(gin::Arguments* args) {
int gesture_source_type = SyntheticGestureParams::DEFAULT_INPUT;
std::string direction = "down";
float speed_in_pixels_s = 800;
+ bool precise_scrolling_deltas = true;
+ bool scroll_by_page = false;
if (!GetOptionalArg(args, &pixels_to_scroll) ||
- !GetOptionalArg(args, &callback) ||
- !GetOptionalArg(args, &start_x) ||
+ !GetOptionalArg(args, &callback) || !GetOptionalArg(args, &start_x) ||
!GetOptionalArg(args, &start_y) ||
!GetOptionalArg(args, &gesture_source_type) ||
!GetOptionalArg(args, &direction) ||
- !GetOptionalArg(args, &speed_in_pixels_s)) {
+ !GetOptionalArg(args, &speed_in_pixels_s) ||
+ !GetOptionalArg(args, &precise_scrolling_deltas) ||
+ !GetOptionalArg(args, &scroll_by_page)) {
return false;
}
+ // For all touch inputs, always scroll by precise deltas.
+ DCHECK(gesture_source_type != SyntheticGestureParams::TOUCH_INPUT ||
+ precise_scrolling_deltas);
+ // Scroll by page only for mouse inputs.
+ DCHECK(!scroll_by_page ||
+ gesture_source_type == SyntheticGestureParams::MOUSE_INPUT);
+
EnsureRemoteInterface();
return BeginSmoothScroll(&context, args, input_injector_, pixels_to_scroll,
callback, gesture_source_type, direction,
- speed_in_pixels_s, true, start_x, start_y);
+ speed_in_pixels_s, true, start_x, start_y, 0,
+ precise_scrolling_deltas, scroll_by_page);
}
bool GpuBenchmarking::SmoothDrag(gin::Arguments* args) {
@@ -699,21 +730,32 @@ bool GpuBenchmarking::Swipe(gin::Arguments* args) {
float start_x = rect.width / 2;
float start_y = rect.height / 2;
float speed_in_pixels_s = 800;
+ float fling_velocity = 0;
+ int gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
if (!GetOptionalArg(args, &direction) ||
!GetOptionalArg(args, &pixels_to_scroll) ||
- !GetOptionalArg(args, &callback) ||
- !GetOptionalArg(args, &start_x) ||
+ !GetOptionalArg(args, &callback) || !GetOptionalArg(args, &start_x) ||
!GetOptionalArg(args, &start_y) ||
- !GetOptionalArg(args, &speed_in_pixels_s)) {
+ !GetOptionalArg(args, &speed_in_pixels_s) ||
+ !GetOptionalArg(args, &fling_velocity) ||
+ !GetOptionalArg(args, &gesture_source_type)) {
return false;
}
+ // For touchpad swipe, we should be given a fling velocity, but it is not
+ // needed for touchscreen swipe, because we will calculate the velocity in
+ // our code.
+ if (gesture_source_type == SyntheticGestureParams::TOUCHPAD_INPUT &&
+ fling_velocity == 0)
+ fling_velocity = 1000;
+
EnsureRemoteInterface();
- return BeginSmoothScroll(
- &context, args, input_injector_, -pixels_to_scroll, callback,
- 1, // TOUCH_INPUT
- direction, speed_in_pixels_s, false, start_x, start_y);
+ return BeginSmoothScroll(&context, args, input_injector_, -pixels_to_scroll,
+ callback, gesture_source_type, direction,
+ speed_in_pixels_s, false, start_x, start_y,
+ fling_velocity, true /* precise_scrolling_deltas */,
+ false /* scroll_by_page */);
}
bool GpuBenchmarking::ScrollBounce(gin::Arguments* args) {
@@ -1079,20 +1121,45 @@ bool GpuBenchmarking::HasGpuProcess() {
return has_gpu_process;
}
+void GpuBenchmarking::CrashGpuProcess() {
+ gpu::GpuChannelHost* gpu_channel =
+ RenderThreadImpl::current()->GetGpuChannel();
+ if (!gpu_channel)
+ return;
+ gpu_channel->CrashGpuProcessForTesting();
+}
+
void GpuBenchmarking::GetGpuDriverBugWorkarounds(gin::Arguments* args) {
std::vector<std::string> gpu_driver_bug_workarounds;
gpu::GpuChannelHost* gpu_channel =
RenderThreadImpl::current()->GetGpuChannel();
if (!gpu_channel)
return;
+ const gpu::GpuFeatureInfo& gpu_feature_info =
+ gpu_channel->gpu_feature_info();
const std::vector<int32_t>& workarounds =
- gpu_channel->gpu_feature_info().enabled_gpu_driver_bug_workarounds;
+ gpu_feature_info.enabled_gpu_driver_bug_workarounds;
for (int32_t workaround : workarounds) {
gpu_driver_bug_workarounds.push_back(
gpu::GpuDriverBugWorkaroundTypeToString(
static_cast<gpu::GpuDriverBugWorkaroundType>(workaround)));
}
+ // This code must be kept in sync with compositor_util's
+ // GetDriverBugWorkaroundsImpl.
+ for (auto ext : base::SplitString(gpu_feature_info.disabled_extensions,
+ " ",
+ base::TRIM_WHITESPACE,
+ base::SPLIT_WANT_NONEMPTY)) {
+ gpu_driver_bug_workarounds.push_back("disabled_extension_" + ext);
+ }
+ for (auto ext : base::SplitString(gpu_feature_info.disabled_webgl_extensions,
+ " ",
+ base::TRIM_WHITESPACE,
+ base::SPLIT_WANT_NONEMPTY)) {
+ gpu_driver_bug_workarounds.push_back("disabled_webgl_extension_" + ext);
+ }
+
v8::Local<v8::Value> result;
if (gin::TryConvertToV8(args->isolate(), gpu_driver_bug_workarounds, &result))
args->Return(result);
diff --git a/chromium/content/renderer/gpu/gpu_benchmarking_extension.h b/chromium/content/renderer/gpu/gpu_benchmarking_extension.h
index f423142cda6..b3a66a5fd40 100644
--- a/chromium/content/renderer/gpu/gpu_benchmarking_extension.h
+++ b/chromium/content/renderer/gpu/gpu_benchmarking_extension.h
@@ -80,6 +80,7 @@ class GpuBenchmarking : public gin::Wrappable<GpuBenchmarking> {
bool SendMessageToMicroBenchmark(int id, v8::Local<v8::Object> message);
bool HasGpuChannel();
bool HasGpuProcess();
+ void CrashGpuProcess();
void GetGpuDriverBugWorkarounds(gin::Arguments* args);
// Starts/stops the sampling profiler. StartProfiling takes one optional
diff --git a/chromium/content/renderer/gpu/layer_tree_view.cc b/chromium/content/renderer/gpu/layer_tree_view.cc
index 511f04a5cac..7b8ae60acba 100644
--- a/chromium/content/renderer/gpu/layer_tree_view.cc
+++ b/chromium/content/renderer/gpu/layer_tree_view.cc
@@ -10,11 +10,12 @@
#include "base/auto_reset.h"
#include "base/callback.h"
+#include "base/feature_list.h"
#include "base/location.h"
#include "base/single_thread_task_runner.h"
-#include "base/task_scheduler/post_task.h"
-#include "base/task_scheduler/task_scheduler.h"
-#include "base/task_scheduler/task_traits.h"
+#include "base/task/post_task.h"
+#include "base/task/task_scheduler/task_scheduler.h"
+#include "base/task/task_traits.h"
#include "base/time/time.h"
#include "base/values.h"
#include "cc/animation/animation_host.h"
@@ -57,6 +58,12 @@ namespace {
using ReportTimeCallback = blink::WebLayerTreeView::ReportTimeCallback;
+// Enables using presentation times instead of swap times in swap promises.
+// Currently, these promises are only used by Paint Timing, but they will be
+// used by other APIs such as Event Timing.
+const base::Feature kUsePresentationTimeInSwapPromise = {
+ "UsePresentationTimeInSwapPromise", base::FEATURE_DISABLED_BY_DEFAULT};
+
class ReportTimeSwapPromise : public cc::SwapPromise {
public:
ReportTimeSwapPromise(ReportTimeCallback callback,
@@ -91,6 +98,11 @@ ReportTimeSwapPromise::~ReportTimeSwapPromise() {}
void ReportTimeSwapPromise::WillSwap(viz::CompositorFrameMetadata* metadata) {
DCHECK_GT(metadata->frame_token, 0u);
metadata->request_presentation_feedback = true;
+ if (!base::FeatureList::IsEnabled(kUsePresentationTimeInSwapPromise))
+ return;
+
+ // If using presentation timestamp, post task here calling
+ // LayerTreeView::AddPresentationCallback.
auto* task_runner = task_runner_.get();
task_runner->PostTask(
FROM_HERE,
@@ -102,8 +114,14 @@ void ReportTimeSwapPromise::WillSwap(viz::CompositorFrameMetadata* metadata) {
}
void ReportTimeSwapPromise::DidSwap() {
- // If swap did happen, then the paint-time will be reported when the
- // presentation feedback is received.
+ if (base::FeatureList::IsEnabled(kUsePresentationTimeInSwapPromise))
+ return;
+
+ // If using swap timestamp, the swap promise should return the current time.
+ task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(std::move(callback_),
+ blink::WebLayerTreeView::SwapResult::kDidSwap,
+ base::TimeTicks::Now()));
}
void ReportTimeSwapPromise::DidNotSwap(
@@ -123,6 +141,8 @@ void ReportTimeSwapPromise::DidNotSwap(
result = blink::WebLayerTreeView::SwapResult::kDidNotSwapActivationFails;
break;
}
+ // During a failed swap, return the current time regardless of whether we're
+ // using presentation or swap timestamps.
task_runner_->PostTask(FROM_HERE, base::BindOnce(std::move(callback_), result,
base::TimeTicks::Now()));
}
@@ -328,7 +348,8 @@ void LayerTreeView::SetNeedsBeginFrame() {
void LayerTreeView::RegisterViewportLayers(const ViewportLayers& layers) {
cc::LayerTreeHost::ViewportLayers viewport_layers;
- viewport_layers.overscroll_elasticity = layers.overscroll_elasticity;
+ viewport_layers.overscroll_elasticity_element_id =
+ layers.overscroll_elasticity_element_id;
viewport_layers.page_scale = layers.page_scale;
viewport_layers.inner_viewport_container = layers.inner_viewport_container;
viewport_layers.outer_viewport_container = layers.outer_viewport_container;
diff --git a/chromium/content/renderer/gpu/queue_message_swap_promise_unittest.cc b/chromium/content/renderer/gpu/queue_message_swap_promise_unittest.cc
index 098d92e1e00..551cef8b5b0 100644
--- a/chromium/content/renderer/gpu/queue_message_swap_promise_unittest.cc
+++ b/chromium/content/renderer/gpu/queue_message_swap_promise_unittest.cc
@@ -26,16 +26,6 @@
namespace content {
-class TestRenderWidget : public RenderWidget {
- public:
- using RenderWidget::QueueMessageImpl;
-
- private:
- ~TestRenderWidget() override {}
-
- DISALLOW_COPY_AND_ASSIGN(TestRenderWidget);
-};
-
class TestSyncMessageFilter : public IPC::SyncMessageFilter {
public:
TestSyncMessageFilter() : IPC::SyncMessageFilter(nullptr) {}
@@ -73,11 +63,6 @@ class TestSyncMessageFilter : public IPC::SyncMessageFilter {
DISALLOW_COPY_AND_ASSIGN(TestSyncMessageFilter);
};
-struct QueueMessageData {
- MessageDeliveryPolicy policy;
- int source_frame_number;
-};
-
class QueueMessageSwapPromiseTest : public testing::Test {
public:
QueueMessageSwapPromiseTest()
@@ -88,11 +73,10 @@ class QueueMessageSwapPromiseTest : public testing::Test {
std::unique_ptr<cc::SwapPromise> QueueMessageImpl(
IPC::Message* msg,
- MessageDeliveryPolicy policy,
int source_frame_number) {
- return TestRenderWidget::QueueMessageImpl(
- msg, policy, frame_swap_message_queue_.get(), sync_message_filter_,
- source_frame_number);
+ return RenderWidget::QueueMessageImpl(msg, frame_swap_message_queue_.get(),
+ sync_message_filter_,
+ source_frame_number);
}
const std::vector<std::unique_ptr<IPC::Message>>& DirectSendMessages() {
@@ -132,13 +116,12 @@ class QueueMessageSwapPromiseTest : public testing::Test {
return ContainsMessage(NextSwapMessages(), message);
}
- void QueueMessages(QueueMessageData data[], size_t count) {
+ void QueueMessages(int source_frame_numbers[], size_t count) {
for (size_t i = 0; i < count; ++i) {
messages_.push_back(
IPC::Message(0, i + 1, IPC::Message::PRIORITY_NORMAL));
promises_.push_back(QueueMessageImpl(new IPC::Message(messages_[i]),
- data[i].policy,
- data[i].source_frame_number));
+ source_frame_numbers[i]));
}
}
@@ -171,11 +154,8 @@ class QueueMessageSwapPromiseTest : public testing::Test {
};
TEST_F(QueueMessageSwapPromiseTest, NextSwapPolicySchedulesMessageForNextSwap) {
- QueueMessageData data[] = {
- /* { policy, source_frame_number } */
- {MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP, 1},
- };
- QueueMessages(data, arraysize(data));
+ int source_frame_numbers[] = {1};
+ QueueMessages(source_frame_numbers, base::size(source_frame_numbers));
ASSERT_TRUE(promises_[0].get());
promises_[0]->DidActivate();
@@ -188,12 +168,8 @@ TEST_F(QueueMessageSwapPromiseTest, NextSwapPolicySchedulesMessageForNextSwap) {
}
TEST_F(QueueMessageSwapPromiseTest, NextSwapPolicyNeedsAtMostOnePromise) {
- QueueMessageData data[] = {
- /* { policy, source_frame_number } */
- {MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP, 1},
- {MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP, 1},
- };
- QueueMessages(data, arraysize(data));
+ int source_frame_numbers[] = {1, 1};
+ QueueMessages(source_frame_numbers, base::size(source_frame_numbers));
ASSERT_TRUE(promises_[0].get());
ASSERT_FALSE(promises_[1].get());
@@ -202,11 +178,8 @@ TEST_F(QueueMessageSwapPromiseTest, NextSwapPolicyNeedsAtMostOnePromise) {
}
TEST_F(QueueMessageSwapPromiseTest, NextSwapPolicySendsMessageOnNoUpdate) {
- QueueMessageData data[] = {
- /* { policy, source_frame_number } */
- {MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP, 1},
- };
- QueueMessages(data, arraysize(data));
+ int source_frame_numbers[] = {1};
+ QueueMessages(source_frame_numbers, base::size(source_frame_numbers));
promises_[0]->DidNotSwap(cc::SwapPromise::COMMIT_NO_UPDATE);
EXPECT_TRUE(ContainsMessage(DirectSendMessages(), messages_[0]));
@@ -215,11 +188,8 @@ TEST_F(QueueMessageSwapPromiseTest, NextSwapPolicySendsMessageOnNoUpdate) {
}
TEST_F(QueueMessageSwapPromiseTest, NextSwapPolicySendsMessageOnSwapFails) {
- QueueMessageData data[] = {
- /* { policy, source_frame_number } */
- {MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP, 1},
- };
- QueueMessages(data, arraysize(data));
+ int source_frame_numbers[] = {1};
+ QueueMessages(source_frame_numbers, base::size(source_frame_numbers));
promises_[0]->DidNotSwap(cc::SwapPromise::SWAP_FAILS);
EXPECT_TRUE(ContainsMessage(DirectSendMessages(), messages_[0]));
@@ -227,28 +197,23 @@ TEST_F(QueueMessageSwapPromiseTest, NextSwapPolicySendsMessageOnSwapFails) {
EXPECT_TRUE(frame_swap_message_queue_->Empty());
}
-TEST_F(QueueMessageSwapPromiseTest, NextSwapPolicyRetainsMessageOnCommitFails) {
- QueueMessageData data[] = {
- /* { policy, source_frame_number } */
- {MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP, 1},
- };
- QueueMessages(data, arraysize(data));
+TEST_F(QueueMessageSwapPromiseTest,
+ NextActivatePolicyRetainsMessageOnCommitFails) {
+ int source_frame_numbers[] = {1};
+ QueueMessages(source_frame_numbers, base::size(source_frame_numbers));
promises_[0]->DidNotSwap(cc::SwapPromise::COMMIT_FAILS);
EXPECT_TRUE(DirectSendMessages().empty());
EXPECT_TRUE(LastSwapMessages().empty());
EXPECT_FALSE(frame_swap_message_queue_->Empty());
- frame_swap_message_queue_->DidSwap(2);
+ frame_swap_message_queue_->DidActivate(2);
EXPECT_TRUE(NextSwapHasMessage(messages_[0]));
}
TEST_F(QueueMessageSwapPromiseTest,
VisualStateQueuesMessageWhenCommitRequested) {
- QueueMessageData data[] = {
- /* { policy, source_frame_number } */
- {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE, 1},
- };
- QueueMessages(data, arraysize(data));
+ int source_frame_numbers[] = {1};
+ QueueMessages(source_frame_numbers, base::size(source_frame_numbers));
ASSERT_TRUE(promises_[0].get());
EXPECT_TRUE(DirectSendMessages().empty());
@@ -260,12 +225,8 @@ TEST_F(QueueMessageSwapPromiseTest,
TEST_F(QueueMessageSwapPromiseTest,
VisualStateQueuesMessageWhenOtherMessageAlreadyQueued) {
- QueueMessageData data[] = {
- /* { policy, source_frame_number } */
- {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE, 1},
- {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE, 1},
- };
- QueueMessages(data, arraysize(data));
+ int source_frame_numbers[] = {1, 1};
+ QueueMessages(source_frame_numbers, base::size(source_frame_numbers));
EXPECT_TRUE(DirectSendMessages().empty());
EXPECT_FALSE(frame_swap_message_queue_->Empty());
@@ -275,13 +236,8 @@ TEST_F(QueueMessageSwapPromiseTest,
}
TEST_F(QueueMessageSwapPromiseTest, VisualStateSwapPromiseDidActivate) {
- QueueMessageData data[] = {
- /* { policy, source_frame_number } */
- {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE, 1},
- {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE, 1},
- {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE, 2},
- };
- QueueMessages(data, arraysize(data));
+ int source_frame_numbers[] = {1, 1, 2};
+ QueueMessages(source_frame_numbers, base::size(source_frame_numbers));
promises_[0]->DidActivate();
promises_[0]->WillSwap(&dummy_metadata_);
@@ -308,13 +264,8 @@ TEST_F(QueueMessageSwapPromiseTest, VisualStateSwapPromiseDidActivate) {
void QueueMessageSwapPromiseTest::VisualStateSwapPromiseDidNotSwap(
cc::SwapPromise::DidNotSwapReason reason) {
- QueueMessageData data[] = {
- /* { policy, source_frame_number } */
- {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE, 1},
- {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE, 1},
- {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE, 2},
- };
- QueueMessages(data, arraysize(data));
+ int source_frame_numbers[] = {1, 1, 2};
+ QueueMessages(source_frame_numbers, base::size(source_frame_numbers));
// If we fail to swap with COMMIT_FAILS or ACTIVATE_FAILS, then
// messages are delivered by the RenderFrameHostImpl destructor,
diff --git a/chromium/content/renderer/ime_event_guard.cc b/chromium/content/renderer/ime_event_guard.cc
index b2d78c6b4f5..c6f5b0b8e89 100644
--- a/chromium/content/renderer/ime_event_guard.cc
+++ b/chromium/content/renderer/ime_event_guard.cc
@@ -13,7 +13,7 @@ namespace content {
// it from other updates so that we can wait for it safely. So it is false by
// default.
ImeEventGuard::ImeEventGuard(RenderWidget* widget)
- : widget_(widget), show_virtual_keyboard_(false), reply_to_request_(false) {
+ : widget_(widget), show_virtual_keyboard_(false) {
widget_->OnImeEventGuardStart(this);
}
diff --git a/chromium/content/renderer/ime_event_guard.h b/chromium/content/renderer/ime_event_guard.h
index 1df77f34d33..a92d453e9e9 100644
--- a/chromium/content/renderer/ime_event_guard.h
+++ b/chromium/content/renderer/ime_event_guard.h
@@ -16,13 +16,11 @@ class ImeEventGuard {
~ImeEventGuard();
bool show_virtual_keyboard() const { return show_virtual_keyboard_; }
- bool reply_to_request() const { return reply_to_request_; }
void set_show_virtual_keyboard(bool show) { show_virtual_keyboard_ = show; }
private:
RenderWidget* widget_;
bool show_virtual_keyboard_;
- bool reply_to_request_;
};
}
diff --git a/chromium/content/renderer/in_process_renderer_thread.cc b/chromium/content/renderer/in_process_renderer_thread.cc
index e6a3a5d9e22..01ffff7bf25 100644
--- a/chromium/content/renderer/in_process_renderer_thread.cc
+++ b/chromium/content/renderer/in_process_renderer_thread.cc
@@ -8,6 +8,7 @@
#include "content/renderer/render_process.h"
#include "content/renderer/render_process_impl.h"
#include "content/renderer/render_thread_impl.h"
+#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
#if defined(OS_ANDROID)
#include "base/android/jni_android.h"
@@ -46,8 +47,14 @@ void InProcessRendererThread::Init() {
// Android. Temporary CHECK() to debug http://crbug.com/514141
CHECK(!render_process_);
#endif
+ std::unique_ptr<blink::scheduler::WebThreadScheduler> main_thread_scheduler =
+ blink::scheduler::WebThreadScheduler::CreateMainThreadScheduler();
+
render_process_ = RenderProcessImpl::Create();
- RenderThreadImpl::Create(params_, message_loop());
+ // RenderThreadImpl doesn't currently support a proper shutdown sequence
+ // and it's okay when we're running in multi-process mode because renderers
+ // get killed by the OS. In-process mode is used for test and debug only.
+ new RenderThreadImpl(params_, std::move(main_thread_scheduler));
}
void InProcessRendererThread::CleanUp() {
diff --git a/chromium/content/renderer/indexed_db/indexed_db_callbacks_impl.cc b/chromium/content/renderer/indexed_db/indexed_db_callbacks_impl.cc
index 3c4baafbdcc..81d7278d0f5 100644
--- a/chromium/content/renderer/indexed_db/indexed_db_callbacks_impl.cc
+++ b/chromium/content/renderer/indexed_db/indexed_db_callbacks_impl.cc
@@ -4,8 +4,6 @@
#include "content/renderer/indexed_db/indexed_db_callbacks_impl.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "content/common/indexed_db/indexed_db_constants.h"
#include "content/renderer/indexed_db/indexed_db_dispatcher.h"
#include "content/renderer/indexed_db/indexed_db_key_builders.h"
#include "content/renderer/indexed_db/webidbcursor_impl.h"
@@ -16,6 +14,7 @@
#include "third_party/blink/public/platform/modules/indexeddb/web_idb_metadata.h"
#include "third_party/blink/public/platform/modules/indexeddb/web_idb_value.h"
+using blink::IndexedDBDatabaseMetadata;
using blink::WebBlobInfo;
using blink::WebData;
using blink::WebIDBCallbacks;
@@ -24,13 +23,13 @@ using blink::WebIDBMetadata;
using blink::WebIDBValue;
using blink::WebString;
using blink::WebVector;
-using indexed_db::mojom::DatabaseAssociatedPtrInfo;
+using blink::mojom::IDBDatabaseAssociatedPtrInfo;
namespace content {
namespace {
-void ConvertIndexMetadata(const content::IndexedDBIndexMetadata& metadata,
+void ConvertIndexMetadata(const blink::IndexedDBIndexMetadata& metadata,
WebIDBMetadata::Index* output) {
output->id = metadata.id;
output->name = WebString::FromUTF16(metadata.name);
@@ -40,7 +39,7 @@ void ConvertIndexMetadata(const content::IndexedDBIndexMetadata& metadata,
}
void ConvertObjectStoreMetadata(
- const content::IndexedDBObjectStoreMetadata& metadata,
+ const blink::IndexedDBObjectStoreMetadata& metadata,
WebIDBMetadata::ObjectStore* output) {
output->id = metadata.id;
output->name = WebString::FromUTF16(metadata.name);
@@ -53,7 +52,7 @@ void ConvertObjectStoreMetadata(
ConvertIndexMetadata(iter.second, &output->indexes[i++]);
}
-void ConvertDatabaseMetadata(const content::IndexedDBDatabaseMetadata& metadata,
+void ConvertDatabaseMetadata(const IndexedDBDatabaseMetadata& metadata,
WebIDBMetadata* output) {
output->id = metadata.id;
output->name = WebString::FromUTF16(metadata.name);
@@ -66,7 +65,7 @@ void ConvertDatabaseMetadata(const content::IndexedDBDatabaseMetadata& metadata,
ConvertObjectStoreMetadata(iter.second, &output->object_stores[i++]);
}
-WebIDBValue ConvertReturnValue(const indexed_db::mojom::ReturnValuePtr& value) {
+WebIDBValue ConvertReturnValue(const blink::mojom::IDBReturnValuePtr& value) {
if (!value)
return WebIDBValue(WebData(), WebVector<WebBlobInfo>());
@@ -80,7 +79,7 @@ WebIDBValue ConvertReturnValue(const indexed_db::mojom::ReturnValuePtr& value) {
// static
WebIDBValue IndexedDBCallbacksImpl::ConvertValue(
- const indexed_db::mojom::ValuePtr& value) {
+ const blink::mojom::IDBValuePtr& value) {
if (!value || value->bits.empty())
return WebIDBValue(WebData(), WebVector<WebBlobInfo>());
@@ -109,159 +108,21 @@ WebIDBValue IndexedDBCallbacksImpl::ConvertValue(
IndexedDBCallbacksImpl::IndexedDBCallbacksImpl(
std::unique_ptr<WebIDBCallbacks> callbacks,
int64_t transaction_id,
- const base::WeakPtr<WebIDBCursorImpl>& cursor,
- scoped_refptr<base::SingleThreadTaskRunner> io_runner,
- scoped_refptr<base::SingleThreadTaskRunner> callback_runner)
- : internal_state_(new InternalState(std::move(callbacks),
- transaction_id,
- cursor,
- std::move(io_runner),
- callback_runner)),
- callback_runner_(std::move(callback_runner)) {}
-
-IndexedDBCallbacksImpl::~IndexedDBCallbacksImpl() {
- callback_runner_->DeleteSoon(FROM_HERE, internal_state_);
-}
-
-void IndexedDBCallbacksImpl::Error(int32_t code,
- const base::string16& message) {
- callback_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&InternalState::Error, base::Unretained(internal_state_),
- code, message));
-}
-
-void IndexedDBCallbacksImpl::SuccessStringList(
- const std::vector<base::string16>& value) {
- callback_runner_->PostTask(
- FROM_HERE, base::BindOnce(&InternalState::SuccessStringList,
- base::Unretained(internal_state_), value));
-}
-
-void IndexedDBCallbacksImpl::Blocked(int64_t existing_version) {
- callback_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&InternalState::Blocked, base::Unretained(internal_state_),
- existing_version));
-}
-
-void IndexedDBCallbacksImpl::UpgradeNeeded(
- DatabaseAssociatedPtrInfo database,
- int64_t old_version,
- blink::WebIDBDataLoss data_loss,
- const std::string& data_loss_message,
- const content::IndexedDBDatabaseMetadata& metadata) {
- callback_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&InternalState::UpgradeNeeded,
- base::Unretained(internal_state_), std::move(database),
- old_version, data_loss, data_loss_message, metadata));
-}
-
-void IndexedDBCallbacksImpl::SuccessDatabase(
- DatabaseAssociatedPtrInfo database,
- const content::IndexedDBDatabaseMetadata& metadata) {
- callback_runner_->PostTask(FROM_HERE,
- base::BindOnce(&InternalState::SuccessDatabase,
- base::Unretained(internal_state_),
- std::move(database), metadata));
-}
-
-void IndexedDBCallbacksImpl::SuccessCursor(
- indexed_db::mojom::CursorAssociatedPtrInfo cursor,
- const IndexedDBKey& key,
- const IndexedDBKey& primary_key,
- indexed_db::mojom::ValuePtr value) {
- callback_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&InternalState::SuccessCursor,
- base::Unretained(internal_state_), std::move(cursor), key,
- primary_key, std::move(value)));
-}
-
-void IndexedDBCallbacksImpl::SuccessValue(
- indexed_db::mojom::ReturnValuePtr value) {
- callback_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&InternalState::SuccessValue,
- base::Unretained(internal_state_), std::move(value)));
-}
-
-void IndexedDBCallbacksImpl::SuccessCursorContinue(
- const IndexedDBKey& key,
- const IndexedDBKey& primary_key,
- indexed_db::mojom::ValuePtr value) {
- callback_runner_->PostTask(
- FROM_HERE, base::BindOnce(&InternalState::SuccessCursorContinue,
- base::Unretained(internal_state_), key,
- primary_key, std::move(value)));
-}
-
-void IndexedDBCallbacksImpl::SuccessCursorPrefetch(
- const std::vector<IndexedDBKey>& keys,
- const std::vector<IndexedDBKey>& primary_keys,
- std::vector<indexed_db::mojom::ValuePtr> values) {
- callback_runner_->PostTask(
- FROM_HERE, base::BindOnce(&InternalState::SuccessCursorPrefetch,
- base::Unretained(internal_state_), keys,
- primary_keys, std::move(values)));
-}
-
-void IndexedDBCallbacksImpl::SuccessArray(
- std::vector<indexed_db::mojom::ReturnValuePtr> values) {
- callback_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&InternalState::SuccessArray,
- base::Unretained(internal_state_), std::move(values)));
-}
-
-void IndexedDBCallbacksImpl::SuccessKey(const IndexedDBKey& key) {
- callback_runner_->PostTask(
- FROM_HERE, base::BindOnce(&InternalState::SuccessKey,
- base::Unretained(internal_state_), key));
-}
-
-void IndexedDBCallbacksImpl::SuccessInteger(int64_t value) {
- callback_runner_->PostTask(
- FROM_HERE, base::BindOnce(&InternalState::SuccessInteger,
- base::Unretained(internal_state_), value));
-}
-
-void IndexedDBCallbacksImpl::Success() {
- callback_runner_->PostTask(FROM_HERE,
- base::BindOnce(&InternalState::Success,
- base::Unretained(internal_state_)));
-}
-
-IndexedDBCallbacksImpl::InternalState::InternalState(
- std::unique_ptr<blink::WebIDBCallbacks> callbacks,
- int64_t transaction_id,
- const base::WeakPtr<WebIDBCursorImpl>& cursor,
- scoped_refptr<base::SingleThreadTaskRunner> io_runner,
- scoped_refptr<base::SingleThreadTaskRunner> callback_runner)
+ const base::WeakPtr<WebIDBCursorImpl>& cursor)
: callbacks_(std::move(callbacks)),
- transaction_id_(transaction_id),
cursor_(cursor),
- io_runner_(std::move(io_runner)),
- callback_runner_(std::move(callback_runner)) {
- IndexedDBDispatcher::ThreadSpecificInstance()->RegisterMojoOwnedCallbacks(
- this);
-}
+ transaction_id_(transaction_id) {}
-IndexedDBCallbacksImpl::InternalState::~InternalState() {
- IndexedDBDispatcher::ThreadSpecificInstance()->UnregisterMojoOwnedCallbacks(
- this);
-}
+IndexedDBCallbacksImpl::~IndexedDBCallbacksImpl() = default;
-void IndexedDBCallbacksImpl::InternalState::Error(
- int32_t code,
- const base::string16& message) {
+void IndexedDBCallbacksImpl::Error(int32_t code,
+ const base::string16& message) {
callbacks_->OnError(
blink::WebIDBDatabaseError(code, WebString::FromUTF16(message)));
callbacks_.reset();
}
-void IndexedDBCallbacksImpl::InternalState::SuccessStringList(
+void IndexedDBCallbacksImpl::SuccessStringList(
const std::vector<base::string16>& value) {
WebVector<WebString> web_value(value.size());
std::transform(
@@ -271,19 +132,18 @@ void IndexedDBCallbacksImpl::InternalState::SuccessStringList(
callbacks_.reset();
}
-void IndexedDBCallbacksImpl::InternalState::Blocked(int64_t existing_version) {
+void IndexedDBCallbacksImpl::Blocked(int64_t existing_version) {
callbacks_->OnBlocked(existing_version);
// Not resetting |callbacks_|.
}
-void IndexedDBCallbacksImpl::InternalState::UpgradeNeeded(
- DatabaseAssociatedPtrInfo database_info,
+void IndexedDBCallbacksImpl::UpgradeNeeded(
+ IDBDatabaseAssociatedPtrInfo database_info,
int64_t old_version,
blink::WebIDBDataLoss data_loss,
const std::string& data_loss_message,
- const content::IndexedDBDatabaseMetadata& metadata) {
- WebIDBDatabase* database = new WebIDBDatabaseImpl(
- std::move(database_info), io_runner_, callback_runner_);
+ const IndexedDBDatabaseMetadata& metadata) {
+ WebIDBDatabase* database = new WebIDBDatabaseImpl(std::move(database_info));
WebIDBMetadata web_metadata;
ConvertDatabaseMetadata(metadata, &web_metadata);
callbacks_->OnUpgradeNeeded(old_version, database, web_metadata, data_loss,
@@ -291,13 +151,12 @@ void IndexedDBCallbacksImpl::InternalState::UpgradeNeeded(
// Not resetting |callbacks_|.
}
-void IndexedDBCallbacksImpl::InternalState::SuccessDatabase(
- DatabaseAssociatedPtrInfo database_info,
- const content::IndexedDBDatabaseMetadata& metadata) {
+void IndexedDBCallbacksImpl::SuccessDatabase(
+ IDBDatabaseAssociatedPtrInfo database_info,
+ const IndexedDBDatabaseMetadata& metadata) {
WebIDBDatabase* database = nullptr;
if (database_info.is_valid()) {
- database = new WebIDBDatabaseImpl(std::move(database_info), io_runner_,
- callback_runner_);
+ database = new WebIDBDatabaseImpl(std::move(database_info));
}
WebIDBMetadata web_metadata;
@@ -306,48 +165,42 @@ void IndexedDBCallbacksImpl::InternalState::SuccessDatabase(
callbacks_.reset();
}
-void IndexedDBCallbacksImpl::InternalState::SuccessCursor(
- indexed_db::mojom::CursorAssociatedPtrInfo cursor_info,
+void IndexedDBCallbacksImpl::SuccessCursor(
+ blink::mojom::IDBCursorAssociatedPtrInfo cursor_info,
const IndexedDBKey& key,
const IndexedDBKey& primary_key,
- indexed_db::mojom::ValuePtr value) {
- WebIDBCursorImpl* cursor = new WebIDBCursorImpl(
- std::move(cursor_info), transaction_id_, io_runner_, callback_runner_);
+ blink::mojom::IDBValuePtr value) {
+ WebIDBCursorImpl* cursor =
+ new WebIDBCursorImpl(std::move(cursor_info), transaction_id_);
callbacks_->OnSuccess(cursor, WebIDBKeyBuilder::Build(key),
WebIDBKeyBuilder::Build(primary_key),
ConvertValue(value));
callbacks_.reset();
}
-void IndexedDBCallbacksImpl::InternalState::SuccessKey(
- const IndexedDBKey& key) {
- callbacks_->OnSuccess(WebIDBKeyBuilder::Build(key));
- callbacks_.reset();
-}
-
-void IndexedDBCallbacksImpl::InternalState::SuccessValue(
- indexed_db::mojom::ReturnValuePtr value) {
+void IndexedDBCallbacksImpl::SuccessValue(
+ blink::mojom::IDBReturnValuePtr value) {
callbacks_->OnSuccess(ConvertReturnValue(value));
callbacks_.reset();
}
-void IndexedDBCallbacksImpl::InternalState::SuccessCursorContinue(
+void IndexedDBCallbacksImpl::SuccessCursorContinue(
const IndexedDBKey& key,
const IndexedDBKey& primary_key,
- indexed_db::mojom::ValuePtr value) {
+ blink::mojom::IDBValuePtr value) {
callbacks_->OnSuccess(WebIDBKeyBuilder::Build(key),
WebIDBKeyBuilder::Build(primary_key),
ConvertValue(value));
callbacks_.reset();
}
-void IndexedDBCallbacksImpl::InternalState::SuccessCursorPrefetch(
+void IndexedDBCallbacksImpl::SuccessCursorPrefetch(
const std::vector<IndexedDBKey>& keys,
const std::vector<IndexedDBKey>& primary_keys,
- std::vector<indexed_db::mojom::ValuePtr> values) {
+ std::vector<blink::mojom::IDBValuePtr> values) {
std::vector<WebIDBValue> web_values;
web_values.reserve(values.size());
- for (const indexed_db::mojom::ValuePtr& value : values)
+ for (const blink::mojom::IDBValuePtr& value : values)
web_values.emplace_back(ConvertValue(value));
if (cursor_) {
@@ -357,22 +210,27 @@ void IndexedDBCallbacksImpl::InternalState::SuccessCursorPrefetch(
callbacks_.reset();
}
-void IndexedDBCallbacksImpl::InternalState::SuccessArray(
- std::vector<indexed_db::mojom::ReturnValuePtr> values) {
+void IndexedDBCallbacksImpl::SuccessArray(
+ std::vector<blink::mojom::IDBReturnValuePtr> values) {
WebVector<WebIDBValue> web_values;
web_values.reserve(values.size());
- for (const indexed_db::mojom::ReturnValuePtr& value : values)
+ for (const blink::mojom::IDBReturnValuePtr& value : values)
web_values.emplace_back(ConvertReturnValue(value));
callbacks_->OnSuccess(std::move(web_values));
callbacks_.reset();
}
-void IndexedDBCallbacksImpl::InternalState::SuccessInteger(int64_t value) {
+void IndexedDBCallbacksImpl::SuccessKey(const IndexedDBKey& key) {
+ callbacks_->OnSuccess(WebIDBKeyBuilder::Build(key));
+ callbacks_.reset();
+}
+
+void IndexedDBCallbacksImpl::SuccessInteger(int64_t value) {
callbacks_->OnSuccess(value);
callbacks_.reset();
}
-void IndexedDBCallbacksImpl::InternalState::Success() {
+void IndexedDBCallbacksImpl::Success() {
callbacks_->OnSuccess();
callbacks_.reset();
}
diff --git a/chromium/content/renderer/indexed_db/indexed_db_callbacks_impl.h b/chromium/content/renderer/indexed_db/indexed_db_callbacks_impl.h
index f60f5862fa1..7fad138c769 100644
--- a/chromium/content/renderer/indexed_db/indexed_db_callbacks_impl.h
+++ b/chromium/content/renderer/indexed_db/indexed_db_callbacks_impl.h
@@ -5,9 +5,11 @@
#ifndef CONTENT_RENDERER_INDEXED_DB_INDEXED_DB_CALLBACKS_IMPL_H_
#define CONTENT_RENDERER_INDEXED_DB_INDEXED_DB_CALLBACKS_IMPL_H_
-#include "base/single_thread_task_runner.h"
-#include "content/common/indexed_db/indexed_db.mojom.h"
#include "mojo/public/cpp/bindings/associated_binding.h"
+#include "third_party/blink/public/common/indexeddb/indexeddb_key.h"
+#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h"
+
+using blink::IndexedDBKey;
namespace blink {
class WebIDBCallbacks;
@@ -21,104 +23,53 @@ class WebIDBCursorImpl;
// Implements the child-process end of the pipe used to deliver callbacks. It
// is owned by the IO thread. |callback_runner_| is used to post tasks back to
// the thread which owns the blink::WebIDBCallbacks.
-class IndexedDBCallbacksImpl : public indexed_db::mojom::Callbacks {
+class IndexedDBCallbacksImpl : public blink::mojom::IDBCallbacks {
public:
enum : int64_t { kNoTransaction = -1 };
- // This class holds the parts of the internal state of IndexedDBCallbacksImpl
- // that must live on whatever renderer or worker thread the API is used from.
- class InternalState {
- public:
- InternalState(std::unique_ptr<blink::WebIDBCallbacks> callbacks,
- int64_t transaction_id,
- const base::WeakPtr<WebIDBCursorImpl>& cursor,
- scoped_refptr<base::SingleThreadTaskRunner> io_runner,
- scoped_refptr<base::SingleThreadTaskRunner> callback_runner);
- ~InternalState();
-
- void Error(int32_t code, const base::string16& message);
- void SuccessStringList(const std::vector<base::string16>& value);
- void Blocked(int64_t existing_version);
- void UpgradeNeeded(indexed_db::mojom::DatabaseAssociatedPtrInfo database,
- int64_t old_version,
- blink::WebIDBDataLoss data_loss,
- const std::string& data_loss_message,
- const content::IndexedDBDatabaseMetadata& metadata);
- void SuccessDatabase(indexed_db::mojom::DatabaseAssociatedPtrInfo database,
- const content::IndexedDBDatabaseMetadata& metadata);
- void SuccessCursor(indexed_db::mojom::CursorAssociatedPtrInfo cursor,
- const IndexedDBKey& key,
- const IndexedDBKey& primary_key,
- indexed_db::mojom::ValuePtr value);
- void SuccessValue(indexed_db::mojom::ReturnValuePtr value);
- void SuccessCursorContinue(const IndexedDBKey& key,
- const IndexedDBKey& primary_key,
- indexed_db::mojom::ValuePtr value);
- void SuccessCursorPrefetch(const std::vector<IndexedDBKey>& keys,
- const std::vector<IndexedDBKey>& primary_keys,
- std::vector<indexed_db::mojom::ValuePtr> values);
- void SuccessArray(std::vector<indexed_db::mojom::ReturnValuePtr> values);
- void SuccessKey(const IndexedDBKey& key);
- void SuccessInteger(int64_t value);
- void Success();
-
- private:
- std::unique_ptr<blink::WebIDBCallbacks> callbacks_;
- int64_t transaction_id_;
- base::WeakPtr<WebIDBCursorImpl> cursor_;
- scoped_refptr<base::SingleThreadTaskRunner> io_runner_;
- scoped_refptr<base::SingleThreadTaskRunner> callback_runner_;
-
- DISALLOW_COPY_AND_ASSIGN(InternalState);
- };
-
static blink::WebIDBValue ConvertValue(
- const indexed_db::mojom::ValuePtr& value);
+ const blink::mojom::IDBValuePtr& value);
- IndexedDBCallbacksImpl(
- std::unique_ptr<blink::WebIDBCallbacks> callbacks,
- int64_t transaction_id,
- const base::WeakPtr<WebIDBCursorImpl>& cursor,
- scoped_refptr<base::SingleThreadTaskRunner> io_runner,
- scoped_refptr<base::SingleThreadTaskRunner> callback_runner);
+ IndexedDBCallbacksImpl(std::unique_ptr<blink::WebIDBCallbacks> callbacks,
+ int64_t transaction_id,
+ const base::WeakPtr<WebIDBCursorImpl>& cursor);
~IndexedDBCallbacksImpl() override;
- // indexed_db::mojom::Callbacks implementation:
+ // blink::mojom::IDBCallbacks implementation:
void Error(int32_t code, const base::string16& message) override;
void SuccessStringList(const std::vector<base::string16>& value) override;
void Blocked(int64_t existing_version) override;
- void UpgradeNeeded(
- indexed_db::mojom::DatabaseAssociatedPtrInfo database_info,
- int64_t old_version,
- blink::WebIDBDataLoss data_loss,
- const std::string& data_loss_message,
- const content::IndexedDBDatabaseMetadata& metadata) override;
+ void UpgradeNeeded(blink::mojom::IDBDatabaseAssociatedPtrInfo database_info,
+ int64_t old_version,
+ blink::WebIDBDataLoss data_loss,
+ const std::string& data_loss_message,
+ const blink::IndexedDBDatabaseMetadata& metadata) override;
void SuccessDatabase(
- indexed_db::mojom::DatabaseAssociatedPtrInfo database_info,
- const content::IndexedDBDatabaseMetadata& metadata) override;
- void SuccessCursor(indexed_db::mojom::CursorAssociatedPtrInfo cursor,
+ blink::mojom::IDBDatabaseAssociatedPtrInfo database_info,
+ const blink::IndexedDBDatabaseMetadata& metadata) override;
+ void SuccessCursor(blink::mojom::IDBCursorAssociatedPtrInfo cursor,
const IndexedDBKey& key,
const IndexedDBKey& primary_key,
- indexed_db::mojom::ValuePtr value) override;
- void SuccessValue(indexed_db::mojom::ReturnValuePtr value) override;
+ blink::mojom::IDBValuePtr value) override;
+ void SuccessValue(blink::mojom::IDBReturnValuePtr value) override;
void SuccessCursorContinue(const IndexedDBKey& key,
const IndexedDBKey& primary_key,
- indexed_db::mojom::ValuePtr value) override;
+ blink::mojom::IDBValuePtr value) override;
void SuccessCursorPrefetch(
const std::vector<IndexedDBKey>& keys,
const std::vector<IndexedDBKey>& primary_keys,
- std::vector<indexed_db::mojom::ValuePtr> values) override;
+ std::vector<blink::mojom::IDBValuePtr> values) override;
void SuccessArray(
- std::vector<indexed_db::mojom::ReturnValuePtr> values) override;
+ std::vector<blink::mojom::IDBReturnValuePtr> values) override;
void SuccessKey(const IndexedDBKey& key) override;
void SuccessInteger(int64_t value) override;
void Success() override;
private:
- // |internal_state_| is owned by the thread on which |callback_runner_|
- // executes tasks and must be destroyed there.
- InternalState* internal_state_;
scoped_refptr<base::SingleThreadTaskRunner> callback_runner_;
+ std::unique_ptr<blink::WebIDBCallbacks> callbacks_;
+ base::WeakPtr<WebIDBCursorImpl> cursor_;
+ int64_t transaction_id_;
DISALLOW_COPY_AND_ASSIGN(IndexedDBCallbacksImpl);
};
diff --git a/chromium/content/renderer/indexed_db/indexed_db_database_callbacks_impl.cc b/chromium/content/renderer/indexed_db/indexed_db_database_callbacks_impl.cc
index 4ccf2af1b8e..a63c0652330 100644
--- a/chromium/content/renderer/indexed_db/indexed_db_database_callbacks_impl.cc
+++ b/chromium/content/renderer/indexed_db/indexed_db_database_callbacks_impl.cc
@@ -21,25 +21,35 @@ using blink::WebIDBObservation;
namespace content {
-namespace {
+IndexedDBDatabaseCallbacksImpl::IndexedDBDatabaseCallbacksImpl(
+ std::unique_ptr<WebIDBDatabaseCallbacks> callbacks)
+ : callbacks_(std::move(callbacks)) {}
+
+IndexedDBDatabaseCallbacksImpl::~IndexedDBDatabaseCallbacksImpl() = default;
+
+void IndexedDBDatabaseCallbacksImpl::ForcedClose() {
+ callbacks_->OnForcedClose();
+}
-void DeleteDatabaseCallbacks(WebIDBDatabaseCallbacks* callbacks) {
- IndexedDBDispatcher::ThreadSpecificInstance()
- ->UnregisterMojoOwnedDatabaseCallbacks(callbacks);
- delete callbacks;
+void IndexedDBDatabaseCallbacksImpl::VersionChange(int64_t old_version,
+ int64_t new_version) {
+ callbacks_->OnVersionChange(old_version, new_version);
}
-void BuildErrorAndAbort(WebIDBDatabaseCallbacks* callbacks,
- int64_t transaction_id,
- int32_t code,
- const base::string16& message) {
- callbacks->OnAbort(
+void IndexedDBDatabaseCallbacksImpl::Abort(int64_t transaction_id,
+ int32_t code,
+ const base::string16& message) {
+ callbacks_->OnAbort(
transaction_id,
blink::WebIDBDatabaseError(code, blink::WebString::FromUTF16(message)));
}
-void BuildObservationsAndNotify(WebIDBDatabaseCallbacks* callbacks,
- indexed_db::mojom::ObserverChangesPtr changes) {
+void IndexedDBDatabaseCallbacksImpl::Complete(int64_t transaction_id) {
+ callbacks_->OnComplete(transaction_id);
+}
+
+void IndexedDBDatabaseCallbacksImpl::Changes(
+ blink::mojom::IDBObserverChangesPtr changes) {
WebVector<WebIDBObservation> web_observations;
web_observations.reserve(changes->observations.size());
for (const auto& observation : changes->observations) {
@@ -64,63 +74,8 @@ void BuildObservationsAndNotify(WebIDBDatabaseCallbacks* callbacks,
std::move(transaction_pair.second->scope));
}
- callbacks->OnChanges(observation_index_map, std::move(web_observations),
- observer_transactions);
-}
-
-} // namespace
-
-IndexedDBDatabaseCallbacksImpl::IndexedDBDatabaseCallbacksImpl(
- std::unique_ptr<WebIDBDatabaseCallbacks> callbacks,
- scoped_refptr<base::SingleThreadTaskRunner> callback_runner)
- : callback_runner_(std::move(callback_runner)),
- callbacks_(callbacks.release()) {
- IndexedDBDispatcher::ThreadSpecificInstance()
- ->RegisterMojoOwnedDatabaseCallbacks(callbacks_);
-}
-
-IndexedDBDatabaseCallbacksImpl::~IndexedDBDatabaseCallbacksImpl() {
- callback_runner_->PostTask(
- FROM_HERE, base::BindOnce(&DeleteDatabaseCallbacks, callbacks_));
-}
-
-void IndexedDBDatabaseCallbacksImpl::ForcedClose() {
- callback_runner_->PostTask(
- FROM_HERE, base::BindOnce(&WebIDBDatabaseCallbacks::OnForcedClose,
- base::Unretained(callbacks_)));
-}
-
-void IndexedDBDatabaseCallbacksImpl::VersionChange(int64_t old_version,
- int64_t new_version) {
- callback_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&WebIDBDatabaseCallbacks::OnVersionChange,
- base::Unretained(callbacks_), old_version, new_version));
-}
-
-void IndexedDBDatabaseCallbacksImpl::Abort(int64_t transaction_id,
- int32_t code,
- const base::string16& message) {
- // Indirect through BuildErrorAndAbort because it isn't safe to pass a
- // WebIDBDatabaseError between threads.
- callback_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&BuildErrorAndAbort, base::Unretained(callbacks_),
- transaction_id, code, message));
-}
-
-void IndexedDBDatabaseCallbacksImpl::Complete(int64_t transaction_id) {
- callback_runner_->PostTask(
- FROM_HERE, base::BindOnce(&WebIDBDatabaseCallbacks::OnComplete,
- base::Unretained(callbacks_), transaction_id));
-}
-
-void IndexedDBDatabaseCallbacksImpl::Changes(
- indexed_db::mojom::ObserverChangesPtr changes) {
- callback_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&BuildObservationsAndNotify, base::Unretained(callbacks_),
- std::move(changes)));
+ callbacks_->OnChanges(observation_index_map, std::move(web_observations),
+ observer_transactions);
}
} // namespace content
diff --git a/chromium/content/renderer/indexed_db/indexed_db_database_callbacks_impl.h b/chromium/content/renderer/indexed_db/indexed_db_database_callbacks_impl.h
index 13df0fa2260..304f9782f3e 100644
--- a/chromium/content/renderer/indexed_db/indexed_db_database_callbacks_impl.h
+++ b/chromium/content/renderer/indexed_db/indexed_db_database_callbacks_impl.h
@@ -6,7 +6,7 @@
#define CONTENT_RENDERER_INDEXED_DB_INDEXED_DB_DATABASE_CALLBACKS_IMPL_H_
#include "base/single_thread_task_runner.h"
-#include "content/common/indexed_db/indexed_db.mojom.h"
+#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h"
namespace blink {
class WebIDBDatabaseCallbacks;
@@ -15,25 +15,23 @@ class WebIDBDatabaseCallbacks;
namespace content {
class IndexedDBDatabaseCallbacksImpl
- : public indexed_db::mojom::DatabaseCallbacks {
+ : public blink::mojom::IDBDatabaseCallbacks {
public:
explicit IndexedDBDatabaseCallbacksImpl(
- std::unique_ptr<blink::WebIDBDatabaseCallbacks> callbacks,
- scoped_refptr<base::SingleThreadTaskRunner> callback_runner);
+ std::unique_ptr<blink::WebIDBDatabaseCallbacks> callbacks);
~IndexedDBDatabaseCallbacksImpl() override;
- // indexed_db::mojom::DatabaseCallbacks implementation
+ // blink::mojom::IDBDatabaseCallbacks implementation
void ForcedClose() override;
void VersionChange(int64_t old_version, int64_t new_version) override;
void Abort(int64_t transaction_id,
int32_t code,
const base::string16& message) override;
void Complete(int64_t transaction_id) override;
- void Changes(indexed_db::mojom::ObserverChangesPtr changes) override;
+ void Changes(blink::mojom::IDBObserverChangesPtr changes) override;
private:
- scoped_refptr<base::SingleThreadTaskRunner> callback_runner_;
- blink::WebIDBDatabaseCallbacks* callbacks_;
+ std::unique_ptr<blink::WebIDBDatabaseCallbacks> callbacks_;
DISALLOW_COPY_AND_ASSIGN(IndexedDBDatabaseCallbacksImpl);
};
diff --git a/chromium/content/renderer/indexed_db/indexed_db_dispatcher.cc b/chromium/content/renderer/indexed_db/indexed_db_dispatcher.cc
index 5af2a9aec44..6237adbb228 100644
--- a/chromium/content/renderer/indexed_db/indexed_db_dispatcher.cc
+++ b/chromium/content/renderer/indexed_db/indexed_db_dispatcher.cc
@@ -35,10 +35,6 @@ IndexedDBDispatcher::IndexedDBDispatcher() {
}
IndexedDBDispatcher::~IndexedDBDispatcher() {
- in_destructor_ = true;
- mojo_owned_callback_state_.clear();
- mojo_owned_database_callback_state_.clear();
-
g_idb_dispatcher_tls.Pointer()->Set(kDeletedIndexedDBDispatcherMarker);
}
@@ -61,38 +57,6 @@ void IndexedDBDispatcher::WillStopCurrentWorkerThread() {
delete this;
}
-void IndexedDBDispatcher::RegisterMojoOwnedCallbacks(
- IndexedDBCallbacksImpl::InternalState* callbacks) {
- mojo_owned_callback_state_[callbacks] = base::WrapUnique(callbacks);
-}
-
-void IndexedDBDispatcher::UnregisterMojoOwnedCallbacks(
- IndexedDBCallbacksImpl::InternalState* callbacks) {
- if (in_destructor_)
- return;
-
- auto it = mojo_owned_callback_state_.find(callbacks);
- DCHECK(it != mojo_owned_callback_state_.end());
- it->second.release();
- mojo_owned_callback_state_.erase(it);
-}
-
-void IndexedDBDispatcher::RegisterMojoOwnedDatabaseCallbacks(
- blink::WebIDBDatabaseCallbacks* callbacks) {
- mojo_owned_database_callback_state_[callbacks] = base::WrapUnique(callbacks);
-}
-
-void IndexedDBDispatcher::UnregisterMojoOwnedDatabaseCallbacks(
- blink::WebIDBDatabaseCallbacks* callbacks) {
- if (in_destructor_)
- return;
-
- auto it = mojo_owned_database_callback_state_.find(callbacks);
- DCHECK(it != mojo_owned_database_callback_state_.end());
- it->second.release();
- mojo_owned_database_callback_state_.erase(it);
-}
-
void IndexedDBDispatcher::RegisterCursor(WebIDBCursorImpl* cursor) {
DCHECK(!base::ContainsKey(cursors_, cursor));
cursors_.insert(cursor);
diff --git a/chromium/content/renderer/indexed_db/indexed_db_dispatcher.h b/chromium/content/renderer/indexed_db/indexed_db_dispatcher.h
index 71ea1cf67ba..18637782ba9 100644
--- a/chromium/content/renderer/indexed_db/indexed_db_dispatcher.h
+++ b/chromium/content/renderer/indexed_db/indexed_db_dispatcher.h
@@ -12,13 +12,12 @@
#include "base/macros.h"
#include "base/strings/nullable_string16.h"
#include "content/common/content_export.h"
-#include "content/common/indexed_db/indexed_db_constants.h"
#include "content/public/renderer/worker_thread.h"
#include "content/renderer/indexed_db/indexed_db_callbacks_impl.h"
#include "content/renderer/indexed_db/indexed_db_database_callbacks_impl.h"
#include "ipc/ipc_sync_message_filter.h"
+#include "third_party/blink/public/common/indexeddb/web_idb_types.h"
#include "third_party/blink/public/platform/modules/indexeddb/web_idb_callbacks.h"
-#include "third_party/blink/public/platform/modules/indexeddb/web_idb_types.h"
#include "url/origin.h"
namespace content {
@@ -46,40 +45,12 @@ class CONTENT_EXPORT IndexedDBDispatcher : public WorkerThread::Observer {
void ResetCursorPrefetchCaches(int64_t transaction_id,
WebIDBCursorImpl* exception_cursor);
- void RegisterMojoOwnedCallbacks(
- IndexedDBCallbacksImpl::InternalState* callback_state);
- void UnregisterMojoOwnedCallbacks(
- IndexedDBCallbacksImpl::InternalState* callback_state);
- void RegisterMojoOwnedDatabaseCallbacks(
- blink::WebIDBDatabaseCallbacks* callback_state);
- void UnregisterMojoOwnedDatabaseCallbacks(
- blink::WebIDBDatabaseCallbacks* callback_state);
-
private:
FRIEND_TEST_ALL_PREFIXES(IndexedDBDispatcherTest, CursorReset);
FRIEND_TEST_ALL_PREFIXES(IndexedDBDispatcherTest, CursorTransactionId);
- // Looking up move-only entries in an std::unordered_set and removing them
- // with out freeing them seems to be impossible so use a map instead so that
- // the key type can remain a raw pointer.
- using CallbackStateSet = std::unordered_map<
- IndexedDBCallbacksImpl::InternalState*,
- std::unique_ptr<IndexedDBCallbacksImpl::InternalState>>;
- using DatabaseCallbackStateSet =
- std::unordered_map<blink::WebIDBDatabaseCallbacks*,
- std::unique_ptr<blink::WebIDBDatabaseCallbacks>>;
-
std::unordered_set<WebIDBCursorImpl*> cursors_;
- // Holds pointers to the worker-thread owned state of IndexedDBCallbacksImpl
- // and IndexedDBDatabaseCallbacksImpl objects to makes sure that it is
- // destroyed on thread exit if the Mojo pipe is not yet closed. Otherwise the
- // object will leak because the thread's task runner is no longer executing
- // tasks.
- CallbackStateSet mojo_owned_callback_state_;
- DatabaseCallbackStateSet mojo_owned_database_callback_state_;
- bool in_destructor_ = false;
-
DISALLOW_COPY_AND_ASSIGN(IndexedDBDispatcher);
};
diff --git a/chromium/content/renderer/indexed_db/indexed_db_key_builders.cc b/chromium/content/renderer/indexed_db/indexed_db_key_builders.cc
index 657655fe7b5..ad9b6b2269d 100644
--- a/chromium/content/renderer/indexed_db/indexed_db_key_builders.cc
+++ b/chromium/content/renderer/indexed_db/indexed_db_key_builders.cc
@@ -11,13 +11,17 @@
#include <vector>
#include "base/logging.h"
+#include "third_party/blink/public/common/indexeddb/indexeddb_key_range.h"
+#include "third_party/blink/public/common/indexeddb/web_idb_types.h"
#include "third_party/blink/public/platform/modules/indexeddb/web_idb_key.h"
#include "third_party/blink/public/platform/modules/indexeddb/web_idb_key_path.h"
#include "third_party/blink/public/platform/modules/indexeddb/web_idb_key_range.h"
-#include "third_party/blink/public/platform/modules/indexeddb/web_idb_types.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_vector.h"
+using blink::IndexedDBKey;
+using blink::IndexedDBKeyPath;
+using blink::IndexedDBKeyRange;
using blink::WebIDBKey;
using blink::WebIDBKeyRange;
using blink::WebIDBKeyView;
@@ -34,8 +38,8 @@ using blink::WebString;
namespace {
-content::IndexedDBKey::KeyArray CopyKeyArray(blink::WebIDBKeyArrayView array) {
- content::IndexedDBKey::KeyArray result;
+IndexedDBKey::KeyArray CopyKeyArray(blink::WebIDBKeyArrayView array) {
+ IndexedDBKey::KeyArray result;
const size_t array_size = array.size();
result.reserve(array_size);
for (size_t i = 0; i < array_size; ++i)
diff --git a/chromium/content/renderer/indexed_db/indexed_db_key_builders.h b/chromium/content/renderer/indexed_db/indexed_db_key_builders.h
index 7462d8dc7fd..841dbb413b7 100644
--- a/chromium/content/renderer/indexed_db/indexed_db_key_builders.h
+++ b/chromium/content/renderer/indexed_db/indexed_db_key_builders.h
@@ -7,13 +7,13 @@
#include "base/macros.h"
#include "content/common/content_export.h"
-#include "content/common/indexed_db/indexed_db_key.h"
-#include "content/common/indexed_db/indexed_db_key_path.h"
-#include "content/common/indexed_db/indexed_db_key_range.h"
+#include "third_party/blink/public/common/indexeddb/indexeddb_key.h"
+#include "third_party/blink/public/common/indexeddb/indexeddb_key_path.h"
#include "third_party/blink/public/platform/modules/indexeddb/web_idb_key.h"
namespace blink {
+class IndexedDBKeyRange;
class WebIDBKeyPath;
class WebIDBKeyRange;
@@ -23,7 +23,7 @@ namespace content {
class CONTENT_EXPORT IndexedDBKeyBuilder {
public:
- static IndexedDBKey Build(blink::WebIDBKeyView key);
+ static blink::IndexedDBKey Build(blink::WebIDBKeyView key);
private:
DISALLOW_COPY_AND_ASSIGN(IndexedDBKeyBuilder);
@@ -31,7 +31,7 @@ class CONTENT_EXPORT IndexedDBKeyBuilder {
class CONTENT_EXPORT WebIDBKeyBuilder {
public:
- static blink::WebIDBKey Build(const content::IndexedDBKey& key);
+ static blink::WebIDBKey Build(const blink::IndexedDBKey& key);
private:
DISALLOW_COPY_AND_ASSIGN(WebIDBKeyBuilder);
@@ -39,10 +39,10 @@ class CONTENT_EXPORT WebIDBKeyBuilder {
class CONTENT_EXPORT IndexedDBKeyRangeBuilder {
public:
- static IndexedDBKeyRange Build(const blink::WebIDBKeyRange& key_range);
+ static blink::IndexedDBKeyRange Build(const blink::WebIDBKeyRange& key_range);
// Builds a point range (containing a single key).
- static IndexedDBKeyRange Build(blink::WebIDBKeyView key);
+ static blink::IndexedDBKeyRange Build(blink::WebIDBKeyView key);
private:
DISALLOW_COPY_AND_ASSIGN(IndexedDBKeyRangeBuilder);
@@ -50,7 +50,7 @@ class CONTENT_EXPORT IndexedDBKeyRangeBuilder {
class CONTENT_EXPORT WebIDBKeyRangeBuilder {
public:
- static blink::WebIDBKeyRange Build(const content::IndexedDBKeyRange& key);
+ static blink::WebIDBKeyRange Build(const blink::IndexedDBKeyRange& key);
private:
DISALLOW_COPY_AND_ASSIGN(WebIDBKeyRangeBuilder);
@@ -58,7 +58,7 @@ class CONTENT_EXPORT WebIDBKeyRangeBuilder {
class CONTENT_EXPORT IndexedDBKeyPathBuilder {
public:
- static IndexedDBKeyPath Build(const blink::WebIDBKeyPath& key_path);
+ static blink::IndexedDBKeyPath Build(const blink::WebIDBKeyPath& key_path);
private:
DISALLOW_COPY_AND_ASSIGN(IndexedDBKeyPathBuilder);
@@ -66,7 +66,7 @@ class CONTENT_EXPORT IndexedDBKeyPathBuilder {
class CONTENT_EXPORT WebIDBKeyPathBuilder {
public:
- static blink::WebIDBKeyPath Build(const IndexedDBKeyPath& key_path);
+ static blink::WebIDBKeyPath Build(const blink::IndexedDBKeyPath& key_path);
private:
DISALLOW_COPY_AND_ASSIGN(WebIDBKeyPathBuilder);
diff --git a/chromium/content/renderer/indexed_db/webidbcursor_impl.cc b/chromium/content/renderer/indexed_db/webidbcursor_impl.cc
index 797d4d8ed39..bdf5ce976ca 100644
--- a/chromium/content/renderer/indexed_db/webidbcursor_impl.cc
+++ b/chromium/content/renderer/indexed_db/webidbcursor_impl.cc
@@ -21,55 +21,22 @@ using blink::WebIDBCallbacks;
using blink::WebIDBKey;
using blink::WebIDBKeyView;
using blink::WebIDBValue;
-using indexed_db::mojom::CallbacksAssociatedPtrInfo;
-using indexed_db::mojom::CursorAssociatedPtrInfo;
+using blink::mojom::IDBCallbacksAssociatedPtrInfo;
+using blink::mojom::IDBCursorAssociatedPtrInfo;
namespace content {
-class WebIDBCursorImpl::IOThreadHelper {
- public:
- explicit IOThreadHelper(
- scoped_refptr<base::SingleThreadTaskRunner> task_runner);
- ~IOThreadHelper();
-
- void Bind(CursorAssociatedPtrInfo cursor_info);
- void Advance(uint32_t count,
- std::unique_ptr<IndexedDBCallbacksImpl> callbacks);
- void Continue(const IndexedDBKey& key,
- const IndexedDBKey& primary_key,
- std::unique_ptr<IndexedDBCallbacksImpl> callbacks);
- void Prefetch(int32_t count,
- std::unique_ptr<IndexedDBCallbacksImpl> callbacks);
- void PrefetchReset(int32_t used_prefetches, int32_t unused_prefetches);
-
- private:
- CallbacksAssociatedPtrInfo GetCallbacksProxy(
- std::unique_ptr<IndexedDBCallbacksImpl> callbacks);
-
- indexed_db::mojom::CursorAssociatedPtr cursor_;
- scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
-
- DISALLOW_COPY_AND_ASSIGN(IOThreadHelper);
-};
-
WebIDBCursorImpl::WebIDBCursorImpl(
- indexed_db::mojom::CursorAssociatedPtrInfo cursor_info,
- int64_t transaction_id,
- scoped_refptr<base::SingleThreadTaskRunner> io_runner,
- scoped_refptr<base::SingleThreadTaskRunner> callback_runner)
+ blink::mojom::IDBCursorAssociatedPtrInfo cursor_info,
+ int64_t transaction_id)
: transaction_id_(transaction_id),
- helper_(new IOThreadHelper(io_runner)),
- io_runner_(std::move(io_runner)),
- callback_runner_(std::move(callback_runner)),
+ cursor_(std::move(cursor_info)),
continue_count_(0),
used_prefetches_(0),
pending_onsuccess_callbacks_(0),
prefetch_amount_(kMinPrefetchAmount),
weak_factory_(this) {
IndexedDBDispatcher::ThreadSpecificInstance()->RegisterCursor(this);
- io_runner_->PostTask(FROM_HERE, base::BindOnce(&IOThreadHelper::Bind,
- base::Unretained(helper_),
- std::move(cursor_info)));
}
WebIDBCursorImpl::~WebIDBCursorImpl() {
@@ -78,7 +45,6 @@ WebIDBCursorImpl::~WebIDBCursorImpl() {
// this object. But, if that ever changed, then we'd need to invalidate
// any such pointers.
IndexedDBDispatcher::ThreadSpecificInstance()->UnregisterCursor(this);
- io_runner_->DeleteSoon(FROM_HERE, helper_);
}
void WebIDBCursorImpl::Advance(unsigned long count,
@@ -95,17 +61,13 @@ void WebIDBCursorImpl::Advance(unsigned long count,
transaction_id_, this);
auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>(
- std::move(callbacks), transaction_id_, weak_factory_.GetWeakPtr(),
- io_runner_, callback_runner_);
- io_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&IOThreadHelper::Advance, base::Unretained(helper_), count,
- std::move(callbacks_impl)));
+ std::move(callbacks), transaction_id_, weak_factory_.GetWeakPtr());
+ cursor_->Advance(count, GetCallbacksProxy(std::move(callbacks_impl)));
}
-void WebIDBCursorImpl::Continue(WebIDBKeyView key,
- WebIDBKeyView primary_key,
- WebIDBCallbacks* callbacks_ptr) {
+void WebIDBCursorImpl::CursorContinue(WebIDBKeyView key,
+ WebIDBKeyView primary_key,
+ WebIDBCallbacks* callbacks_ptr) {
std::unique_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
if (key.KeyType() == blink::kWebIDBKeyTypeNull &&
@@ -124,12 +86,9 @@ void WebIDBCursorImpl::Continue(WebIDBKeyView key,
++pending_onsuccess_callbacks_;
auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>(
- std::move(callbacks), transaction_id_, weak_factory_.GetWeakPtr(),
- io_runner_, callback_runner_);
- io_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&IOThreadHelper::Prefetch, base::Unretained(helper_),
- prefetch_amount_, std::move(callbacks_impl)));
+ std::move(callbacks), transaction_id_, weak_factory_.GetWeakPtr());
+ cursor_->Prefetch(prefetch_amount_,
+ GetCallbacksProxy(std::move(callbacks_impl)));
// Increase prefetch_amount_ exponentially.
prefetch_amount_ *= 2;
@@ -148,14 +107,10 @@ void WebIDBCursorImpl::Continue(WebIDBKeyView key,
transaction_id_, this);
auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>(
- std::move(callbacks), transaction_id_, weak_factory_.GetWeakPtr(),
- io_runner_, callback_runner_);
- io_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&IOThreadHelper::Continue, base::Unretained(helper_),
- IndexedDBKeyBuilder::Build(key),
- IndexedDBKeyBuilder::Build(primary_key),
- std::move(callbacks_impl)));
+ std::move(callbacks), transaction_id_, weak_factory_.GetWeakPtr());
+ cursor_->CursorContinue(IndexedDBKeyBuilder::Build(key),
+ IndexedDBKeyBuilder::Build(primary_key),
+ GetCallbacksProxy(std::move(callbacks_impl)));
}
void WebIDBCursorImpl::PostSuccessHandlerCallback() {
@@ -239,10 +194,7 @@ void WebIDBCursorImpl::ResetPrefetchCache() {
}
// Reset the back-end cursor.
- io_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&IOThreadHelper::PrefetchReset, base::Unretained(helper_),
- used_prefetches_, prefetch_keys_.size()));
+ cursor_->PrefetchReset(used_prefetches_, prefetch_keys_.size());
// Reset the prefetch cache.
prefetch_keys_.clear();
@@ -252,45 +204,9 @@ void WebIDBCursorImpl::ResetPrefetchCache() {
pending_onsuccess_callbacks_ = 0;
}
-WebIDBCursorImpl::IOThreadHelper::IOThreadHelper(
- scoped_refptr<base::SingleThreadTaskRunner> task_runner)
- : task_runner_(std::move(task_runner)) {}
-
-WebIDBCursorImpl::IOThreadHelper::~IOThreadHelper() {}
-
-void WebIDBCursorImpl::IOThreadHelper::Bind(
- CursorAssociatedPtrInfo cursor_info) {
- cursor_.Bind(std::move(cursor_info), task_runner_);
-}
-
-void WebIDBCursorImpl::IOThreadHelper::Advance(
- uint32_t count,
- std::unique_ptr<IndexedDBCallbacksImpl> callbacks) {
- cursor_->Advance(count, GetCallbacksProxy(std::move(callbacks)));
-}
-
-void WebIDBCursorImpl::IOThreadHelper::Continue(
- const IndexedDBKey& key,
- const IndexedDBKey& primary_key,
- std::unique_ptr<IndexedDBCallbacksImpl> callbacks) {
- cursor_->Continue(key, primary_key, GetCallbacksProxy(std::move(callbacks)));
-}
-
-void WebIDBCursorImpl::IOThreadHelper::Prefetch(
- int32_t count,
- std::unique_ptr<IndexedDBCallbacksImpl> callbacks) {
- cursor_->Prefetch(count, GetCallbacksProxy(std::move(callbacks)));
-}
-
-void WebIDBCursorImpl::IOThreadHelper::PrefetchReset(
- int32_t used_prefetches,
- int32_t unused_prefetches) {
- cursor_->PrefetchReset(used_prefetches, unused_prefetches);
-}
-
-CallbacksAssociatedPtrInfo WebIDBCursorImpl::IOThreadHelper::GetCallbacksProxy(
+IDBCallbacksAssociatedPtrInfo WebIDBCursorImpl::GetCallbacksProxy(
std::unique_ptr<IndexedDBCallbacksImpl> callbacks) {
- CallbacksAssociatedPtrInfo ptr_info;
+ IDBCallbacksAssociatedPtrInfo ptr_info;
auto request = mojo::MakeRequest(&ptr_info);
mojo::MakeStrongAssociatedBinding(std::move(callbacks), std::move(request));
return ptr_info;
diff --git a/chromium/content/renderer/indexed_db/webidbcursor_impl.h b/chromium/content/renderer/indexed_db/webidbcursor_impl.h
index 3a6778ed013..39baa2c51b9 100644
--- a/chromium/content/renderer/indexed_db/webidbcursor_impl.h
+++ b/chromium/content/renderer/indexed_db/webidbcursor_impl.h
@@ -14,35 +14,31 @@
#include "base/gtest_prod_util.h"
#include "base/memory/ref_counted.h"
#include "content/common/content_export.h"
-#include "content/common/indexed_db/indexed_db.mojom.h"
-#include "content/common/indexed_db/indexed_db_key.h"
+#include "third_party/blink/public/common/indexeddb/indexeddb_key.h"
+#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h"
#include "third_party/blink/public/platform/modules/indexeddb/web_idb_callbacks.h"
#include "third_party/blink/public/platform/modules/indexeddb/web_idb_cursor.h"
#include "third_party/blink/public/platform/modules/indexeddb/web_idb_key.h"
#include "third_party/blink/public/platform/modules/indexeddb/web_idb_value.h"
-namespace base {
-class SingleThreadTaskRunner;
-}
-
namespace content {
+class IndexedDBCallbacksImpl;
+
class CONTENT_EXPORT WebIDBCursorImpl : public blink::WebIDBCursor {
public:
- WebIDBCursorImpl(indexed_db::mojom::CursorAssociatedPtrInfo cursor,
- int64_t transaction_id,
- scoped_refptr<base::SingleThreadTaskRunner> io_runner,
- scoped_refptr<base::SingleThreadTaskRunner> callback_runner);
+ WebIDBCursorImpl(blink::mojom::IDBCursorAssociatedPtrInfo cursor,
+ int64_t transaction_id);
~WebIDBCursorImpl() override;
void Advance(unsigned long count, blink::WebIDBCallbacks* callback) override;
- void Continue(blink::WebIDBKeyView key,
- blink::WebIDBKeyView primary_key,
- blink::WebIDBCallbacks* callback) override;
+ void CursorContinue(blink::WebIDBKeyView key,
+ blink::WebIDBKeyView primary_key,
+ blink::WebIDBCallbacks* callback) override;
void PostSuccessHandlerCallback() override;
- void SetPrefetchData(const std::vector<IndexedDBKey>& keys,
- const std::vector<IndexedDBKey>& primary_keys,
+ void SetPrefetchData(const std::vector<blink::IndexedDBKey>& keys,
+ const std::vector<blink::IndexedDBKey>& primary_keys,
std::vector<blink::WebIDBValue> values);
void CachedAdvance(unsigned long count, blink::WebIDBCallbacks* callbacks);
@@ -54,14 +50,15 @@ class CONTENT_EXPORT WebIDBCursorImpl : public blink::WebIDBCursor {
int64_t transaction_id() const { return transaction_id_; }
private:
+ blink::mojom::IDBCallbacksAssociatedPtrInfo GetCallbacksProxy(
+ std::unique_ptr<IndexedDBCallbacksImpl> callbacks);
+
FRIEND_TEST_ALL_PREFIXES(IndexedDBDispatcherTest, CursorReset);
FRIEND_TEST_ALL_PREFIXES(IndexedDBDispatcherTest, CursorTransactionId);
FRIEND_TEST_ALL_PREFIXES(WebIDBCursorImplTest, AdvancePrefetchTest);
FRIEND_TEST_ALL_PREFIXES(WebIDBCursorImplTest, PrefetchReset);
FRIEND_TEST_ALL_PREFIXES(WebIDBCursorImplTest, PrefetchTest);
- class IOThreadHelper;
-
enum { kInvalidCursorId = -1 };
enum { kPrefetchContinueThreshold = 2 };
enum { kMinPrefetchAmount = 5 };
@@ -69,13 +66,11 @@ class CONTENT_EXPORT WebIDBCursorImpl : public blink::WebIDBCursor {
int64_t transaction_id_;
- IOThreadHelper* helper_;
- scoped_refptr<base::SingleThreadTaskRunner> io_runner_;
- scoped_refptr<base::SingleThreadTaskRunner> callback_runner_;
+ blink::mojom::IDBCursorAssociatedPtr cursor_;
// Prefetch cache.
- base::circular_deque<IndexedDBKey> prefetch_keys_;
- base::circular_deque<IndexedDBKey> prefetch_primary_keys_;
+ base::circular_deque<blink::IndexedDBKey> prefetch_keys_;
+ base::circular_deque<blink::IndexedDBKey> prefetch_primary_keys_;
base::circular_deque<blink::WebIDBValue> prefetch_values_;
// Number of continue calls that would qualify for a pre-fetch.
diff --git a/chromium/content/renderer/indexed_db/webidbcursor_impl_unittest.cc b/chromium/content/renderer/indexed_db/webidbcursor_impl_unittest.cc
index eec2bbac8f4..212b2167d5c 100644
--- a/chromium/content/renderer/indexed_db/webidbcursor_impl_unittest.cc
+++ b/chromium/content/renderer/indexed_db/webidbcursor_impl_unittest.cc
@@ -16,7 +16,6 @@
#include "base/threading/thread_task_runner_handle.h"
#include "base/values.h"
#include "content/child/thread_safe_sender.h"
-#include "content/common/indexed_db/indexed_db_key.h"
#include "content/renderer/indexed_db/indexed_db_key_builders.h"
#include "content/renderer/indexed_db/mock_webidbcallbacks.h"
#include "mojo/public/cpp/bindings/associated_binding.h"
@@ -24,6 +23,7 @@
#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
#include "third_party/blink/public/platform/web_data.h"
+using blink::IndexedDBKey;
using blink::WebBlobInfo;
using blink::WebData;
using blink::WebIDBCallbacks;
@@ -32,16 +32,16 @@ using blink::kWebIDBKeyTypeNumber;
using blink::WebIDBValue;
using blink::WebString;
using blink::WebVector;
-using indexed_db::mojom::Cursor;
+using blink::mojom::IDBCursor;
using testing::StrictMock;
namespace content {
namespace {
-class MockCursorImpl : public Cursor {
+class MockCursorImpl : public IDBCursor {
public:
- explicit MockCursorImpl(indexed_db::mojom::CursorAssociatedRequest request)
+ explicit MockCursorImpl(blink::mojom::IDBCursorAssociatedRequest request)
: binding_(this, std::move(request)) {
binding_.set_connection_error_handler(base::BindOnce(
&MockCursorImpl::CursorDestroyed, base::Unretained(this)));
@@ -49,7 +49,7 @@ class MockCursorImpl : public Cursor {
void Prefetch(
int32_t count,
- ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks) override {
+ blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks) override {
++prefetch_calls_;
last_prefetch_count_ = count;
}
@@ -60,16 +60,15 @@ class MockCursorImpl : public Cursor {
last_used_count_ = used_prefetches;
}
- void Advance(
- uint32_t count,
- ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks) override {
+ void Advance(uint32_t count,
+ blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks) override {
++advance_calls_;
}
- void Continue(
+ void CursorContinue(
const IndexedDBKey& key,
const IndexedDBKey& primary_key,
- ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks) override {
+ blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks) override {
++continue_calls_;
}
@@ -92,7 +91,7 @@ class MockCursorImpl : public Cursor {
int continue_calls_ = 0;
bool destroyed_ = false;
- mojo::AssociatedBinding<Cursor> binding_;
+ mojo::AssociatedBinding<IDBCursor> binding_;
};
class MockContinueCallbacks : public StrictMock<MockWebIDBCallbacks> {
@@ -120,13 +119,10 @@ class MockContinueCallbacks : public StrictMock<MockWebIDBCallbacks> {
class WebIDBCursorImplTest : public testing::Test {
public:
WebIDBCursorImplTest() : null_key_(WebIDBKey::CreateNull()) {
- indexed_db::mojom::CursorAssociatedPtr ptr;
+ blink::mojom::IDBCursorAssociatedPtr ptr;
mock_cursor_ = std::make_unique<MockCursorImpl>(
mojo::MakeRequestAssociatedWithDedicatedPipe(&ptr));
- cursor_ = std::make_unique<WebIDBCursorImpl>(
- ptr.PassInterface(), 1,
- blink::scheduler::GetSingleThreadTaskRunnerForTesting(),
- blink::scheduler::GetSingleThreadTaskRunnerForTesting());
+ cursor_ = std::make_unique<WebIDBCursorImpl>(ptr.PassInterface(), 1);
}
protected:
@@ -144,8 +140,8 @@ TEST_F(WebIDBCursorImplTest, PrefetchTest) {
int continue_calls = 0;
EXPECT_EQ(mock_cursor_->continue_calls(), 0);
for (int i = 0; i < WebIDBCursorImpl::kPrefetchContinueThreshold; ++i) {
- cursor_->Continue(null_key_.View(), null_key_.View(),
- new MockContinueCallbacks());
+ cursor_->CursorContinue(null_key_.View(), null_key_.View(),
+ new MockContinueCallbacks());
base::RunLoop().RunUntilIdle();
EXPECT_EQ(++continue_calls, mock_cursor_->continue_calls());
EXPECT_EQ(0, mock_cursor_->prefetch_calls());
@@ -159,8 +155,8 @@ TEST_F(WebIDBCursorImplTest, PrefetchTest) {
int last_prefetch_count = 0;
for (int repetitions = 0; repetitions < kPrefetchRepetitions; ++repetitions) {
// Initiate the prefetch
- cursor_->Continue(null_key_.View(), null_key_.View(),
- new MockContinueCallbacks());
+ cursor_->CursorContinue(null_key_.View(), null_key_.View(),
+ new MockContinueCallbacks());
base::RunLoop().RunUntilIdle();
EXPECT_EQ(continue_calls, mock_cursor_->continue_calls());
EXPECT_EQ(repetitions + 1, mock_cursor_->prefetch_calls());
@@ -196,8 +192,8 @@ TEST_F(WebIDBCursorImplTest, PrefetchTest) {
for (int i = 0; i < prefetch_count; ++i) {
IndexedDBKey key;
WebVector<WebBlobInfo> blobs;
- cursor_->Continue(null_key_.View(), null_key_.View(),
- new MockContinueCallbacks(&key, &blobs));
+ cursor_->CursorContinue(null_key_.View(), null_key_.View(),
+ new MockContinueCallbacks(&key, &blobs));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(continue_calls, mock_cursor_->continue_calls());
EXPECT_EQ(repetitions + 1, mock_cursor_->prefetch_calls());
@@ -217,15 +213,15 @@ TEST_F(WebIDBCursorImplTest, AdvancePrefetchTest) {
// Call continue() until prefetching should kick in.
EXPECT_EQ(0, mock_cursor_->continue_calls());
for (int i = 0; i < WebIDBCursorImpl::kPrefetchContinueThreshold; ++i) {
- cursor_->Continue(null_key_.View(), null_key_.View(),
- new MockContinueCallbacks());
+ cursor_->CursorContinue(null_key_.View(), null_key_.View(),
+ new MockContinueCallbacks());
}
base::RunLoop().RunUntilIdle();
EXPECT_EQ(0, mock_cursor_->prefetch_calls());
// Initiate the prefetch
- cursor_->Continue(null_key_.View(), null_key_.View(),
- new MockContinueCallbacks());
+ cursor_->CursorContinue(null_key_.View(), null_key_.View(),
+ new MockContinueCallbacks());
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1, mock_cursor_->prefetch_calls());
@@ -263,8 +259,8 @@ TEST_F(WebIDBCursorImplTest, AdvancePrefetchTest) {
// IDBCursor.continue()
IndexedDBKey key;
- cursor_->Continue(null_key_.View(), null_key_.View(),
- new MockContinueCallbacks(&key));
+ cursor_->CursorContinue(null_key_.View(), null_key_.View(),
+ new MockContinueCallbacks(&key));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(0, key.number());
@@ -274,8 +270,8 @@ TEST_F(WebIDBCursorImplTest, AdvancePrefetchTest) {
EXPECT_EQ(1, key.number());
// IDBCursor.continue()
- cursor_->Continue(null_key_.View(), null_key_.View(),
- new MockContinueCallbacks(&key));
+ cursor_->CursorContinue(null_key_.View(), null_key_.View(),
+ new MockContinueCallbacks(&key));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(2, key.number());
@@ -305,16 +301,16 @@ TEST_F(WebIDBCursorImplTest, PrefetchReset) {
int continue_calls = 0;
EXPECT_EQ(mock_cursor_->continue_calls(), 0);
for (int i = 0; i < WebIDBCursorImpl::kPrefetchContinueThreshold; ++i) {
- cursor_->Continue(null_key_.View(), null_key_.View(),
- new MockContinueCallbacks());
+ cursor_->CursorContinue(null_key_.View(), null_key_.View(),
+ new MockContinueCallbacks());
base::RunLoop().RunUntilIdle();
EXPECT_EQ(++continue_calls, mock_cursor_->continue_calls());
EXPECT_EQ(0, mock_cursor_->prefetch_calls());
}
// Initiate the prefetch
- cursor_->Continue(null_key_.View(), null_key_.View(),
- new MockContinueCallbacks());
+ cursor_->CursorContinue(null_key_.View(), null_key_.View(),
+ new MockContinueCallbacks());
base::RunLoop().RunUntilIdle();
EXPECT_EQ(continue_calls, mock_cursor_->continue_calls());
EXPECT_EQ(1, mock_cursor_->prefetch_calls());
diff --git a/chromium/content/renderer/indexed_db/webidbdatabase_impl.cc b/chromium/content/renderer/indexed_db/webidbdatabase_impl.cc
index 711dc4aee37..aea8e1840cd 100644
--- a/chromium/content/renderer/indexed_db/webidbdatabase_impl.cc
+++ b/chromium/content/renderer/indexed_db/webidbdatabase_impl.cc
@@ -17,6 +17,7 @@
#include "content/renderer/indexed_db/indexed_db_dispatcher.h"
#include "content/renderer/indexed_db/indexed_db_key_builders.h"
#include "mojo/public/cpp/bindings/strong_associated_binding.h"
+#include "third_party/blink/public/common/indexeddb/indexeddb_key.h"
#include "third_party/blink/public/platform/file_path_conversion.h"
#include "third_party/blink/public/platform/modules/indexeddb/web_idb_database_error.h"
#include "third_party/blink/public/platform/modules/indexeddb/web_idb_database_exception.h"
@@ -26,6 +27,8 @@
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_vector.h"
+using blink::IndexedDBKey;
+using blink::IndexedDBIndexKeys;
using blink::WebBlobInfo;
using blink::WebIDBCallbacks;
using blink::WebIDBDatabase;
@@ -37,22 +40,22 @@ using blink::WebIDBKeyRange;
using blink::WebIDBKeyView;
using blink::WebString;
using blink::WebVector;
-using indexed_db::mojom::CallbacksAssociatedPtrInfo;
-using indexed_db::mojom::DatabaseAssociatedPtrInfo;
+using blink::mojom::IDBCallbacksAssociatedPtrInfo;
+using blink::mojom::IDBDatabaseAssociatedPtrInfo;
namespace content {
namespace {
-std::vector<content::IndexedDBIndexKeys> ConvertWebIndexKeys(
+std::vector<IndexedDBIndexKeys> ConvertWebIndexKeys(
const WebVector<long long>& index_ids,
const WebVector<WebIDBDatabase::WebIndexKeys>& index_keys) {
DCHECK_EQ(index_ids.size(), index_keys.size());
- std::vector<content::IndexedDBIndexKeys> result;
+ std::vector<IndexedDBIndexKeys> result;
result.reserve(index_ids.size());
for (size_t i = 0, len = index_ids.size(); i < len; ++i) {
- result.emplace_back(index_ids[i], std::vector<content::IndexedDBKey>());
- std::vector<content::IndexedDBKey>& result_keys = result.back().second;
+ result.emplace_back(index_ids[i], std::vector<IndexedDBKey>());
+ std::vector<IndexedDBKey>& result_keys = result.back().second;
result_keys.reserve(index_keys[i].size());
for (const WebIDBKey& index_key : index_keys[i])
result_keys.emplace_back(IndexedDBKeyBuilder::Build(index_key.View()));
@@ -62,175 +65,50 @@ std::vector<content::IndexedDBIndexKeys> ConvertWebIndexKeys(
} // namespace
-class WebIDBDatabaseImpl::IOThreadHelper {
- public:
- explicit IOThreadHelper(
- scoped_refptr<base::SingleThreadTaskRunner> task_runner);
- ~IOThreadHelper();
-
- void Bind(DatabaseAssociatedPtrInfo database_info);
- void CreateObjectStore(int64_t transaction_id,
- int64_t object_store_id,
- const base::string16& name,
- const IndexedDBKeyPath& key_path,
- bool auto_increment);
- void DeleteObjectStore(int64_t transaction_id, int64_t object_store_id);
- void RenameObjectStore(int64_t transaction_id,
- int64_t object_store_id,
- const base::string16& new_name);
- void CreateTransaction(int64_t transaction_id,
- const std::vector<int64_t>& object_store_ids,
- blink::WebIDBTransactionMode mode);
- void Close();
- void VersionChangeIgnored();
- void AddObserver(int64_t transaction_id,
- int32_t observer_id,
- bool include_transaction,
- bool no_records,
- bool values,
- uint16_t operation_types);
- void RemoveObservers(const std::vector<int32_t>& observers);
- void Get(int64_t transaction_id,
- int64_t object_store_id,
- int64_t index_id,
- const IndexedDBKeyRange& key_range,
- bool key_only,
- std::unique_ptr<IndexedDBCallbacksImpl> callbacks);
- void GetAll(int64_t transaction_id,
- int64_t object_store_id,
- int64_t index_id,
- const IndexedDBKeyRange& key_range,
- int64_t max_count,
- bool key_only,
- std::unique_ptr<IndexedDBCallbacksImpl> callbacks);
- void Put(int64_t transaction_id,
- int64_t object_store_id,
- indexed_db::mojom::ValuePtr value,
- const IndexedDBKey& key,
- blink::WebIDBPutMode mode,
- std::unique_ptr<IndexedDBCallbacksImpl> callbacks,
- const std::vector<content::IndexedDBIndexKeys>& index_keys);
- void SetIndexKeys(int64_t transaction_id,
- int64_t object_store_id,
- const IndexedDBKey& primary_key,
- const std::vector<content::IndexedDBIndexKeys>& index_keys);
- void SetIndexesReady(int64_t transaction_id,
- int64_t object_store_id,
- const std::vector<int64_t>& index_ids);
- void OpenCursor(int64_t transaction_id,
- int64_t object_store_id,
- int64_t index_id,
- const IndexedDBKeyRange& key_range,
- blink::WebIDBCursorDirection direction,
- bool key_only,
- blink::WebIDBTaskType task_type,
- std::unique_ptr<IndexedDBCallbacksImpl> callbacks);
- void Count(int64_t transaction_id,
- int64_t object_store_id,
- int64_t index_id,
- const IndexedDBKeyRange& key_range,
- std::unique_ptr<IndexedDBCallbacksImpl> callbacks);
- void DeleteRange(int64_t transaction_id,
- int64_t object_store_id,
- const IndexedDBKeyRange& key_range,
- std::unique_ptr<IndexedDBCallbacksImpl> callbacks);
- void Clear(int64_t transaction_id,
- int64_t object_store_id,
- std::unique_ptr<IndexedDBCallbacksImpl> callbacks);
- void CreateIndex(int64_t transaction_id,
- int64_t object_store_id,
- int64_t index_id,
- const base::string16& name,
- const IndexedDBKeyPath& key_path,
- bool unique,
- bool multi_entry);
- void DeleteIndex(int64_t transaction_id,
- int64_t object_store_id,
- int64_t index_id);
- void RenameIndex(int64_t transaction_id,
- int64_t object_store_id,
- int64_t index_id,
- const base::string16& new_name);
- void Abort(int64_t transaction_id);
- void Commit(int64_t transaction_id);
-
- private:
- CallbacksAssociatedPtrInfo GetCallbacksProxy(
- std::unique_ptr<IndexedDBCallbacksImpl> callbacks);
-
- indexed_db::mojom::DatabaseAssociatedPtr database_;
- scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
-
- DISALLOW_COPY_AND_ASSIGN(IOThreadHelper);
-};
-
WebIDBDatabaseImpl::WebIDBDatabaseImpl(
- DatabaseAssociatedPtrInfo database_info,
- scoped_refptr<base::SingleThreadTaskRunner> io_runner,
- scoped_refptr<base::SingleThreadTaskRunner> callback_runner)
- : helper_(new IOThreadHelper(io_runner)),
- io_runner_(std::move(io_runner)),
- callback_runner_(std::move(callback_runner)) {
- io_runner_->PostTask(FROM_HERE, base::BindOnce(&IOThreadHelper::Bind,
- base::Unretained(helper_),
- std::move(database_info)));
-}
+ IDBDatabaseAssociatedPtrInfo database_info)
+ : database_(std::move(database_info)) {}
-WebIDBDatabaseImpl::~WebIDBDatabaseImpl() {
- io_runner_->DeleteSoon(FROM_HERE, helper_);
-}
+WebIDBDatabaseImpl::~WebIDBDatabaseImpl() = default;
void WebIDBDatabaseImpl::CreateObjectStore(long long transaction_id,
long long object_store_id,
const WebString& name,
const WebIDBKeyPath& key_path,
bool auto_increment) {
- io_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&IOThreadHelper::CreateObjectStore,
- base::Unretained(helper_), transaction_id, object_store_id,
- name.Utf16(), IndexedDBKeyPathBuilder::Build(key_path),
- auto_increment));
+ database_->CreateObjectStore(transaction_id, object_store_id, name.Utf16(),
+ IndexedDBKeyPathBuilder::Build(key_path),
+ auto_increment);
}
void WebIDBDatabaseImpl::DeleteObjectStore(long long transaction_id,
long long object_store_id) {
- io_runner_->PostTask(FROM_HERE,
- base::BindOnce(&IOThreadHelper::DeleteObjectStore,
- base::Unretained(helper_), transaction_id,
- object_store_id));
+ database_->DeleteObjectStore(transaction_id, object_store_id);
}
void WebIDBDatabaseImpl::RenameObjectStore(long long transaction_id,
long long object_store_id,
const blink::WebString& new_name) {
- io_runner_->PostTask(FROM_HERE,
- base::BindOnce(&IOThreadHelper::RenameObjectStore,
- base::Unretained(helper_), transaction_id,
- object_store_id, new_name.Utf16()));
+ database_->RenameObjectStore(transaction_id, object_store_id,
+ new_name.Utf16());
}
void WebIDBDatabaseImpl::CreateTransaction(
long long transaction_id,
const WebVector<long long>& object_store_ids,
blink::WebIDBTransactionMode mode) {
- io_runner_->PostTask(
- FROM_HERE, base::BindOnce(&IOThreadHelper::CreateTransaction,
- base::Unretained(helper_), transaction_id,
- std::vector<int64_t>(object_store_ids.begin(),
- object_store_ids.end()),
- mode));
+ database_->CreateTransaction(
+ transaction_id,
+ std::vector<int64_t>(object_store_ids.begin(), object_store_ids.end()),
+ mode);
}
void WebIDBDatabaseImpl::Close() {
- io_runner_->PostTask(FROM_HERE, base::BindOnce(&IOThreadHelper::Close,
- base::Unretained(helper_)));
+ database_->Close();
}
void WebIDBDatabaseImpl::VersionChangeIgnored() {
- io_runner_->PostTask(FROM_HERE,
- base::BindOnce(&IOThreadHelper::VersionChangeIgnored,
- base::Unretained(helper_)));
+ database_->VersionChangeIgnored();
}
void WebIDBDatabaseImpl::AddObserver(
@@ -242,11 +120,8 @@ void WebIDBDatabaseImpl::AddObserver(
const std::bitset<blink::kWebIDBOperationTypeCount>& operation_types) {
static_assert(blink::kWebIDBOperationTypeCount < sizeof(uint16_t) * CHAR_BIT,
"WebIDBOperationType Count exceeds size of uint16_t");
- io_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&IOThreadHelper::AddObserver, base::Unretained(helper_),
- transaction_id, observer_id, include_transaction,
- no_records, values, operation_types.to_ulong()));
+ database_->AddObserver(transaction_id, observer_id, include_transaction,
+ no_records, values, operation_types.to_ulong());
}
void WebIDBDatabaseImpl::RemoveObservers(
@@ -254,11 +129,7 @@ void WebIDBDatabaseImpl::RemoveObservers(
std::vector<int32_t> remove_observer_ids(
observer_ids_to_remove.Data(),
observer_ids_to_remove.Data() + observer_ids_to_remove.size());
-
- io_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&IOThreadHelper::RemoveObservers,
- base::Unretained(helper_), remove_observer_ids));
+ database_->RemoveObservers(remove_observer_ids);
}
void WebIDBDatabaseImpl::Get(long long transaction_id,
@@ -271,13 +142,10 @@ void WebIDBDatabaseImpl::Get(long long transaction_id,
transaction_id, nullptr);
auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>(
- base::WrapUnique(callbacks), transaction_id, nullptr, io_runner_,
- callback_runner_);
- io_runner_->PostTask(
- FROM_HERE, base::BindOnce(&IOThreadHelper::Get, base::Unretained(helper_),
- transaction_id, object_store_id, index_id,
- IndexedDBKeyRangeBuilder::Build(key_range),
- key_only, std::move(callbacks_impl)));
+ base::WrapUnique(callbacks), transaction_id, nullptr);
+ database_->Get(transaction_id, object_store_id, index_id,
+ IndexedDBKeyRangeBuilder::Build(key_range), key_only,
+ GetCallbacksProxy(std::move(callbacks_impl)));
}
void WebIDBDatabaseImpl::GetAll(long long transaction_id,
@@ -291,14 +159,10 @@ void WebIDBDatabaseImpl::GetAll(long long transaction_id,
transaction_id, nullptr);
auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>(
- base::WrapUnique(callbacks), transaction_id, nullptr, io_runner_,
- callback_runner_);
- io_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&IOThreadHelper::GetAll, base::Unretained(helper_),
- transaction_id, object_store_id, index_id,
- IndexedDBKeyRangeBuilder::Build(key_range), max_count,
- key_only, std::move(callbacks_impl)));
+ base::WrapUnique(callbacks), transaction_id, nullptr);
+ database_->GetAll(transaction_id, object_store_id, index_id,
+ IndexedDBKeyRangeBuilder::Build(key_range), key_only,
+ max_count, GetCallbacksProxy(std::move(callbacks_impl)));
}
void WebIDBDatabaseImpl::Put(long long transaction_id,
@@ -325,7 +189,7 @@ void WebIDBDatabaseImpl::Put(long long transaction_id,
IndexedDBDispatcher::ThreadSpecificInstance()->ResetCursorPrefetchCaches(
transaction_id, nullptr);
- auto mojo_value = indexed_db::mojom::Value::New();
+ auto mojo_value = blink::mojom::IDBValue::New();
DCHECK(mojo_value->bits.empty());
mojo_value->bits.reserve(value.size());
value.ForEachSegment([&mojo_value](const char* segment, size_t segment_size,
@@ -335,9 +199,9 @@ void WebIDBDatabaseImpl::Put(long long transaction_id,
});
mojo_value->blob_or_file_info.reserve(web_blob_info.size());
for (const WebBlobInfo& info : web_blob_info) {
- auto blob_info = indexed_db::mojom::BlobInfo::New();
+ auto blob_info = blink::mojom::IDBBlobInfo::New();
if (info.IsFile()) {
- blob_info->file = indexed_db::mojom::FileInfo::New();
+ blob_info->file = blink::mojom::IDBFileInfo::New();
blob_info->file->path = blink::WebStringToFilePath(info.FilePath());
blob_info->file->name = info.FileName().Utf16();
blob_info->file->last_modified =
@@ -353,14 +217,10 @@ void WebIDBDatabaseImpl::Put(long long transaction_id,
}
auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>(
- base::WrapUnique(callbacks), transaction_id, nullptr, io_runner_,
- callback_runner_);
- io_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&IOThreadHelper::Put, base::Unretained(helper_),
- transaction_id, object_store_id, std::move(mojo_value),
- key, put_mode, std::move(callbacks_impl),
- ConvertWebIndexKeys(index_ids, index_keys)));
+ base::WrapUnique(callbacks), transaction_id, nullptr);
+ database_->Put(transaction_id, object_store_id, std::move(mojo_value), key,
+ put_mode, ConvertWebIndexKeys(index_ids, index_keys),
+ GetCallbacksProxy(std::move(callbacks_impl)));
}
void WebIDBDatabaseImpl::SetIndexKeys(
@@ -369,12 +229,9 @@ void WebIDBDatabaseImpl::SetIndexKeys(
WebIDBKeyView primary_key,
const WebVector<long long>& index_ids,
const WebVector<WebIndexKeys>& index_keys) {
- io_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&IOThreadHelper::SetIndexKeys, base::Unretained(helper_),
- transaction_id, object_store_id,
- IndexedDBKeyBuilder::Build(primary_key),
- ConvertWebIndexKeys(index_ids, index_keys)));
+ database_->SetIndexKeys(transaction_id, object_store_id,
+ IndexedDBKeyBuilder::Build(primary_key),
+ ConvertWebIndexKeys(index_ids, index_keys));
}
void WebIDBDatabaseImpl::SetIndexesReady(
@@ -383,10 +240,8 @@ void WebIDBDatabaseImpl::SetIndexesReady(
const WebVector<long long>& web_index_ids) {
std::vector<int64_t> index_ids(web_index_ids.Data(),
web_index_ids.Data() + web_index_ids.size());
- io_runner_->PostTask(FROM_HERE,
- base::BindOnce(&IOThreadHelper::SetIndexesReady,
- base::Unretained(helper_), transaction_id,
- object_store_id, std::move(index_ids)));
+ database_->SetIndexesReady(transaction_id, object_store_id,
+ std::move(index_ids));
}
void WebIDBDatabaseImpl::OpenCursor(long long transaction_id,
@@ -401,14 +256,11 @@ void WebIDBDatabaseImpl::OpenCursor(long long transaction_id,
transaction_id, nullptr);
auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>(
- base::WrapUnique(callbacks), transaction_id, nullptr, io_runner_,
- callback_runner_);
- io_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&IOThreadHelper::OpenCursor, base::Unretained(helper_),
- transaction_id, object_store_id, index_id,
- IndexedDBKeyRangeBuilder::Build(key_range), direction,
- key_only, task_type, std::move(callbacks_impl)));
+ base::WrapUnique(callbacks), transaction_id, nullptr);
+ database_->OpenCursor(transaction_id, object_store_id, index_id,
+ IndexedDBKeyRangeBuilder::Build(key_range), direction,
+ key_only, task_type,
+ GetCallbacksProxy(std::move(callbacks_impl)));
}
void WebIDBDatabaseImpl::Count(long long transaction_id,
@@ -420,14 +272,10 @@ void WebIDBDatabaseImpl::Count(long long transaction_id,
transaction_id, nullptr);
auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>(
- base::WrapUnique(callbacks), transaction_id, nullptr, io_runner_,
- callback_runner_);
- io_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&IOThreadHelper::Count, base::Unretained(helper_),
- transaction_id, object_store_id, index_id,
- IndexedDBKeyRangeBuilder::Build(key_range),
- std::move(callbacks_impl)));
+ base::WrapUnique(callbacks), transaction_id, nullptr);
+ database_->Count(transaction_id, object_store_id, index_id,
+ IndexedDBKeyRangeBuilder::Build(key_range),
+ GetCallbacksProxy(std::move(callbacks_impl)));
}
void WebIDBDatabaseImpl::Delete(long long transaction_id,
@@ -438,14 +286,10 @@ void WebIDBDatabaseImpl::Delete(long long transaction_id,
transaction_id, nullptr);
auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>(
- base::WrapUnique(callbacks), transaction_id, nullptr, io_runner_,
- callback_runner_);
- io_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&IOThreadHelper::DeleteRange, base::Unretained(helper_),
- transaction_id, object_store_id,
- IndexedDBKeyRangeBuilder::Build(primary_key),
- std::move(callbacks_impl)));
+ base::WrapUnique(callbacks), transaction_id, nullptr);
+ database_->DeleteRange(transaction_id, object_store_id,
+ IndexedDBKeyRangeBuilder::Build(primary_key),
+ GetCallbacksProxy(std::move(callbacks_impl)));
}
void WebIDBDatabaseImpl::DeleteRange(long long transaction_id,
@@ -456,14 +300,10 @@ void WebIDBDatabaseImpl::DeleteRange(long long transaction_id,
transaction_id, nullptr);
auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>(
- base::WrapUnique(callbacks), transaction_id, nullptr, io_runner_,
- callback_runner_);
- io_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&IOThreadHelper::DeleteRange, base::Unretained(helper_),
- transaction_id, object_store_id,
- IndexedDBKeyRangeBuilder::Build(key_range),
- std::move(callbacks_impl)));
+ base::WrapUnique(callbacks), transaction_id, nullptr);
+ database_->DeleteRange(transaction_id, object_store_id,
+ IndexedDBKeyRangeBuilder::Build(key_range),
+ GetCallbacksProxy(std::move(callbacks_impl)));
}
void WebIDBDatabaseImpl::Clear(long long transaction_id,
@@ -473,12 +313,9 @@ void WebIDBDatabaseImpl::Clear(long long transaction_id,
transaction_id, nullptr);
auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>(
- base::WrapUnique(callbacks), transaction_id, nullptr, io_runner_,
- callback_runner_);
- io_runner_->PostTask(
- FROM_HERE, base::BindOnce(&IOThreadHelper::Clear,
- base::Unretained(helper_), transaction_id,
- object_store_id, std::move(callbacks_impl)));
+ base::WrapUnique(callbacks), transaction_id, nullptr);
+ database_->Clear(transaction_id, object_store_id,
+ GetCallbacksProxy(std::move(callbacks_impl)));
}
void WebIDBDatabaseImpl::CreateIndex(long long transaction_id,
@@ -488,240 +325,36 @@ void WebIDBDatabaseImpl::CreateIndex(long long transaction_id,
const WebIDBKeyPath& key_path,
bool unique,
bool multi_entry) {
- io_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&IOThreadHelper::CreateIndex, base::Unretained(helper_),
- transaction_id, object_store_id, index_id, name.Utf16(),
- IndexedDBKeyPathBuilder::Build(key_path), unique,
- multi_entry));
+ database_->CreateIndex(transaction_id, object_store_id, index_id,
+ name.Utf16(), IndexedDBKeyPathBuilder::Build(key_path),
+ unique, multi_entry);
}
void WebIDBDatabaseImpl::DeleteIndex(long long transaction_id,
long long object_store_id,
long long index_id) {
- io_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&IOThreadHelper::DeleteIndex, base::Unretained(helper_),
- transaction_id, object_store_id, index_id));
+ database_->DeleteIndex(transaction_id, object_store_id, index_id);
}
void WebIDBDatabaseImpl::RenameIndex(long long transaction_id,
long long object_store_id,
long long index_id,
const WebString& new_name) {
- io_runner_->PostTask(
- FROM_HERE, base::BindOnce(&IOThreadHelper::RenameIndex,
- base::Unretained(helper_), transaction_id,
- object_store_id, index_id, new_name.Utf16()));
+ database_->RenameIndex(transaction_id, object_store_id, index_id,
+ new_name.Utf16());
}
void WebIDBDatabaseImpl::Abort(long long transaction_id) {
- io_runner_->PostTask(
- FROM_HERE, base::BindOnce(&IOThreadHelper::Abort,
- base::Unretained(helper_), transaction_id));
-}
-
-void WebIDBDatabaseImpl::Commit(long long transaction_id) {
- io_runner_->PostTask(
- FROM_HERE, base::BindOnce(&IOThreadHelper::Commit,
- base::Unretained(helper_), transaction_id));
-}
-
-WebIDBDatabaseImpl::IOThreadHelper::IOThreadHelper(
- scoped_refptr<base::SingleThreadTaskRunner> task_runner)
- : task_runner_(std::move(task_runner)) {}
-
-WebIDBDatabaseImpl::IOThreadHelper::~IOThreadHelper() {}
-
-void WebIDBDatabaseImpl::IOThreadHelper::Bind(
- DatabaseAssociatedPtrInfo database_info) {
- database_.Bind(std::move(database_info), task_runner_);
-}
-
-void WebIDBDatabaseImpl::IOThreadHelper::CreateObjectStore(
- int64_t transaction_id,
- int64_t object_store_id,
- const base::string16& name,
- const IndexedDBKeyPath& key_path,
- bool auto_increment) {
- database_->CreateObjectStore(transaction_id, object_store_id, name, key_path,
- auto_increment);
-}
-
-void WebIDBDatabaseImpl::IOThreadHelper::DeleteObjectStore(
- int64_t transaction_id,
- int64_t object_store_id) {
- database_->DeleteObjectStore(transaction_id, object_store_id);
-}
-
-void WebIDBDatabaseImpl::IOThreadHelper::RenameObjectStore(
- int64_t transaction_id,
- int64_t object_store_id,
- const base::string16& new_name) {
- database_->RenameObjectStore(transaction_id, object_store_id, new_name);
-}
-
-void WebIDBDatabaseImpl::IOThreadHelper::CreateTransaction(
- int64_t transaction_id,
- const std::vector<int64_t>& object_store_ids,
- blink::WebIDBTransactionMode mode) {
- database_->CreateTransaction(transaction_id, object_store_ids, mode);
-}
-
-void WebIDBDatabaseImpl::IOThreadHelper::Close() {
- database_->Close();
-}
-
-void WebIDBDatabaseImpl::IOThreadHelper::VersionChangeIgnored() {
- database_->VersionChangeIgnored();
-}
-
-void WebIDBDatabaseImpl::IOThreadHelper::AddObserver(int64_t transaction_id,
- int32_t observer_id,
- bool include_transaction,
- bool no_records,
- bool values,
- uint16_t operation_types) {
- database_->AddObserver(transaction_id, observer_id, include_transaction,
- no_records, values, operation_types);
-}
-
-void WebIDBDatabaseImpl::IOThreadHelper::RemoveObservers(
- const std::vector<int32_t>& observers) {
- database_->RemoveObservers(observers);
-}
-
-void WebIDBDatabaseImpl::IOThreadHelper::Get(
- int64_t transaction_id,
- int64_t object_store_id,
- int64_t index_id,
- const IndexedDBKeyRange& key_range,
- bool key_only,
- std::unique_ptr<IndexedDBCallbacksImpl> callbacks) {
- database_->Get(transaction_id, object_store_id, index_id, key_range, key_only,
- GetCallbacksProxy(std::move(callbacks)));
-}
-
-void WebIDBDatabaseImpl::IOThreadHelper::GetAll(
- int64_t transaction_id,
- int64_t object_store_id,
- int64_t index_id,
- const IndexedDBKeyRange& key_range,
- int64_t max_count,
- bool key_only,
- std::unique_ptr<IndexedDBCallbacksImpl> callbacks) {
- database_->GetAll(transaction_id, object_store_id, index_id, key_range,
- key_only, max_count,
- GetCallbacksProxy(std::move(callbacks)));
-}
-
-void WebIDBDatabaseImpl::IOThreadHelper::Put(
- int64_t transaction_id,
- int64_t object_store_id,
- indexed_db::mojom::ValuePtr value,
- const IndexedDBKey& key,
- blink::WebIDBPutMode mode,
- std::unique_ptr<IndexedDBCallbacksImpl> callbacks,
- const std::vector<content::IndexedDBIndexKeys>& index_keys) {
- database_->Put(transaction_id, object_store_id, std::move(value), key, mode,
- index_keys, GetCallbacksProxy(std::move(callbacks)));
-}
-
-void WebIDBDatabaseImpl::IOThreadHelper::SetIndexKeys(
- int64_t transaction_id,
- int64_t object_store_id,
- const IndexedDBKey& primary_key,
- const std::vector<content::IndexedDBIndexKeys>& index_keys) {
- database_->SetIndexKeys(transaction_id, object_store_id, primary_key,
- index_keys);
-}
-
-void WebIDBDatabaseImpl::IOThreadHelper::SetIndexesReady(
- int64_t transaction_id,
- int64_t object_store_id,
- const std::vector<int64_t>& index_ids) {
- database_->SetIndexesReady(transaction_id, object_store_id, index_ids);
-}
-
-void WebIDBDatabaseImpl::IOThreadHelper::OpenCursor(
- int64_t transaction_id,
- int64_t object_store_id,
- int64_t index_id,
- const IndexedDBKeyRange& key_range,
- blink::WebIDBCursorDirection direction,
- bool key_only,
- blink::WebIDBTaskType task_type,
- std::unique_ptr<IndexedDBCallbacksImpl> callbacks) {
- database_->OpenCursor(transaction_id, object_store_id, index_id, key_range,
- direction, key_only, task_type,
- GetCallbacksProxy(std::move(callbacks)));
-}
-
-void WebIDBDatabaseImpl::IOThreadHelper::Count(
- int64_t transaction_id,
- int64_t object_store_id,
- int64_t index_id,
- const IndexedDBKeyRange& key_range,
- std::unique_ptr<IndexedDBCallbacksImpl> callbacks) {
- database_->Count(transaction_id, object_store_id, index_id, key_range,
- GetCallbacksProxy(std::move(callbacks)));
-}
-
-void WebIDBDatabaseImpl::IOThreadHelper::DeleteRange(
- int64_t transaction_id,
- int64_t object_store_id,
- const IndexedDBKeyRange& key_range,
- std::unique_ptr<IndexedDBCallbacksImpl> callbacks) {
- database_->DeleteRange(transaction_id, object_store_id, key_range,
- GetCallbacksProxy(std::move(callbacks)));
-}
-
-void WebIDBDatabaseImpl::IOThreadHelper::Clear(
- int64_t transaction_id,
- int64_t object_store_id,
- std::unique_ptr<IndexedDBCallbacksImpl> callbacks) {
- database_->Clear(transaction_id, object_store_id,
- GetCallbacksProxy(std::move(callbacks)));
-}
-
-void WebIDBDatabaseImpl::IOThreadHelper::CreateIndex(
- int64_t transaction_id,
- int64_t object_store_id,
- int64_t index_id,
- const base::string16& name,
- const IndexedDBKeyPath& key_path,
- bool unique,
- bool multi_entry) {
- database_->CreateIndex(transaction_id, object_store_id, index_id, name,
- key_path, unique, multi_entry);
-}
-
-void WebIDBDatabaseImpl::IOThreadHelper::DeleteIndex(int64_t transaction_id,
- int64_t object_store_id,
- int64_t index_id) {
- database_->DeleteIndex(transaction_id, object_store_id, index_id);
-}
-
-void WebIDBDatabaseImpl::IOThreadHelper::RenameIndex(
- int64_t transaction_id,
- int64_t object_store_id,
- int64_t index_id,
- const base::string16& new_name) {
- database_->RenameIndex(transaction_id, object_store_id, index_id, new_name);
-}
-
-void WebIDBDatabaseImpl::IOThreadHelper::Abort(int64_t transaction_id) {
database_->Abort(transaction_id);
}
-void WebIDBDatabaseImpl::IOThreadHelper::Commit(int64_t transaction_id) {
+void WebIDBDatabaseImpl::Commit(long long transaction_id) {
database_->Commit(transaction_id);
}
-CallbacksAssociatedPtrInfo
-WebIDBDatabaseImpl::IOThreadHelper::GetCallbacksProxy(
+IDBCallbacksAssociatedPtrInfo WebIDBDatabaseImpl::GetCallbacksProxy(
std::unique_ptr<IndexedDBCallbacksImpl> callbacks) {
- CallbacksAssociatedPtrInfo ptr_info;
+ IDBCallbacksAssociatedPtrInfo ptr_info;
auto request = mojo::MakeRequest(&ptr_info);
mojo::MakeStrongAssociatedBinding(std::move(callbacks), std::move(request));
return ptr_info;
diff --git a/chromium/content/renderer/indexed_db/webidbdatabase_impl.h b/chromium/content/renderer/indexed_db/webidbdatabase_impl.h
index dfe7649639f..95fed9c766a 100644
--- a/chromium/content/renderer/indexed_db/webidbdatabase_impl.h
+++ b/chromium/content/renderer/indexed_db/webidbdatabase_impl.h
@@ -12,11 +12,10 @@
#include "base/memory/ref_counted.h"
#include "base/single_thread_task_runner.h"
#include "content/common/content_export.h"
-#include "content/common/indexed_db/indexed_db.mojom.h"
-#include "content/common/indexed_db/indexed_db_constants.h"
+#include "third_party/blink/public/common/indexeddb/web_idb_types.h"
+#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h"
#include "third_party/blink/public/platform/modules/indexeddb/web_idb_cursor.h"
#include "third_party/blink/public/platform/modules/indexeddb/web_idb_database.h"
-#include "third_party/blink/public/platform/modules/indexeddb/web_idb_types.h"
namespace blink {
class WebBlobInfo;
@@ -26,12 +25,11 @@ class WebString;
namespace content {
+class IndexedDBCallbacksImpl;
+
class CONTENT_EXPORT WebIDBDatabaseImpl : public blink::WebIDBDatabase {
public:
- WebIDBDatabaseImpl(
- indexed_db::mojom::DatabaseAssociatedPtrInfo database,
- scoped_refptr<base::SingleThreadTaskRunner> io_runner,
- scoped_refptr<base::SingleThreadTaskRunner> callback_runner);
+ WebIDBDatabaseImpl(blink::mojom::IDBDatabaseAssociatedPtrInfo database);
~WebIDBDatabaseImpl() override;
// blink::WebIDBDatabase
@@ -134,21 +132,21 @@ class CONTENT_EXPORT WebIDBDatabaseImpl : public blink::WebIDBDatabase {
void Commit(long long transaction_id) override;
private:
+ blink::mojom::IDBCallbacksAssociatedPtrInfo GetCallbacksProxy(
+ std::unique_ptr<IndexedDBCallbacksImpl> callbacks);
+
FRIEND_TEST_ALL_PREFIXES(WebIDBDatabaseImplTest, ValueSizeTest);
FRIEND_TEST_ALL_PREFIXES(WebIDBDatabaseImplTest, KeyAndValueSizeTest);
- class IOThreadHelper;
-
// Maximum size (in bytes) of value/key pair allowed for put requests. Any
// requests larger than this size will be rejected.
// Used by unit tests to exercise behavior without allocating huge chunks
// of memory.
- size_t max_put_value_size_ = kMaxIDBMessageSizeInBytes;
+ size_t max_put_value_size_ =
+ blink::mojom::kIDBMaxMessageSize - blink::mojom::kIDBMaxMessageOverhead;
- IOThreadHelper* helper_;
std::set<int32_t> observer_ids_;
- scoped_refptr<base::SingleThreadTaskRunner> io_runner_;
- scoped_refptr<base::SingleThreadTaskRunner> callback_runner_;
+ blink::mojom::IDBDatabaseAssociatedPtr database_;
};
} // namespace content
diff --git a/chromium/content/renderer/indexed_db/webidbdatabase_impl_unittest.cc b/chromium/content/renderer/indexed_db/webidbdatabase_impl_unittest.cc
index 31b31f6bf3e..be6629f1f76 100644
--- a/chromium/content/renderer/indexed_db/webidbdatabase_impl_unittest.cc
+++ b/chromium/content/renderer/indexed_db/webidbdatabase_impl_unittest.cc
@@ -10,16 +10,17 @@
#include "base/macros.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/child/thread_safe_sender.h"
-#include "content/common/indexed_db/indexed_db_key.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/renderer/indexed_db/mock_webidbcallbacks.h"
#include "content/renderer/indexed_db/webidbdatabase_impl.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/indexeddb/indexeddb_key.h"
#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
#include "third_party/blink/public/platform/web_blob_info.h"
#include "third_party/blink/public/platform/web_data.h"
#include "third_party/blink/public/web/web_heap.h"
+using blink::IndexedDBKey;
using blink::WebBlobInfo;
using blink::WebData;
using blink::WebIDBCursor;
@@ -59,9 +60,7 @@ TEST_F(WebIDBDatabaseImplTest, ValueSizeTest) {
StrictMock<MockWebIDBCallbacks> callbacks;
EXPECT_CALL(callbacks, OnError(_)).Times(1);
- WebIDBDatabaseImpl database_impl(
- nullptr, blink::scheduler::GetSingleThreadTaskRunnerForTesting(),
- blink::scheduler::GetSingleThreadTaskRunnerForTesting());
+ WebIDBDatabaseImpl database_impl(nullptr);
database_impl.max_put_value_size_ = kMaxValueSizeForTesting;
const WebIDBKey idb_key = WebIDBKey::CreateNumber(0);
database_impl.Put(transaction_id, object_store_id, value, web_blob_info,
@@ -88,9 +87,7 @@ TEST_F(WebIDBDatabaseImplTest, KeyAndValueSizeTest) {
StrictMock<MockWebIDBCallbacks> callbacks;
EXPECT_CALL(callbacks, OnError(_)).Times(1);
- WebIDBDatabaseImpl database_impl(
- nullptr, blink::scheduler::GetSingleThreadTaskRunnerForTesting(),
- blink::scheduler::GetSingleThreadTaskRunnerForTesting());
+ WebIDBDatabaseImpl database_impl(nullptr);
database_impl.max_put_value_size_ = kMaxValueSizeForTesting;
database_impl.Put(transaction_id, object_store_id, value, web_blob_info,
key.View(), blink::kWebIDBPutModeAddOrUpdate, &callbacks,
diff --git a/chromium/content/renderer/indexed_db/webidbfactory_impl.cc b/chromium/content/renderer/indexed_db/webidbfactory_impl.cc
index 753c35a361f..fb3fd54724a 100644
--- a/chromium/content/renderer/indexed_db/webidbfactory_impl.cc
+++ b/chromium/content/renderer/indexed_db/webidbfactory_impl.cc
@@ -18,52 +18,16 @@ using blink::WebIDBDatabase;
using blink::WebIDBDatabaseCallbacks;
using blink::WebSecurityOrigin;
using blink::WebString;
-using indexed_db::mojom::CallbacksAssociatedPtrInfo;
-using indexed_db::mojom::DatabaseCallbacksAssociatedPtrInfo;
-using indexed_db::mojom::FactoryAssociatedPtr;
+using blink::mojom::IDBCallbacksAssociatedPtrInfo;
+using blink::mojom::IDBDatabaseCallbacksAssociatedPtrInfo;
+using blink::mojom::IDBFactoryPtrInfo;
namespace content {
-class WebIDBFactoryImpl::IOThreadHelper {
- public:
- IOThreadHelper(scoped_refptr<IPC::SyncMessageFilter> sync_message_filter);
- ~IOThreadHelper();
+WebIDBFactoryImpl::WebIDBFactoryImpl(IDBFactoryPtrInfo factory_info)
+ : factory_(std::move(factory_info)) {}
- FactoryAssociatedPtr& GetService();
- CallbacksAssociatedPtrInfo GetCallbacksProxy(
- std::unique_ptr<IndexedDBCallbacksImpl> callbacks);
- DatabaseCallbacksAssociatedPtrInfo GetDatabaseCallbacksProxy(
- std::unique_ptr<IndexedDBDatabaseCallbacksImpl> callbacks);
-
- void GetDatabaseNames(std::unique_ptr<IndexedDBCallbacksImpl> callbacks,
- const url::Origin& origin);
- void Open(const base::string16& name,
- int64_t version,
- int64_t transaction_id,
- std::unique_ptr<IndexedDBCallbacksImpl> callbacks,
- std::unique_ptr<IndexedDBDatabaseCallbacksImpl> database_callbacks,
- const url::Origin& origin);
- void DeleteDatabase(const base::string16& name,
- std::unique_ptr<IndexedDBCallbacksImpl> callbacks,
- const url::Origin& origin,
- bool force_close);
-
- private:
- scoped_refptr<IPC::SyncMessageFilter> sync_message_filter_;
- FactoryAssociatedPtr service_;
-
- DISALLOW_COPY_AND_ASSIGN(IOThreadHelper);
-};
-
-WebIDBFactoryImpl::WebIDBFactoryImpl(
- scoped_refptr<IPC::SyncMessageFilter> sync_message_filter,
- scoped_refptr<base::SingleThreadTaskRunner> io_runner)
- : io_helper_(new IOThreadHelper(std::move(sync_message_filter))),
- io_runner_(std::move(io_runner)) {}
-
-WebIDBFactoryImpl::~WebIDBFactoryImpl() {
- io_runner_->DeleteSoon(FROM_HERE, io_helper_);
-}
+WebIDBFactoryImpl::~WebIDBFactoryImpl() = default;
void WebIDBFactoryImpl::GetDatabaseNames(
WebIDBCallbacks* callbacks,
@@ -71,12 +35,9 @@ void WebIDBFactoryImpl::GetDatabaseNames(
scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>(
base::WrapUnique(callbacks), IndexedDBCallbacksImpl::kNoTransaction,
- nullptr, io_runner_, std::move(task_runner));
- io_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&IOThreadHelper::GetDatabaseNames,
- base::Unretained(io_helper_), std::move(callbacks_impl),
- url::Origin(origin)));
+ nullptr);
+ factory_->GetDatabaseNames(GetCallbacksProxy(std::move(callbacks_impl)),
+ url::Origin(origin));
}
void WebIDBFactoryImpl::Open(
@@ -88,17 +49,13 @@ void WebIDBFactoryImpl::Open(
const WebSecurityOrigin& origin,
scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>(
- base::WrapUnique(callbacks), transaction_id, nullptr, io_runner_,
- task_runner);
+ base::WrapUnique(callbacks), transaction_id, nullptr);
auto database_callbacks_impl =
std::make_unique<IndexedDBDatabaseCallbacksImpl>(
- base::WrapUnique(database_callbacks), std::move(task_runner));
- io_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&IOThreadHelper::Open, base::Unretained(io_helper_),
- name.Utf16(), version, transaction_id,
- std::move(callbacks_impl),
- std::move(database_callbacks_impl), url::Origin(origin)));
+ base::WrapUnique(database_callbacks));
+ factory_->Open(GetCallbacksProxy(std::move(callbacks_impl)),
+ GetDatabaseCallbacksProxy(std::move(database_callbacks_impl)),
+ url::Origin(origin), name.Utf16(), version, transaction_id);
}
void WebIDBFactoryImpl::DeleteDatabase(
@@ -109,69 +66,26 @@ void WebIDBFactoryImpl::DeleteDatabase(
scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>(
base::WrapUnique(callbacks), IndexedDBCallbacksImpl::kNoTransaction,
- nullptr, io_runner_, std::move(task_runner));
- io_runner_->PostTask(
- FROM_HERE, base::BindOnce(&IOThreadHelper::DeleteDatabase,
- base::Unretained(io_helper_), name.Utf16(),
- std::move(callbacks_impl), url::Origin(origin),
- force_close));
-}
-
-WebIDBFactoryImpl::IOThreadHelper::IOThreadHelper(
- scoped_refptr<IPC::SyncMessageFilter> sync_message_filter)
- : sync_message_filter_(std::move(sync_message_filter)) {}
-
-WebIDBFactoryImpl::IOThreadHelper::~IOThreadHelper() {}
-
-FactoryAssociatedPtr& WebIDBFactoryImpl::IOThreadHelper::GetService() {
- if (!service_)
- sync_message_filter_->GetRemoteAssociatedInterface(&service_);
- return service_;
+ nullptr);
+ factory_->DeleteDatabase(GetCallbacksProxy(std::move(callbacks_impl)),
+ url::Origin(origin), name.Utf16(), force_close);
}
-CallbacksAssociatedPtrInfo WebIDBFactoryImpl::IOThreadHelper::GetCallbacksProxy(
+IDBCallbacksAssociatedPtrInfo WebIDBFactoryImpl::GetCallbacksProxy(
std::unique_ptr<IndexedDBCallbacksImpl> callbacks) {
- CallbacksAssociatedPtrInfo ptr_info;
+ IDBCallbacksAssociatedPtrInfo ptr_info;
auto request = mojo::MakeRequest(&ptr_info);
mojo::MakeStrongAssociatedBinding(std::move(callbacks), std::move(request));
return ptr_info;
}
-DatabaseCallbacksAssociatedPtrInfo
-WebIDBFactoryImpl::IOThreadHelper::GetDatabaseCallbacksProxy(
+IDBDatabaseCallbacksAssociatedPtrInfo
+WebIDBFactoryImpl::GetDatabaseCallbacksProxy(
std::unique_ptr<IndexedDBDatabaseCallbacksImpl> callbacks) {
- DatabaseCallbacksAssociatedPtrInfo ptr_info;
+ IDBDatabaseCallbacksAssociatedPtrInfo ptr_info;
auto request = mojo::MakeRequest(&ptr_info);
mojo::MakeStrongAssociatedBinding(std::move(callbacks), std::move(request));
return ptr_info;
}
-void WebIDBFactoryImpl::IOThreadHelper::GetDatabaseNames(
- std::unique_ptr<IndexedDBCallbacksImpl> callbacks,
- const url::Origin& origin) {
- GetService()->GetDatabaseNames(GetCallbacksProxy(std::move(callbacks)),
- origin);
-}
-
-void WebIDBFactoryImpl::IOThreadHelper::Open(
- const base::string16& name,
- int64_t version,
- int64_t transaction_id,
- std::unique_ptr<IndexedDBCallbacksImpl> callbacks,
- std::unique_ptr<IndexedDBDatabaseCallbacksImpl> database_callbacks,
- const url::Origin& origin) {
- GetService()->Open(GetCallbacksProxy(std::move(callbacks)),
- GetDatabaseCallbacksProxy(std::move(database_callbacks)),
- origin, name, version, transaction_id);
-}
-
-void WebIDBFactoryImpl::IOThreadHelper::DeleteDatabase(
- const base::string16& name,
- std::unique_ptr<IndexedDBCallbacksImpl> callbacks,
- const url::Origin& origin,
- bool force_close) {
- GetService()->DeleteDatabase(GetCallbacksProxy(std::move(callbacks)), origin,
- name, force_close);
-}
-
} // namespace content
diff --git a/chromium/content/renderer/indexed_db/webidbfactory_impl.h b/chromium/content/renderer/indexed_db/webidbfactory_impl.h
index 5195900dd61..8aab9cfe851 100644
--- a/chromium/content/renderer/indexed_db/webidbfactory_impl.h
+++ b/chromium/content/renderer/indexed_db/webidbfactory_impl.h
@@ -7,7 +7,9 @@
#include "base/memory/ref_counted.h"
#include "base/single_thread_task_runner.h"
-#include "content/common/indexed_db/indexed_db.mojom.h"
+#include "content/renderer/indexed_db/indexed_db_callbacks_impl.h"
+#include "content/renderer/indexed_db/indexed_db_database_callbacks_impl.h"
+#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h"
#include "third_party/blink/public/platform/modules/indexeddb/web_idb_callbacks.h"
#include "third_party/blink/public/platform/modules/indexeddb/web_idb_database_callbacks.h"
#include "third_party/blink/public/platform/modules/indexeddb/web_idb_factory.h"
@@ -17,16 +19,11 @@ class WebSecurityOrigin;
class WebString;
}
-namespace IPC {
-class SyncMessageFilter;
-}
-
namespace content {
class WebIDBFactoryImpl : public blink::WebIDBFactory {
public:
- WebIDBFactoryImpl(scoped_refptr<IPC::SyncMessageFilter> sync_message_filter,
- scoped_refptr<base::SingleThreadTaskRunner> io_runner);
+ explicit WebIDBFactoryImpl(blink::mojom::IDBFactoryPtrInfo factory_info);
~WebIDBFactoryImpl() override;
// See WebIDBFactory.h for documentation on these functions.
@@ -49,10 +46,12 @@ class WebIDBFactoryImpl : public blink::WebIDBFactory {
scoped_refptr<base::SingleThreadTaskRunner> task_runner) override;
private:
- class IOThreadHelper;
+ blink::mojom::IDBCallbacksAssociatedPtrInfo GetCallbacksProxy(
+ std::unique_ptr<IndexedDBCallbacksImpl> callbacks);
+ blink::mojom::IDBDatabaseCallbacksAssociatedPtrInfo GetDatabaseCallbacksProxy(
+ std::unique_ptr<IndexedDBDatabaseCallbacksImpl> callbacks);
- IOThreadHelper* io_helper_;
- scoped_refptr<base::SingleThreadTaskRunner> io_runner_;
+ blink::mojom::IDBFactoryPtr factory_;
};
} // namespace content
diff --git a/chromium/content/renderer/input/frame_input_handler_impl.cc b/chromium/content/renderer/input/frame_input_handler_impl.cc
index 206f5181794..175e4aaaf34 100644
--- a/chromium/content/renderer/input/frame_input_handler_impl.cc
+++ b/chromium/content/renderer/input/frame_input_handler_impl.cc
@@ -214,7 +214,7 @@ void FrameInputHandlerImpl::Replace(const base::string16& word) {
if (!render_frame_)
return;
blink::WebLocalFrame* frame = render_frame_->GetWebFrame();
- if (frame->HasSelection())
+ if (!frame->HasSelection())
frame->SelectWordAroundCaret();
frame->ReplaceSelection(blink::WebString::FromUTF16(word));
render_frame_->SyncSelectionIfRequired();
diff --git a/chromium/content/renderer/input/input_handler_manager_client.h b/chromium/content/renderer/input/input_handler_manager_client.h
index 7793a656c17..6f91e63a338 100644
--- a/chromium/content/renderer/input/input_handler_manager_client.h
+++ b/chromium/content/renderer/input/input_handler_manager_client.h
@@ -49,7 +49,6 @@ class CONTENT_EXPORT InputHandlerManagerClient {
// Otherwise |DidOverscroll| will be fired.
virtual void DidOverscroll(int routing_id,
const ui::DidOverscrollParams& params) = 0;
- virtual void DidStopFlinging(int routing_id) = 0;
virtual void DidStartScrollingViewport(int routing_id) = 0;
virtual void DispatchNonBlockingEventToMainThread(
int routing_id,
diff --git a/chromium/content/renderer/input/input_target_client_impl.cc b/chromium/content/renderer/input/input_target_client_impl.cc
index db8a81e4921..b8ee18d5fe4 100644
--- a/chromium/content/renderer/input/input_target_client_impl.cc
+++ b/chromium/content/renderer/input/input_target_client_impl.cc
@@ -24,8 +24,10 @@ void InputTargetClientImpl::BindToRequest(
void InputTargetClientImpl::FrameSinkIdAt(const gfx::Point& point,
FrameSinkIdAtCallback callback) {
- std::move(callback).Run(
- render_frame_->GetRenderWidget()->GetFrameSinkIdAtPoint(point));
+ gfx::PointF local_point;
+ viz::FrameSinkId id = render_frame_->GetRenderWidget()->GetFrameSinkIdAtPoint(
+ point, &local_point);
+ std::move(callback).Run(id, local_point);
}
} // namespace content
diff --git a/chromium/content/renderer/input/main_thread_event_queue.cc b/chromium/content/renderer/input/main_thread_event_queue.cc
index 3503cbbd5d2..301dc04a77d 100644
--- a/chromium/content/renderer/input/main_thread_event_queue.cc
+++ b/chromium/content/renderer/input/main_thread_event_queue.cc
@@ -61,6 +61,14 @@ class QueuedWebInputEvent : public ScopedWebInputEventWithLatencyInfo,
~QueuedWebInputEvent() override {}
+ bool ArePointerMoveEventTypes(QueuedWebInputEvent* other_event) {
+ // 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;
+ }
+
FilterResult FilterNewEvent(MainThreadEventQueueTask* other_task) override {
if (!other_task->IsWebInputEvent())
return FilterResult::StopIterating;
@@ -75,8 +83,14 @@ class QueuedWebInputEvent : public ScopedWebInputEventWithLatencyInfo,
if (!event().IsSameEventClass(other_event->event()))
return FilterResult::KeepIterating;
- if (!ScopedWebInputEventWithLatencyInfo::CanCoalesceWith(*other_event))
+ 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
+ // events and only their pointer_type, id, or event_type was different.
+ if (ArePointerMoveEventTypes(other_event))
+ return FilterResult::KeepIterating;
return FilterResult::StopIterating;
+ }
// If the other event was blocking store its callback to call later.
if (other_event->callback_) {
@@ -302,6 +316,34 @@ void MainThreadEventQueue::HandleEvent(
event_callback = std::move(callback);
}
+ if (has_pointerrawmove_handlers_) {
+ if (event->GetType() == WebInputEvent::kMouseMove) {
+ ui::WebScopedInputEvent raw_event(new blink::WebPointerEvent(
+ WebInputEvent::kPointerRawMove,
+ *(static_cast<blink::WebMouseEvent*>(event.get()))));
+ std::unique_ptr<QueuedWebInputEvent> raw_queued_event(
+ new QueuedWebInputEvent(std::move(raw_event), latency, false,
+ HandledEventCallback(), false));
+
+ QueueEvent(std::move(raw_queued_event));
+ } else if (event->GetType() == WebInputEvent::kTouchMove) {
+ const blink::WebTouchEvent& touch_event =
+ *static_cast<const blink::WebTouchEvent*>(event.get());
+ for (unsigned i = 0; i < touch_event.touches_length; ++i) {
+ const blink::WebTouchPoint& touch_point = touch_event.touches[i];
+ if (touch_point.state == blink::WebTouchPoint::kStateMoved) {
+ ui::WebScopedInputEvent raw_event(
+ new blink::WebPointerEvent(touch_event, touch_point));
+ raw_event->SetType(WebInputEvent::kPointerRawMove);
+ std::unique_ptr<QueuedWebInputEvent> raw_queued_event(
+ new QueuedWebInputEvent(std::move(raw_event), latency, false,
+ HandledEventCallback(), false));
+ QueueEvent(std::move(raw_queued_event));
+ }
+ }
+ }
+ }
+
std::unique_ptr<QueuedWebInputEvent> queued_event(new QueuedWebInputEvent(
std::move(event), latency, originally_cancelable,
std::move(event_callback), IsForwardedAndSchedulerKnown(ack_result)));
@@ -343,6 +385,7 @@ void MainThreadEventQueue::PossiblyScheduleMainFrame() {
void MainThreadEventQueue::DispatchEvents() {
size_t events_to_process;
+ size_t queue_size;
// Record the queue size so that we only process
// that maximum number of events.
@@ -353,7 +396,7 @@ void MainThreadEventQueue::DispatchEvents() {
// Don't process rAF aligned events at tail of queue.
while (events_to_process > 0 &&
- IsRafAlignedEvent(shared_state_.events_.at(events_to_process - 1))) {
+ !ShouldFlushQueue(shared_state_.events_.at(events_to_process - 1))) {
--events_to_process;
}
}
@@ -371,6 +414,45 @@ void MainThreadEventQueue::DispatchEvents() {
// Dispatching the event is outside of critical section.
task->Dispatch(this);
}
+
+ // Dispatch all raw move events as well regardless of where they are in the
+ // queue
+ {
+ base::AutoLock lock(shared_state_lock_);
+ queue_size = shared_state_.events_.size();
+ }
+
+ for (size_t current_task_index = 0; current_task_index < queue_size;
+ ++current_task_index) {
+ std::unique_ptr<MainThreadEventQueueTask> task;
+ {
+ base::AutoLock lock(shared_state_lock_);
+ while (current_task_index < queue_size &&
+ current_task_index < shared_state_.events_.size()) {
+ if (!IsRafAlignedEvent(shared_state_.events_.at(current_task_index)))
+ break;
+ current_task_index++;
+ }
+ if (current_task_index >= queue_size ||
+ current_task_index >= shared_state_.events_.size())
+ break;
+ if (IsRawMoveEvent(shared_state_.events_.at(current_task_index))) {
+ task = shared_state_.events_.remove(current_task_index);
+ --queue_size;
+ --current_task_index;
+ } else if (!IsRafAlignedEvent(
+ shared_state_.events_.at(current_task_index))) {
+ // Do not pass a non-rAF-aligned event to avoid delivering raw move
+ // events and down/up events out of order to js.
+ break;
+ }
+ }
+
+ // Dispatching the event is outside of critical section.
+ if (task)
+ task->Dispatch(this);
+ }
+
PossiblyScheduleMainFrame();
}
@@ -467,6 +549,21 @@ void MainThreadEventQueue::QueueEvent(
SetNeedsMainFrame();
}
+bool MainThreadEventQueue::IsRawMoveEvent(
+ const std::unique_ptr<MainThreadEventQueueTask>& item) const {
+ return item->IsWebInputEvent() &&
+ static_cast<const QueuedWebInputEvent*>(item.get())
+ ->event()
+ .GetType() == blink::WebInputEvent::kPointerRawMove;
+}
+
+bool MainThreadEventQueue::ShouldFlushQueue(
+ const std::unique_ptr<MainThreadEventQueueTask>& item) const {
+ if (IsRawMoveEvent(item))
+ return false;
+ return !IsRafAlignedEvent(item);
+}
+
bool MainThreadEventQueue::IsRafAlignedEvent(
const std::unique_ptr<MainThreadEventQueueTask>& item) const {
if (!item->IsWebInputEvent())
@@ -522,7 +619,7 @@ void MainThreadEventQueue::SetNeedsMainFrame() {
if (use_raf_fallback_timer_) {
raf_fallback_timer_.Start(
FROM_HERE, kMaxRafDelay,
- base::Bind(&MainThreadEventQueue::RafFallbackTimerFired, this));
+ base::BindOnce(&MainThreadEventQueue::RafFallbackTimerFired, this));
}
if (client_)
client_->SetNeedsMainFrame();
@@ -545,6 +642,10 @@ void MainThreadEventQueue::SetNeedsLowLatency(bool low_latency) {
needs_low_latency_ = low_latency;
}
+void MainThreadEventQueue::HasPointerRawMoveEventHandlers(bool has_handlers) {
+ has_pointerrawmove_handlers_ = has_handlers;
+}
+
void MainThreadEventQueue::RequestUnbufferedInputEvents() {
needs_low_latency_until_pointer_up_ = true;
}
diff --git a/chromium/content/renderer/input/main_thread_event_queue.h b/chromium/content/renderer/input/main_thread_event_queue.h
index f1a690f58d5..aa1354b3b01 100644
--- a/chromium/content/renderer/input/main_thread_event_queue.h
+++ b/chromium/content/renderer/input/main_thread_event_queue.h
@@ -100,6 +100,7 @@ class CONTENT_EXPORT MainThreadEventQueue
void ClearClient();
void SetNeedsLowLatency(bool low_latency);
+ void HasPointerRawMoveEventHandlers(bool has_handlers);
// Request unbuffered input events until next pointerup.
void RequestUnbufferedInputEvents();
@@ -126,6 +127,10 @@ class CONTENT_EXPORT MainThreadEventQueue
const ui::LatencyInfo& latency,
HandledEventCallback handled_callback);
+ bool IsRawMoveEvent(
+ const std::unique_ptr<MainThreadEventQueueTask>& item) const;
+ bool ShouldFlushQueue(
+ const std::unique_ptr<MainThreadEventQueueTask>& item) const;
bool IsRafAlignedEvent(
const std::unique_ptr<MainThreadEventQueueTask>& item) const;
void RafFallbackTimerFired();
@@ -143,6 +148,7 @@ class CONTENT_EXPORT MainThreadEventQueue
bool needs_low_latency_;
bool allow_raf_aligned_input_;
bool needs_low_latency_until_pointer_up_ = false;
+ bool has_pointerrawmove_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_task_list.cc b/chromium/content/renderer/input/main_thread_event_queue_task_list.cc
index 5a3b40a15c0..32a5eaa1585 100644
--- a/chromium/content/renderer/input/main_thread_event_queue_task_list.cc
+++ b/chromium/content/renderer/input/main_thread_event_queue_task_list.cc
@@ -36,4 +36,14 @@ std::unique_ptr<MainThreadEventQueueTask> MainThreadEventQueueTaskList::Pop() {
return result;
}
+std::unique_ptr<MainThreadEventQueueTask> MainThreadEventQueueTaskList::remove(
+ size_t pos) {
+ std::unique_ptr<MainThreadEventQueueTask> result;
+ if (!queue_.empty()) {
+ result.reset(queue_.at(pos).release());
+ queue_.erase(queue_.begin() + pos);
+ }
+ return result;
+}
+
} // namespace
diff --git a/chromium/content/renderer/input/main_thread_event_queue_task_list.h b/chromium/content/renderer/input/main_thread_event_queue_task_list.h
index d0580871e6a..94c01623c9b 100644
--- a/chromium/content/renderer/input/main_thread_event_queue_task_list.h
+++ b/chromium/content/renderer/input/main_thread_event_queue_task_list.h
@@ -31,6 +31,8 @@ class MainThreadEventQueueTaskList {
return queue_.at(pos);
}
+ std::unique_ptr<MainThreadEventQueueTask> remove(size_t pos);
+
bool empty() const { return queue_.empty(); }
size_t size() const { return queue_.size(); }
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 66d57509894..670672eb0f1 100644
--- a/chromium/content/renderer/input/main_thread_event_queue_unittest.cc
+++ b/chromium/content/renderer/input/main_thread_event_queue_unittest.cc
@@ -1314,6 +1314,77 @@ TEST_F(MainThreadEventQueueTest, UnbufferedDispatchTouchEvent) {
EXPECT_FALSE(needs_main_frame_);
}
+TEST_F(MainThreadEventQueueTest, PointerEventsCoalescing) {
+ queue_->HasPointerRawMoveEventHandlers(true);
+ WebMouseEvent mouse_move = SyntheticWebMouseEventBuilder::Build(
+ WebInputEvent::kMouseMove, 10, 10, 0);
+ SyntheticWebTouchEvent touch_move;
+ touch_move.PressPoint(10, 10);
+ touch_move.MovePoint(0, 50, 50);
+
+ EXPECT_FALSE(main_task_runner_->HasPendingTask());
+ EXPECT_EQ(0u, event_queue().size());
+
+ HandleEvent(mouse_move, INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING);
+ HandleEvent(touch_move, INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING);
+ EXPECT_EQ(4u, event_queue().size());
+
+ HandleEvent(mouse_move, INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING);
+ HandleEvent(touch_move, INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING);
+ HandleEvent(mouse_move, INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING);
+ HandleEvent(touch_move, INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING);
+ EXPECT_EQ(4u, event_queue().size());
+
+ main_task_runner_->RunUntilIdle();
+ EXPECT_EQ(2u, event_queue().size());
+
+ RunPendingTasksWithSimulatedRaf();
+ EXPECT_EQ(0u, event_queue().size());
+ EXPECT_FALSE(needs_main_frame_);
+}
+
+TEST_F(MainThreadEventQueueTest, PointerRawMoveEvents) {
+ WebMouseEvent mouse_move = SyntheticWebMouseEventBuilder::Build(
+ WebInputEvent::kMouseMove, 10, 10, 0);
+
+ EXPECT_FALSE(main_task_runner_->HasPendingTask());
+ EXPECT_EQ(0u, event_queue().size());
+
+ EXPECT_CALL(renderer_scheduler_,
+ DidHandleInputEventOnMainThread(testing::_, testing::_))
+ .Times(0);
+
+ HandleEvent(mouse_move, INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING);
+ EXPECT_EQ(1u, event_queue().size());
+ RunPendingTasksWithSimulatedRaf();
+ EXPECT_EQ(0u, event_queue().size());
+ EXPECT_FALSE(needs_main_frame_);
+
+ queue_->HasPointerRawMoveEventHandlers(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);
+ SyntheticWebTouchEvent touch_move;
+ touch_move.PressPoint(10, 10);
+ touch_move.MovePoint(0, 50, 50);
+ HandleEvent(touch_move, INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING);
+ EXPECT_EQ(1u, event_queue().size());
+ RunPendingTasksWithSimulatedRaf();
+ EXPECT_EQ(0u, event_queue().size());
+ EXPECT_FALSE(needs_main_frame_);
+
+ queue_->HasPointerRawMoveEventHandlers(true);
+ HandleEvent(touch_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_);
+}
+
TEST_F(MainThreadEventQueueTest, UnbufferedDispatchMouseEvent) {
WebMouseEvent mouse_down = SyntheticWebMouseEventBuilder::Build(
WebInputEvent::kMouseDown, 10, 10, 0);
diff --git a/chromium/content/renderer/input/render_widget_input_handler.cc b/chromium/content/renderer/input/render_widget_input_handler.cc
index e4636407871..0af0606b149 100644
--- a/chromium/content/renderer/input/render_widget_input_handler.cc
+++ b/chromium/content/renderer/input/render_widget_input_handler.cc
@@ -18,6 +18,7 @@
#include "content/public/common/content_switches.h"
#include "content/public/common/input_event_ack_state.h"
#include "content/public/renderer/render_frame.h"
+#include "content/renderer/browser_plugin/browser_plugin.h"
#include "content/renderer/gpu/layer_tree_view.h"
#include "content/renderer/ime_event_guard.h"
#include "content/renderer/input/render_widget_input_handler_delegate.h"
@@ -172,6 +173,16 @@ blink::WebCoalescedInputEvent GetCoalescedWebPointerEventForTouch(
return blink::WebCoalescedInputEvent(pointer_event, related_pointer_events);
}
+viz::FrameSinkId GetRemoteFrameSinkId(const blink::WebNode& node) {
+ blink::WebFrame* result_frame = blink::WebFrame::FromFrameOwnerElement(node);
+ if (result_frame && result_frame->IsWebRemoteFrame()) {
+ return RenderFrameProxy::FromWebFrame(result_frame->ToWebRemoteFrame())
+ ->frame_sink_id();
+ }
+ auto* plugin = BrowserPlugin::GetFromNode(node);
+ return plugin ? plugin->frame_sink_id() : viz::FrameSinkId();
+}
+
} // namespace
RenderWidgetInputHandler::RenderWidgetInputHandler(
@@ -191,16 +202,18 @@ RenderWidgetInputHandler::RenderWidgetInputHandler(
RenderWidgetInputHandler::~RenderWidgetInputHandler() {}
viz::FrameSinkId RenderWidgetInputHandler::GetFrameSinkIdAtPoint(
- const gfx::Point& point) {
+ const gfx::Point& point,
+ gfx::PointF* local_point) {
gfx::PointF point_in_pixel(point);
if (widget_->compositor_deps()->IsUseZoomForDSFEnabled()) {
point_in_pixel = gfx::ConvertPointToPixel(
widget_->GetOriginalScreenInfo().device_scale_factor, point_in_pixel);
}
- blink::WebNode result_node = widget_->GetWebWidget()
- ->HitTestResultAt(blink::WebPoint(
- point_in_pixel.x(), point_in_pixel.y()))
- .GetNode();
+ blink::WebHitTestResult result = widget_->GetWebWidget()->HitTestResultAt(
+ blink::WebPoint(point_in_pixel.x(), point_in_pixel.y()));
+
+ blink::WebNode result_node = result.GetNode();
+ *local_point = gfx::PointF(point);
// TODO(crbug.com/797828): When the node is null the caller may
// need to do extra checks. Like maybe update the layout and then
@@ -211,15 +224,16 @@ viz::FrameSinkId RenderWidgetInputHandler::GetFrameSinkIdAtPoint(
widget_->routing_id());
}
- blink::WebFrame* result_frame =
- blink::WebFrame::FromFrameOwnerElement(result_node);
- if (result_frame && result_frame->IsWebRemoteFrame()) {
- viz::FrameSinkId frame_sink_id =
- RenderFrameProxy::FromWebFrame(result_frame->ToWebRemoteFrame())
- ->frame_sink_id();
- if (frame_sink_id.is_valid())
- return frame_sink_id;
+ viz::FrameSinkId frame_sink_id = GetRemoteFrameSinkId(result_node);
+ if (frame_sink_id.is_valid()) {
+ *local_point = gfx::PointF(result.LocalPointWithoutContentBoxOffset());
+ if (widget_->compositor_deps()->IsUseZoomForDSFEnabled()) {
+ *local_point = gfx::ConvertPointToDIP(
+ widget_->GetOriginalScreenInfo().device_scale_factor, *local_point);
+ }
+ return frame_sink_id;
}
+
// Return the FrameSinkId for the current widget if the point did not hit
// test to a remote frame, or the remote frame doesn't have a valid
// FrameSinkId yet.
diff --git a/chromium/content/renderer/input/render_widget_input_handler.h b/chromium/content/renderer/input/render_widget_input_handler.h
index 4ebdb4f9c91..e3884c43b87 100644
--- a/chromium/content/renderer/input/render_widget_input_handler.h
+++ b/chromium/content/renderer/input/render_widget_input_handler.h
@@ -47,8 +47,10 @@ class CONTENT_EXPORT RenderWidgetInputHandler {
virtual ~RenderWidgetInputHandler();
// Hit test the given point to find out the frame underneath and
- // returns the FrameSinkId for that frame.
- viz::FrameSinkId GetFrameSinkIdAtPoint(const gfx::Point& point);
+ // returns the FrameSinkId for that frame. |local_point| returns the point
+ // in the coordinate space of the FrameSinkId that was hit.
+ viz::FrameSinkId GetFrameSinkIdAtPoint(const gfx::Point& point,
+ gfx::PointF* local_point);
// Handle input events from the input event provider.
virtual void HandleInputEvent(
diff --git a/chromium/content/renderer/input/widget_input_handler_impl.cc b/chromium/content/renderer/input/widget_input_handler_impl.cc
index 09384eed9c0..f50fe69d1c8 100644
--- a/chromium/content/renderer/input/widget_input_handler_impl.cc
+++ b/chromium/content/renderer/input/widget_input_handler_impl.cc
@@ -19,6 +19,7 @@
#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
#include "third_party/blink/public/platform/web_coalesced_input_event.h"
#include "third_party/blink/public/platform/web_keyboard_event.h"
+#include "third_party/blink/public/web/web_ime_text_span.h"
#include "third_party/blink/public/web/web_local_frame.h"
namespace content {
@@ -100,15 +101,32 @@ void WidgetInputHandlerImpl::ImeSetComposition(
range, start, end));
}
+static void ImeCommitTextOnMainThread(
+ base::WeakPtr<RenderWidget> render_widget,
+ scoped_refptr<base::SingleThreadTaskRunner> callback_task_runner,
+ const base::string16& text,
+ const std::vector<blink::WebImeTextSpan>& ime_text_spans,
+ const gfx::Range& range,
+ int32_t relative_cursor_position,
+ WidgetInputHandlerImpl::ImeCommitTextCallback callback) {
+ if (render_widget) {
+ render_widget->OnImeCommitText(text, ime_text_spans, range,
+ relative_cursor_position);
+ }
+ callback_task_runner->PostTask(FROM_HERE, std::move(callback));
+}
+
void WidgetInputHandlerImpl::ImeCommitText(
const base::string16& text,
const std::vector<ui::ImeTextSpan>& ime_text_spans,
const gfx::Range& range,
- int32_t relative_cursor_position) {
+ int32_t relative_cursor_position,
+ ImeCommitTextCallback callback) {
RunOnMainThread(
- base::BindOnce(&RenderWidget::OnImeCommitText, render_widget_, text,
+ base::BindOnce(&ImeCommitTextOnMainThread, render_widget_,
+ base::ThreadTaskRunnerHandle::Get(), text,
ConvertUiImeTextSpansToBlinkImeTextSpans(ime_text_spans),
- range, relative_cursor_position));
+ range, relative_cursor_position, std::move(callback)));
}
void WidgetInputHandlerImpl::ImeFinishComposingText(bool keep_selection) {
diff --git a/chromium/content/renderer/input/widget_input_handler_impl.h b/chromium/content/renderer/input/widget_input_handler_impl.h
index 51ffba24ae7..689f973a146 100644
--- a/chromium/content/renderer/input/widget_input_handler_impl.h
+++ b/chromium/content/renderer/input/widget_input_handler_impl.h
@@ -45,7 +45,8 @@ class WidgetInputHandlerImpl : public mojom::WidgetInputHandler {
void ImeCommitText(const base::string16& text,
const std::vector<ui::ImeTextSpan>& ime_text_spans,
const gfx::Range& range,
- int32_t relative_cursor_position) override;
+ int32_t relative_cursor_position,
+ ImeCommitTextCallback callback) override;
void ImeFinishComposingText(bool keep_selection) override;
void RequestTextInputStateUpdate() override;
void RequestCompositionUpdates(bool immediate_request,
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 9dd95c396a7..4e66f652480 100644
--- a/chromium/content/renderer/loader/child_url_loader_factory_bundle.cc
+++ b/chromium/content/renderer/loader/child_url_loader_factory_bundle.cc
@@ -96,15 +96,18 @@ ChildURLLoaderFactoryBundleInfo::ChildURLLoaderFactoryBundleInfo() = default;
ChildURLLoaderFactoryBundleInfo::ChildURLLoaderFactoryBundleInfo(
std::unique_ptr<URLLoaderFactoryBundleInfo> base_info)
: URLLoaderFactoryBundleInfo(std::move(base_info->default_factory_info()),
- std::move(base_info->factories_info())) {}
+ std::move(base_info->factories_info()),
+ base_info->bypass_redirect_checks()) {}
ChildURLLoaderFactoryBundleInfo::ChildURLLoaderFactoryBundleInfo(
network::mojom::URLLoaderFactoryPtrInfo default_factory_info,
std::map<std::string, network::mojom::URLLoaderFactoryPtrInfo>
factories_info,
- PossiblyAssociatedURLLoaderFactoryPtrInfo direct_network_factory_info)
+ PossiblyAssociatedURLLoaderFactoryPtrInfo direct_network_factory_info,
+ bool bypass_redirect_checks)
: URLLoaderFactoryBundleInfo(std::move(default_factory_info),
- std::move(factories_info)),
+ std::move(factories_info),
+ bypass_redirect_checks),
direct_network_factory_info_(std::move(direct_network_factory_info)) {}
ChildURLLoaderFactoryBundleInfo::~ChildURLLoaderFactoryBundleInfo() = default;
@@ -115,6 +118,7 @@ ChildURLLoaderFactoryBundleInfo::CreateFactory() {
other->default_factory_info_ = std::move(default_factory_info_);
other->factories_info_ = std::move(factories_info_);
other->direct_network_factory_info_ = std::move(direct_network_factory_info_);
+ other->bypass_redirect_checks_ = bypass_redirect_checks_;
return base::MakeRefCounted<ChildURLLoaderFactoryBundle>(std::move(other));
}
@@ -250,7 +254,7 @@ ChildURLLoaderFactoryBundle::CloneInternal(bool include_default) {
return std::make_unique<ChildURLLoaderFactoryBundleInfo>(
std::move(default_factory_info), std::move(factories_info),
- std::move(direct_network_factory_info));
+ std::move(direct_network_factory_info), bypass_redirect_checks_);
}
std::unique_ptr<ChildURLLoaderFactoryBundleInfo>
@@ -274,7 +278,7 @@ ChildURLLoaderFactoryBundle::PassInterface() {
return std::make_unique<ChildURLLoaderFactoryBundleInfo>(
std::move(default_factory_info), std::move(factories_info),
- std::move(direct_network_factory_info));
+ std::move(direct_network_factory_info), bypass_redirect_checks_);
}
} // namespace content
diff --git a/chromium/content/renderer/loader/child_url_loader_factory_bundle.h b/chromium/content/renderer/loader/child_url_loader_factory_bundle.h
index bcf816a026c..0ba0c4950a3 100644
--- a/chromium/content/renderer/loader/child_url_loader_factory_bundle.h
+++ b/chromium/content/renderer/loader/child_url_loader_factory_bundle.h
@@ -29,7 +29,8 @@ class CONTENT_EXPORT ChildURLLoaderFactoryBundleInfo
network::mojom::URLLoaderFactoryPtrInfo default_factory_info,
std::map<std::string, network::mojom::URLLoaderFactoryPtrInfo>
factories_info,
- PossiblyAssociatedURLLoaderFactoryPtrInfo direct_network_factory_info);
+ PossiblyAssociatedURLLoaderFactoryPtrInfo direct_network_factory_info,
+ bool bypass_redirect_checks);
~ChildURLLoaderFactoryBundleInfo() override;
PossiblyAssociatedURLLoaderFactoryPtrInfo& direct_network_factory_info() {
@@ -84,7 +85,7 @@ class CONTENT_EXPORT ChildURLLoaderFactoryBundle
// Returns an info that omits this bundle's default factory, if any. This is
// useful to make a clone that bypasses AppCache, for example.
- std::unique_ptr<network::SharedURLLoaderFactoryInfo>
+ virtual std::unique_ptr<network::SharedURLLoaderFactoryInfo>
CloneWithoutDefaultFactory();
std::unique_ptr<ChildURLLoaderFactoryBundleInfo> PassInterface();
diff --git a/chromium/content/renderer/loader/code_cache_loader_impl.cc b/chromium/content/renderer/loader/code_cache_loader_impl.cc
new file mode 100644
index 00000000000..0fbbeac5e1b
--- /dev/null
+++ b/chromium/content/renderer/loader/code_cache_loader_impl.cc
@@ -0,0 +1,108 @@
+// 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/renderer/loader/code_cache_loader_impl.h"
+#include "base/task/post_task.h"
+#include "third_party/blink/public/platform/platform.h"
+
+namespace content {
+
+CodeCacheLoaderImpl::CodeCacheLoaderImpl() : CodeCacheLoaderImpl(nullptr) {}
+
+CodeCacheLoaderImpl::CodeCacheLoaderImpl(
+ base::WaitableEvent* terminate_sync_load_event)
+ : terminate_sync_load_event_(terminate_sync_load_event),
+ weak_ptr_factory_(this) {}
+
+CodeCacheLoaderImpl::~CodeCacheLoaderImpl() = default;
+
+void CodeCacheLoaderImpl::FetchFromCodeCacheSynchronously(
+ const GURL& url,
+ base::Time* response_time_out,
+ std::vector<uint8_t>* data_out) {
+ base::WaitableEvent fetch_code_cache_event(
+ base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner =
+ base::CreateSingleThreadTaskRunnerWithTraits({});
+
+ // Also watch for terminate requests from the main thread when running on
+ // worker threads.
+ if (terminate_sync_load_event_) {
+ terminate_watcher_.StartWatching(
+ terminate_sync_load_event_,
+ base::BindOnce(&CodeCacheLoaderImpl::OnTerminate,
+ weak_ptr_factory_.GetWeakPtr(),
+ base::Unretained(&fetch_code_cache_event)),
+ task_runner);
+ }
+
+ FetchCodeCacheCallback callback =
+ base::BindOnce(&CodeCacheLoaderImpl::ReceiveDataForSynchronousFetch,
+ weak_ptr_factory_.GetWeakPtr());
+
+ // It is Ok to pass |fetch_code_cache_event| with base::Unretained. Since
+ // this thread is stalled, the fetch_code_cache_event will be kept alive.
+ task_runner->PostTask(
+ FROM_HERE,
+ base::BindOnce(&CodeCacheLoaderImpl::FetchFromCodeCacheImpl,
+ weak_ptr_factory_.GetWeakPtr(), url, std::move(callback),
+ base::Unretained(&fetch_code_cache_event)));
+
+ // Wait for the fetch from code cache to finish.
+ fetch_code_cache_event.Wait();
+
+ // Set the output data
+ *response_time_out = response_time_for_sync_load_;
+ *data_out = data_for_sync_load_;
+}
+
+void CodeCacheLoaderImpl::FetchFromCodeCache(const GURL& url,
+ FetchCodeCacheCallback callback) {
+ FetchFromCodeCacheImpl(url, std::move(callback), nullptr);
+}
+
+void CodeCacheLoaderImpl::FetchFromCodeCacheImpl(
+ const GURL& gurl,
+ FetchCodeCacheCallback callback,
+ base::WaitableEvent* fetch_event) {
+ // This may run on a different thread for synchronous events. It is Ok to pass
+ // fetch_event, because the thread is stalled and it will keep the fetch_event
+ // alive.
+ blink::Platform::Current()->FetchCachedCode(
+ gurl, base::BindOnce(&CodeCacheLoaderImpl::OnReceiveCachedCode,
+ weak_ptr_factory_.GetWeakPtr(), std::move(callback),
+ fetch_event));
+}
+
+void CodeCacheLoaderImpl::OnReceiveCachedCode(
+ FetchCodeCacheCallback callback,
+ base::WaitableEvent* fetch_event,
+ base::Time response_time,
+ const std::vector<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.
+ DCHECK(!terminated_);
+ std::move(callback).Run(response_time, data);
+ if (fetch_event)
+ fetch_event->Signal();
+}
+
+void CodeCacheLoaderImpl::ReceiveDataForSynchronousFetch(
+ const base::Time& response_time,
+ const std::vector<uint8_t>& data) {
+ response_time_for_sync_load_ = response_time;
+ data_for_sync_load_ = data;
+}
+
+void CodeCacheLoaderImpl::OnTerminate(base::WaitableEvent* fetch_event,
+ base::WaitableEvent* terminate_event) {
+ DCHECK(!terminated_);
+ terminated_ = true;
+ DCHECK(fetch_event);
+ fetch_event->Signal();
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/loader/code_cache_loader_impl.h b/chromium/content/renderer/loader/code_cache_loader_impl.h
new file mode 100644
index 00000000000..99c9d156e18
--- /dev/null
+++ b/chromium/content/renderer/loader/code_cache_loader_impl.h
@@ -0,0 +1,57 @@
+// 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_RENDERER_LOADER_CODE_CACHE_LOADER_IMPL_H_
+#define CONTENT_RENDERER_LOADER_CODE_CACHE_LOADER_IMPL_H_
+
+#include "base/memory/weak_ptr.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/synchronization/waitable_event_watcher.h"
+#include "third_party/blink/public/platform/code_cache_loader.h"
+#include "url/gurl.h"
+
+namespace content {
+
+class CodeCacheLoaderImpl : public blink::CodeCacheLoader {
+ public:
+ CodeCacheLoaderImpl();
+ explicit CodeCacheLoaderImpl(base::WaitableEvent* terminate_sync_load_event);
+
+ ~CodeCacheLoaderImpl() override;
+
+ // Fetches code cache corresponding to |url| and returns response in
+ // |response_time_out| and |data_out|. |response_time_out| and |data_out|
+ // cannot be nullptrs.
+ void FetchFromCodeCacheSynchronously(const GURL& url,
+ base::Time* response_time_out,
+ std::vector<uint8_t>* data_out) override;
+
+ void FetchFromCodeCache(const GURL& url,
+ FetchCodeCacheCallback callback) override;
+
+ private:
+ void FetchFromCodeCacheImpl(const GURL& url,
+ FetchCodeCacheCallback callback,
+ base::WaitableEvent* event);
+
+ 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);
+ void OnTerminate(base::WaitableEvent* fetch_event,
+ base::WaitableEvent* terminate_event);
+
+ base::Time response_time_for_sync_load_;
+ std::vector<uint8_t> data_for_sync_load_;
+ bool terminated_ = false;
+ base::WaitableEventWatcher terminate_watcher_;
+ base::WaitableEvent* terminate_sync_load_event_ = nullptr;
+ base::WeakPtrFactory<CodeCacheLoaderImpl> weak_ptr_factory_;
+};
+
+} // namespace content
+
+#endif
diff --git a/chromium/content/renderer/loader/frame_request_blocker.cc b/chromium/content/renderer/loader/frame_request_blocker.cc
new file mode 100644
index 00000000000..d74e0125186
--- /dev/null
+++ b/chromium/content/renderer/loader/frame_request_blocker.cc
@@ -0,0 +1,98 @@
+// 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/renderer/loader/frame_request_blocker.h"
+
+#include "content/public/common/url_loader_throttle.h"
+
+namespace content {
+
+class RequestBlockerThrottle : public URLLoaderThrottle,
+ public FrameRequestBlocker::Client {
+ public:
+ explicit RequestBlockerThrottle(
+ scoped_refptr<FrameRequestBlocker> frame_request_blocker)
+ : frame_request_blocker_(std::move(frame_request_blocker)) {}
+
+ ~RequestBlockerThrottle() override {
+ if (frame_request_blocker_)
+ frame_request_blocker_->RemoveObserver(this);
+ }
+
+ // URLLoaderThrottle implementation:
+ void WillStartRequest(network::ResourceRequest* request,
+ bool* defer) override {
+ // Wait until this method to add as a client for FrameRequestBlocker because
+ // this throttle could have moved sequences in the case of sync XHR.
+ if (!frame_request_blocker_->RegisterClientIfRequestsBlocked(this)) {
+ frame_request_blocker_ = nullptr;
+ return;
+ }
+
+ *defer = true;
+ }
+
+ // FrameRequestBlocker::Client implementation:
+ void Resume() override {
+ frame_request_blocker_->RemoveObserver(this);
+ frame_request_blocker_ = nullptr;
+ delegate_->Resume();
+ }
+
+ void Cancel() override {
+ frame_request_blocker_->RemoveObserver(this);
+ frame_request_blocker_ = nullptr;
+ delegate_->CancelWithError(net::ERR_FAILED);
+ }
+
+ private:
+ scoped_refptr<FrameRequestBlocker> frame_request_blocker_;
+};
+
+FrameRequestBlocker::FrameRequestBlocker()
+ : clients_(new base::ObserverListThreadSafe<Client>()) {}
+
+void FrameRequestBlocker::Block() {
+ DCHECK(blocked_.IsZero());
+ blocked_.Increment();
+}
+
+void FrameRequestBlocker::Resume() {
+ // In normal operation it's valid to get a Resume without a Block.
+ if (blocked_.IsZero())
+ return;
+
+ blocked_.Decrement();
+ clients_->Notify(FROM_HERE, &Client::Resume);
+}
+
+void FrameRequestBlocker::Cancel() {
+ DCHECK(blocked_.IsOne());
+ blocked_.Decrement();
+ clients_->Notify(FROM_HERE, &Client::Cancel);
+}
+
+std::unique_ptr<URLLoaderThrottle>
+FrameRequestBlocker::GetThrottleIfRequestsBlocked() {
+ if (blocked_.IsZero())
+ return nullptr;
+
+ return std::make_unique<RequestBlockerThrottle>(this);
+}
+
+void FrameRequestBlocker::RemoveObserver(Client* client) {
+ clients_->RemoveObserver(client);
+}
+
+FrameRequestBlocker::~FrameRequestBlocker() = default;
+
+bool FrameRequestBlocker::RegisterClientIfRequestsBlocked(Client* client) {
+ if (blocked_.IsZero())
+ return false;
+
+ clients_->AddObserver(client);
+ return true;
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/loader/frame_request_blocker.h b/chromium/content/renderer/loader/frame_request_blocker.h
new file mode 100644
index 00000000000..7f3504de098
--- /dev/null
+++ b/chromium/content/renderer/loader/frame_request_blocker.h
@@ -0,0 +1,64 @@
+// 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_RENDERER_LOADER_FRAME_REQUEST_BLOCKER_H_
+#define CONTENT_RENDERER_LOADER_FRAME_REQUEST_BLOCKER_H_
+
+#include "base/atomic_ref_count.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/observer_list_threadsafe.h"
+
+namespace content {
+
+class URLLoaderThrottle;
+
+// Allows the browser to block and then resume requests from a frame. This
+// includes requests from the frame's dedicated workers as well.
+// This class is thread-safe because it can be used on multiple threads, for
+// example by sync XHRs and dedicated workers.
+// TODO(crbug.com/581037): once committed interstitials launch, the remaining
+// use cases should be switched to pause the frame request in the browser and
+// this code can be removed.
+class FrameRequestBlocker
+ : public base::RefCountedThreadSafe<FrameRequestBlocker> {
+ public:
+ FrameRequestBlocker();
+
+ // Block any new subresource requests.
+ void Block();
+
+ // Resumes any blocked subresource requests.
+ void Resume();
+
+ // Cancels any blocked subresource requests.
+ void Cancel();
+
+ std::unique_ptr<URLLoaderThrottle> GetThrottleIfRequestsBlocked();
+
+ private:
+ class Client {
+ public:
+ virtual void Resume() = 0;
+ virtual void Cancel() = 0;
+ };
+
+ friend class base::RefCountedThreadSafe<FrameRequestBlocker>;
+ friend class RequestBlockerThrottle;
+ virtual ~FrameRequestBlocker();
+
+ bool RegisterClientIfRequestsBlocked(Client* client);
+
+ void RemoveObserver(Client* client);
+
+ scoped_refptr<base::ObserverListThreadSafe<Client>> clients_;
+
+ base::AtomicRefCount blocked_;
+
+ DISALLOW_COPY_AND_ASSIGN(FrameRequestBlocker);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_LOADER_FRAME_REQUEST_BLOCKER_H_
diff --git a/chromium/content/renderer/loader/request_extra_data.h b/chromium/content/renderer/loader/request_extra_data.h
index 1c2f0bacdce..2239ee9443d 100644
--- a/chromium/content/renderer/loader/request_extra_data.h
+++ b/chromium/content/renderer/loader/request_extra_data.h
@@ -12,6 +12,7 @@
#include "content/common/content_export.h"
#include "content/common/navigation_params.h"
#include "content/public/common/url_loader_throttle.h"
+#include "content/renderer/loader/frame_request_blocker.h"
#include "content/renderer/loader/navigation_response_override_parameters.h"
#include "content/renderer/loader/web_url_loader_impl.h"
#include "third_party/blink/public/mojom/page/page_visibility_state.mojom.h"
@@ -152,6 +153,15 @@ class CONTENT_EXPORT RequestExtraData : public blink::WebURLRequest::ExtraData {
url_loader_throttles_ = std::move(throttles);
}
+ void set_frame_request_blocker(
+ scoped_refptr<FrameRequestBlocker> frame_request_blocker) {
+ frame_request_blocker_ = frame_request_blocker;
+ }
+
+ scoped_refptr<FrameRequestBlocker> frame_request_blocker() {
+ return frame_request_blocker_;
+ }
+
void CopyToResourceRequest(network::ResourceRequest* request) const;
private:
@@ -176,6 +186,7 @@ class CONTENT_EXPORT RequestExtraData : public blink::WebURLRequest::ExtraData {
bool navigation_initiated_by_renderer_;
bool attach_same_site_cookies_;
std::vector<std::unique_ptr<URLLoaderThrottle>> url_loader_throttles_;
+ scoped_refptr<FrameRequestBlocker> frame_request_blocker_;
DISALLOW_COPY_AND_ASSIGN(RequestExtraData);
};
diff --git a/chromium/content/renderer/loader/resource_dispatcher.cc b/chromium/content/renderer/loader/resource_dispatcher.cc
index 3d5bd290d7b..f07e67896b5 100644
--- a/chromium/content/renderer/loader/resource_dispatcher.cc
+++ b/chromium/content/renderer/loader/resource_dispatcher.cc
@@ -18,16 +18,18 @@
#include "base/rand_util.h"
#include "base/strings/string_util.h"
#include "base/synchronization/waitable_event.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "content/common/inter_process_time_ticks_converter.h"
+#include "content/common/mime_sniffing_throttle.h"
#include "content/common/navigation_params.h"
#include "content/common/net/record_load_histograms.h"
#include "content/common/throttling_url_loader.h"
#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/resource_load_info.mojom.h"
#include "content/public/common/resource_type.h"
+#include "content/public/common/url_utils.h"
#include "content/public/renderer/fixed_received_data.h"
#include "content/public/renderer/request_peer.h"
#include "content/public/renderer/resource_dispatcher_delegate.h"
@@ -45,6 +47,7 @@
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/resource_response.h"
#include "services/network/public/cpp/url_loader_completion_status.h"
+#include "third_party/blink/public/common/service_worker/service_worker_utils.h"
namespace content {
@@ -222,6 +225,22 @@ int GetInitialRequestID() {
return base::RandInt(kMin, kMax);
}
+// Determines if the loader should be restarted on a redirect using
+// ThrottlingURLLoader::FollowRedirectForcingRestart.
+bool RedirectRequiresLoaderRestart(const GURL& original_url,
+ const GURL& redirect_url) {
+ if (!base::FeatureList::IsEnabled(network::features::kNetworkService))
+ return false;
+
+ // Restart is needed if the URL is no longer handled by network service.
+ if (IsURLHandledByNetworkService(original_url))
+ return !IsURLHandledByNetworkService(redirect_url);
+
+ // If URL wasn't originally handled by network service, restart is needed if
+ // schemes are different.
+ return original_url.scheme_piece() != redirect_url.scheme_piece();
+}
+
} // namespace
// static
@@ -275,6 +294,18 @@ void ResourceDispatcher::OnReceivedResponse(
&renderer_response_info);
request_info->load_timing_info = renderer_response_info.load_timing;
+ if (renderer_response_info.network_accessed) {
+ if (request_info->resource_type == RESOURCE_TYPE_MAIN_FRAME) {
+ UMA_HISTOGRAM_ENUMERATION("Net.ConnectionInfo.MainFrame",
+ renderer_response_info.connection_info,
+ net::HttpResponseInfo::NUM_OF_CONNECTION_INFOS);
+ } else {
+ UMA_HISTOGRAM_ENUMERATION("Net.ConnectionInfo.SubResource",
+ renderer_response_info.connection_info,
+ net::HttpResponseInfo::NUM_OF_CONNECTION_INFOS);
+ }
+ }
+
network::ResourceResponseHead response_head;
std::unique_ptr<NavigationResponseOverrideParameters> response_override =
std::move(request_info->navigation_response_override);
@@ -348,8 +379,23 @@ void ResourceDispatcher::OnReceivedRedirect(
PendingRequestInfo* request_info = GetPendingRequestInfo(request_id);
if (!request_info)
return;
+ if (!request_info->url_loader && request_info->should_follow_redirect) {
+ // This is a redirect that synchronously came as the loader is being
+ // constructed, due to a URLLoaderThrottle that changed the starting
+ // URL. Handle this in a posted task, as we don't have the loader
+ // pointer yet.
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(&ResourceDispatcher::OnReceivedRedirect,
+ weak_factory_.GetWeakPtr(), request_id,
+ redirect_info, response_head, task_runner));
+ return;
+ }
+
request_info->local_response_start = base::TimeTicks::Now();
request_info->remote_request_start = response_head.load_timing.request_start;
+ request_info->redirect_requires_loader_restart =
+ RedirectRequiresLoaderRestart(request_info->response_url,
+ redirect_info.new_url);
network::ResourceResponseInfo renderer_response_info;
ToResourceResponseInfo(*request_info, response_head, &renderer_response_info);
@@ -390,7 +436,13 @@ void ResourceDispatcher::FollowPendingRedirect(
request_info->has_pending_redirect = false;
// net::URLRequest clears its request_start on redirect, so should we.
request_info->local_request_start = base::TimeTicks::Now();
- request_info->url_loader->FollowRedirect(base::nullopt);
+ // Redirect URL may not be handled by the network service, so force a
+ // restart in case another URLLoaderFactory should handle the URL.
+ if (request_info->redirect_requires_loader_restart) {
+ request_info->url_loader->FollowRedirectForcingRestart();
+ } else {
+ request_info->url_loader->FollowRedirect(base::nullopt);
+ }
}
}
@@ -676,9 +728,12 @@ int ResourceDispatcher::StartAsync(
request->referrer, std::move(response_override_params));
if (override_url_loader) {
+ // Redirect checks are handled by NavigationURLLoaderImpl, so it's safe to
+ // pass true for |bypass_redirect_checks|.
pending_requests_[request_id]->url_loader_client =
- std::make_unique<URLLoaderClientImpl>(request_id, this,
- loading_task_runner);
+ std::make_unique<URLLoaderClientImpl>(
+ request_id, this, loading_task_runner,
+ true /* bypass_redirect_checks */, request->url);
DCHECK(continue_navigation_function);
*continue_navigation_function =
@@ -687,8 +742,9 @@ int ResourceDispatcher::StartAsync(
return request_id;
}
- std::unique_ptr<URLLoaderClientImpl> client(
- new URLLoaderClientImpl(request_id, this, loading_task_runner));
+ std::unique_ptr<URLLoaderClientImpl> client(new URLLoaderClientImpl(
+ request_id, this, loading_task_runner,
+ url_loader_factory->BypassRedirectChecks(), request->url));
if (pass_response_pipe_to_peer)
client->SetPassResponsePipeToDispatcher(true);
@@ -696,10 +752,11 @@ int ResourceDispatcher::StartAsync(
uint32_t options = network::mojom::kURLLoadOptionNone;
// TODO(jam): use this flag for ResourceDispatcherHost code path once
// MojoLoading is the only IPC code path.
- if (base::FeatureList::IsEnabled(network::features::kNetworkService) &&
- request->fetch_request_context_type != REQUEST_CONTEXT_TYPE_FETCH) {
+ if (request->fetch_request_context_type != REQUEST_CONTEXT_TYPE_FETCH) {
// MIME sniffing should be disabled for a request initiated by fetch().
options |= network::mojom::kURLLoadOptionSniffMimeType;
+ if (blink::ServiceWorkerUtils::IsServicificationEnabled())
+ throttles.push_back(std::make_unique<MimeSniffingThrottle>());
}
if (is_sync) {
options |= network::mojom::kURLLoadOptionSynchronous;
diff --git a/chromium/content/renderer/loader/resource_dispatcher.h b/chromium/content/renderer/loader/resource_dispatcher.h
index 3040fbd1189..89143458c59 100644
--- a/chromium/content/renderer/loader/resource_dispatcher.h
+++ b/chromium/content/renderer/loader/resource_dispatcher.h
@@ -215,6 +215,7 @@ class CONTENT_EXPORT ResourceDispatcher {
navigation_response_override;
bool should_follow_redirect = true;
bool always_access_network = false;
+ bool redirect_requires_loader_restart = false;
// Network error code the request completed with, or net::ERR_IO_PENDING if
// it's not completed. Used both to distinguish completion from
// cancellation, and to log histograms.
diff --git a/chromium/content/renderer/loader/tracked_child_url_loader_factory_bundle.cc b/chromium/content/renderer/loader/tracked_child_url_loader_factory_bundle.cc
index 75485fe551a..22997f9d413 100644
--- a/chromium/content/renderer/loader/tracked_child_url_loader_factory_bundle.cc
+++ b/chromium/content/renderer/loader/tracked_child_url_loader_factory_bundle.cc
@@ -16,10 +16,12 @@ TrackedChildURLLoaderFactoryBundleInfo::TrackedChildURLLoaderFactoryBundleInfo(
std::map<std::string, network::mojom::URLLoaderFactoryPtrInfo>
factories_info,
PossiblyAssociatedURLLoaderFactoryPtrInfo direct_network_factory_info,
- std::unique_ptr<HostPtrAndTaskRunner> main_thread_host_bundle)
+ std::unique_ptr<HostPtrAndTaskRunner> main_thread_host_bundle,
+ bool bypass_redirect_checks)
: ChildURLLoaderFactoryBundleInfo(std::move(default_factory_info),
std::move(factories_info),
- std::move(direct_network_factory_info)),
+ std::move(direct_network_factory_info),
+ bypass_redirect_checks),
main_thread_host_bundle_(std::move(main_thread_host_bundle)) {}
TrackedChildURLLoaderFactoryBundleInfo::
@@ -32,6 +34,7 @@ TrackedChildURLLoaderFactoryBundleInfo::CreateFactory() {
other->factories_info_ = std::move(factories_info_);
other->direct_network_factory_info_ = std::move(direct_network_factory_info_);
other->main_thread_host_bundle_ = std::move(main_thread_host_bundle_);
+ other->bypass_redirect_checks_ = bypass_redirect_checks_;
return base::MakeRefCounted<TrackedChildURLLoaderFactoryBundle>(
std::move(other));
@@ -65,7 +68,7 @@ TrackedChildURLLoaderFactoryBundle::Clone() {
std::move(info->default_factory_info()),
std::move(info->factories_info()),
std::move(info->direct_network_factory_info()),
- std::move(main_thread_host_bundle_clone));
+ std::move(main_thread_host_bundle_clone), info->bypass_redirect_checks());
}
void TrackedChildURLLoaderFactoryBundle::AddObserverOnMainThread() {
@@ -128,7 +131,24 @@ HostChildURLLoaderFactoryBundle::Clone() {
std::move(info->default_factory_info()),
std::move(info->factories_info()),
std::move(info->direct_network_factory_info()),
- std::move(main_thread_host_bundle_clone));
+ std::move(main_thread_host_bundle_clone), info->bypass_redirect_checks());
+}
+
+std::unique_ptr<network::SharedURLLoaderFactoryInfo>
+HostChildURLLoaderFactoryBundle::CloneWithoutDefaultFactory() {
+ auto info = base::WrapUnique(static_cast<ChildURLLoaderFactoryBundleInfo*>(
+ ChildURLLoaderFactoryBundle::CloneWithoutDefaultFactory().release()));
+
+ DCHECK(base::SequencedTaskRunnerHandle::IsSet());
+ auto main_thread_host_bundle_clone = std::make_unique<
+ TrackedChildURLLoaderFactoryBundle::HostPtrAndTaskRunner>(AsWeakPtr(),
+ task_runner_);
+
+ return std::make_unique<TrackedChildURLLoaderFactoryBundleInfo>(
+ std::move(info->default_factory_info()),
+ std::move(info->factories_info()),
+ std::move(info->direct_network_factory_info()),
+ std::move(main_thread_host_bundle_clone), info->bypass_redirect_checks());
}
void HostChildURLLoaderFactoryBundle::UpdateThisAndAllClones(
diff --git a/chromium/content/renderer/loader/tracked_child_url_loader_factory_bundle.h b/chromium/content/renderer/loader/tracked_child_url_loader_factory_bundle.h
index d76f70f6355..0b183ec2180 100644
--- a/chromium/content/renderer/loader/tracked_child_url_loader_factory_bundle.h
+++ b/chromium/content/renderer/loader/tracked_child_url_loader_factory_bundle.h
@@ -28,7 +28,8 @@ class CONTENT_EXPORT TrackedChildURLLoaderFactoryBundleInfo
std::map<std::string, network::mojom::URLLoaderFactoryPtrInfo>
factories_info,
PossiblyAssociatedURLLoaderFactoryPtrInfo direct_network_factory_info,
- std::unique_ptr<HostPtrAndTaskRunner> main_thread_host_bundle);
+ std::unique_ptr<HostPtrAndTaskRunner> main_thread_host_bundle,
+ bool bypass_redirect_checks);
~TrackedChildURLLoaderFactoryBundleInfo() override;
std::unique_ptr<HostPtrAndTaskRunner>& main_thread_host_bundle() {
@@ -114,6 +115,8 @@ class CONTENT_EXPORT HostChildURLLoaderFactoryBundle
// ChildURLLoaderFactoryBundle overrides.
// Returns |std::unique_ptr<TrackedChildURLLoaderFactoryBundleInfo>|.
std::unique_ptr<network::SharedURLLoaderFactoryInfo> Clone() override;
+ std::unique_ptr<network::SharedURLLoaderFactoryInfo>
+ CloneWithoutDefaultFactory() override;
bool IsHostChildURLLoaderFactoryBundle() const override;
// Update this bundle with |info|, and post cloned |info| to tracked bundles.
diff --git a/chromium/content/renderer/loader/url_loader_client_impl.cc b/chromium/content/renderer/loader/url_loader_client_impl.cc
index 0deb4423338..bf813ff292a 100644
--- a/chromium/content/renderer/loader/url_loader_client_impl.cc
+++ b/chromium/content/renderer/loader/url_loader_client_impl.cc
@@ -7,12 +7,25 @@
#include <iterator>
#include "base/callback.h"
+#include "base/feature_list.h"
#include "base/single_thread_task_runner.h"
+#include "content/public/common/url_utils.h"
+#include "content/public/renderer/content_renderer_client.h"
#include "content/renderer/loader/resource_dispatcher.h"
#include "content/renderer/loader/url_response_body_consumer.h"
#include "net/url_request/redirect_info.h"
+#include "services/network/public/cpp/features.h"
namespace content {
+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);
+}
+
+} // namespace
class URLLoaderClientImpl::DeferredMessage {
public:
@@ -113,10 +126,14 @@ class URLLoaderClientImpl::DeferredOnComplete final : public DeferredMessage {
URLLoaderClientImpl::URLLoaderClientImpl(
int request_id,
ResourceDispatcher* resource_dispatcher,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ bool bypass_redirect_checks,
+ const GURL& request_url)
: request_id_(request_id),
resource_dispatcher_(resource_dispatcher),
task_runner_(std::move(task_runner)),
+ bypass_redirect_checks_(bypass_redirect_checks),
+ last_loaded_url_(request_url),
url_loader_client_binding_(this),
weak_factory_(this) {}
@@ -231,6 +248,14 @@ void URLLoaderClientImpl::OnReceiveRedirect(
const network::ResourceResponseHead& response_head) {
DCHECK(!has_received_response_);
DCHECK(!body_consumer_);
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService) &&
+ !bypass_redirect_checks_ &&
+ !IsRedirectSafe(last_loaded_url_, redirect_info.new_url)) {
+ OnComplete(network::URLLoaderCompletionStatus(net::ERR_UNSAFE_REDIRECT));
+ return;
+ }
+
+ last_loaded_url_ = redirect_info.new_url;
if (NeedsStoringMessage()) {
StoreAndDispatch(std::make_unique<DeferredOnReceiveRedirect>(
redirect_info, response_head, task_runner_));
diff --git a/chromium/content/renderer/loader/url_loader_client_impl.h b/chromium/content/renderer/loader/url_loader_client_impl.h
index 6ede15c50e6..06321932492 100644
--- a/chromium/content/renderer/loader/url_loader_client_impl.h
+++ b/chromium/content/renderer/loader/url_loader_client_impl.h
@@ -37,7 +37,9 @@ class CONTENT_EXPORT URLLoaderClientImpl final
public:
URLLoaderClientImpl(int request_id,
ResourceDispatcher* resource_dispatcher,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ bool bypass_redirect_checks,
+ const GURL& request_url);
~URLLoaderClientImpl() override;
// Sets |is_deferred_|. From now, the received messages are not dispatched
@@ -103,6 +105,8 @@ class CONTENT_EXPORT URLLoaderClientImpl final
int32_t accumulated_transfer_size_diff_during_deferred_ = 0;
ResourceDispatcher* const resource_dispatcher_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+ bool bypass_redirect_checks_ = false;
+ GURL last_loaded_url_;
network::mojom::URLLoaderPtr url_loader_;
mojo::Binding<network::mojom::URLLoaderClient> url_loader_client_binding_;
diff --git a/chromium/content/renderer/loader/url_loader_client_impl_unittest.cc b/chromium/content/renderer/loader/url_loader_client_impl_unittest.cc
index 71bdf233be9..2fc2884de80 100644
--- a/chromium/content/renderer/loader/url_loader_client_impl_unittest.cc
+++ b/chromium/content/renderer/loader/url_loader_client_impl_unittest.cc
@@ -7,6 +7,7 @@
#include <vector>
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
+#include "content/public/common/request_context_type.h"
#include "content/renderer/loader/navigation_response_override_parameters.h"
#include "content/renderer/loader/resource_dispatcher.h"
#include "content/renderer/loader/test_request_peer.h"
@@ -25,8 +26,13 @@ class URLLoaderClientImplTest : public ::testing::Test,
public network::mojom::URLLoaderFactory {
protected:
URLLoaderClientImplTest() : dispatcher_(new ResourceDispatcher()) {
+ auto request = std::make_unique<network::ResourceRequest>();
+ // Set request context type to fetch so that ResourceDispatcher doesn't
+ // install MimeSniffingThrottle, which makes URLLoaderThrottleLoader
+ // defer the request.
+ request->fetch_request_context_type = REQUEST_CONTEXT_TYPE_FETCH;
request_id_ = dispatcher_->StartAsync(
- std::make_unique<network::ResourceRequest>(), 0,
+ std::move(request), 0,
blink::scheduler::GetSingleThreadTaskRunnerForTesting(),
TRAFFIC_ANNOTATION_FOR_TESTS, false, false,
std::make_unique<TestRequestPeer>(dispatcher_.get(),
diff --git a/chromium/content/renderer/loader/web_url_loader_impl.cc b/chromium/content/renderer/loader/web_url_loader_impl.cc
index b031f857bb1..5d63b5a8728 100644
--- a/chromium/content/renderer/loader/web_url_loader_impl.cc
+++ b/chromium/content/renderer/loader/web_url_loader_impl.cc
@@ -160,6 +160,8 @@ void PopulateURLLoadTiming(const net::LoadTimingInfo& load_timing,
url_timing->SetPushEnd(load_timing.push_end);
}
+// This is complementary to ConvertNetPriorityToWebKitPriority, defined in
+// service_worker_context_client.cc.
net::RequestPriority ConvertWebKitPriorityToNetPriority(
const WebURLRequest::Priority& priority) {
switch (priority) {
@@ -212,7 +214,6 @@ int GetInfoFromDataURL(const GURL& url,
info->content_length = data->length();
info->encoded_data_length = 0;
info->encoded_body_length = 0;
- info->previews_state = PREVIEWS_OFF;
return net::OK;
}
@@ -603,6 +604,10 @@ void WebURLLoaderImpl::Context::Start(const WebURLRequest& request,
SyncLoadResponse* sync_load_response) {
DCHECK(request_id_ == -1);
+ // Notify Blink's scheduler with the initial resource fetch priority.
+ task_runner_handle_->DidChangeRequestPriority(
+ ConvertWebKitPriorityToNetPriority(request.GetPriority()));
+
url_ = request.Url();
use_stream_on_response_ = request.UseStreamOnResponse();
report_raw_headers_ = request.ReportRawHeaders();
@@ -637,6 +642,8 @@ void WebURLLoaderImpl::Context::Start(const WebURLRequest& request,
request.GetFrameType() ==
network::mojom::RequestContextFrameType::kNone);
+ // TODO(domfarolino): Retrieve the referrer in the form of a referrer member
+ // instead of the header field. See https://crbug.com/850813.
GURL referrer_url(
request.HttpHeaderField(WebString::FromASCII("Referer")).Latin1());
const std::string& method = request.HttpMethod().Latin1();
@@ -719,6 +726,8 @@ void WebURLLoaderImpl::Context::Start(const WebURLRequest& request,
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
resource_request->previews_state =
static_cast<int>(request.GetPreviewsState());
resource_request->throttling_profile_id = request.GetDevToolsToken();
@@ -750,6 +759,17 @@ void WebURLLoaderImpl::Context::Start(const WebURLRequest& request,
std::make_unique<WebURLLoaderImpl::RequestPeerImpl>(this, discard_body);
}
+ auto throttles = extra_data->TakeURLLoaderThrottles();
+ // The frame request blocker is only for a frame's subresources.
+ if (extra_data->frame_request_blocker() &&
+ !IsResourceTypeFrame(
+ static_cast<ResourceType>(resource_request->resource_type))) {
+ auto throttle =
+ extra_data->frame_request_blocker()->GetThrottleIfRequestsBlocked();
+ if (throttle)
+ throttles.push_back(std::move(throttle));
+ }
+
if (sync_load_response) {
DCHECK(defers_loading_ == NOT_DEFERRING);
@@ -761,9 +781,8 @@ void WebURLLoaderImpl::Context::Start(const WebURLRequest& request,
resource_dispatcher_->StartSync(
std::move(resource_request), request.RequestorID(),
GetTrafficAnnotationTag(request), sync_load_response,
- url_loader_factory_, extra_data->TakeURLLoaderThrottles(),
- request.TimeoutInterval(), std::move(download_to_blob_registry),
- std::move(peer));
+ url_loader_factory_, std::move(throttles), request.TimeoutInterval(),
+ std::move(download_to_blob_registry), std::move(peer));
return;
}
@@ -774,7 +793,7 @@ void WebURLLoaderImpl::Context::Start(const WebURLRequest& request,
std::move(resource_request), request.RequestorID(), task_runner_,
GetTrafficAnnotationTag(request), false /* is_sync */,
request.PassResponsePipeToClient(), std::move(peer), url_loader_factory_,
- extra_data->TakeURLLoaderThrottles(), std::move(response_override),
+ std::move(throttles), std::move(response_override),
&continue_navigation_function);
extra_data->set_continue_navigation_function(
std::move(continue_navigation_function));
@@ -800,7 +819,7 @@ bool WebURLLoaderImpl::Context::OnReceivedRedirect(
this, TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
WebURLResponse response;
- PopulateURLResponse(url_, info, &response, report_raw_headers_);
+ PopulateURLResponse(url_, info, &response, report_raw_headers_, request_id_);
url_ = WebURL(redirect_info.new_url);
return client_->WillFollowRedirect(
@@ -822,7 +841,7 @@ void WebURLLoaderImpl::Context::OnReceivedResponse(
this, TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
WebURLResponse response;
- PopulateURLResponse(url_, info, &response, report_raw_headers_);
+ PopulateURLResponse(url_, info, &response, report_raw_headers_, request_id_);
bool show_raw_listing = false;
if (info.mime_type == "text/vnd.chromium.ftp-dir") {
@@ -1158,7 +1177,8 @@ void WebURLLoaderImpl::PopulateURLResponse(
const WebURL& url,
const network::ResourceResponseInfo& info,
WebURLResponse* response,
- bool report_security_info) {
+ bool report_security_info,
+ int request_id) {
response->SetURL(url);
response->SetResponseTime(info.response_time);
response->SetMIMEType(WebString::FromUTF8(info.mime_type));
@@ -1183,8 +1203,7 @@ void WebURLLoaderImpl::PopulateURLResponse(
response->SetWasFetchedViaServiceWorker(info.was_fetched_via_service_worker);
response->SetWasFallbackRequiredByServiceWorker(
info.was_fallback_required_by_service_worker);
- response->SetResponseTypeViaServiceWorker(
- info.response_type_via_service_worker);
+ response->SetType(info.response_type);
response->SetURLListViaServiceWorker(info.url_list_via_service_worker);
response->SetCacheStorageCacheName(
info.is_in_cache_storage
@@ -1213,9 +1232,8 @@ void WebURLLoaderImpl::PopulateURLResponse(
extra_data->set_was_alpn_negotiated(info.was_alpn_negotiated);
extra_data->set_was_alternate_protocol_available(
info.was_alternate_protocol_available);
- extra_data->set_previews_state(
- static_cast<PreviewsState>(info.previews_state));
extra_data->set_effective_connection_type(info.effective_connection_type);
+ extra_data->set_request_id(request_id);
// If there's no received headers end time, don't set load timing. This is
// the case for non-HTTP requests, requests that don't go over the wire, and
@@ -1326,7 +1344,7 @@ void WebURLLoaderImpl::LoadSynchronously(
}
PopulateURLResponse(final_url, sync_load_response.info, &response,
- request.ReportRawHeaders());
+ request.ReportRawHeaders(), context_->request_id());
encoded_data_length = sync_load_response.info.encoded_data_length;
encoded_body_length = sync_load_response.info.encoded_body_length;
if (sync_load_response.downloaded_blob) {
diff --git a/chromium/content/renderer/loader/web_url_loader_impl.h b/chromium/content/renderer/loader/web_url_loader_impl.h
index 890893884c1..6844de4a8b7 100644
--- a/chromium/content/renderer/loader/web_url_loader_impl.h
+++ b/chromium/content/renderer/loader/web_url_loader_impl.h
@@ -69,7 +69,8 @@ class CONTENT_EXPORT WebURLLoaderImpl : public blink::WebURLLoader {
static void PopulateURLResponse(const blink::WebURL& url,
const network::ResourceResponseInfo& info,
blink::WebURLResponse* response,
- bool report_security_info);
+ bool report_security_info,
+ int request_id);
// WebURLLoader methods:
void LoadSynchronously(const blink::WebURLRequest& request,
blink::WebURLLoaderClient* client,
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 9a92c2bcb8f..282e275354b 100644
--- a/chromium/content/renderer/loader/web_url_loader_impl_unittest.cc
+++ b/chromium/content/renderer/loader/web_url_loader_impl_unittest.cc
@@ -691,7 +691,7 @@ TEST_F(WebURLLoaderImplTest, ResponseIPAddress) {
network::ResourceResponseInfo info;
info.socket_address = net::HostPortPair(test.ip, 443);
blink::WebURLResponse response;
- WebURLLoaderImpl::PopulateURLResponse(url, info, &response, true);
+ WebURLLoaderImpl::PopulateURLResponse(url, info, &response, true, -1);
EXPECT_EQ(test.expected, response.RemoteIPAddress().Utf8());
};
}
@@ -718,7 +718,7 @@ TEST_F(WebURLLoaderImplTest, ResponseCert) {
network::ResourceResponseInfo info;
info.ssl_info = ssl_info;
blink::WebURLResponse web_url_response;
- WebURLLoaderImpl::PopulateURLResponse(url, info, &web_url_response, true);
+ WebURLLoaderImpl::PopulateURLResponse(url, info, &web_url_response, true, -1);
blink::WebURLResponse::WebSecurityDetails security_details =
web_url_response.SecurityDetailsForTesting();
@@ -755,7 +755,7 @@ TEST_F(WebURLLoaderImplTest, ResponseCertWithNoSANs) {
network::ResourceResponseInfo info;
info.ssl_info = ssl_info;
blink::WebURLResponse web_url_response;
- WebURLLoaderImpl::PopulateURLResponse(url, info, &web_url_response, true);
+ WebURLLoaderImpl::PopulateURLResponse(url, info, &web_url_response, true, -1);
blink::WebURLResponse::WebSecurityDetails security_details =
web_url_response.SecurityDetailsForTesting();
diff --git a/chromium/content/renderer/loader/web_url_request_util.cc b/chromium/content/renderer/loader/web_url_request_util.cc
index bceb21b9362..a7c47640c90 100644
--- a/chromium/content/renderer/loader/web_url_request_util.cc
+++ b/chromium/content/renderer/loader/web_url_request_util.cc
@@ -11,7 +11,7 @@
#include "base/logging.h"
#include "base/strings/string_util.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "content/child/child_thread_impl.h"
#include "content/public/common/service_names.mojom.h"
#include "content/renderer/loader/request_extra_data.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 d548ae54b5d..61e6dbb61eb 100644
--- a/chromium/content/renderer/loader/web_worker_fetch_context_impl.cc
+++ b/chromium/content/renderer/loader/web_worker_fetch_context_impl.cc
@@ -8,7 +8,7 @@
#include "base/feature_list.h"
#include "base/single_thread_task_runner.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "content/child/child_thread_impl.h"
#include "content/child/thread_safe_sender.h"
#include "content/common/content_constants_internal.h"
@@ -19,6 +19,8 @@
#include "content/public/common/service_names.mojom.h"
#include "content/public/renderer/url_loader_throttle_provider.h"
#include "content/public/renderer/websocket_handshake_throttle_provider.h"
+#include "content/renderer/loader/code_cache_loader_impl.h"
+#include "content/renderer/loader/frame_request_blocker.h"
#include "content/renderer/loader/request_extra_data.h"
#include "content/renderer/loader/resource_dispatcher.h"
#include "content/renderer/loader/web_url_loader_impl.h"
@@ -147,6 +149,7 @@ class WebWorkerFetchContextImpl::Factory : public blink::WebURLLoaderFactory {
WebWorkerFetchContextImpl::WebWorkerFetchContextImpl(
RendererPreferences renderer_preferences,
+ mojom::RendererPreferenceWatcherRequest preference_watcher_request,
mojom::ServiceWorkerWorkerClientRequest service_worker_client_request,
mojom::ServiceWorkerWorkerClientRegistryPtrInfo
service_worker_worker_client_registry_info,
@@ -168,6 +171,8 @@ WebWorkerFetchContextImpl::WebWorkerFetchContextImpl(
fallback_factory_info_(std::move(fallback_factory_info)),
thread_safe_sender_(thread_safe_sender),
renderer_preferences_(std::move(renderer_preferences)),
+ preference_watcher_binding_(this),
+ preference_watcher_request_(std::move(preference_watcher_request)),
throttle_provider_(std::move(throttle_provider)),
websocket_handshake_throttle_provider_(
std::move(websocket_handshake_throttle_provider)),
@@ -200,8 +205,10 @@ WebWorkerFetchContextImpl::CloneForNestedWorker() {
mojo::MakeRequest(&host_ptr_info));
}
+ mojom::RendererPreferenceWatcherPtr preference_watcher;
auto new_context = std::make_unique<WebWorkerFetchContextImpl>(
- renderer_preferences_, std::move(service_worker_client_request),
+ renderer_preferences_, mojo::MakeRequest(&preference_watcher),
+ std::move(service_worker_client_request),
std::move(service_worker_worker_client_registry_ptr_info),
std::move(host_ptr_info), loader_factory_->Clone(),
fallback_factory_->Clone(),
@@ -215,13 +222,18 @@ WebWorkerFetchContextImpl::CloneForNestedWorker() {
is_controlled_by_service_worker_;
new_context->is_on_sub_frame_ = is_on_sub_frame_;
new_context->ancestor_frame_id_ = ancestor_frame_id_;
+ new_context->frame_request_blocker_ = frame_request_blocker_;
new_context->appcache_host_id_ = appcache_host_id_;
+
+ child_preference_watchers_.AddPtr(std::move(preference_watcher));
+
return new_context;
}
void WebWorkerFetchContextImpl::InitializeOnWorkerThread() {
DCHECK(!resource_dispatcher_);
DCHECK(!binding_.is_bound());
+ DCHECK(!preference_watcher_binding_.is_bound());
resource_dispatcher_ = std::make_unique<ResourceDispatcher>();
resource_dispatcher_->set_terminate_sync_load_event(
terminate_sync_load_event_);
@@ -236,6 +248,9 @@ void WebWorkerFetchContextImpl::InitializeOnWorkerThread() {
service_worker_worker_client_registry_.Bind(
std::move(service_worker_worker_client_registry_info_));
+ if (preference_watcher_request_.is_pending())
+ preference_watcher_binding_.Bind(std::move(preference_watcher_request_));
+
if (blink::ServiceWorkerUtils::IsServicificationEnabled()) {
service_worker_container_host_.Bind(
std::move(service_worker_container_host_info_));
@@ -274,6 +289,11 @@ WebWorkerFetchContextImpl::WrapURLLoaderFactory(
network::mojom::URLLoaderFactory::Version_)));
}
+std::unique_ptr<blink::CodeCacheLoader>
+WebWorkerFetchContextImpl::CreateCodeCacheLoader() {
+ return std::make_unique<CodeCacheLoaderImpl>(terminate_sync_load_event_);
+}
+
void WebWorkerFetchContextImpl::WillSendRequest(blink::WebURLRequest& request) {
if (renderer_preferences_.enable_do_not_track) {
request.SetHTTPHeaderField(blink::WebString::FromUTF8(kDoNotTrackHeader),
@@ -283,6 +303,7 @@ void WebWorkerFetchContextImpl::WillSendRequest(blink::WebURLRequest& request) {
auto extra_data = std::make_unique<RequestExtraData>();
extra_data->set_service_worker_provider_id(service_worker_provider_id_);
extra_data->set_render_frame_id(ancestor_frame_id_);
+ extra_data->set_frame_request_blocker(frame_request_blocker_);
extra_data->set_initiated_in_secure_context(is_secure_context_);
if (throttle_provider_) {
extra_data->set_url_loader_throttles(throttle_provider_->CreateThrottles(
@@ -374,6 +395,11 @@ void WebWorkerFetchContextImpl::set_ancestor_frame_id(int id) {
ancestor_frame_id_ = id;
}
+void WebWorkerFetchContextImpl::set_frame_request_blocker(
+ scoped_refptr<FrameRequestBlocker> frame_request_blocker) {
+ frame_request_blocker_ = frame_request_blocker;
+}
+
void WebWorkerFetchContextImpl::set_site_for_cookies(
const blink::WebURL& site_for_cookies) {
site_for_cookies_ = site_for_cookies;
@@ -439,4 +465,13 @@ void WebWorkerFetchContextImpl::ResetServiceWorkerURLLoaderFactory() {
std::move(service_worker_url_loader_factory));
}
+void WebWorkerFetchContextImpl::NotifyUpdate(
+ const RendererPreferences& new_prefs) {
+ renderer_preferences_ = new_prefs;
+ child_preference_watchers_.ForAllPtrs(
+ [&new_prefs](mojom::RendererPreferenceWatcher* watcher) {
+ watcher->NotifyUpdate(new_prefs);
+ });
+}
+
} // namespace content
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 519e3bc570d..cb2223afacf 100644
--- a/chromium/content/renderer/loader/web_worker_fetch_context_impl.h
+++ b/chromium/content/renderer/loader/web_worker_fetch_context_impl.h
@@ -11,9 +11,11 @@
#include "base/synchronization/waitable_event.h"
#include "content/common/service_worker/service_worker_provider.mojom.h"
#include "content/common/service_worker/service_worker_types.h"
+#include "content/public/common/renderer_preference_watcher.mojom.h"
#include "content/public/common/renderer_preferences.h"
#include "ipc/ipc_message.h"
#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/interface_ptr_set.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "services/service_manager/public/cpp/connector.h"
@@ -29,6 +31,7 @@ class Message;
namespace content {
+class FrameRequestBlocker;
class ResourceDispatcher;
class ThreadSafeSender;
class URLLoaderThrottleProvider;
@@ -40,7 +43,8 @@ class WebSocketHandshakeThrottleProvider;
// service workers, ServiceWorkerFetchContextImpl class is used instead.
class CONTENT_EXPORT WebWorkerFetchContextImpl
: public blink::WebWorkerFetchContext,
- public mojom::ServiceWorkerWorkerClient {
+ public mojom::ServiceWorkerWorkerClient,
+ public mojom::RendererPreferenceWatcher {
public:
// |service_worker_client_request| is bound to |this| to receive
// OnControllerChanged() notifications.
@@ -62,6 +66,7 @@ class CONTENT_EXPORT WebWorkerFetchContextImpl
// chrome-extension://).
WebWorkerFetchContextImpl(
RendererPreferences renderer_preferences,
+ mojom::RendererPreferenceWatcherRequest watcher_request,
mojom::ServiceWorkerWorkerClientRequest service_worker_client_request,
mojom::ServiceWorkerWorkerClientRegistryPtrInfo
service_worker_worker_client_registry_info,
@@ -84,6 +89,7 @@ class CONTENT_EXPORT WebWorkerFetchContextImpl
std::unique_ptr<blink::WebURLLoaderFactory> CreateURLLoaderFactory() override;
std::unique_ptr<blink::WebURLLoaderFactory> WrapURLLoaderFactory(
mojo::ScopedMessagePipeHandle url_loader_factory_handle) override;
+ std::unique_ptr<blink::CodeCacheLoader> CreateCodeCacheLoader() override;
void WillSendRequest(blink::WebURLRequest&) override;
blink::mojom::ControllerServiceWorkerMode IsControlledByServiceWorker()
const override;
@@ -114,6 +120,8 @@ class CONTENT_EXPORT WebWorkerFetchContextImpl
void set_is_controlled_by_service_worker(
blink::mojom::ControllerServiceWorkerMode mode);
void set_ancestor_frame_id(int id);
+ void set_frame_request_blocker(
+ scoped_refptr<FrameRequestBlocker> frame_request_blocker);
void set_site_for_cookies(const blink::WebURL& site_for_cookies);
// Sets whether the worker context is a secure context.
// https://w3c.github.io/webappsec-secure-contexts/
@@ -136,6 +144,9 @@ class CONTENT_EXPORT WebWorkerFetchContextImpl
// controlled by a service worker.
void ResetServiceWorkerURLLoaderFactory();
+ // Implements mojom::RendererPreferenceWatcher.
+ void NotifyUpdate(const RendererPreferences& new_prefs) override;
+
mojo::Binding<mojom::ServiceWorkerWorkerClient> binding_;
mojom::ServiceWorkerWorkerClientRegistryPtr
service_worker_worker_client_registry_;
@@ -195,15 +206,26 @@ class CONTENT_EXPORT WebWorkerFetchContextImpl
// workers, this is the shadow page.
bool is_on_sub_frame_ = false;
int ancestor_frame_id_ = MSG_ROUTING_NONE;
+ // Set to non-null if the ancestor frame has an associated RequestBlocker,
+ // which blocks requests from this worker too when the ancestor frame is
+ // blocked.
+ scoped_refptr<FrameRequestBlocker> frame_request_blocker_;
GURL site_for_cookies_;
bool is_secure_context_ = false;
GURL origin_url_;
int appcache_host_id_ = blink::WebApplicationCacheHost::kAppCacheNoHostId;
- // TODO(crbug.com/862854): Propagate preference changes from the browser
- // process.
RendererPreferences renderer_preferences_;
+ // |watcher_binding_| and |child_preference_watchers_| are for keeping track
+ // of updates in the renderer preferences.
+ mojo::Binding<mojom::RendererPreferenceWatcher> preference_watcher_binding_;
+ // Kept while staring up the worker thread. Valid until
+ // InitializeOnWorkerThread().
+ mojom::RendererPreferenceWatcherRequest preference_watcher_request_;
+ mojo::InterfacePtrSet<mojom::RendererPreferenceWatcher>
+ child_preference_watchers_;
+
// This is owned by ThreadedMessagingProxyBase on the main thread.
base::WaitableEvent* terminate_sync_load_event_ = nullptr;
diff --git a/chromium/content/renderer/loader/weburlresponse_extradata_impl.h b/chromium/content/renderer/loader/weburlresponse_extradata_impl.h
index 5d857655774..9b26d307ac1 100644
--- a/chromium/content/renderer/loader/weburlresponse_extradata_impl.h
+++ b/chromium/content/renderer/loader/weburlresponse_extradata_impl.h
@@ -10,7 +10,6 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "content/common/content_export.h"
-#include "content/public/common/previews_state.h"
#include "net/http/http_response_info.h"
#include "net/nqe/effective_connection_type.h"
#include "third_party/blink/public/platform/web_url_response.h"
@@ -55,12 +54,6 @@ class CONTENT_EXPORT WebURLResponseExtraDataImpl
is_ftp_directory_listing_ = is_ftp_directory_listing;
}
- // Returns a bitmask of potentially several Previews optimizations.
- PreviewsState previews_state() const { return previews_state_; }
- void set_previews_state(PreviewsState previews_state) {
- previews_state_ = previews_state;
- }
-
net::EffectiveConnectionType effective_connection_type() const {
return effective_connection_type_;
}
@@ -69,13 +62,17 @@ class CONTENT_EXPORT WebURLResponseExtraDataImpl
effective_connection_type_ = effective_connection_type;
}
+ // Request ID generated by the renderer.
+ int request_id() const { return request_id_; }
+ void set_request_id(int request_id) { request_id_ = request_id; }
+
private:
bool is_ftp_directory_listing_;
bool was_fetched_via_spdy_;
bool was_alpn_negotiated_;
bool was_alternate_protocol_available_;
- PreviewsState previews_state_;
net::EffectiveConnectionType effective_connection_type_;
+ int request_id_;
DISALLOW_COPY_AND_ASSIGN(WebURLResponseExtraDataImpl);
};
diff --git a/chromium/content/renderer/manifest/manifest_parser.cc b/chromium/content/renderer/manifest/manifest_parser.cc
index 22fba6ba3bd..c952a6b760c 100644
--- a/chromium/content/renderer/manifest/manifest_parser.cc
+++ b/chromium/content/renderer/manifest/manifest_parser.cc
@@ -15,7 +15,6 @@
#include "base/values.h"
#include "content/public/common/manifest_util.h"
#include "content/renderer/manifest/manifest_uma_util.h"
-#include "third_party/blink/public/common/manifest/manifest_share_target_util.h"
#include "third_party/blink/public/platform/web_icon_sizes_parser.h"
#include "third_party/blink/public/platform/web_size.h"
#include "third_party/blink/public/platform/web_string.h"
@@ -341,18 +340,15 @@ std::vector<blink::Manifest::ImageResource> ManifestParser::ParseIcons(
return icons;
}
-GURL ManifestParser::ParseShareTargetURLTemplate(
- const base::DictionaryValue& share_target) {
- GURL url_template = ParseURL(share_target, "url_template", manifest_url_,
- ParseURLOriginRestrictions::kSameOriginOnly);
- if (!blink::ValidateWebShareUrlTemplate(url_template)) {
- AddErrorInfo(
- "property 'url_template' ignored. Placeholders have incorrect "
- "syntax.");
- return GURL();
- }
-
- return url_template;
+blink::Manifest::ShareTargetParams ManifestParser::ParseShareTargetParams(
+ const base::DictionaryValue& share_target_params) {
+ blink::Manifest::ShareTargetParams params;
+ // NOTE: These are key names for query parameters, which are filled with share
+ // data. As such, |params.url| is just a string.
+ params.text = ParseString(share_target_params, "text", Trim);
+ params.title = ParseString(share_target_params, "title", Trim);
+ params.url = ParseString(share_target_params, "url", Trim);
+ return params;
}
base::Optional<blink::Manifest::ShareTarget> ManifestParser::ParseShareTarget(
@@ -363,10 +359,25 @@ base::Optional<blink::Manifest::ShareTarget> ManifestParser::ParseShareTarget(
blink::Manifest::ShareTarget share_target;
const base::DictionaryValue* share_target_dict = nullptr;
dictionary.GetDictionary("share_target", &share_target_dict);
- share_target.url_template = ParseShareTargetURLTemplate(*share_target_dict);
+ share_target.action = ParseURL(*share_target_dict, "action", manifest_url_,
+ ParseURLOriginRestrictions::kSameOriginOnly);
+ if (!share_target.action.is_valid()) {
+ AddErrorInfo(
+ "property 'share_target' ignored. Property 'action' is "
+ "invalid.");
+ return base::nullopt;
+ }
- if (share_target.url_template.is_empty())
+ const base::DictionaryValue* share_target_params_dict = nullptr;
+ if (!share_target_dict->GetDictionary("params", &share_target_params_dict)) {
+ AddErrorInfo(
+ "property 'share_target' ignored. Property 'params' type "
+ "dictionary expected.");
return base::nullopt;
+ }
+
+ share_target.params = ParseShareTargetParams(*share_target_params_dict);
+
return base::Optional<blink::Manifest::ShareTarget>(share_target);
}
diff --git a/chromium/content/renderer/manifest/manifest_parser.h b/chromium/content/renderer/manifest/manifest_parser.h
index 69551b8c3f3..e7ccc3a479e 100644
--- a/chromium/content/renderer/manifest/manifest_parser.h
+++ b/chromium/content/renderer/manifest/manifest_parser.h
@@ -156,10 +156,12 @@ class CONTENT_EXPORT ManifestParser {
std::vector<blink::Manifest::ImageResource> ParseIcons(
const base::DictionaryValue& dictionary);
- // Parses the 'url_template' field of a Share Target, as defined in:
+ // Parses the 'params' field of a Share Target, as defined in:
// https://github.com/WICG/web-share-target/blob/master/docs/interface.md
- // Returns the parsed GURL if any, or an empty GURL if the parsing failed.
- GURL ParseShareTargetURLTemplate(const base::DictionaryValue& share_target);
+ // Returns a parsed Manifest::ShareTargetParams, not all fields need to be
+ // populated.
+ blink::Manifest::ShareTargetParams ParseShareTargetParams(
+ const base::DictionaryValue& share_target_params);
// Parses the 'share_target' field of a Manifest, as defined in:
// https://github.com/WICG/web-share-target/blob/master/docs/interface.md
diff --git a/chromium/content/renderer/manifest/manifest_parser_unittest.cc b/chromium/content/renderer/manifest/manifest_parser_unittest.cc
index a47995053f4..8eb69dadff2 100644
--- a/chromium/content/renderer/manifest/manifest_parser_unittest.cc
+++ b/chromium/content/renderer/manifest/manifest_parser_unittest.cc
@@ -1031,7 +1031,33 @@ TEST_F(ManifestParserTest, ShareTargetParseRules) {
blink::Manifest manifest = ParseManifest("{ \"share_target\": {} }");
EXPECT_FALSE(manifest.share_target.has_value());
EXPECT_TRUE(manifest.IsEmpty());
- EXPECT_EQ(0u, GetErrorCount());
+ EXPECT_EQ(1u, GetErrorCount());
+ EXPECT_EQ("property 'share_target' ignored. Property 'action' is invalid.",
+ errors()[0]);
+ }
+
+ // Contains share_target field but no params key.
+ {
+ blink::Manifest manifest =
+ ParseManifest("{ \"share_target\": { \"action\": \"\" } }");
+ EXPECT_FALSE(manifest.share_target.has_value());
+ EXPECT_TRUE(manifest.IsEmpty());
+ EXPECT_EQ(1u, GetErrorCount());
+ EXPECT_EQ(
+ "property 'share_target' ignored. Property 'params' type "
+ "dictionary expected.",
+ errors()[0]);
+ }
+
+ // Contains share_target field but no action key.
+ {
+ blink::Manifest manifest =
+ ParseManifest("{ \"share_target\": { \"params\": {} } }");
+ EXPECT_FALSE(manifest.share_target.has_value());
+ EXPECT_TRUE(manifest.IsEmpty());
+ EXPECT_EQ(1u, GetErrorCount());
+ EXPECT_EQ("property 'share_target' ignored. Property 'action' is invalid.",
+ errors()[0]);
}
// Key in share_target that isn't valid.
@@ -1040,7 +1066,9 @@ TEST_F(ManifestParserTest, ShareTargetParseRules) {
"{ \"share_target\": {\"incorrect_key\": \"some_value\" } }");
ASSERT_FALSE(manifest.share_target.has_value());
EXPECT_TRUE(manifest.IsEmpty());
- EXPECT_EQ(0u, GetErrorCount());
+ EXPECT_EQ(1u, GetErrorCount());
+ EXPECT_EQ("property 'share_target' ignored. Property 'action' is invalid.",
+ errors()[0]);
}
}
@@ -1048,134 +1076,234 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
GURL manifest_url = GURL("https://foo.com/manifest.json");
GURL document_url = GURL("https://foo.com/index.html");
- // Contains share_target and url_template, but url_template is empty.
+ // Contains share_target, but action is empty.
{
blink::Manifest manifest = ParseManifestWithURLs(
- "{ \"share_target\": { \"url_template\": \"\" } }", manifest_url,
- document_url);
+ "{ \"share_target\": { \"action\": \"\", \"params\": {} } }",
+ manifest_url, document_url);
ASSERT_TRUE(manifest.share_target.has_value());
- EXPECT_EQ(manifest.share_target.value().url_template.spec(),
- manifest_url.spec());
+ EXPECT_EQ(manifest.share_target->action.spec(), manifest_url.spec());
+ EXPECT_TRUE(manifest.share_target->params.text.is_null());
+ EXPECT_TRUE(manifest.share_target->params.title.is_null());
+ EXPECT_TRUE(manifest.share_target->params.url.is_null());
EXPECT_FALSE(manifest.IsEmpty());
EXPECT_EQ(0u, GetErrorCount());
}
- // Don't parse if property isn't a string.
+ // Parse but throw an error if url_template property isn't a string.
{
- blink::Manifest manifest =
- ParseManifestWithURLs("{ \"share_target\": { \"url_template\": {} } }",
- manifest_url, document_url);
+ blink::Manifest manifest = ParseManifestWithURLs(
+ "{ \"share_target\": { \"action\": \"\", \"params\": {} } }",
+ manifest_url, document_url);
+ EXPECT_TRUE(manifest.share_target.has_value());
+ EXPECT_EQ(manifest.share_target->action.spec(), manifest_url.spec());
+ EXPECT_TRUE(manifest.share_target->params.text.is_null());
+ EXPECT_TRUE(manifest.share_target->params.title.is_null());
+ EXPECT_TRUE(manifest.share_target->params.url.is_null());
+ EXPECT_FALSE(manifest.IsEmpty());
+ EXPECT_EQ(0u, GetErrorCount());
+ }
+
+ // Don't parse if action property isn't a string.
+ {
+ blink::Manifest manifest = ParseManifestWithURLs(
+ "{ \"share_target\": { \"action\": {}, \"params\": {} } }",
+ manifest_url, document_url);
EXPECT_FALSE(manifest.share_target.has_value());
EXPECT_TRUE(manifest.IsEmpty());
- EXPECT_EQ(1u, GetErrorCount());
- EXPECT_EQ("property 'url_template' ignored, type string expected.",
- errors()[0]);
+ EXPECT_EQ(2u, GetErrorCount());
+ EXPECT_EQ("property 'action' ignored, type string expected.", errors()[0]);
+ EXPECT_EQ("property 'share_target' ignored. Property 'action' is invalid.",
+ errors()[1]);
}
- // Don't parse if property isn't a string.
+ // Don't parse if action property isn't a string.
{
- blink::Manifest manifest =
- ParseManifestWithURLs("{ \"share_target\": { \"url_template\": 42 } }",
- manifest_url, document_url);
+ blink::Manifest manifest = ParseManifestWithURLs(
+ "{ \"share_target\": { \"action\": 42, \"params\": {} } }",
+ manifest_url, document_url);
EXPECT_FALSE(manifest.share_target.has_value());
EXPECT_TRUE(manifest.IsEmpty());
- EXPECT_EQ(1u, GetErrorCount());
- EXPECT_EQ("property 'url_template' ignored, type string expected.",
- errors()[0]);
+ EXPECT_EQ(2u, GetErrorCount());
+ EXPECT_EQ("property 'action' ignored, type string expected.", errors()[0]);
+ EXPECT_EQ("property 'share_target' ignored. Property 'action' is invalid.",
+ errors()[1]);
}
- // Don't parse if property isn't a valid URL.
+ // Don't parse if params property isn't a dict.
{
blink::Manifest manifest = ParseManifestWithURLs(
- "{ \"share_target\": { \"url_template\": \"https://foo.com:a\" } "
- "}",
+ "{ \"share_target\": { \"action\": \"\", \"params\": \"\" } }",
manifest_url, document_url);
EXPECT_FALSE(manifest.share_target.has_value());
EXPECT_TRUE(manifest.IsEmpty());
EXPECT_EQ(1u, GetErrorCount());
- EXPECT_EQ("property 'url_template' ignored, URL is invalid.", errors()[0]);
+ EXPECT_EQ(
+ "property 'share_target' ignored. Property 'params' type "
+ "dictionary expected.",
+ errors()[0]);
}
- // Fail parsing if url_template is at a different origin than the Web
- // Manifest.
+ // Don't parse if params property isn't a dict.
{
blink::Manifest manifest = ParseManifestWithURLs(
- "{ \"share_target\": { \"url_template\": \"https://foo2.com/\" } }",
+ "{ \"share_target\": { \"action\": \"\", \"params\": 42 } }",
manifest_url, document_url);
EXPECT_FALSE(manifest.share_target.has_value());
EXPECT_TRUE(manifest.IsEmpty());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ(
- "property 'url_template' ignored, should be same origin as document.",
+ "property 'share_target' ignored. Property 'params' type "
+ "dictionary expected.",
errors()[0]);
}
- // Smoke test: Contains share_target and url_template, and url_template is
- // valid template.
+ // Ignore params keys with invalid types.
{
blink::Manifest manifest = ParseManifestWithURLs(
- "{ \"share_target\": {\"url_template\": \"share/?title={title}\" } }",
+ "{ \"share_target\": { \"action\": \"\", \"params\": { \"text\": 42 }"
+ " } }",
manifest_url, document_url);
ASSERT_TRUE(manifest.share_target.has_value());
- EXPECT_EQ(manifest.share_target.value().url_template.spec(),
- "https://foo.com/share/?title={title}");
+ EXPECT_EQ(manifest.share_target->action.spec(), manifest_url.spec());
+ EXPECT_TRUE(manifest.share_target->params.text.is_null());
+ EXPECT_TRUE(manifest.share_target->params.title.is_null());
+ EXPECT_TRUE(manifest.share_target->params.url.is_null());
EXPECT_FALSE(manifest.IsEmpty());
- EXPECT_EQ(0u, GetErrorCount());
+ EXPECT_EQ("property 'text' ignored, type string expected.", errors()[0]);
}
- // Smoke test: Contains share_target and url_template, and url_template is
- // invalid template.
+ // Ignore params keys with invalid types.
{
blink::Manifest manifest = ParseManifestWithURLs(
- "{ \"share_target\": {\"url_template\": \"share/?title={title\" } }",
+ "{ \"share_target\": { \"action\": \"\", "
+ "\"params\": { \"title\": 42 } } }",
manifest_url, document_url);
- ASSERT_FALSE(manifest.share_target.has_value());
+ ASSERT_TRUE(manifest.share_target.has_value());
+ EXPECT_EQ(manifest.share_target->action.spec(), manifest_url.spec());
+ EXPECT_TRUE(manifest.share_target->params.text.is_null());
+ EXPECT_TRUE(manifest.share_target->params.title.is_null());
+ EXPECT_TRUE(manifest.share_target->params.url.is_null());
+ EXPECT_FALSE(manifest.IsEmpty());
+ EXPECT_EQ("property 'title' ignored, type string expected.", errors()[0]);
+ }
+
+ // Don't parse if params property has keys with invalid types.
+ {
+ blink::Manifest manifest = ParseManifestWithURLs(
+ "{ \"share_target\": { \"action\": \"\", \"params\": { \"url\": {}, "
+ "\"text\": \"hi\" } } }",
+ manifest_url, document_url);
+ ASSERT_TRUE(manifest.share_target.has_value());
+ EXPECT_EQ(manifest.share_target->action.spec(), manifest_url.spec());
+ EXPECT_TRUE(
+ base::EqualsASCII(manifest.share_target->params.text.string(), "hi"));
+ EXPECT_TRUE(manifest.share_target->params.title.is_null());
+ EXPECT_TRUE(manifest.share_target->params.url.is_null());
+ EXPECT_FALSE(manifest.IsEmpty());
+ EXPECT_EQ("property 'url' ignored, type string expected.", errors()[0]);
+ }
+
+ // Don't parse if action property isn't a valid URL.
+ {
+ blink::Manifest manifest = ParseManifestWithURLs(
+ "{ \"share_target\": { \"action\": \"https://foo.com:a\", \"params\": "
+ "{} } }",
+ manifest_url, document_url);
+ EXPECT_FALSE(manifest.share_target.has_value());
EXPECT_TRUE(manifest.IsEmpty());
- EXPECT_EQ(1u, GetErrorCount());
+ EXPECT_EQ(2u, GetErrorCount());
+ EXPECT_EQ("property 'action' ignored, URL is invalid.", errors()[0]);
+ EXPECT_EQ("property 'share_target' ignored. Property 'action' is invalid.",
+ errors()[1]);
+ }
+
+ // Fail parsing if action is at a different origin than the Web
+ // Manifest.
+ {
+ blink::Manifest manifest = ParseManifestWithURLs(
+ "{ \"share_target\": { \"action\": \"https://foo2.com/\" }, "
+ "\"params\": {} }",
+ manifest_url, document_url);
+ EXPECT_FALSE(manifest.share_target.has_value());
+ EXPECT_TRUE(manifest.IsEmpty());
+ EXPECT_EQ(2u, GetErrorCount());
+ EXPECT_EQ("property 'action' ignored, should be same origin as document.",
+ errors()[0]);
EXPECT_EQ(
- "property 'url_template' ignored. Placeholders have incorrect "
- "syntax.",
- errors()[0]);
+ "property 'share_target' ignored. Property 'action' is "
+ "invalid.",
+ errors()[1]);
+ }
+
+ // Smoke test: Contains share_target and action, and action is valid.
+ {
+ blink::Manifest manifest = ParseManifestWithURLs(
+ "{ \"share_target\": {\"action\": \"share/\", \"params\": {} } }",
+ manifest_url, document_url);
+ ASSERT_TRUE(manifest.share_target.has_value());
+ EXPECT_EQ(manifest.share_target->action.spec(), "https://foo.com/share/");
+ EXPECT_TRUE(manifest.share_target->params.text.is_null());
+ EXPECT_TRUE(manifest.share_target->params.title.is_null());
+ EXPECT_TRUE(manifest.share_target->params.url.is_null());
+ EXPECT_FALSE(manifest.IsEmpty());
+ EXPECT_EQ(0u, GetErrorCount());
}
- // Smoke test: Contains share_target and url_template, and url_template
- // contains unknown placeholder.
+ // Smoke test: Contains share_target and action, and action is valid, params
+ // is populated.
{
blink::Manifest manifest = ParseManifestWithURLs(
- "{ \"share_target\": {\"url_template\": \"share/?title={abcxyz}\" } }",
+ "{ \"share_target\": {\"action\": \"share/\", \"params\": { \"text\": "
+ "\"foo\", \"title\": \"bar\", \"url\": \"baz\" } } }",
manifest_url, document_url);
ASSERT_TRUE(manifest.share_target.has_value());
- EXPECT_EQ(manifest.share_target.value().url_template.spec(),
- "https://foo.com/share/?title={abcxyz}");
+ EXPECT_EQ(manifest.share_target->action.spec(), "https://foo.com/share/");
+ EXPECT_TRUE(
+ base::EqualsASCII(manifest.share_target->params.text.string(), "foo"));
+ EXPECT_TRUE(
+ base::EqualsASCII(manifest.share_target->params.title.string(), "bar"));
+ EXPECT_TRUE(
+ base::EqualsASCII(manifest.share_target->params.url.string(), "baz"));
EXPECT_FALSE(manifest.IsEmpty());
EXPECT_EQ(0u, GetErrorCount());
}
- // Smoke test: Contains share_target and url_template, and url_template has
- // '{' and '}' in path, query and fragment. Only '{' and '}' in path should be
- // escaped.
+ // Backwards compatibility test: Contains share_target, url_template and
+ // action, and action is valid, params is populated.
{
blink::Manifest manifest = ParseManifestWithURLs(
- "{ \"share_target\": {\"url_template\": "
- "\"share/a{text}/?title={title}#{frag}\" } }",
+ "{ \"share_target\": { \"url_template\": "
+ "\"foo.com/share?title={title}\", "
+ "\"action\": \"share/\", \"params\": { \"text\": "
+ "\"foo\", \"title\": \"bar\", \"url\": \"baz\" } } }",
manifest_url, document_url);
ASSERT_TRUE(manifest.share_target.has_value());
- EXPECT_EQ(manifest.share_target.value().url_template.spec(),
- "https://foo.com/share/a%7Btext%7D/?title={title}#{frag}");
+ EXPECT_EQ(manifest.share_target->action.spec(), "https://foo.com/share/");
+ EXPECT_TRUE(
+ base::EqualsASCII(manifest.share_target->params.text.string(), "foo"));
+ EXPECT_TRUE(
+ base::EqualsASCII(manifest.share_target->params.title.string(), "bar"));
+ EXPECT_TRUE(
+ base::EqualsASCII(manifest.share_target->params.url.string(), "baz"));
EXPECT_FALSE(manifest.IsEmpty());
EXPECT_EQ(0u, GetErrorCount());
}
- // Smoke test: Contains share_target and url_template. url_template is
- // valid template and is absolute.
+ // Smoke test: Contains share_target, action and params. action is
+ // valid and is absolute.
{
blink::Manifest manifest = ParseManifestWithURLs(
- "{ \"share_target\": { \"url_template\": \"https://foo.com/#{text}\" } "
+ "{ \"share_target\": { \"action\": \"https://foo.com/#\", \"params\": "
+ "{ \"title\": \"mytitle\" } } "
"}",
manifest_url, document_url);
ASSERT_TRUE(manifest.share_target.has_value());
- EXPECT_EQ(manifest.share_target.value().url_template.spec(),
- "https://foo.com/#{text}");
+ EXPECT_EQ(manifest.share_target.value().action.spec(), "https://foo.com/#");
+ EXPECT_TRUE(manifest.share_target->params.text.is_null());
+ EXPECT_TRUE(base::EqualsASCII(manifest.share_target->params.title.string(),
+ "mytitle"));
+ EXPECT_TRUE(manifest.share_target->params.url.is_null());
EXPECT_FALSE(manifest.IsEmpty());
EXPECT_EQ(0u, GetErrorCount());
}
diff --git a/chromium/content/renderer/media/android/stream_texture_factory.cc b/chromium/content/renderer/media/android/stream_texture_factory.cc
index 86b022e7e59..537ed58883d 100644
--- a/chromium/content/renderer/media/android/stream_texture_factory.cc
+++ b/chromium/content/renderer/media/android/stream_texture_factory.cc
@@ -9,7 +9,7 @@
#include "gpu/ipc/client/command_buffer_proxy_impl.h"
#include "gpu/ipc/client/gpu_channel_host.h"
#include "gpu/ipc/common/gpu_messages.h"
-#include "services/ui/public/cpp/gpu/context_provider_command_buffer.h"
+#include "services/ws/public/cpp/gpu/context_provider_command_buffer.h"
#include "ui/gfx/geometry/size.h"
namespace content {
@@ -80,12 +80,12 @@ void StreamTextureProxy::ForwardStreamTextureForSurfaceRequest(
// static
scoped_refptr<StreamTextureFactory> StreamTextureFactory::Create(
- scoped_refptr<ui::ContextProviderCommandBuffer> context_provider) {
+ scoped_refptr<ws::ContextProviderCommandBuffer> context_provider) {
return new StreamTextureFactory(std::move(context_provider));
}
StreamTextureFactory::StreamTextureFactory(
- scoped_refptr<ui::ContextProviderCommandBuffer> context_provider)
+ scoped_refptr<ws::ContextProviderCommandBuffer> context_provider)
: context_provider_(std::move(context_provider)),
channel_(context_provider_->GetCommandBufferProxy()->channel()) {
DCHECK(channel_);
diff --git a/chromium/content/renderer/media/android/stream_texture_factory.h b/chromium/content/renderer/media/android/stream_texture_factory.h
index 9585c03a9fd..4a4359abcec 100644
--- a/chromium/content/renderer/media/android/stream_texture_factory.h
+++ b/chromium/content/renderer/media/android/stream_texture_factory.h
@@ -26,7 +26,7 @@ class GLES2Interface;
class GpuChannelHost;
} // namespace gpu
-namespace ui {
+namespace ws {
class ContextProviderCommandBuffer;
}
@@ -90,7 +90,7 @@ class CONTENT_EXPORT StreamTextureFactory
: public base::RefCounted<StreamTextureFactory> {
public:
static scoped_refptr<StreamTextureFactory> Create(
- scoped_refptr<ui::ContextProviderCommandBuffer> context_provider);
+ scoped_refptr<ws::ContextProviderCommandBuffer> context_provider);
// Create the StreamTextureProxy object. This internally calls
// CreateSteamTexture with the recieved arguments. CreateSteamTexture
@@ -108,7 +108,7 @@ class CONTENT_EXPORT StreamTextureFactory
private:
friend class base::RefCounted<StreamTextureFactory>;
StreamTextureFactory(
- scoped_refptr<ui::ContextProviderCommandBuffer> context_provider);
+ scoped_refptr<ws::ContextProviderCommandBuffer> context_provider);
~StreamTextureFactory();
// Creates a gpu::StreamTexture and returns its id. Sets |*texture_id| to the
// client-side id of the gpu::StreamTexture. The texture is produced into
@@ -116,7 +116,7 @@ class CONTENT_EXPORT StreamTextureFactory
unsigned CreateStreamTexture(unsigned* texture_id,
gpu::Mailbox* texture_mailbox);
- scoped_refptr<ui::ContextProviderCommandBuffer> context_provider_;
+ scoped_refptr<ws::ContextProviderCommandBuffer> context_provider_;
scoped_refptr<gpu::GpuChannelHost> channel_;
DISALLOW_IMPLICIT_CONSTRUCTORS(StreamTextureFactory);
diff --git a/chromium/content/renderer/media/audio/audio_device_factory.cc b/chromium/content/renderer/media/audio/audio_device_factory.cc
index d20dbe3a5b0..8870dd31aa5 100644
--- a/chromium/content/renderer/media/audio/audio_device_factory.cc
+++ b/chromium/content/renderer/media/audio/audio_device_factory.cc
@@ -43,11 +43,10 @@ const int64_t kMaxAuthorizationTimeoutMs = 0; // No timeout.
scoped_refptr<media::AudioOutputDevice> NewOutputDevice(
int render_frame_id,
- int session_id,
- const std::string& device_id) {
+ const media::AudioSinkParameters& params) {
auto device = base::MakeRefCounted<media::AudioOutputDevice>(
AudioOutputIPCFactory::get()->CreateAudioOutputIPC(render_frame_id),
- AudioOutputIPCFactory::get()->io_task_runner(), session_id, device_id,
+ AudioOutputIPCFactory::get()->io_task_runner(), params,
// Set authorization request timeout at 80% of renderer hung timeout,
// but no more than kMaxAuthorizationTimeout.
base::TimeDelta::FromMilliseconds(
@@ -69,14 +68,14 @@ bool IsMixable(AudioDeviceFactory::SourceType source_type) {
scoped_refptr<media::SwitchableAudioRendererSink> NewMixableSink(
AudioDeviceFactory::SourceType source_type,
int render_frame_id,
- int session_id,
- const std::string& device_id) {
+ const media::AudioSinkParameters& params) {
RenderThreadImpl* render_thread = RenderThreadImpl::current();
DCHECK(render_thread) << "RenderThreadImpl is not instantiated, or "
<< "GetOutputDeviceInfo() is called on a wrong thread ";
+ DCHECK(!params.processing_id.has_value());
return scoped_refptr<media::AudioRendererMixerInput>(
render_thread->GetAudioRendererMixerManager()->CreateInput(
- render_frame_id, session_id, device_id,
+ render_frame_id, params.session_id, params.device_id,
AudioDeviceFactory::GetSourceLatencyType(source_type)));
}
@@ -103,32 +102,35 @@ media::AudioLatency::LatencyType AudioDeviceFactory::GetSourceLatencyType(
}
scoped_refptr<media::AudioRendererSink>
-AudioDeviceFactory::NewAudioRendererMixerSink(int render_frame_id,
- int session_id,
- const std::string& device_id) {
- return NewFinalAudioRendererSink(render_frame_id, session_id, device_id);
+AudioDeviceFactory::NewAudioRendererMixerSink(
+ int render_frame_id,
+ const media::AudioSinkParameters& params) {
+ return NewFinalAudioRendererSink(render_frame_id, params);
}
// static
scoped_refptr<media::AudioRendererSink>
-AudioDeviceFactory::NewAudioRendererSink(SourceType source_type,
- int render_frame_id,
- int session_id,
- const std::string& device_id) {
+AudioDeviceFactory::NewAudioRendererSink(
+ SourceType source_type,
+ int render_frame_id,
+ const media::AudioSinkParameters& params) {
if (factory_) {
scoped_refptr<media::AudioRendererSink> device =
- factory_->CreateAudioRendererSink(source_type, render_frame_id,
- session_id, device_id);
+ factory_->CreateAudioRendererSink(source_type, render_frame_id, params);
if (device)
return device;
}
+ // Perhaps streams with a processing ID just shouldn't be mixable, i.e. call
+ // NewFinalAudioRendererSink for them rather than DCHECK?
+ DCHECK(!(params.processing_id.has_value() && IsMixable(source_type)));
+
if (IsMixable(source_type))
- return NewMixableSink(source_type, render_frame_id, session_id, device_id);
+ return NewMixableSink(source_type, render_frame_id, params);
UMA_HISTOGRAM_BOOLEAN("Media.Audio.Render.SinkCache.UsedForSinkCreation",
false);
- return NewFinalAudioRendererSink(render_frame_id, session_id, device_id);
+ return NewFinalAudioRendererSink(render_frame_id, params);
}
// static
@@ -136,18 +138,17 @@ scoped_refptr<media::SwitchableAudioRendererSink>
AudioDeviceFactory::NewSwitchableAudioRendererSink(
SourceType source_type,
int render_frame_id,
- int session_id,
- const std::string& device_id) {
+ const media::AudioSinkParameters& params) {
if (factory_) {
scoped_refptr<media::SwitchableAudioRendererSink> sink =
- factory_->CreateSwitchableAudioRendererSink(
- source_type, render_frame_id, session_id, device_id);
+ factory_->CreateSwitchableAudioRendererSink(source_type,
+ render_frame_id, params);
if (sink)
return sink;
}
if (IsMixable(source_type))
- return NewMixableSink(source_type, render_frame_id, session_id, device_id);
+ return NewMixableSink(source_type, render_frame_id, params);
// AudioOutputDevice is not RestartableAudioRendererSink, so we can't return
// anything for those who wants to create an unmixable sink.
@@ -157,32 +158,31 @@ AudioDeviceFactory::NewSwitchableAudioRendererSink(
// static
scoped_refptr<media::AudioCapturerSource>
-AudioDeviceFactory::NewAudioCapturerSource(int render_frame_id,
- int session_id) {
+AudioDeviceFactory::NewAudioCapturerSource(
+ int render_frame_id,
+ const media::AudioSourceParameters& params) {
if (factory_) {
// We don't pass on |session_id|, as this branch is only used for tests.
scoped_refptr<media::AudioCapturerSource> source =
- factory_->CreateAudioCapturerSource(render_frame_id);
+ factory_->CreateAudioCapturerSource(render_frame_id, params);
if (source)
return source;
}
return base::MakeRefCounted<media::AudioInputDevice>(
- AudioInputIPCFactory::get()->CreateAudioInputIPC(render_frame_id,
- session_id),
+ AudioInputIPCFactory::get()->CreateAudioInputIPC(render_frame_id, params),
base::ThreadPriority::REALTIME_AUDIO);
}
// static
media::OutputDeviceInfo AudioDeviceFactory::GetOutputDeviceInfo(
int render_frame_id,
- int session_id,
- const std::string& device_id) {
+ const media::AudioSinkParameters& params) {
RenderThreadImpl* render_thread = RenderThreadImpl::current();
DCHECK(render_thread) << "RenderThreadImpl is not instantiated, or "
<< "GetOutputDeviceInfo() is called on a wrong thread ";
return render_thread->GetAudioRendererMixerManager()->GetOutputDeviceInfo(
- render_frame_id, session_id, device_id);
+ render_frame_id, params.session_id, params.device_id);
}
AudioDeviceFactory::AudioDeviceFactory() {
@@ -196,18 +196,17 @@ AudioDeviceFactory::~AudioDeviceFactory() {
// static
scoped_refptr<media::AudioRendererSink>
-AudioDeviceFactory::NewFinalAudioRendererSink(int render_frame_id,
- int session_id,
- const std::string& device_id) {
+AudioDeviceFactory::NewFinalAudioRendererSink(
+ int render_frame_id,
+ const media::AudioSinkParameters& params) {
if (factory_) {
scoped_refptr<media::AudioRendererSink> sink =
- factory_->CreateFinalAudioRendererSink(render_frame_id, session_id,
- device_id);
+ factory_->CreateFinalAudioRendererSink(render_frame_id, params);
if (sink)
return sink;
}
- return NewOutputDevice(render_frame_id, session_id, device_id);
+ return NewOutputDevice(render_frame_id, params);
}
} // namespace content
diff --git a/chromium/content/renderer/media/audio/audio_device_factory.h b/chromium/content/renderer/media/audio/audio_device_factory.h
index d4f3704a70e..cd3f54a4ffc 100644
--- a/chromium/content/renderer/media/audio/audio_device_factory.h
+++ b/chromium/content/renderer/media/audio/audio_device_factory.h
@@ -11,6 +11,8 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "content/common/content_export.h"
+#include "media/audio/audio_sink_parameters.h"
+#include "media/audio/audio_source_parameters.h"
#include "media/base/audio_latency.h"
#include "media/base/output_device_info.h"
@@ -18,7 +20,7 @@ namespace media {
class AudioRendererSink;
class SwitchableAudioRendererSink;
class AudioCapturerSource;
-}
+} // namespace media
namespace content {
@@ -51,16 +53,10 @@ class CONTENT_EXPORT AudioDeviceFactory {
// Creates a sink for AudioRendererMixer.
// |render_frame_id| refers to the RenderFrame containing the entity
- // producing the audio. If |session_id| is nonzero, it is used by the browser
- // to select the correct input device ID and its associated output device, if
- // it exists. If |session_id| is zero, |device_id| identify the output device
- // to use.
- // If |session_id| is zero and |device_id| is empty, the default output
- // device will be selected.
+ // producing the audio.
static scoped_refptr<media::AudioRendererSink> NewAudioRendererMixerSink(
int render_frame_id,
- int session_id,
- const std::string& device_id);
+ const media::AudioSinkParameters& params);
// Creates an AudioRendererSink bound to an AudioOutputDevice.
// Basing on |source_type| and build configuration, audio played out through
@@ -70,8 +66,7 @@ class CONTENT_EXPORT AudioDeviceFactory {
static scoped_refptr<media::AudioRendererSink> NewAudioRendererSink(
SourceType source_type,
int render_frame_id,
- int session_id,
- const std::string& device_id);
+ const media::AudioSinkParameters& params);
// Creates a SwitchableAudioRendererSink bound to an AudioOutputDevice
// Basing on |source_type| and build configuration, audio played out through
@@ -79,22 +74,20 @@ class CONTENT_EXPORT AudioDeviceFactory {
static scoped_refptr<media::SwitchableAudioRendererSink>
NewSwitchableAudioRendererSink(SourceType source_type,
int render_frame_id,
- int session_id,
- const std::string& device_id);
+ const media::AudioSinkParameters& params);
// A helper to get device info in the absence of AudioOutputDevice.
// Must be called on renderer thread only.
static media::OutputDeviceInfo GetOutputDeviceInfo(
int render_frame_id,
- int session_id,
- const std::string& device_id);
+ const media::AudioSinkParameters& params);
// Creates an AudioCapturerSource using the currently registered factory.
// |render_frame_id| refers to the RenderFrame containing the entity
// consuming the audio.
static scoped_refptr<media::AudioCapturerSource> NewAudioCapturerSource(
int render_frame_id,
- int session_id);
+ const media::AudioSourceParameters& params);
protected:
AudioDeviceFactory();
@@ -109,23 +102,22 @@ class CONTENT_EXPORT AudioDeviceFactory {
// output device.
virtual scoped_refptr<media::AudioRendererSink> CreateFinalAudioRendererSink(
int render_frame_id,
- int sesssion_id,
- const std::string& device_id) = 0;
+ const media::AudioSinkParameters& params) = 0;
virtual scoped_refptr<media::AudioRendererSink> CreateAudioRendererSink(
SourceType source_type,
int render_frame_id,
- int sesssion_id,
- const std::string& device_id) = 0;
+ const media::AudioSinkParameters& params) = 0;
virtual scoped_refptr<media::SwitchableAudioRendererSink>
- CreateSwitchableAudioRendererSink(SourceType source_type,
- int render_frame_id,
- int sesssion_id,
- const std::string& device_id) = 0;
+ CreateSwitchableAudioRendererSink(
+ SourceType source_type,
+ int render_frame_id,
+ const media::AudioSinkParameters& params) = 0;
virtual scoped_refptr<media::AudioCapturerSource> CreateAudioCapturerSource(
- int render_frame_id) = 0;
+ int render_frame_id,
+ const media::AudioSourceParameters& params) = 0;
private:
// The current globally registered factory. This is NULL when we should
@@ -134,8 +126,7 @@ class CONTENT_EXPORT AudioDeviceFactory {
static scoped_refptr<media::AudioRendererSink> NewFinalAudioRendererSink(
int render_frame_id,
- int session_id,
- const std::string& device_id);
+ const media::AudioSinkParameters& params);
DISALLOW_COPY_AND_ASSIGN(AudioDeviceFactory);
};
diff --git a/chromium/content/renderer/media/audio/audio_input_ipc_factory.cc b/chromium/content/renderer/media/audio/audio_input_ipc_factory.cc
index f301aace7c4..da267e6f44f 100644
--- a/chromium/content/renderer/media/audio/audio_input_ipc_factory.cc
+++ b/chromium/content/renderer/media/audio/audio_input_ipc_factory.cc
@@ -4,6 +4,7 @@
#include "content/renderer/media/audio/audio_input_ipc_factory.h"
+#include <string>
#include <utility>
#include "base/logging.h"
@@ -12,6 +13,7 @@
#include "content/common/media/renderer_audio_input_stream_factory.mojom.h"
#include "content/renderer/media/audio/mojo_audio_input_ipc.h"
#include "content/renderer/render_frame_impl.h"
+#include "services/audio/public/mojom/audio_processing.mojom.h"
#include "services/service_manager/public/cpp/interface_provider.h"
namespace content {
@@ -20,30 +22,39 @@ namespace {
void CreateMojoAudioInputStreamOnMainThread(
int frame_id,
- int32_t session_id,
+ const media::AudioSourceParameters& source_params,
mojom::RendererAudioInputStreamFactoryClientPtr client,
+ audio::mojom::AudioProcessorControlsRequest controls_request,
const media::AudioParameters& params,
bool automatic_gain_control,
uint32_t total_segments) {
RenderFrameImpl* frame = RenderFrameImpl::FromRoutingID(frame_id);
if (frame) {
+ audio::mojom::AudioProcessingConfigPtr processing_config;
+ if (source_params.processing) {
+ processing_config = audio::mojom::AudioProcessingConfig::New(
+ std::move(controls_request), source_params.processing->id,
+ source_params.processing->settings);
+ }
frame->GetAudioInputStreamFactory()->CreateStream(
- std::move(client), session_id, params, automatic_gain_control,
- total_segments);
+ std::move(client), source_params.session_id, params,
+ automatic_gain_control, total_segments, std::move(processing_config));
}
}
void CreateMojoAudioInputStream(
scoped_refptr<base::SequencedTaskRunner> main_task_runner,
int frame_id,
- int32_t session_id,
+ const media::AudioSourceParameters& source_params,
mojom::RendererAudioInputStreamFactoryClientPtr client,
+ audio::mojom::AudioProcessorControlsRequest controls_request,
const media::AudioParameters& params,
bool automatic_gain_control,
uint32_t total_segments) {
main_task_runner->PostTask(
FROM_HERE, base::BindOnce(&CreateMojoAudioInputStreamOnMainThread,
- frame_id, session_id, std::move(client), params,
+ frame_id, source_params, std::move(client),
+ std::move(controls_request), params,
automatic_gain_control, total_segments));
}
@@ -86,11 +97,12 @@ AudioInputIPCFactory::~AudioInputIPCFactory() {
std::unique_ptr<media::AudioInputIPC> AudioInputIPCFactory::CreateAudioInputIPC(
int frame_id,
- int session_id) const {
- DCHECK_NE(0, session_id);
+ const media::AudioSourceParameters& source_params) const {
+ DCHECK_NE(0, source_params.session_id);
return std::make_unique<MojoAudioInputIPC>(
+ source_params,
base::BindRepeating(&CreateMojoAudioInputStream, main_task_runner_,
- frame_id, session_id),
+ frame_id),
base::BindRepeating(&AssociateInputAndOutputForAec, main_task_runner_,
frame_id));
}
diff --git a/chromium/content/renderer/media/audio/audio_input_ipc_factory.h b/chromium/content/renderer/media/audio/audio_input_ipc_factory.h
index ea3956945f3..2b5c70f5605 100644
--- a/chromium/content/renderer/media/audio/audio_input_ipc_factory.h
+++ b/chromium/content/renderer/media/audio/audio_input_ipc_factory.h
@@ -10,6 +10,7 @@
#include "base/containers/flat_map.h"
#include "base/memory/ref_counted.h"
#include "content/common/content_export.h"
+#include "media/audio/audio_source_parameters.h"
namespace base {
class SequencedTaskRunner;
@@ -43,7 +44,7 @@ class CONTENT_EXPORT AudioInputIPCFactory {
// The returned object may only be used on io_task_runner().
std::unique_ptr<media::AudioInputIPC> CreateAudioInputIPC(
int frame_id,
- int session_id) const;
+ const media::AudioSourceParameters& source_params) const;
private:
const scoped_refptr<base::SequencedTaskRunner> main_task_runner_;
diff --git a/chromium/content/renderer/media/audio/audio_renderer_sink_cache_impl.cc b/chromium/content/renderer/media/audio/audio_renderer_sink_cache_impl.cc
index a28bcf9eed6..9a89887847d 100644
--- a/chromium/content/renderer/media/audio/audio_renderer_sink_cache_impl.cc
+++ b/chromium/content/renderer/media/audio/audio_renderer_sink_cache_impl.cc
@@ -25,6 +25,7 @@ namespace content {
AudioRendererSinkCacheImpl* AudioRendererSinkCacheImpl::instance_ = nullptr;
constexpr int kDeleteTimeoutMs = 5000;
+constexpr int kDefaultSessionId = 0;
class AudioRendererSinkCacheImpl::FrameObserver : public RenderFrameObserver {
public:
@@ -138,7 +139,7 @@ media::OutputDeviceInfo AudioRendererSinkCacheImpl::GetSinkInfo(
// We are provided with session id instead of device id. Session id is
// unique, so we can't find any matching sink. Creating a new one.
scoped_refptr<media::AudioRendererSink> sink =
- create_sink_cb_.Run(source_render_frame_id, session_id, device_id);
+ create_sink_cb_.Run(source_render_frame_id, {session_id, device_id});
CacheOrStopUnusedSink(source_render_frame_id,
sink->GetOutputDeviceInfo().device_id(), sink);
@@ -169,7 +170,8 @@ media::OutputDeviceInfo AudioRendererSinkCacheImpl::GetSinkInfo(
// No matching sink found, create a new one.
scoped_refptr<media::AudioRendererSink> sink = create_sink_cb_.Run(
- source_render_frame_id, 0 /* session_id */, device_id);
+ source_render_frame_id,
+ media::AudioSinkParameters(kDefaultSessionId, device_id));
CacheOrStopUnusedSink(source_render_frame_id, device_id, sink);
@@ -208,10 +210,12 @@ scoped_refptr<media::AudioRendererSink> AudioRendererSinkCacheImpl::GetSink(
}
// No unused sink is found, create one, mark it used, cache it and return.
- CacheEntry cache_entry = {source_render_frame_id, device_id,
- create_sink_cb_.Run(source_render_frame_id,
- 0 /* session_id */, device_id),
- true /* used */};
+ CacheEntry cache_entry = {
+ source_render_frame_id, device_id,
+ create_sink_cb_.Run(
+ source_render_frame_id,
+ media::AudioSinkParameters(kDefaultSessionId, device_id)),
+ true /* used */};
if (SinkIsHealthy(cache_entry.sink.get())) {
TRACE_EVENT_INSTANT0(
diff --git a/chromium/content/renderer/media/audio/audio_renderer_sink_cache_impl.h b/chromium/content/renderer/media/audio/audio_renderer_sink_cache_impl.h
index 0b6e872f4b9..21e92df1127 100644
--- a/chromium/content/renderer/media/audio/audio_renderer_sink_cache_impl.h
+++ b/chromium/content/renderer/media/audio/audio_renderer_sink_cache_impl.h
@@ -16,6 +16,7 @@
#include "base/synchronization/lock.h"
#include "base/time/time.h"
#include "content/common/content_export.h"
+#include "media/audio/audio_sink_parameters.h"
namespace content {
@@ -29,8 +30,7 @@ class CONTENT_EXPORT AudioRendererSinkCacheImpl
using CreateSinkCallback =
base::RepeatingCallback<scoped_refptr<media::AudioRendererSink>(
int render_frame_id,
- int session_id,
- const std::string& device_id)>;
+ const media::AudioSinkParameters& params)>;
AudioRendererSinkCacheImpl(
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
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 3c3172e277d..a08ba6a9719 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
@@ -55,10 +55,9 @@ class AudioRendererSinkCacheTest : public testing::Test {
scoped_refptr<media::AudioRendererSink> CreateSink(
int render_frame_id,
- int session_id,
- const std::string& device_id) {
+ const media::AudioSinkParameters& params) {
return new testing::NiceMock<media::MockAudioRendererSink>(
- device_id, (device_id == kUnhealthyDeviceId)
+ params.device_id, (params.device_id == kUnhealthyDeviceId)
? media::OUTPUT_DEVICE_STATUS_ERROR_INTERNAL
: media::OUTPUT_DEVICE_STATUS_OK);
}
@@ -250,10 +249,10 @@ TEST_F(AudioRendererSinkCacheTest, UnhealthySinkIsStopped) {
task_env_.GetMainThreadTaskRunner(),
base::BindRepeating(
[](scoped_refptr<media::AudioRendererSink> sink, int render_frame_id,
- int session_id, const std::string& device_id) {
+ const media::AudioSinkParameters& params) {
EXPECT_EQ(kRenderFrameId, render_frame_id);
- EXPECT_EQ(0, session_id);
- EXPECT_EQ(kUnhealthyDeviceId, device_id);
+ EXPECT_EQ(0, params.session_id);
+ EXPECT_EQ(kUnhealthyDeviceId, params.device_id);
return sink;
},
sink),
@@ -276,10 +275,10 @@ TEST_F(AudioRendererSinkCacheTest, UnhealthySinkUsingSessionIdIsStopped) {
task_env_.GetMainThreadTaskRunner(),
base::BindRepeating(
[](scoped_refptr<media::AudioRendererSink> sink, int render_frame_id,
- int session_id, const std::string& device_id) {
+ const media::AudioSinkParameters& params) {
EXPECT_EQ(kRenderFrameId, render_frame_id);
- EXPECT_EQ(kNonZeroSessionId, session_id);
- EXPECT_TRUE(device_id.empty());
+ EXPECT_EQ(kNonZeroSessionId, params.session_id);
+ EXPECT_TRUE(params.device_id.empty());
return sink;
},
sink),
diff --git a/chromium/content/renderer/media/audio/mock_audio_device_factory.cc b/chromium/content/renderer/media/audio/mock_audio_device_factory.cc
index 69c1589a53b..2a8930f9b54 100644
--- a/chromium/content/renderer/media/audio/mock_audio_device_factory.cc
+++ b/chromium/content/renderer/media/audio/mock_audio_device_factory.cc
@@ -22,7 +22,9 @@ MockAudioDeviceFactory::MockAudioDeviceFactory()
MockAudioDeviceFactory::~MockAudioDeviceFactory() {}
scoped_refptr<media::AudioCapturerSource>
-MockAudioDeviceFactory::CreateAudioCapturerSource(int render_frame_id) {
+MockAudioDeviceFactory::CreateAudioCapturerSource(
+ int render_frame_id,
+ const media::AudioSourceParameters& params) {
CHECK(!did_create_once_);
did_create_once_ = true;
return scoped_refptr<media::AudioCapturerSource>(mock_capturer_source_);
diff --git a/chromium/content/renderer/media/audio/mock_audio_device_factory.h b/chromium/content/renderer/media/audio/mock_audio_device_factory.h
index 0958cc23b47..2582de5fcaa 100644
--- a/chromium/content/renderer/media/audio/mock_audio_device_factory.h
+++ b/chromium/content/renderer/media/audio/mock_audio_device_factory.h
@@ -46,28 +46,26 @@ class MockAudioDeviceFactory : public AudioDeviceFactory {
// These methods are just mocked because tests currently don't need them to be
// implemented.
- MOCK_METHOD3(
- CreateFinalAudioRendererSink,
- scoped_refptr<media::AudioRendererSink>(int render_frame_id,
- int sesssion_id,
- const std::string& device_id));
- MOCK_METHOD4(
- CreateAudioRendererSink,
- scoped_refptr<media::AudioRendererSink>(SourceType source_type,
- int render_frame_id,
- int sesssion_id,
- const std::string& device_id));
- MOCK_METHOD4(CreateSwitchableAudioRendererSink,
+ MOCK_METHOD2(CreateFinalAudioRendererSink,
+ scoped_refptr<media::AudioRendererSink>(
+ int render_frame_id,
+ const media::AudioSinkParameters& params));
+ MOCK_METHOD3(CreateAudioRendererSink,
+ scoped_refptr<media::AudioRendererSink>(
+ SourceType source_type,
+ int render_frame_id,
+ const media::AudioSinkParameters& params));
+ MOCK_METHOD3(CreateSwitchableAudioRendererSink,
scoped_refptr<media::SwitchableAudioRendererSink>(
SourceType source_type,
int render_frame_id,
- int sesssion_id,
- const std::string& device_id));
+ const media::AudioSinkParameters& params));
// Returns mock_capturer_source_ once. If called a second time, the process
// will crash.
scoped_refptr<media::AudioCapturerSource> CreateAudioCapturerSource(
- int render_frame_id) override;
+ int render_frame_id,
+ const media::AudioSourceParameters& params) override;
private:
scoped_refptr<MockCapturerSource> mock_capturer_source_;
diff --git a/chromium/content/renderer/media/audio/mojo_audio_input_ipc.cc b/chromium/content/renderer/media/audio/mojo_audio_input_ipc.cc
index 490b3cd0a6b..43d2cb84858 100644
--- a/chromium/content/renderer/media/audio/mojo_audio_input_ipc.cc
+++ b/chromium/content/renderer/media/audio/mojo_audio_input_ipc.cc
@@ -13,9 +13,12 @@
namespace content {
-MojoAudioInputIPC::MojoAudioInputIPC(StreamCreatorCB stream_creator,
- StreamAssociatorCB stream_associator)
- : stream_creator_(std::move(stream_creator)),
+MojoAudioInputIPC::MojoAudioInputIPC(
+ const media::AudioSourceParameters& source_params,
+ StreamCreatorCB stream_creator,
+ StreamAssociatorCB stream_associator)
+ : source_params_(source_params),
+ stream_creator_(std::move(stream_creator)),
stream_associator_(std::move(stream_associator)),
stream_client_binding_(this),
factory_client_binding_(this),
@@ -43,8 +46,12 @@ void MojoAudioInputIPC::CreateStream(media::AudioInputIPCDelegate* delegate,
&media::AudioInputIPCDelegate::OnError, base::Unretained(delegate_)));
stream_creation_start_time_ = base::TimeTicks::Now();
- stream_creator_.Run(std::move(client), params, automatic_gain_control,
- total_segments);
+ audio::mojom::AudioProcessorControlsRequest controls_request;
+ if (source_params_.processing.has_value())
+ controls_request = mojo::MakeRequest(&processor_controls_);
+ stream_creator_.Run(source_params_, std::move(client),
+ std::move(controls_request), params,
+ automatic_gain_control, total_segments);
}
void MojoAudioInputIPC::RecordStream() {
@@ -68,6 +75,10 @@ void MojoAudioInputIPC::SetOutputDeviceForAec(
stream_associator_.Run(*stream_id_, output_device_id);
}
+media::AudioProcessorControls* MojoAudioInputIPC::GetProcessorControls() {
+ return processor_controls_ ? this : nullptr;
+}
+
void MojoAudioInputIPC::CloseStream() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
delegate_ = nullptr;
@@ -76,6 +87,25 @@ void MojoAudioInputIPC::CloseStream() {
if (stream_client_binding_.is_bound())
stream_client_binding_.Unbind();
stream_.reset();
+ processor_controls_.reset();
+}
+
+void MojoAudioInputIPC::GetStats(GetStatsCB callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (processor_controls_)
+ processor_controls_->GetStats(std::move(callback));
+}
+
+void MojoAudioInputIPC::StartEchoCancellationDump(base::File file) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (processor_controls_)
+ processor_controls_->StartEchoCancellationDump(std::move(file));
+}
+
+void MojoAudioInputIPC::StopEchoCancellationDump() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (processor_controls_)
+ processor_controls_->StopEchoCancellationDump();
}
void MojoAudioInputIPC::StreamCreated(
diff --git a/chromium/content/renderer/media/audio/mojo_audio_input_ipc.h b/chromium/content/renderer/media/audio/mojo_audio_input_ipc.h
index b47c1d0fcea..03cac6d4e70 100644
--- a/chromium/content/renderer/media/audio/mojo_audio_input_ipc.h
+++ b/chromium/content/renderer/media/audio/mojo_audio_input_ipc.h
@@ -15,7 +15,9 @@
#include "content/common/content_export.h"
#include "content/common/media/renderer_audio_input_stream_factory.mojom.h"
#include "media/audio/audio_input_ipc.h"
+#include "media/audio/audio_source_parameters.h"
#include "media/mojo/interfaces/audio_input_stream.mojom.h"
+#include "media/webrtc/audio_processor_controls.h"
#include "mojo/public/cpp/bindings/binding.h"
namespace content {
@@ -25,6 +27,7 @@ namespace content {
// thread.
class CONTENT_EXPORT MojoAudioInputIPC
: public media::AudioInputIPC,
+ public media::AudioProcessorControls,
public mojom::RendererAudioInputStreamFactoryClient,
public media::mojom::AudioInputStreamClient {
public:
@@ -32,7 +35,9 @@ class CONTENT_EXPORT MojoAudioInputIPC
// It is expected that after calling, either client->StreamCreated() is
// called or |client| is destructed.
using StreamCreatorCB = base::RepeatingCallback<void(
+ const media::AudioSourceParameters& source_params,
mojom::RendererAudioInputStreamFactoryClientPtr client,
+ audio::mojom::AudioProcessorControlsRequest controls_request,
const media::AudioParameters& params,
bool automatic_gain_control,
uint32_t total_segments)>;
@@ -41,8 +46,9 @@ class CONTENT_EXPORT MojoAudioInputIPC
base::RepeatingCallback<void(const base::UnguessableToken& stream_id,
const std::string& output_device_id)>;
- explicit MojoAudioInputIPC(StreamCreatorCB stream_creator,
- StreamAssociatorCB stream_associator);
+ MojoAudioInputIPC(const media::AudioSourceParameters& source_params,
+ StreamCreatorCB stream_creator,
+ StreamAssociatorCB stream_associator);
~MojoAudioInputIPC() override;
// AudioInputIPC implementation
@@ -50,11 +56,18 @@ class CONTENT_EXPORT MojoAudioInputIPC
const media::AudioParameters& params,
bool automatic_gain_control,
uint32_t total_segments) override;
+
void RecordStream() override;
void SetVolume(double volume) override;
void SetOutputDeviceForAec(const std::string& output_device_id) override;
+ AudioProcessorControls* GetProcessorControls() override;
void CloseStream() override;
+ // AudioProcessorControls implementation
+ void GetStats(GetStatsCB callback) override;
+ void StartEchoCancellationDump(base::File file) override;
+ void StopEchoCancellationDump() override;
+
private:
void StreamCreated(
media::mojom::AudioInputStreamPtr stream,
@@ -65,12 +78,15 @@ class CONTENT_EXPORT MojoAudioInputIPC
void OnError() override;
void OnMutedStateChanged(bool is_muted) override;
+ SEQUENCE_CHECKER(sequence_checker_);
+
+ const media::AudioSourceParameters source_params_;
+
StreamCreatorCB stream_creator_;
StreamAssociatorCB stream_associator_;
- SEQUENCE_CHECKER(sequence_checker_);
-
media::mojom::AudioInputStreamPtr stream_;
+ audio::mojom::AudioProcessorControlsPtr processor_controls_;
// Initialized on StreamCreated.
base::Optional<base::UnguessableToken> stream_id_;
mojo::Binding<AudioInputStreamClient> stream_client_binding_;
diff --git a/chromium/content/renderer/media/audio/mojo_audio_input_ipc_unittest.cc b/chromium/content/renderer/media/audio/mojo_audio_input_ipc_unittest.cc
index f9f33fe2e11..a45f6367412 100644
--- a/chromium/content/renderer/media/audio/mojo_audio_input_ipc_unittest.cc
+++ b/chromium/content/renderer/media/audio/mojo_audio_input_ipc_unittest.cc
@@ -41,6 +41,10 @@ media::AudioParameters Params() {
return media::AudioParameters::UnavailableDeviceParams();
}
+media::AudioSourceParameters SourceParams() {
+ return media::AudioSourceParameters(1234);
+}
+
class MockStream : public media::mojom::AudioInputStream {
public:
MOCK_METHOD0(Record, void());
@@ -71,12 +75,15 @@ class FakeStreamCreator {
bool initially_muted)
: stream_(stream), binding_(stream_), initially_muted_(initially_muted) {}
- void Create(mojom::RendererAudioInputStreamFactoryClientPtr factory_client,
+ void Create(const media::AudioSourceParameters& source_params,
+ mojom::RendererAudioInputStreamFactoryClientPtr factory_client,
+ audio::mojom::AudioProcessorControlsRequest controls_request,
const media::AudioParameters& params,
bool automatic_gain_control,
uint32_t total_segments) {
EXPECT_FALSE(binding_.is_bound());
EXPECT_NE(stream_, nullptr);
+ EXPECT_EQ(source_params.session_id, SourceParams().session_id);
std::swap(factory_client_, factory_client);
media::mojom::AudioInputStreamPtr stream_ptr;
binding_.Bind(mojo::MakeRequest(&stream_ptr));
@@ -132,7 +139,8 @@ TEST(MojoAudioInputIPC, OnStreamCreated_Propagates) {
const std::unique_ptr<media::AudioInputIPC> ipc =
std::make_unique<MojoAudioInputIPC>(
- creator.GetCallback(), base::BindRepeating(&AssociateOutputForAec));
+ SourceParams(), creator.GetCallback(),
+ base::BindRepeating(&AssociateOutputForAec));
EXPECT_CALL(delegate, GotOnStreamCreated(false));
@@ -149,8 +157,11 @@ TEST(MojoAudioInputIPC, FactoryDisconnected_SendsError) {
const std::unique_ptr<media::AudioInputIPC> ipc =
std::make_unique<MojoAudioInputIPC>(
+ SourceParams(),
base::BindRepeating(
- [](mojom::RendererAudioInputStreamFactoryClientPtr factory_client,
+ [](const media::AudioSourceParameters&,
+ mojom::RendererAudioInputStreamFactoryClientPtr factory_client,
+ audio::mojom::AudioProcessorControlsRequest controls_request,
const media::AudioParameters& params,
bool automatic_gain_control, uint32_t total_segments) {}),
base::BindRepeating(&AssociateOutputForAec));
@@ -172,7 +183,8 @@ TEST(MojoAudioInputIPC, OnStreamCreated_PropagatesInitiallyMuted) {
const std::unique_ptr<media::AudioInputIPC> ipc =
std::make_unique<MojoAudioInputIPC>(
- creator.GetCallback(), base::BindRepeating(&AssociateOutputForAec));
+ SourceParams(), creator.GetCallback(),
+ base::BindRepeating(&AssociateOutputForAec));
EXPECT_CALL(delegate, GotOnStreamCreated(true));
@@ -191,7 +203,8 @@ TEST(MojoAudioInputIPC, IsReusable) {
const std::unique_ptr<media::AudioInputIPC> ipc =
std::make_unique<MojoAudioInputIPC>(
- creator.GetCallback(), base::BindRepeating(&AssociateOutputForAec));
+ SourceParams(), creator.GetCallback(),
+ base::BindRepeating(&AssociateOutputForAec));
for (int i = 0; i < 5; ++i) {
creator.Rearm();
@@ -215,7 +228,8 @@ TEST(MojoAudioInputIPC, IsReusableAfterError) {
const std::unique_ptr<media::AudioInputIPC> ipc =
std::make_unique<MojoAudioInputIPC>(
- creator.GetCallback(), base::BindRepeating(&AssociateOutputForAec));
+ SourceParams(), creator.GetCallback(),
+ base::BindRepeating(&AssociateOutputForAec));
for (int i = 0; i < 5; ++i) {
creator.Rearm();
@@ -244,7 +258,8 @@ TEST(MojoAudioInputIPC, Record_Records) {
const std::unique_ptr<media::AudioInputIPC> ipc =
std::make_unique<MojoAudioInputIPC>(
- creator.GetCallback(), base::BindRepeating(&AssociateOutputForAec));
+ SourceParams(), creator.GetCallback(),
+ base::BindRepeating(&AssociateOutputForAec));
EXPECT_CALL(delegate, GotOnStreamCreated(_));
EXPECT_CALL(stream, Record());
@@ -266,7 +281,8 @@ TEST(MojoAudioInputIPC, SetVolume_SetsVolume) {
const std::unique_ptr<media::AudioInputIPC> ipc =
std::make_unique<MojoAudioInputIPC>(
- creator.GetCallback(), base::BindRepeating(&AssociateOutputForAec));
+ SourceParams(), creator.GetCallback(),
+ base::BindRepeating(&AssociateOutputForAec));
EXPECT_CALL(delegate, GotOnStreamCreated(_));
EXPECT_CALL(stream, SetVolume(kNewVolume));
@@ -288,7 +304,8 @@ TEST(MojoAudioInputIPC, SetOutputDeviceForAec_AssociatesInputAndOutputForAec) {
const std::unique_ptr<media::AudioInputIPC> ipc =
std::make_unique<MojoAudioInputIPC>(
- creator.GetCallback(), base::BindRepeating(&AssociateOutputForAec));
+ SourceParams(), creator.GetCallback(),
+ base::BindRepeating(&AssociateOutputForAec));
EXPECT_CALL(delegate, GotOnStreamCreated(_));
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 1782dd20420..1aa79bbe2b6 100644
--- a/chromium/content/renderer/media/audio/mojo_audio_output_ipc.cc
+++ b/chromium/content/renderer/media/audio/mojo_audio_output_ipc.cc
@@ -61,8 +61,10 @@ void MojoAudioOutputIPC::RequestDeviceAuthorization(
media::AudioParameters::UnavailableDeviceParams(), std::string()));
}
-void MojoAudioOutputIPC::CreateStream(media::AudioOutputIPCDelegate* delegate,
- const media::AudioParameters& params) {
+void MojoAudioOutputIPC::CreateStream(
+ media::AudioOutputIPCDelegate* delegate,
+ const media::AudioParameters& params,
+ const base::Optional<base::UnguessableToken>& processing_id) {
DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
DCHECK(delegate);
DCHECK(!StreamCreationRequested());
@@ -87,7 +89,7 @@ void MojoAudioOutputIPC::CreateStream(media::AudioOutputIPCDelegate* delegate,
binding_.set_connection_error_with_reason_handler(
base::BindOnce(&MojoAudioOutputIPC::ProviderClientBindingDisconnected,
base::Unretained(this)));
- stream_provider_->Acquire(params, std::move(client_ptr));
+ stream_provider_->Acquire(params, std::move(client_ptr), processing_id);
}
void MojoAudioOutputIPC::PlayStream() {
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 00084e5928e..3770e2aeb5e 100644
--- a/chromium/content/renderer/media/audio/mojo_audio_output_ipc.h
+++ b/chromium/content/renderer/media/audio/mojo_audio_output_ipc.h
@@ -43,8 +43,10 @@ class CONTENT_EXPORT MojoAudioOutputIPC
void RequestDeviceAuthorization(media::AudioOutputIPCDelegate* delegate,
int session_id,
const std::string& device_id) override;
- void CreateStream(media::AudioOutputIPCDelegate* delegate,
- const media::AudioParameters& params) override;
+ void CreateStream(
+ media::AudioOutputIPCDelegate* delegate,
+ const media::AudioParameters& params,
+ const base::Optional<base::UnguessableToken>& processing_id) override;
void PlayStream() override;
void PauseStream() override;
void CloseStream() 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 100687c928c..1f8f1e3dac6 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
@@ -57,9 +57,10 @@ class TestStreamProvider : public media::mojom::AudioOutputStreamProvider {
EXPECT_TRUE(binding_);
}
- void Acquire(const media::AudioParameters& params,
- media::mojom::AudioOutputStreamProviderClientPtr provider_client)
- override {
+ void Acquire(
+ const media::AudioParameters& params,
+ media::mojom::AudioOutputStreamProviderClientPtr provider_client,
+ const base::Optional<base::UnguessableToken>& processing_id) override {
EXPECT_EQ(binding_, base::nullopt);
EXPECT_NE(stream_, nullptr);
std::swap(provider_client, provider_client_);
@@ -228,7 +229,7 @@ TEST(MojoAudioOutputIPC,
NullAccessor(),
blink::scheduler::GetSingleThreadTaskRunnerForTesting());
- ipc->CreateStream(&delegate, Params());
+ ipc->CreateStream(&delegate, Params(), base::nullopt);
// No call to OnDeviceAuthorized since authotization wasn't explicitly
// requested.
@@ -273,7 +274,7 @@ TEST(MojoAudioOutputIPC, OnDeviceCreated_Propagates) {
kSessionId, kDeviceId, std::make_unique<TestStreamProvider>(&stream));
ipc->RequestDeviceAuthorization(&delegate, kSessionId, kDeviceId);
- ipc->CreateStream(&delegate, Params());
+ ipc->CreateStream(&delegate, Params(), base::nullopt);
EXPECT_CALL(delegate, OnDeviceAuthorized(
media::OutputDeviceStatus::OUTPUT_DEVICE_STATUS_OK,
@@ -304,7 +305,7 @@ TEST(MojoAudioOutputIPC,
0, std::string(media::AudioDeviceDescription::kDefaultDeviceId),
std::make_unique<TestStreamProvider>(&stream));
- ipc->CreateStream(&delegate, Params());
+ ipc->CreateStream(&delegate, Params(), base::nullopt);
EXPECT_CALL(delegate, GotOnStreamCreated());
base::RunLoop().RunUntilIdle();
@@ -329,7 +330,7 @@ TEST(MojoAudioOutputIPC, IsReusable) {
kSessionId, kDeviceId, std::make_unique<TestStreamProvider>(&stream));
ipc->RequestDeviceAuthorization(&delegate, kSessionId, kDeviceId);
- ipc->CreateStream(&delegate, Params());
+ ipc->CreateStream(&delegate, Params(), base::nullopt);
EXPECT_CALL(
delegate,
@@ -377,7 +378,7 @@ TEST(MojoAudioOutputIPC, IsReusableAfterError) {
kSessionId, kDeviceId, std::make_unique<TestStreamProvider>(&stream));
ipc->RequestDeviceAuthorization(&delegate, kSessionId, kDeviceId);
- ipc->CreateStream(&delegate, Params());
+ ipc->CreateStream(&delegate, Params(), base::nullopt);
EXPECT_CALL(
delegate,
@@ -519,7 +520,7 @@ TEST(MojoAudioOutputIPC, CreateNoClose_DCHECKs) {
stream_factory.GetAccessor(),
blink::scheduler::GetSingleThreadTaskRunnerForTesting());
- ipc->CreateStream(&delegate, Params());
+ ipc->CreateStream(&delegate, Params(), base::nullopt);
EXPECT_DCHECK_DEATH(ipc.reset());
ipc->CloseStream();
ipc.reset();
@@ -546,7 +547,7 @@ TEST(MojoAudioOutputIPC, Play_Plays) {
kSessionId, kDeviceId, std::make_unique<TestStreamProvider>(&stream));
ipc->RequestDeviceAuthorization(&delegate, kSessionId, kDeviceId);
- ipc->CreateStream(&delegate, Params());
+ ipc->CreateStream(&delegate, Params(), base::nullopt);
base::RunLoop().RunUntilIdle();
ipc->PlayStream();
base::RunLoop().RunUntilIdle();
@@ -574,7 +575,7 @@ TEST(MojoAudioOutputIPC, Pause_Pauses) {
kSessionId, kDeviceId, std::make_unique<TestStreamProvider>(&stream));
ipc->RequestDeviceAuthorization(&delegate, kSessionId, kDeviceId);
- ipc->CreateStream(&delegate, Params());
+ ipc->CreateStream(&delegate, Params(), base::nullopt);
base::RunLoop().RunUntilIdle();
ipc->PauseStream();
base::RunLoop().RunUntilIdle();
@@ -602,7 +603,7 @@ TEST(MojoAudioOutputIPC, SetVolume_SetsVolume) {
kSessionId, kDeviceId, std::make_unique<TestStreamProvider>(&stream));
ipc->RequestDeviceAuthorization(&delegate, kSessionId, kDeviceId);
- ipc->CreateStream(&delegate, Params());
+ ipc->CreateStream(&delegate, Params(), base::nullopt);
base::RunLoop().RunUntilIdle();
ipc->SetVolume(kNewVolume);
base::RunLoop().RunUntilIdle();
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 6022a765b1b..902db29ef01 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
@@ -17,6 +17,7 @@
#include "content/public/common/content_features.h"
#include "content/public/common/service_names.mojom.h"
#include "content/renderer/render_thread_impl.h"
+#include "gpu/command_buffer/client/context_support.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
#include "gpu/command_buffer/common/gpu_memory_buffer_support.h"
@@ -29,7 +30,8 @@
#include "media/video/video_decode_accelerator.h"
#include "media/video/video_encode_accelerator.h"
#include "services/service_manager/public/cpp/connector.h"
-#include "services/ui/public/cpp/gpu/context_provider_command_buffer.h"
+#include "services/ws/public/cpp/gpu/context_provider_command_buffer.h"
+#include "third_party/skia/include/core/SkPostConfig.h"
namespace content {
@@ -55,7 +57,7 @@ GpuVideoAcceleratorFactoriesImpl::Create(
scoped_refptr<gpu::GpuChannelHost> gpu_channel_host,
const scoped_refptr<base::SingleThreadTaskRunner>& main_thread_task_runner,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
- const scoped_refptr<ui::ContextProviderCommandBuffer>& context_provider,
+ const scoped_refptr<ws::ContextProviderCommandBuffer>& context_provider,
bool enable_video_gpu_memory_buffers,
bool enable_media_stream_gpu_memory_buffers,
bool enable_video_accelerator,
@@ -73,7 +75,7 @@ GpuVideoAcceleratorFactoriesImpl::GpuVideoAcceleratorFactoriesImpl(
scoped_refptr<gpu::GpuChannelHost> gpu_channel_host,
const scoped_refptr<base::SingleThreadTaskRunner>& main_thread_task_runner,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
- const scoped_refptr<ui::ContextProviderCommandBuffer>& context_provider,
+ const scoped_refptr<ws::ContextProviderCommandBuffer>& context_provider,
bool enable_video_gpu_memory_buffers,
bool enable_media_stream_gpu_memory_buffers,
bool enable_video_accelerator,
@@ -109,10 +111,8 @@ GpuVideoAcceleratorFactoriesImpl::~GpuVideoAcceleratorFactoriesImpl() {}
void GpuVideoAcceleratorFactoriesImpl::BindContextToTaskRunner() {
DCHECK(task_runner_->BelongsToCurrentThread());
DCHECK(context_provider_);
- if (context_provider_->BindToCurrentThread() !=
- gpu::ContextResult::kSuccess) {
+ if (context_provider_->BindToCurrentThread() != gpu::ContextResult::kSuccess)
SetContextProviderLost();
- }
}
bool GpuVideoAcceleratorFactoriesImpl::CheckContextLost() {
@@ -266,6 +266,17 @@ void GpuVideoAcceleratorFactoriesImpl::WaitSyncToken(
gles2->ShallowFlushCHROMIUM();
}
+void GpuVideoAcceleratorFactoriesImpl::SignalSyncToken(
+ const gpu::SyncToken& sync_token,
+ base::OnceClosure callback) {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ if (CheckContextLost())
+ return;
+
+ context_provider_->ContextSupport()->SignalSyncToken(sync_token,
+ std::move(callback));
+}
+
void GpuVideoAcceleratorFactoriesImpl::ShallowFlushCHROMIUM() {
DCHECK(task_runner_->BelongsToCurrentThread());
if (CheckContextLost())
@@ -297,11 +308,23 @@ unsigned GpuVideoAcceleratorFactoriesImpl::ImageTextureTarget(
}
media::GpuVideoAcceleratorFactories::OutputFormat
-GpuVideoAcceleratorFactoriesImpl::VideoFrameOutputFormat(size_t bit_depth) {
+GpuVideoAcceleratorFactoriesImpl::VideoFrameOutputFormat(
+ media::VideoPixelFormat pixel_format) {
DCHECK(task_runner_->BelongsToCurrentThread());
if (CheckContextLost())
return media::GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED;
+#if defined(OS_CHROMEOS) && defined(USE_OZONE)
+ // TODO(sugoi): This configuration is currently used only for testing ChromeOS
+ // on Linux and doesn't support hardware acceleration. OSMesa did not support
+ // any hardware acceleration here, so this was never an issue, but SwiftShader
+ // revealed this issue. See https://crbug.com/859946
+ if (gpu_channel_host_->gpu_info().gl_renderer.find("SwiftShader") !=
+ std::string::npos) {
+ return media::GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED;
+ }
+#endif
auto capabilities = context_provider_->ContextCapabilities();
+ const size_t bit_depth = media::BitDepth(pixel_format);
if (bit_depth > 8) {
// If high bit depth rendering is enabled, bail here, otherwise try and use
// XR30 storage, and if not and we support RG textures, use those, albeit at
@@ -326,6 +349,15 @@ GpuVideoAcceleratorFactoriesImpl::VideoFrameOutputFormat(size_t bit_depth) {
return media::GpuVideoAcceleratorFactories::OutputFormat::I420;
return media::GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED;
}
+
+ if (pixel_format == media::PIXEL_FORMAT_I420A) {
+#if SK_PMCOLOR_BYTE_ORDER(B, G, R, A)
+ return media::GpuVideoAcceleratorFactories::OutputFormat::BGRA;
+#elif SK_PMCOLOR_BYTE_ORDER(R, G, B, A)
+ return media::GpuVideoAcceleratorFactories::OutputFormat::RGBA;
+#endif
+ }
+
if (capabilities.image_ycbcr_420v &&
!capabilities.image_ycbcr_420v_disabled_for_video_frames) {
return media::GpuVideoAcceleratorFactories::OutputFormat::NV12_SINGLE_GMB;
@@ -368,7 +400,7 @@ GpuVideoAcceleratorFactoriesImpl::GetVideoEncodeAcceleratorSupportedProfiles() {
.video_encode_accelerator_supported_profiles);
}
-scoped_refptr<ui::ContextProviderCommandBuffer>
+scoped_refptr<ws::ContextProviderCommandBuffer>
GpuVideoAcceleratorFactoriesImpl::GetMediaContextProvider() {
return CheckContextLost() ? nullptr : context_provider_;
}
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 2085f328f91..19894023019 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
@@ -54,7 +54,7 @@ class CONTENT_EXPORT GpuVideoAcceleratorFactoriesImpl
const scoped_refptr<base::SingleThreadTaskRunner>&
main_thread_task_runner,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
- const scoped_refptr<ui::ContextProviderCommandBuffer>& context_provider,
+ const scoped_refptr<ws::ContextProviderCommandBuffer>& context_provider,
bool enable_video_gpu_memory_buffers,
bool enable_media_stream_gpu_memory_buffers,
bool enable_video_accelerator,
@@ -78,6 +78,8 @@ class CONTENT_EXPORT GpuVideoAcceleratorFactoriesImpl
void DeleteTexture(uint32_t texture_id) override;
gpu::SyncToken CreateSyncToken() override;
void WaitSyncToken(const gpu::SyncToken& sync_token) override;
+ void SignalSyncToken(const gpu::SyncToken& sync_token,
+ base::OnceClosure callback) override;
void ShallowFlushCHROMIUM() override;
std::unique_ptr<gfx::GpuMemoryBuffer> CreateGpuMemoryBuffer(
@@ -88,7 +90,8 @@ class CONTENT_EXPORT GpuVideoAcceleratorFactoriesImpl
bool ShouldUseGpuMemoryBuffersForVideoFrames(
bool for_media_stream) const override;
unsigned ImageTextureTarget(gfx::BufferFormat format) override;
- OutputFormat VideoFrameOutputFormat(size_t bit_depth) override;
+ OutputFormat VideoFrameOutputFormat(
+ media::VideoPixelFormat pixel_format) override;
// Called on the media thread. Returns the GLES2Interface unless the
// ContextProvider has been lost, in which case it returns null.
@@ -111,7 +114,7 @@ class CONTENT_EXPORT GpuVideoAcceleratorFactoriesImpl
std::vector<media::VideoEncodeAccelerator::SupportedProfile>
GetVideoEncodeAcceleratorSupportedProfiles() override;
- scoped_refptr<ui::ContextProviderCommandBuffer> GetMediaContextProvider()
+ scoped_refptr<ws::ContextProviderCommandBuffer> GetMediaContextProvider()
override;
void SetRenderingColorSpace(const gfx::ColorSpace& color_space) override;
@@ -129,7 +132,7 @@ class CONTENT_EXPORT GpuVideoAcceleratorFactoriesImpl
const scoped_refptr<base::SingleThreadTaskRunner>&
main_thread_task_runner,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
- const scoped_refptr<ui::ContextProviderCommandBuffer>& context_provider,
+ const scoped_refptr<ws::ContextProviderCommandBuffer>& context_provider,
bool enable_gpu_memory_buffer_video_frames_for_video,
bool enable_gpu_memory_buffer_video_frames_for_media_stream,
bool enable_video_accelerator,
@@ -148,7 +151,7 @@ class CONTENT_EXPORT GpuVideoAcceleratorFactoriesImpl
// Shared pointer to a shared context provider. It is initially set on main
// thread, but all subsequent access and destruction should happen only on the
// media thread.
- scoped_refptr<ui::ContextProviderCommandBuffer> context_provider_;
+ scoped_refptr<ws::ContextProviderCommandBuffer> context_provider_;
// Signals if |context_provider_| is alive on the media thread. For use on the
// main thread.
bool context_provider_lost_ = false;
diff --git a/chromium/content/renderer/media/media_factory.cc b/chromium/content/renderer/media/media_factory.cc
index fe25c6b87ab..97aacde6a45 100644
--- a/chromium/content/renderer/media/media_factory.cc
+++ b/chromium/content/renderer/media/media_factory.cc
@@ -24,6 +24,7 @@
#include "content/renderer/render_frame_impl.h"
#include "content/renderer/render_thread_impl.h"
#include "content/renderer/render_view_impl.h"
+#include "media/base/bind_to_current_loop.h"
#include "media/base/cdm_factory.h"
#include "media/base/decoder_factory.h"
#include "media/base/media_switches.h"
@@ -40,7 +41,7 @@
#include "mojo/public/cpp/bindings/associated_interface_ptr.h"
#include "services/service_manager/public/cpp/connect.h"
#include "services/service_manager/public/cpp/interface_provider.h"
-#include "services/ui/public/cpp/gpu/context_provider_command_buffer.h"
+#include "services/ws/public/cpp/gpu/context_provider_command_buffer.h"
#include "third_party/blink/public/platform/web_surface_layer_bridge.h"
#include "third_party/blink/public/platform/web_video_frame_submitter.h"
#include "third_party/blink/public/web/blink.h"
@@ -100,38 +101,26 @@ class FrameFetchContext : public media::ResourceFetchContext {
DISALLOW_COPY_AND_ASSIGN(FrameFetchContext);
};
-void ObtainAndSetContextProvider(
- base::OnceCallback<void(bool,
- scoped_refptr<ui::ContextProviderCommandBuffer>)>
- set_context_provider_callback,
- std::pair<media::GpuVideoAcceleratorFactories*, bool> gpu_info) {
- if (gpu_info.first) {
- scoped_refptr<ui::ContextProviderCommandBuffer> context_provider =
- gpu_info.first->GetMediaContextProvider();
- std::move(set_context_provider_callback)
- .Run(gpu_info.second, std::move(context_provider));
- } else {
- std::move(set_context_provider_callback).Run(false, nullptr);
- }
-}
-
// Obtains the media ContextProvider and calls the given callback on the same
// thread this is called on. Obtaining the media ContextProvider requires
-// getting GPuVideoAcceleratorFactories, which must be done on the main
-// thread.
-void PostMediaContextProviderToCallback(
+// establishing a GPUChannelHost, which must be done on the main thread.
+void PostContextProviderToCallback(
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
- base::OnceCallback<void(bool,
- scoped_refptr<ui::ContextProviderCommandBuffer>)>
- set_context_provider_callback) {
- base::PostTaskAndReplyWithResult(
- main_task_runner.get(), FROM_HERE, base::BindOnce([]() {
- return std::pair<media::GpuVideoAcceleratorFactories*, bool>(
- content::RenderThreadImpl::current()->GetGpuFactories(),
- !content::RenderThreadImpl::current()->IsGpuCompositingDisabled());
- }),
- base::BindOnce(&ObtainAndSetContextProvider,
- std::move(set_context_provider_callback)));
+ scoped_refptr<viz::ContextProvider> unwanted_context_provider,
+ blink::WebSubmitterConfigurationCallback set_context_provider_callback) {
+ main_task_runner->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ [](scoped_refptr<viz::ContextProvider> unwanted_context_provider,
+ blink::WebSubmitterConfigurationCallback cb) {
+ auto* rti = content::RenderThreadImpl::current();
+ auto context_provider = rti->GetVideoFrameCompositorContextProvider(
+ unwanted_context_provider);
+ std::move(cb).Run(!rti->IsGpuCompositingDisabled(),
+ std::move(context_provider));
+ },
+ std::move(unwanted_context_provider),
+ media::BindToCurrentLoop(std::move(set_context_provider_callback))));
}
} // namespace
@@ -139,7 +128,30 @@ void PostMediaContextProviderToCallback(
namespace content {
// static
-bool MediaFactory::VideoSurfaceLayerEnabled() {
+media::WebMediaPlayerParams::SurfaceLayerMode
+MediaFactory::GetVideoSurfaceLayerMode() {
+ // LayoutTests do not support SurfaceLayer by default at the moment.
+ // See https://crbug.com/838128
+ content::RenderThreadImpl* render_thread =
+ content::RenderThreadImpl::current();
+ if (render_thread && render_thread->layout_test_mode() &&
+ !render_thread->LayoutTestModeUsesDisplayCompositorPixelDump()) {
+ return media::WebMediaPlayerParams::SurfaceLayerMode::kNever;
+ }
+
+ if (features::IsMultiProcessMash())
+ return media::WebMediaPlayerParams::SurfaceLayerMode::kNever;
+
+ if (base::FeatureList::IsEnabled(media::kUseSurfaceLayerForVideo))
+ return media::WebMediaPlayerParams::SurfaceLayerMode::kAlways;
+
+ if (base::FeatureList::IsEnabled(media::kUseSurfaceLayerForVideoPIP))
+ return media::WebMediaPlayerParams::SurfaceLayerMode::kOnDemand;
+
+ return media::WebMediaPlayerParams::SurfaceLayerMode::kNever;
+}
+
+bool MediaFactory::VideoSurfaceLayerEnabledForMS() {
// LayoutTests do not support SurfaceLayer by default at the moment.
// See https://crbug.com/838128
content::RenderThreadImpl* render_thread =
@@ -149,8 +161,8 @@ bool MediaFactory::VideoSurfaceLayerEnabled() {
return false;
}
- return base::FeatureList::IsEnabled(media::kUseSurfaceLayerForVideo) &&
- features::IsAshInBrowserProcess();
+ return base::FeatureList::IsEnabled(media::kUseSurfaceLayerForVideoMS) &&
+ !features::IsMultiProcessMash();
}
MediaFactory::MediaFactory(
@@ -214,7 +226,7 @@ blink::WebMediaPlayer* MediaFactory::CreateMediaPlayer(
GetWebMediaStreamFromWebMediaPlayerSource(source);
if (!web_stream.IsNull())
return CreateWebMediaPlayerForMediaStream(client, sink_id, security_origin,
- web_frame);
+ web_frame, layer_tree_view);
// If |source| was not a MediaStream, it must be a URL.
// TODO(guidou): Fix this when support for other srcObject types is added.
@@ -229,7 +241,8 @@ blink::WebMediaPlayer* MediaFactory::CreateMediaPlayer(
scoped_refptr<media::SwitchableAudioRendererSink> audio_renderer_sink =
AudioDeviceFactory::NewSwitchableAudioRendererSink(
AudioDeviceFactory::kSourceMediaElement,
- render_frame_->GetRoutingID(), 0, sink_id.Utf8());
+ render_frame_->GetRoutingID(),
+ media::AudioSinkParameters(0, sink_id.Utf8()));
const WebPreferences webkit_preferences =
render_frame_->GetWebkitPreferences();
@@ -290,17 +303,20 @@ blink::WebMediaPlayer* MediaFactory::CreateMediaPlayer(
scoped_refptr<base::SingleThreadTaskRunner>
video_frame_compositor_task_runner;
std::unique_ptr<blink::WebVideoFrameSubmitter> submitter;
- bool use_surface_layer_for_video = VideoSurfaceLayerEnabled();
- if (use_surface_layer_for_video) {
- // TODO(lethalantidote): Use a separate task_runner. https://crbug/753605.
+ media::WebMediaPlayerParams::SurfaceLayerMode use_surface_layer_for_video =
+ GetVideoSurfaceLayerMode();
+ bool use_sync_primitives = false;
+ if (use_surface_layer_for_video ==
+ media::WebMediaPlayerParams::SurfaceLayerMode::kAlways) {
+ // Run the compositor / frame submitter on its own thread.
video_frame_compositor_task_runner =
- render_thread->GetMediaThreadTaskRunner();
- submitter = blink::WebVideoFrameSubmitter::Create(
- base::BindRepeating(
- &PostMediaContextProviderToCallback,
- RenderThreadImpl::current()->GetCompositorMainThreadTaskRunner()),
- settings);
+ render_thread->CreateVideoFrameCompositorTaskRunner();
+ // We must use sync primitives on this thread.
+ use_sync_primitives = true;
} else {
+ // Run on the cc thread, even if we may switch to SurfaceLayer mode later
+ // if we're in kOnDemand mode. We do this to avoid switching threads when
+ // switching to SurfaceLayer.
video_frame_compositor_task_runner =
render_thread->compositor_task_runner()
? render_thread->compositor_task_runner()
@@ -308,6 +324,15 @@ blink::WebMediaPlayer* MediaFactory::CreateMediaPlayer(
blink::TaskType::kInternalMediaRealTime);
}
+ if (use_surface_layer_for_video !=
+ media::WebMediaPlayerParams::SurfaceLayerMode::kNever) {
+ submitter = blink::WebVideoFrameSubmitter::Create(
+ base::BindRepeating(
+ &PostContextProviderToCallback,
+ RenderThreadImpl::current()->GetCompositorMainThreadTaskRunner()),
+ settings, use_sync_primitives);
+ }
+
DCHECK(layer_tree_view);
scoped_refptr<base::SingleThreadTaskRunner> media_task_runner =
render_thread->GetMediaThreadTaskRunner();
@@ -507,7 +532,8 @@ blink::WebMediaPlayer* MediaFactory::CreateWebMediaPlayerForMediaStream(
blink::WebMediaPlayerClient* client,
const blink::WebString& sink_id,
const blink::WebSecurityOrigin& security_origin,
- blink::WebLocalFrame* frame) {
+ blink::WebLocalFrame* frame,
+ blink::WebLayerTreeView* layer_tree_view) {
RenderThreadImpl* const render_thread = RenderThreadImpl::current();
scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner =
@@ -516,6 +542,7 @@ blink::WebMediaPlayer* MediaFactory::CreateWebMediaPlayerForMediaStream(
compositor_task_runner =
render_frame_->GetTaskRunner(blink::TaskType::kInternalMediaRealTime);
+ DCHECK(layer_tree_view);
return new WebMediaPlayerMS(
frame, client, GetWebMediaPlayerDelegate(),
std::make_unique<RenderMediaLog>(
@@ -524,7 +551,9 @@ blink::WebMediaPlayer* MediaFactory::CreateWebMediaPlayerForMediaStream(
CreateMediaStreamRendererFactory(), render_thread->GetIOTaskRunner(),
compositor_task_runner, render_thread->GetMediaThreadTaskRunner(),
render_thread->GetWorkerTaskRunner(), render_thread->GetGpuFactories(),
- sink_id);
+ sink_id,
+ base::BindOnce(&blink::WebSurfaceLayerBridge::Create, layer_tree_view),
+ VideoSurfaceLayerEnabledForMS());
}
media::RendererWebMediaPlayerDelegate*
diff --git a/chromium/content/renderer/media/media_factory.h b/chromium/content/renderer/media/media_factory.h
index 7c4ea973a11..730c283e3fe 100644
--- a/chromium/content/renderer/media/media_factory.h
+++ b/chromium/content/renderer/media/media_factory.h
@@ -12,6 +12,7 @@
#include "media/base/renderer_factory_selector.h"
#include "media/base/routing_token_callback.h"
#include "media/blink/url_index.h"
+#include "media/blink/webmediaplayer_params.h"
#include "media/media_buildflags.h"
#include "media/mojo/buildflags.h"
#include "media/mojo/interfaces/remoting.mojom.h"
@@ -72,7 +73,12 @@ class RendererMediaPlayerManager;
class MediaFactory {
public:
// Helper function returning whether VideoSurfaceLayer should be enabled.
- static bool VideoSurfaceLayerEnabled();
+ static media::WebMediaPlayerParams::SurfaceLayerMode
+ GetVideoSurfaceLayerMode();
+
+ // Helper function returning whether VideoSurfaceLayer should be enabled for
+ // MediaStreams.
+ static bool VideoSurfaceLayerEnabledForMS();
// Create a MediaFactory to assist the |render_frame| with media tasks.
// |request_routing_token_cb| bound to |render_frame| IPC functions for
@@ -122,7 +128,8 @@ class MediaFactory {
blink::WebMediaPlayerClient* client,
const blink::WebString& sink_id,
const blink::WebSecurityOrigin& security_origin,
- blink::WebLocalFrame* frame);
+ blink::WebLocalFrame* frame,
+ blink::WebLayerTreeView* layer_tree_view);
// Returns the media delegate for WebMediaPlayer usage. If
// |media_player_delegate_| is NULL, one is created.
diff --git a/chromium/content/renderer/media/render_media_log.cc b/chromium/content/renderer/media/render_media_log.cc
index 380f66397c5..fb9f926221f 100644
--- a/chromium/content/renderer/media/render_media_log.cc
+++ b/chromium/content/renderer/media/render_media_log.cc
@@ -57,6 +57,9 @@ RenderMediaLog::RenderMediaLog(
RenderMediaLog::~RenderMediaLog() {
DCHECK(task_runner_->BelongsToCurrentThread());
+ // AddEvent() could be in-flight on some other thread. Wait for it, and make
+ // sure that nobody else calls it.
+ InvalidateLog();
// There's no further chance to handle this, so send them now. This should not
// be racy since nothing should have a pointer to the media log on another
@@ -65,7 +68,8 @@ RenderMediaLog::~RenderMediaLog() {
SendQueuedMediaEvents();
}
-void RenderMediaLog::AddEvent(std::unique_ptr<media::MediaLogEvent> event) {
+void RenderMediaLog::AddEventLocked(
+ std::unique_ptr<media::MediaLogEvent> event) {
Log(event.get());
// For enforcing delay until it's been a second since the last ipc message was
@@ -74,7 +78,6 @@ void RenderMediaLog::AddEvent(std::unique_ptr<media::MediaLogEvent> event) {
{
base::AutoLock auto_lock(lock_);
-
switch (event->type) {
case media::MediaLogEvent::DURATION_SET:
// Similar to the extents changed message, this may fire many times for
@@ -125,12 +128,9 @@ void RenderMediaLog::AddEvent(std::unique_ptr<media::MediaLogEvent> event) {
base::BindOnce(&RenderMediaLog::SendQueuedMediaEvents, weak_this_));
}
-std::string RenderMediaLog::GetErrorMessage() {
- base::AutoLock auto_lock(lock_);
-
+std::string RenderMediaLog::GetErrorMessageLocked() {
// Keep message structure in sync with
// HTMLMediaElement::BuildElementErrorMessage().
-
std::stringstream result;
if (last_pipeline_error_)
result << MediaEventToMessageString(*last_pipeline_error_);
@@ -147,8 +147,10 @@ std::string RenderMediaLog::GetErrorMessage() {
return result.str();
}
-void RenderMediaLog::RecordRapporWithSecurityOrigin(const std::string& metric) {
+void RenderMediaLog::RecordRapporWithSecurityOriginLocked(
+ const std::string& metric) {
if (!task_runner_->BelongsToCurrentThread()) {
+ // Note that we don't post back to *Locked.
task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&RenderMediaLog::RecordRapporWithSecurityOrigin,
@@ -165,7 +167,6 @@ void RenderMediaLog::SendQueuedMediaEvents() {
std::vector<media::MediaLogEvent> events_to_send;
{
base::AutoLock auto_lock(lock_);
-
DCHECK(ipc_send_pending_);
ipc_send_pending_ = false;
diff --git a/chromium/content/renderer/media/render_media_log.h b/chromium/content/renderer/media/render_media_log.h
index 636be30574b..e65d6fe60fb 100644
--- a/chromium/content/renderer/media/render_media_log.h
+++ b/chromium/content/renderer/media/render_media_log.h
@@ -11,7 +11,6 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
-#include "base/synchronization/lock.h"
#include "base/time/time.h"
#include "content/common/content_export.h"
#include "media/base/media_log.h"
@@ -39,16 +38,17 @@ class CONTENT_EXPORT RenderMediaLog : public media::MediaLog {
scoped_refptr<base::SingleThreadTaskRunner> task_runner);
~RenderMediaLog() override;
- // MediaLog implementation.
- void AddEvent(std::unique_ptr<media::MediaLogEvent> event) override;
- std::string GetErrorMessage() override;
- void RecordRapporWithSecurityOrigin(const std::string& metric) override;
-
// Will reset |last_ipc_send_time_| with the value of NowTicks().
void SetTickClockForTesting(const base::TickClock* tick_clock);
void SetTaskRunnerForTesting(
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner);
+ protected:
+ // MediaLog implementation.
+ void AddEventLocked(std::unique_ptr<media::MediaLogEvent> event) override;
+ std::string GetErrorMessageLocked() override;
+ void RecordRapporWithSecurityOriginLocked(const std::string& metric) override;
+
private:
// Posted as a delayed task on |task_runner_| to throttle ipc message
// frequency.
@@ -62,7 +62,9 @@ class CONTENT_EXPORT RenderMediaLog : public media::MediaLog {
// |lock_| protects access to all of the following member variables. It
// allows any render process thread to AddEvent(), while preserving their
// sequence for throttled send on |task_runner_| and coherent retrieval by
- // GetErrorMessage().
+ // GetErrorMessage(). This is needed in addition to the synchronization
+ // guarantees provided by MediaLog, since SendQueuedMediaEvents must also
+ // be synchronized with respect to AddEvent.
mutable base::Lock lock_;
const base::TickClock* tick_clock_;
base::TimeTicks last_ipc_send_time_;
diff --git a/chromium/content/renderer/media/renderer_webaudiodevice_impl.cc b/chromium/content/renderer/media/renderer_webaudiodevice_impl.cc
index 1c57ddf3713..16dfe2e6832 100644
--- a/chromium/content/renderer/media/renderer_webaudiodevice_impl.cc
+++ b/chromium/content/renderer/media/renderer_webaudiodevice_impl.cc
@@ -92,8 +92,8 @@ int FrameIdFromCurrentContext() {
media::AudioParameters GetOutputDeviceParameters(int frame_id,
int session_id,
const std::string& device_id) {
- return AudioDeviceFactory::GetOutputDeviceInfo(frame_id, session_id,
- device_id)
+ return AudioDeviceFactory::GetOutputDeviceInfo(frame_id,
+ {session_id, device_id})
.output_params();
}
@@ -168,7 +168,7 @@ void RendererWebAudioDeviceImpl::Start() {
sink_ = AudioDeviceFactory::NewAudioRendererSink(
GetLatencyHintSourceType(latency_hint_.Category()), frame_id_,
- session_id_, std::string());
+ media::AudioSinkParameters(session_id_, std::string()));
// Use the media thread instead of the render thread for fake Render() calls
// since it has special connotations for Blink and garbage collection. Timeout
diff --git a/chromium/content/renderer/media/renderer_webaudiodevice_impl_unittest.cc b/chromium/content/renderer/media/renderer_webaudiodevice_impl_unittest.cc
index 337fff50fc4..6da7d4f72ea 100644
--- a/chromium/content/renderer/media/renderer_webaudiodevice_impl_unittest.cc
+++ b/chromium/content/renderer/media/renderer_webaudiodevice_impl_unittest.cc
@@ -80,29 +80,29 @@ class RendererWebAudioDeviceImplTest
webaudio_device_->SetMediaTaskRunnerForTesting(message_loop_.task_runner());
}
- MOCK_METHOD1(CreateAudioCapturerSource,
- scoped_refptr<media::AudioCapturerSource>(int));
- MOCK_METHOD3(CreateFinalAudioRendererSink,
- scoped_refptr<media::AudioRendererSink>(int,
- int,
- const std::string&));
- MOCK_METHOD4(
- CreateSwitchableAudioRendererSink,
- scoped_refptr<media::SwitchableAudioRendererSink>(SourceType,
- int,
- int,
- const std::string&));
+ MOCK_METHOD2(CreateAudioCapturerSource,
+ scoped_refptr<media::AudioCapturerSource>(
+ int,
+ const media::AudioSourceParameters&));
+ MOCK_METHOD2(CreateFinalAudioRendererSink,
+ scoped_refptr<media::AudioRendererSink>(
+ int,
+ const media::AudioSinkParameters&));
+ MOCK_METHOD3(CreateSwitchableAudioRendererSink,
+ scoped_refptr<media::SwitchableAudioRendererSink>(
+ SourceType,
+ int,
+ const media::AudioSinkParameters&));
scoped_refptr<media::AudioRendererSink> CreateAudioRendererSink(
SourceType source_type,
int render_frame_id,
- int session_id,
- const std::string& device_id) override {
+ const media::AudioSinkParameters& params) override {
scoped_refptr<media::MockAudioRendererSink> mock_sink =
new media::MockAudioRendererSink(
- device_id, media::OUTPUT_DEVICE_STATUS_OK,
- MockGetOutputDeviceParameters(render_frame_id, session_id,
- device_id));
+ params.device_id, media::OUTPUT_DEVICE_STATUS_OK,
+ MockGetOutputDeviceParameters(render_frame_id, params.session_id,
+ params.device_id));
EXPECT_CALL(*mock_sink.get(), Start());
EXPECT_CALL(*mock_sink.get(), Play());
diff --git a/chromium/content/renderer/media/renderer_webmediaplayer_delegate.cc b/chromium/content/renderer/media/renderer_webmediaplayer_delegate.cc
index f644a25e76f..1080b18e7c5 100644
--- a/chromium/content/renderer/media/renderer_webmediaplayer_delegate.cc
+++ b/chromium/content/renderer/media/renderer_webmediaplayer_delegate.cc
@@ -15,6 +15,7 @@
#include "content/public/renderer/content_renderer_client.h"
#include "content/public/renderer/render_frame.h"
#include "content/public/renderer/render_thread.h"
+#include "third_party/blink/public/common/picture_in_picture/picture_in_picture_control_info.h"
#include "third_party/blink/public/platform/web_fullscreen_video_status.h"
#include "third_party/blink/public/platform/web_size.h"
#include "third_party/blink/public/web/web_scoped_user_gesture.h"
@@ -38,7 +39,11 @@ RendererWebMediaPlayerDelegate::RendererWebMediaPlayerDelegate(
content::RenderFrame* render_frame)
: RenderFrameObserver(render_frame),
allow_idle_cleanup_(
- content::GetContentClient()->renderer()->AllowIdleMediaSuspend()),
+ content::GetContentClient()->renderer()->IsIdleMediaSuspendEnabled()),
+ background_suspend_enabled_(
+ content::GetContentClient()
+ ->renderer()
+ ->IsBackgroundMediaSuspendEnabled(render_frame)),
tick_clock_(base::DefaultTickClock::GetInstance()) {
idle_cleanup_interval_ = base::TimeDelta::FromSeconds(5);
idle_timeout_ = base::TimeDelta::FromSeconds(15);
@@ -140,6 +145,13 @@ void RendererWebMediaPlayerDelegate::DidPictureInPictureModeEnd(
routing_id(), delegate_id, request_id));
}
+void RendererWebMediaPlayerDelegate::DidSetPictureInPictureCustomControls(
+ int delegate_id,
+ const std::vector<blink::PictureInPictureControlInfo>& controls) {
+ Send(new MediaPlayerDelegateHostMsg_OnSetPictureInPictureCustomControls(
+ routing_id(), delegate_id, controls));
+}
+
void RendererWebMediaPlayerDelegate::DidPictureInPictureSurfaceChange(
int delegate_id,
const viz::SurfaceId& surface_id,
@@ -156,6 +168,10 @@ void RendererWebMediaPlayerDelegate::
std::make_pair(player_id, std::move(callback));
}
+bool RendererWebMediaPlayerDelegate::IsBackgroundMediaSuspendEnabled() {
+ return background_suspend_enabled_;
+}
+
void RendererWebMediaPlayerDelegate::DidPause(int player_id) {
DVLOG(2) << __func__ << "(" << player_id << ")";
DCHECK(id_map_.Lookup(player_id));
@@ -215,8 +231,8 @@ void RendererWebMediaPlayerDelegate::ClearStaleFlag(int player_id) {
if (!idle_cleanup_timer_.IsRunning() && !pending_update_task_) {
idle_cleanup_timer_.Start(
FROM_HERE, idle_cleanup_interval_,
- base::Bind(&RendererWebMediaPlayerDelegate::UpdateTask,
- base::Unretained(this)));
+ base::BindOnce(&RendererWebMediaPlayerDelegate::UpdateTask,
+ base::Unretained(this)));
}
}
@@ -485,8 +501,8 @@ void RendererWebMediaPlayerDelegate::UpdateTask() {
if (!idle_player_map_.empty()) {
idle_cleanup_timer_.Start(
FROM_HERE, idle_cleanup_interval_,
- base::Bind(&RendererWebMediaPlayerDelegate::UpdateTask,
- base::Unretained(this)));
+ base::BindOnce(&RendererWebMediaPlayerDelegate::UpdateTask,
+ base::Unretained(this)));
}
}
diff --git a/chromium/content/renderer/media/renderer_webmediaplayer_delegate.h b/chromium/content/renderer/media/renderer_webmediaplayer_delegate.h
index 5897004debb..cb3e715174d 100644
--- a/chromium/content/renderer/media/renderer_webmediaplayer_delegate.h
+++ b/chromium/content/renderer/media/renderer_webmediaplayer_delegate.h
@@ -71,12 +71,16 @@ class CONTENT_EXPORT RendererWebMediaPlayerDelegate
const gfx::Size&,
blink::WebMediaPlayer::PipWindowOpenedCallback) override;
void DidPictureInPictureModeEnd(int delegate_id, base::OnceClosure) override;
+ void DidSetPictureInPictureCustomControls(
+ int delegate_id,
+ const std::vector<blink::PictureInPictureControlInfo>& controls) override;
void DidPictureInPictureSurfaceChange(int delegate_id,
const viz::SurfaceId&,
const gfx::Size&) override;
void RegisterPictureInPictureWindowResizeCallback(
int player_id,
blink::WebMediaPlayer::PipWindowResizedCallback) override;
+ bool IsBackgroundMediaSuspendEnabled() override;
// content::RenderFrameObserver overrides.
void WasHidden() override;
@@ -146,6 +150,9 @@ class CONTENT_EXPORT RendererWebMediaPlayerDelegate
// period of inactivity.
bool allow_idle_cleanup_ = true;
+ // Flag for whether players should suspend when tab is in background.
+ bool background_suspend_enabled_ = true;
+
// Tracks which players have entered an idle state. After some period of
// inactivity these players will be notified and become stale.
std::map<int, base::TimeTicks> idle_player_map_;
diff --git a/chromium/content/renderer/media/stream/audio_service_audio_processor_proxy.cc b/chromium/content/renderer/media/stream/audio_service_audio_processor_proxy.cc
new file mode 100644
index 00000000000..2f40b052466
--- /dev/null
+++ b/chromium/content/renderer/media/stream/audio_service_audio_processor_proxy.cc
@@ -0,0 +1,167 @@
+// 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/renderer/media/stream/audio_service_audio_processor_proxy.h"
+
+#include <stddef.h>
+#include <stdint.h>
+#include <algorithm>
+#include <limits>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/single_thread_task_runner.h"
+#include "base/task/post_task.h"
+#include "base/task/task_traits.h"
+#include "base/timer/timer.h"
+#include "build/build_config.h"
+
+namespace content {
+
+namespace {
+constexpr base::TimeDelta kMaxStatsInterval = base::TimeDelta::FromSeconds(5);
+constexpr base::TimeDelta kMinStatsInterval =
+ base::TimeDelta::FromMilliseconds(100);
+} // namespace
+
+AudioServiceAudioProcessorProxy::AudioServiceAudioProcessorProxy(
+ scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner)
+ : main_thread_runner_(std::move(main_thread_task_runner)),
+ target_stats_interval_(kMaxStatsInterval),
+ aec_dump_message_filter_(AecDumpMessageFilter::Get()),
+ weak_ptr_factory_(this) {
+ DCHECK(main_thread_runner_->BelongsToCurrentThread());
+}
+
+AudioServiceAudioProcessorProxy::~AudioServiceAudioProcessorProxy() {
+ DCHECK(main_thread_runner_->BelongsToCurrentThread());
+ Stop();
+}
+
+void AudioServiceAudioProcessorProxy::Stop() {
+ DCHECK(main_thread_runner_->BelongsToCurrentThread());
+
+ if (aec_dump_message_filter_.get()) {
+ aec_dump_message_filter_->RemoveDelegate(this);
+ aec_dump_message_filter_ = nullptr;
+ }
+
+ if (processor_controls_) {
+ processor_controls_->StopEchoCancellationDump();
+ processor_controls_ = nullptr;
+ }
+
+ stats_update_timer_.Stop();
+}
+
+void AudioServiceAudioProcessorProxy::OnAecDumpFile(
+ const IPC::PlatformFileForTransit& file_handle) {
+ DCHECK(main_thread_runner_->BelongsToCurrentThread());
+ base::File file = IPC::PlatformFileForTransitToFile(file_handle);
+ DCHECK(file.IsValid());
+ if (processor_controls_) {
+ processor_controls_->StartEchoCancellationDump(std::move(file));
+ } else {
+ // Post the file close to avoid blocking the main thread.
+ base::PostTaskWithTraits(
+ FROM_HERE, {base::TaskPriority::LOWEST, base::MayBlock()},
+ base::BindOnce([](base::File) {}, std::move(file)));
+ }
+}
+
+void AudioServiceAudioProcessorProxy::OnDisableAecDump() {
+ DCHECK(main_thread_runner_->BelongsToCurrentThread());
+ if (processor_controls_)
+ processor_controls_->StopEchoCancellationDump();
+}
+
+void AudioServiceAudioProcessorProxy::OnIpcClosing() {
+ DCHECK(main_thread_runner_->BelongsToCurrentThread());
+ aec_dump_message_filter_->RemoveDelegate(this);
+ aec_dump_message_filter_ = nullptr;
+}
+
+void AudioServiceAudioProcessorProxy::SetControls(
+ media::AudioProcessorControls* controls) {
+ DCHECK(main_thread_runner_->BelongsToCurrentThread());
+ DCHECK(!processor_controls_);
+ DCHECK(controls);
+ processor_controls_ = controls;
+
+ // Initialize the stats interval request timer with the current time ticks,
+ // so it makes any sort of sense.
+ last_stats_request_time_ = base::TimeTicks::Now();
+ stats_update_timer_.SetTaskRunner(main_thread_runner_);
+ RescheduleStatsUpdateTimer(target_stats_interval_);
+ // In unit tests not creating a message filter, |aec_dump_message_filter_|
+ // will be null. We can just ignore that. Other unit tests and browser tests
+ // ensure that we do get the filter when we should.
+ if (aec_dump_message_filter_)
+ aec_dump_message_filter_->AddDelegate(this);
+}
+
+void AudioServiceAudioProcessorProxy::GetStats(AudioProcessorStats* out) {
+ // This is the old GetStats interface from webrtc::AudioProcessorInterface.
+ // It should not be in use by Chrome any longer.
+ NOTREACHED();
+}
+
+webrtc::AudioProcessorInterface::AudioProcessorStatistics
+AudioServiceAudioProcessorProxy::GetStats(bool has_remote_tracks) {
+ base::AutoLock lock(stats_lock_);
+ // Find some reasonable update interval, rounding down to the nearest one
+ // tenth of a second. The update interval is chosen so that the rate of
+ // updates we get from the audio service is near the interval at which the
+ // client calls GetStats.
+ const auto rounded = [](base::TimeDelta d) {
+ return d - (d % base::TimeDelta::FromMilliseconds(100));
+ };
+ const auto now = base::TimeTicks::Now();
+ const auto request_interval = rounded(now - last_stats_request_time_);
+ target_stats_interval_ = std::max(
+ kMinStatsInterval, std::min(request_interval, kMaxStatsInterval));
+
+ last_stats_request_time_ = now;
+
+ // |has_remote_tracks| is ignored, since the remote AudioProcessingModule gets
+ // this information more directly.
+ return latest_stats_;
+}
+
+void AudioServiceAudioProcessorProxy::RescheduleStatsUpdateTimer(
+ base::TimeDelta new_interval) {
+ DCHECK(main_thread_runner_->BelongsToCurrentThread());
+ // Unretained is safe since |this| owns |stats_update_timer_|.
+ stats_update_timer_.Start(
+ FROM_HERE, new_interval,
+ base::BindRepeating(&AudioServiceAudioProcessorProxy::RequestStats,
+ base::Unretained(this)));
+}
+
+void AudioServiceAudioProcessorProxy::RequestStats() {
+ DCHECK(main_thread_runner_->BelongsToCurrentThread());
+ if (processor_controls_) {
+ processor_controls_->GetStats(
+ base::BindOnce(&AudioServiceAudioProcessorProxy::UpdateStats,
+ weak_ptr_factory_.GetWeakPtr()));
+ }
+}
+
+void AudioServiceAudioProcessorProxy::UpdateStats(
+ const AudioProcessorStatistics& new_stats) {
+ DCHECK(main_thread_runner_->BelongsToCurrentThread());
+ base::TimeDelta target_interval;
+ {
+ base::AutoLock lock(stats_lock_);
+ latest_stats_ = new_stats;
+ target_interval = target_stats_interval_;
+ }
+
+ if (target_interval != stats_update_timer_.GetCurrentDelay()) {
+ RescheduleStatsUpdateTimer(target_interval);
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/media/stream/audio_service_audio_processor_proxy.h b/chromium/content/renderer/media/stream/audio_service_audio_processor_proxy.h
new file mode 100644
index 00000000000..7f110621cf4
--- /dev/null
+++ b/chromium/content/renderer/media/stream/audio_service_audio_processor_proxy.h
@@ -0,0 +1,93 @@
+// 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_RENDERER_MEDIA_STREAM_AUDIO_SERVICE_AUDIO_PROCESSOR_PROXY_H_
+#define CONTENT_RENDERER_MEDIA_STREAM_AUDIO_SERVICE_AUDIO_PROCESSOR_PROXY_H_
+
+#include <memory>
+
+#include "base/files/file.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/synchronization/lock.h"
+#include "base/threading/thread_checker.h"
+#include "content/common/content_export.h"
+#include "content/renderer/media/stream/aec_dump_message_filter.h"
+#include "media/audio/audio_processing.h"
+#include "media/webrtc/audio_processor_controls.h"
+#include "third_party/webrtc/api/mediastreaminterface.h"
+#include "third_party/webrtc/modules/audio_processing/include/audio_processing.h"
+#include "third_party/webrtc/rtc_base/task_queue.h"
+
+namespace content {
+
+// This class owns an object of webrtc::AudioProcessing which contains signal
+// processing components like AGC, AEC and NS. It enables the components based
+// on the getUserMedia constraints, processes the data and outputs it in a unit
+// of 10 ms data chunk.
+// TODO(https://crbug.com/879296): Add tests. Possibly the timer update rate
+// calculation code should be encapsulated in a class.
+class CONTENT_EXPORT AudioServiceAudioProcessorProxy
+ : public webrtc::AudioProcessorInterface,
+ public AecDumpMessageFilter::AecDumpDelegate {
+ public:
+ // All methods (including constructor and destructor) must be called on the
+ // main thread except for GetStats.
+ AudioServiceAudioProcessorProxy(
+ scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner);
+
+ // Stops the audio processor, no more AEC dump or render data after calling
+ // this method.
+ void Stop();
+
+ // webrtc::AudioProcessorInterface implementation.
+ // This method is called on the libjingle thread.
+ void GetStats(AudioProcessorStats* stats) override;
+
+ // This method is called on the libjingle thread.
+ AudioProcessorStatistics GetStats(bool has_remote_tracks) override;
+
+ // AecDumpMessageFilter::AecDumpDelegate implementation.
+ // Called on the main render thread.
+ void OnAecDumpFile(const IPC::PlatformFileForTransit& file_handle) override;
+ void OnDisableAecDump() override;
+ void OnIpcClosing() override;
+
+ // Set the AudioProcessorControls which to proxy to. Must only be called once
+ // and |controls| cannot be nullptr.
+ void SetControls(media::AudioProcessorControls* controls);
+
+ protected:
+ ~AudioServiceAudioProcessorProxy() override;
+
+ private:
+ void RescheduleStatsUpdateTimer(base::TimeDelta new_interval);
+
+ void RequestStats();
+ void UpdateStats(const AudioProcessorStatistics& new_stats);
+ AudioProcessorStatistics GetLatestStats();
+
+ // This task runner is used to post tasks to the main thread.
+ const scoped_refptr<base::SingleThreadTaskRunner> main_thread_runner_;
+
+ media::AudioProcessorControls* processor_controls_ = nullptr;
+ base::RepeatingTimer stats_update_timer_;
+ base::TimeTicks last_stats_request_time_;
+
+ // |stats_lock_| protects both |target_stats_interval_| and |latest_stats_|.
+ base::Lock stats_lock_;
+ base::TimeDelta target_stats_interval_;
+ AudioProcessorStatistics latest_stats_ = {};
+
+ // Communication with browser for AEC dump.
+ scoped_refptr<AecDumpMessageFilter> aec_dump_message_filter_;
+
+ base::WeakPtrFactory<AudioServiceAudioProcessorProxy> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(AudioServiceAudioProcessorProxy);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_MEDIA_STREAM_AUDIO_SERVICE_AUDIO_PROCESSOR_PROXY_H_
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 a51cc04af8f..6b826e25c95 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
@@ -66,7 +66,8 @@ bool LocalMediaStreamAudioSource::EnsureSourceIsStarted() {
<< GetAudioParameters().AsHumanReadableString() << "}.";
source_ = AudioDeviceFactory::NewAudioCapturerSource(
- consumer_render_frame_id_, device().session_id);
+ consumer_render_frame_id_,
+ media::AudioSourceParameters(device().session_id));
source_->Initialize(GetAudioParameters(), this);
source_->Start();
return true;
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 d71f25992ac..40af27f948d 100644
--- a/chromium/content/renderer/media/stream/media_stream_audio_processor.cc
+++ b/chromium/content/renderer/media/stream/media_stream_audio_processor.cc
@@ -23,12 +23,13 @@
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "content/public/common/content_features.h"
-#include "content/public/common/content_switches.h"
#include "content/renderer/media/webrtc/webrtc_audio_device_impl.h"
#include "media/base/audio_converter.h"
#include "media/base/audio_fifo.h"
#include "media/base/audio_parameters.h"
#include "media/base/channel_layout.h"
+#include "media/webrtc/echo_information.h"
+#include "media/webrtc/webrtc_switches.h"
#include "third_party/webrtc/api/audio/echo_canceller3_factory.h"
#include "third_party/webrtc/api/mediaconstraintsinterface.h"
#include "third_party/webrtc/modules/audio_processing/include/audio_processing_statistics.h"
@@ -523,9 +524,9 @@ void MediaStreamAudioProcessor::OnRenderThreadChanged() {
}
void MediaStreamAudioProcessor::GetStats(AudioProcessorStats* stats) {
- stats->typing_noise_detected =
- (base::subtle::Acquire_Load(&typing_detected_) != false);
- GetAudioProcessingStats(audio_processing_.get(), stats);
+ // This is the old GetStats interface from webrtc::AudioProcessorInterface.
+ // It should not be in use by Chrome any longer.
+ NOTREACHED();
}
webrtc::AudioProcessorInterface::AudioProcessorStatistics
@@ -589,8 +590,12 @@ void MediaStreamAudioProcessor::InitializeAudioProcessingModule(
// If the experimental AGC is enabled, check for overridden config params.
if (properties.goog_experimental_auto_gain_control) {
auto startup_min_volume = GetStartupMinVolumeForAgc();
- config.Set<webrtc::ExperimentalAgc>(
- new webrtc::ExperimentalAgc(true, startup_min_volume.value_or(0)));
+ auto* experimental_agc =
+ new webrtc::ExperimentalAgc(true, startup_min_volume.value_or(0));
+ experimental_agc->digital_adaptive_disabled =
+ base::FeatureList::IsEnabled(features::kWebRtcHybridAgc);
+
+ config.Set<webrtc::ExperimentalAgc>(experimental_agc);
}
// Create and configure the webrtc::AudioProcessing.
@@ -612,8 +617,6 @@ void MediaStreamAudioProcessor::InitializeAudioProcessingModule(
audio_processing_.reset(ap_builder.Create(config));
// Enable the audio processing components.
- webrtc::AudioProcessing::Config apm_config;
-
if (playout_data_source_) {
playout_data_source_->AddPlayoutSink(this);
}
@@ -626,15 +629,13 @@ void MediaStreamAudioProcessor::InitializeAudioProcessingModule(
// updated.
if (properties.echo_cancellation_type !=
EchoCancellationType::kEchoCancellationAec3) {
- echo_information_ = std::make_unique<EchoInformation>();
+ echo_information_ = std::make_unique<media::EchoInformation>();
}
}
if (properties.goog_noise_suppression)
EnableNoiseSuppression(audio_processing_.get(), NoiseSuppression::kHigh);
- apm_config.high_pass_filter.enabled = properties.goog_highpass_filter;
-
if (goog_typing_detection) {
// TODO(xians): Remove this |typing_detector_| after the typing suppression
// is enabled by default.
@@ -645,6 +646,14 @@ void MediaStreamAudioProcessor::InitializeAudioProcessingModule(
if (properties.goog_auto_gain_control)
EnableAutomaticGainControl(audio_processing_.get());
+ 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_gain_db = 0.f;
+ }
audio_processing_->ApplyConfig(apm_config);
RecordProcessingState(AUDIO_PROCESSING_ENABLED);
@@ -743,9 +752,10 @@ int MediaStreamAudioProcessor::ProcessData(const float* const* process_ptrs,
render_delay_ms);
int total_delay_ms = capture_delay_ms + render_delay_ms;
- if (total_delay_ms > 300) {
+ if (total_delay_ms > 300 && large_delay_log_count_ < 10) {
LOG(WARNING) << "Large audio delay, capture delay: " << capture_delay_ms
<< "ms; render delay: " << render_delay_ms << "ms";
+ ++large_delay_log_count_;
}
webrtc::AudioProcessing* ap = audio_processing_.get();
@@ -777,7 +787,8 @@ int MediaStreamAudioProcessor::ProcessData(const float* const* process_ptrs,
main_thread_runner_->PostTask(
FROM_HERE,
- base::BindOnce(&MediaStreamAudioProcessor::UpdateAecStats, this));
+ base::BindOnce(&MediaStreamAudioProcessor::UpdateAecStats,
+ 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) ?
diff --git a/chromium/content/renderer/media/stream/media_stream_audio_processor.h b/chromium/content/renderer/media/stream/media_stream_audio_processor.h
index c5237570077..edf302f3460 100644
--- a/chromium/content/renderer/media/stream/media_stream_audio_processor.h
+++ b/chromium/content/renderer/media/stream/media_stream_audio_processor.h
@@ -30,6 +30,7 @@
namespace media {
class AudioBus;
class AudioParameters;
+class EchoInformation;
} // namespace media
namespace webrtc {
@@ -38,7 +39,6 @@ class TypingDetection;
namespace content {
-class EchoInformation;
class MediaStreamAudioBus;
class MediaStreamAudioFifo;
@@ -147,11 +147,6 @@ class CONTENT_EXPORT MediaStreamAudioProcessor
// Helper to initialize the capture converter.
void InitializeCaptureFifo(const media::AudioParameters& input_format);
- // Helper to initialize the render converter.
- void InitializeRenderFifoIfNeeded(int sample_rate,
- int number_of_channels,
- int frames_per_buffer);
-
// Called by ProcessAndConsumeData().
// Returns the new microphone volume in the range of |0, 255].
// When the volume does not need to be updated, it returns 0.
@@ -218,10 +213,11 @@ class CONTENT_EXPORT MediaStreamAudioProcessor
// Counters to avoid excessively logging errors in OnPlayoutData.
size_t unsupported_buffer_size_log_count_ = 0;
size_t apm_playout_error_code_log_count_ = 0;
+ size_t large_delay_log_count_ = 0;
// Object for logging UMA stats for echo information when the AEC is enabled.
// Accessed on the main render thread.
- std::unique_ptr<EchoInformation> echo_information_;
+ std::unique_ptr<media::EchoInformation> echo_information_;
DISALLOW_COPY_AND_ASSIGN(MediaStreamAudioProcessor);
};
diff --git a/chromium/content/renderer/media/stream/media_stream_audio_processor_options.cc b/chromium/content/renderer/media/stream/media_stream_audio_processor_options.cc
index 7a5a6274a5c..eceaaee43d2 100644
--- a/chromium/content/renderer/media/stream/media_stream_audio_processor_options.cc
+++ b/chromium/content/renderer/media/stream/media_stream_audio_processor_options.cc
@@ -28,40 +28,6 @@
namespace content {
-namespace {
-
-// Used to log echo quality based on delay estimates.
-enum DelayBasedEchoQuality {
- DELAY_BASED_ECHO_QUALITY_GOOD = 0,
- DELAY_BASED_ECHO_QUALITY_SPURIOUS,
- DELAY_BASED_ECHO_QUALITY_BAD,
- DELAY_BASED_ECHO_QUALITY_INVALID,
- DELAY_BASED_ECHO_QUALITY_MAX
-};
-
-DelayBasedEchoQuality EchoDelayFrequencyToQuality(float delay_frequency) {
- const float kEchoDelayFrequencyLowerLimit = 0.1f;
- const float kEchoDelayFrequencyUpperLimit = 0.8f;
- // DELAY_BASED_ECHO_QUALITY_GOOD
- // delay is out of bounds during at most 10 % of the time.
- // DELAY_BASED_ECHO_QUALITY_SPURIOUS
- // delay is out of bounds 10-80 % of the time.
- // DELAY_BASED_ECHO_QUALITY_BAD
- // delay is mostly out of bounds >= 80 % of the time.
- // DELAY_BASED_ECHO_QUALITY_INVALID
- // delay_frequency is negative which happens if we have insufficient data.
- if (delay_frequency < 0)
- return DELAY_BASED_ECHO_QUALITY_INVALID;
- else if (delay_frequency <= kEchoDelayFrequencyLowerLimit)
- return DELAY_BASED_ECHO_QUALITY_GOOD;
- else if (delay_frequency < kEchoDelayFrequencyUpperLimit)
- return DELAY_BASED_ECHO_QUALITY_SPURIOUS;
- else
- return DELAY_BASED_ECHO_QUALITY_BAD;
-}
-
-} // namespace
-
AudioProcessingProperties::AudioProcessingProperties() = default;
AudioProcessingProperties::AudioProcessingProperties(
const AudioProcessingProperties& other) = default;
@@ -90,125 +56,52 @@ bool AudioProcessingProperties::EchoCancellationIsWebRtcProvided() const {
echo_cancellation_type == EchoCancellationType::kEchoCancellationAec3;
}
-EchoInformation::EchoInformation()
- : delay_stats_time_ms_(0),
- echo_frames_received_(false),
- divergent_filter_stats_time_ms_(0),
- num_divergent_filter_fraction_(0),
- num_non_zero_divergent_filter_fraction_(0) {}
-
-EchoInformation::~EchoInformation() {
- DCHECK(thread_checker_.CalledOnValidThread());
- ReportAndResetAecDivergentFilterStats();
-}
-
-void EchoInformation::UpdateAecStats(
- webrtc::EchoCancellation* echo_cancellation) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- if (!echo_cancellation->is_enabled())
- return;
-
- UpdateAecDelayStats(echo_cancellation);
- UpdateAecDivergentFilterStats(echo_cancellation);
-}
-
-void EchoInformation::UpdateAecDelayStats(
- webrtc::EchoCancellation* echo_cancellation) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- // Only start collecting stats if we know echo cancellation has measured an
- // echo. Otherwise we clutter the stats with for example cases where only the
- // microphone is used.
- if (!echo_frames_received_ & !echo_cancellation->stream_has_echo())
- return;
-
- echo_frames_received_ = true;
-
- // In WebRTC, three echo delay metrics are calculated and updated every
- // five seconds. We use one of them, |fraction_poor_delays| to log in a UMA
- // histogram an Echo Cancellation quality metric. The stat in WebRTC has a
- // fixed aggregation window of five seconds, so we use the same query
- // frequency to avoid logging old values.
- if (!echo_cancellation->is_delay_logging_enabled())
- return;
-
- delay_stats_time_ms_ += webrtc::AudioProcessing::kChunkSizeMs;
- if (delay_stats_time_ms_ <
- 500 * webrtc::AudioProcessing::kChunkSizeMs) { // 5 seconds
- return;
- }
-
- int dummy_median = 0, dummy_std = 0;
- float fraction_poor_delays = 0;
- if (echo_cancellation->GetDelayMetrics(
- &dummy_median, &dummy_std, &fraction_poor_delays) ==
- webrtc::AudioProcessing::kNoError) {
- delay_stats_time_ms_ = 0;
- // Map |fraction_poor_delays| to an Echo Cancellation quality and log in UMA
- // histogram. See DelayBasedEchoQuality for information on histogram
- // buckets.
- UMA_HISTOGRAM_ENUMERATION("WebRTC.AecDelayBasedQuality",
- EchoDelayFrequencyToQuality(fraction_poor_delays),
- DELAY_BASED_ECHO_QUALITY_MAX);
- }
-}
-
-void EchoInformation::UpdateAecDivergentFilterStats(
- webrtc::EchoCancellation* echo_cancellation) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- if (!echo_cancellation->are_metrics_enabled())
- return;
-
- divergent_filter_stats_time_ms_ += webrtc::AudioProcessing::kChunkSizeMs;
- if (divergent_filter_stats_time_ms_ <
- 100 * webrtc::AudioProcessing::kChunkSizeMs) { // 1 second
- return;
- }
-
- webrtc::EchoCancellation::Metrics metrics;
- if (echo_cancellation->GetMetrics(&metrics) ==
- webrtc::AudioProcessing::kNoError) {
- // If not yet calculated, |metrics.divergent_filter_fraction| is -1.0. After
- // being calculated the first time, it is updated periodically.
- if (metrics.divergent_filter_fraction < 0.0f) {
- DCHECK_EQ(num_divergent_filter_fraction_, 0);
- return;
- }
- if (metrics.divergent_filter_fraction > 0.0f) {
- ++num_non_zero_divergent_filter_fraction_;
+media::AudioProcessingSettings
+AudioProcessingProperties::ToAudioProcessingSettings() const {
+ media::AudioProcessingSettings out;
+ auto convert_type =
+ [](EchoCancellationType type) -> media::EchoCancellationType {
+ switch (type) {
+ case EchoCancellationType::kEchoCancellationDisabled:
+ return media::EchoCancellationType::kDisabled;
+ case EchoCancellationType::kEchoCancellationAec2:
+ return media::EchoCancellationType::kAec2;
+ case EchoCancellationType::kEchoCancellationAec3:
+ return media::EchoCancellationType::kAec3;
+ case EchoCancellationType::kEchoCancellationSystem:
+ return media::EchoCancellationType::kSystemAec;
}
- } else {
- DLOG(WARNING) << "Get echo cancellation metrics failed.";
- }
- ++num_divergent_filter_fraction_;
- divergent_filter_stats_time_ms_ = 0;
-}
-
-void EchoInformation::ReportAndResetAecDivergentFilterStats() {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- if (num_divergent_filter_fraction_ == 0)
- return;
-
- int non_zero_percent = 100 * num_non_zero_divergent_filter_fraction_ /
- num_divergent_filter_fraction_;
- UMA_HISTOGRAM_PERCENTAGE("WebRTC.AecFilterHasDivergence", non_zero_percent);
-
- divergent_filter_stats_time_ms_ = 0;
- num_non_zero_divergent_filter_fraction_ = 0;
- num_divergent_filter_fraction_ = 0;
+ };
+
+ out.echo_cancellation = convert_type(echo_cancellation_type);
+ out.noise_suppression =
+ goog_noise_suppression ? (goog_experimental_noise_suppression
+ ? media::NoiseSuppressionType::kExperimental
+ : media::NoiseSuppressionType::kDefault)
+ : media::NoiseSuppressionType::kDisabled;
+ out.automatic_gain_control =
+ goog_auto_gain_control
+ ? (goog_experimental_auto_gain_control
+ ? media::AutomaticGainControlType::kExperimental
+ : media::AutomaticGainControlType::kDefault)
+ : media::AutomaticGainControlType::kDisabled;
+ out.high_pass_filter = goog_highpass_filter;
+ out.typing_detection = goog_typing_noise_detection;
+ return out;
}
void EnableEchoCancellation(AudioProcessing* audio_processing) {
+ // TODO(bugs.webrtc.org/9535): Remove double-booking AEC toggle when the
+ // config applies (from 2018-08-16).
+ webrtc::AudioProcessing::Config apm_config = audio_processing->GetConfig();
+ apm_config.echo_canceller.enabled = true;
#if defined(OS_ANDROID)
// Mobile devices are using AECM.
CHECK_EQ(0, audio_processing->echo_control_mobile()->set_routing_mode(
webrtc::EchoControlMobile::kSpeakerphone));
CHECK_EQ(0, audio_processing->echo_control_mobile()->Enable(true));
- return;
-#endif
+ apm_config.echo_canceller.mobile_mode = true;
+#else
int err = audio_processing->echo_cancellation()->set_suppression_level(
webrtc::EchoCancellation::kHighSuppression);
@@ -217,6 +110,9 @@ void EnableEchoCancellation(AudioProcessing* audio_processing) {
err |= audio_processing->echo_cancellation()->enable_delay_logging(true);
err |= audio_processing->echo_cancellation()->Enable(true);
CHECK_EQ(err, 0);
+ apm_config.echo_canceller.mobile_mode = false;
+#endif
+ audio_processing->ApplyConfig(apm_config);
}
void EnableNoiseSuppression(AudioProcessing* audio_processing,
diff --git a/chromium/content/renderer/media/stream/media_stream_audio_processor_options.h b/chromium/content/renderer/media/stream/media_stream_audio_processor_options.h
index 75dd60a9879..c730fab589e 100644
--- a/chromium/content/renderer/media/stream/media_stream_audio_processor_options.h
+++ b/chromium/content/renderer/media/stream/media_stream_audio_processor_options.h
@@ -13,6 +13,7 @@
#include "base/threading/thread_checker.h"
#include "content/common/content_export.h"
#include "content/public/common/media_stream_request.h"
+#include "media/audio/audio_processing.h"
#include "media/base/audio_point.h"
#include "third_party/blink/public/platform/web_media_constraints.h"
#include "third_party/webrtc/api/mediastreaminterface.h"
@@ -22,7 +23,6 @@
namespace webrtc {
-class EchoCancellation;
class TypingDetection;
}
@@ -60,6 +60,11 @@ struct CONTENT_EXPORT AudioProcessingProperties {
// Returns whether WebRTC-provided echo cancellation is enabled.
bool EchoCancellationIsWebRtcProvided() const;
+ // Converts this struct to an equivalent media::AudioProcessingSettings.
+ // TODO(https://crbug.com/878757): Eliminate this class in favor of the media
+ // one.
+ media::AudioProcessingSettings ToAudioProcessingSettings() const;
+
EchoCancellationType echo_cancellation_type =
EchoCancellationType::kEchoCancellationAec2;
bool disable_hw_noise_suppression = false;
@@ -78,46 +83,6 @@ struct CONTENT_EXPORT AudioProcessingProperties {
bool goog_experimental_auto_gain_control = true;
};
-// A helper class to log echo information in general and Echo Cancellation
-// quality in particular.
-class CONTENT_EXPORT EchoInformation {
- public:
- EchoInformation();
- virtual ~EchoInformation();
-
- // Updates stats, and reports delay metrics as UMA stats every 5 seconds.
- // Must be called every time AudioProcessing::ProcessStream() is called.
- void UpdateAecStats(webrtc::EchoCancellation* echo_cancellation);
-
- // Reports AEC divergent filter metrics as UMA and resets the associated data.
- void ReportAndResetAecDivergentFilterStats();
-
- private:
- void UpdateAecDelayStats(webrtc::EchoCancellation* echo_cancellation);
- void UpdateAecDivergentFilterStats(
- webrtc::EchoCancellation* echo_cancellation);
-
- // Counter to track 5 seconds of data in order to query a new metric from
- // webrtc::EchoCancellation::GetEchoDelayMetrics().
- int delay_stats_time_ms_;
- bool echo_frames_received_;
-
- // Counter to track 1 second of data in order to query a new divergent filter
- // fraction metric from webrtc::EchoCancellation::GetMetrics().
- int divergent_filter_stats_time_ms_;
-
- // Total number of times we queried for the divergent filter fraction metric.
- int num_divergent_filter_fraction_;
-
- // Number of non-zero divergent filter fraction metrics.
- int num_non_zero_divergent_filter_fraction_;
-
- // Ensures that this class is accessed on the same thread.
- base::ThreadChecker thread_checker_;
-
- DISALLOW_COPY_AND_ASSIGN(EchoInformation);
-};
-
// Enables the echo cancellation in |audio_processing|.
void EnableEchoCancellation(AudioProcessing* audio_processing);
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 faf854cacbb..ac494175f9c 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
@@ -710,8 +710,8 @@ SelectSettingsAudioCapture(MediaStreamAudioSource* source,
const blink::WebMediaConstraints& constraints) {
DCHECK(source);
if (source->device().type != MEDIA_DEVICE_AUDIO_CAPTURE &&
- source->device().type != MEDIA_TAB_AUDIO_CAPTURE &&
- source->device().type != MEDIA_DESKTOP_AUDIO_CAPTURE) {
+ source->device().type != MEDIA_GUM_TAB_AUDIO_CAPTURE &&
+ source->device().type != MEDIA_GUM_DESKTOP_AUDIO_CAPTURE) {
return AudioCaptureSettings();
}
@@ -722,13 +722,13 @@ SelectSettingsAudioCapture(MediaStreamAudioSource* source,
constraints.Basic().media_stream_source.GetName());
}
- if (source->device().type == MEDIA_TAB_AUDIO_CAPTURE &&
+ if (source->device().type == MEDIA_GUM_TAB_AUDIO_CAPTURE &&
!media_stream_source.empty() &&
media_stream_source != kMediaStreamSourceTab) {
return AudioCaptureSettings(
constraints.Basic().media_stream_source.GetName());
}
- if (source->device().type == MEDIA_DESKTOP_AUDIO_CAPTURE &&
+ if (source->device().type == MEDIA_GUM_DESKTOP_AUDIO_CAPTURE &&
!media_stream_source.empty() &&
media_stream_source != kMediaStreamSourceSystem &&
media_stream_source != kMediaStreamSourceDesktop) {
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 2977c75f436..bce1de0a82c 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
@@ -10,7 +10,6 @@
#include <utility>
#include "base/message_loop/message_loop.h"
-#include "content/common/media/media_stream_controls.h"
#include "content/renderer/media/stream/local_media_stream_audio_source.h"
#include "content/renderer/media/stream/media_stream_audio_source.h"
#include "content/renderer/media/stream/media_stream_source.h"
@@ -137,8 +136,8 @@ class MediaStreamConstraintsUtilAudioTest
if (media_source.empty())
return MEDIA_DEVICE_AUDIO_CAPTURE;
else if (media_source == kMediaStreamSourceTab)
- return MEDIA_TAB_AUDIO_CAPTURE;
- return MEDIA_DESKTOP_AUDIO_CAPTURE;
+ return MEDIA_GUM_TAB_AUDIO_CAPTURE;
+ return MEDIA_GUM_DESKTOP_AUDIO_CAPTURE;
}
std::unique_ptr<ProcessedLocalAudioSource> GetProcessedLocalAudioSource(
@@ -492,12 +491,10 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, Unconstrained) {
// echo cancellation constraints, which are not mapped 1:1 to output audio
// processing properties).
TEST_P(MediaStreamConstraintsUtilAudioTest, SingleBoolConstraint) {
- // TODO(crbug.com/736309): Use braced initialization instead of push_back once
- // clang has been fixed.
- AudioSettingsBoolMembers kMainSettings;
- kMainSettings.push_back(&AudioCaptureSettings::hotword_enabled);
- kMainSettings.push_back(&AudioCaptureSettings::disable_local_echo);
- kMainSettings.push_back(&AudioCaptureSettings::render_to_associated_sink);
+ AudioSettingsBoolMembers kMainSettings = {
+ &AudioCaptureSettings::hotword_enabled,
+ &AudioCaptureSettings::disable_local_echo,
+ &AudioCaptureSettings::render_to_associated_sink};
const std::vector<
blink::BooleanConstraint blink::WebMediaTrackConstraintSet::*>
diff --git a/chromium/content/renderer/media/stream/media_stream_constraints_util_sets_unittest.cc b/chromium/content/renderer/media/stream/media_stream_constraints_util_sets_unittest.cc
index 62f74c126cb..cd8eb4a8e2f 100644
--- a/chromium/content/renderer/media/stream/media_stream_constraints_util_sets_unittest.cc
+++ b/chromium/content/renderer/media/stream/media_stream_constraints_util_sets_unittest.cc
@@ -792,7 +792,7 @@ TEST_F(MediaStreamConstraintsUtilSetsTest,
// Ideal height.
{
factory_.Reset();
- factory_.basic().height.SetIdeal(std::numeric_limits<long>::max());
+ factory_.basic().height.SetIdeal(std::numeric_limits<int32_t>::max());
Point point = SelectClosestPointToIdeal(set);
EXPECT_POINT_EQ(
Point(ResolutionSet::kMaxDimension, ResolutionSet::kMaxDimension),
@@ -805,7 +805,7 @@ TEST_F(MediaStreamConstraintsUtilSetsTest,
// Ideal width.
{
factory_.Reset();
- factory_.basic().width.SetIdeal(std::numeric_limits<long>::max());
+ factory_.basic().width.SetIdeal(std::numeric_limits<int32_t>::max());
Point point = SelectClosestPointToIdeal(set);
EXPECT_POINT_EQ(Point(ResolutionSet::kMaxDimension / kDefaultAspectRatio,
ResolutionSet::kMaxDimension),
diff --git a/chromium/content/renderer/media/stream/media_stream_constraints_util_video_content.cc b/chromium/content/renderer/media/stream/media_stream_constraints_util_video_content.cc
index 7fa6b1f9c08..273a64b3f12 100644
--- a/chromium/content/renderer/media/stream/media_stream_constraints_util_video_content.cc
+++ b/chromium/content/renderer/media/stream/media_stream_constraints_util_video_content.cc
@@ -260,7 +260,7 @@ int ClampToValidScreenCastDimension(int value) {
VideoCaptureSettings SelectResultFromCandidates(
const VideoContentCaptureCandidates& candidates,
const blink::WebMediaTrackConstraintSet& basic_constraint_set,
- const std::string& stream_source,
+ MediaStreamType stream_type,
int screen_width,
int screen_height) {
std::string device_id = SelectDeviceIDFromCandidates(
@@ -300,7 +300,7 @@ VideoCaptureSettings SelectResultFromCandidates(
// This default comes from the old algorithm.
media::ResolutionChangePolicy default_resolution_policy =
- stream_source == kMediaStreamSourceTab
+ stream_type == MEDIA_GUM_TAB_VIDEO_CAPTURE
? media::ResolutionChangePolicy::FIXED_RESOLUTION
: media::ResolutionChangePolicy::ANY_WITHIN_LIMIT;
@@ -346,7 +346,7 @@ VideoCaptureSettings UnsatisfiedConstraintsResult(
VideoCaptureSettings SelectSettingsVideoContentCapture(
const blink::WebMediaConstraints& constraints,
- const std::string& stream_source,
+ MediaStreamType stream_type,
int screen_width,
int screen_height) {
VideoContentCaptureCandidates candidates;
@@ -367,7 +367,7 @@ VideoCaptureSettings SelectSettingsVideoContentCapture(
DCHECK(!candidates.IsEmpty());
return SelectResultFromCandidates(candidates, constraints.Basic(),
- stream_source, screen_width, screen_height);
+ stream_type, screen_width, screen_height);
}
} // namespace content
diff --git a/chromium/content/renderer/media/stream/media_stream_constraints_util_video_content.h b/chromium/content/renderer/media/stream/media_stream_constraints_util_video_content.h
index cbc9db71fb4..f46927cc000 100644
--- a/chromium/content/renderer/media/stream/media_stream_constraints_util_video_content.h
+++ b/chromium/content/renderer/media/stream/media_stream_constraints_util_video_content.h
@@ -8,6 +8,7 @@
#include <string>
#include "content/common/content_export.h"
+#include "content/public/common/media_stream_request.h"
#include "content/renderer/media/stream/media_stream_constraints_util.h"
namespace blink {
@@ -28,7 +29,7 @@ CONTENT_EXPORT extern const double kDefaultScreenCastFrameRate;
// for content video capture based on the given |constraints|.
VideoCaptureSettings CONTENT_EXPORT
SelectSettingsVideoContentCapture(const blink::WebMediaConstraints& constraints,
- const std::string& stream_source,
+ MediaStreamType stream_type,
int screen_width,
int screen_height);
diff --git a/chromium/content/renderer/media/stream/media_stream_constraints_util_video_content_unittest.cc b/chromium/content/renderer/media/stream/media_stream_constraints_util_video_content_unittest.cc
index b8c888f6c13..7fcd5e8c8be 100644
--- a/chromium/content/renderer/media/stream/media_stream_constraints_util_video_content_unittest.cc
+++ b/chromium/content/renderer/media/stream/media_stream_constraints_util_video_content_unittest.cc
@@ -7,7 +7,7 @@
#include <cmath>
#include <string>
-#include "content/common/media/media_stream_controls.h"
+#include "content/renderer/media/stream/media_stream_source.h"
#include "content/renderer/media/stream/mock_constraint_factory.h"
#include "media/base/limits.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -60,11 +60,10 @@ void CheckTrackAdapterSettingsEqualsFormatDefaultAspectRatio(
class MediaStreamConstraintsUtilVideoContentTest : public testing::Test {
protected:
VideoCaptureSettings SelectSettings(
- const std::string& stream_source =
- std::string(kMediaStreamSourceScreen)) {
+ MediaStreamType stream_type = MEDIA_GUM_DESKTOP_VIDEO_CAPTURE) {
blink::WebMediaConstraints constraints =
constraint_factory_.CreateWebMediaConstraints();
- return SelectSettingsVideoContentCapture(constraints, stream_source,
+ return SelectSettingsVideoContentCapture(constraints, stream_type,
kDefaultScreenCastWidth,
kDefaultScreenCastHeight);
}
@@ -2035,7 +2034,7 @@ TEST_F(MediaStreamConstraintsUtilVideoContentTest, ResolutionChangePolicy) {
}
{
constraint_factory_.Reset();
- auto result = SelectSettings(kMediaStreamSourceTab);
+ auto result = SelectSettings(MEDIA_GUM_TAB_VIDEO_CAPTURE);
EXPECT_EQ(kDefaultScreenCastWidth, result.Width());
EXPECT_EQ(kDefaultScreenCastHeight, result.Height());
// Default policy for tab capture is fixed resolution.
diff --git a/chromium/content/renderer/media/stream/media_stream_constraints_util_video_device.cc b/chromium/content/renderer/media/stream/media_stream_constraints_util_video_device.cc
index 66c6cabdd42..0062de4435e 100644
--- a/chromium/content/renderer/media/stream/media_stream_constraints_util_video_device.cc
+++ b/chromium/content/renderer/media/stream/media_stream_constraints_util_video_device.cc
@@ -204,19 +204,19 @@ void GetSourceAspectRatioRange(const ConstrainedFormat& constrained_format,
const blink::LongConstraint& width_constraint,
double* min_source_aspect_ratio,
double* max_source_aspect_ratio) {
- long min_height = constrained_format.MinHeight();
+ int32_t min_height = constrained_format.MinHeight();
if (ConstraintHasMin(height_constraint))
min_height = std::max(min_height, ConstraintMin(height_constraint));
- long max_height = constrained_format.MaxHeight();
+ int32_t max_height = constrained_format.MaxHeight();
if (ConstraintHasMax(height_constraint))
max_height = std::min(max_height, ConstraintMax(height_constraint));
- long min_width = constrained_format.MinWidth();
+ int32_t min_width = constrained_format.MinWidth();
if (ConstraintHasMin(width_constraint))
min_width = std::max(min_width, ConstraintMin(width_constraint));
- long max_width = constrained_format.MaxWidth();
+ int32_t max_width = constrained_format.MaxWidth();
if (ConstraintHasMax(width_constraint))
max_width = std::min(max_width, ConstraintMax(width_constraint));
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 c8b571ee6df..80a3e5df962 100644
--- a/chromium/content/renderer/media/stream/media_stream_device_observer.cc
+++ b/chromium/content/renderer/media/stream/media_stream_device_observer.cc
@@ -133,7 +133,7 @@ void MediaStreamDeviceObserver::AddStream(const std::string& label,
Stream stream;
if (IsAudioInputMediaType(device.type))
stream.audio_devices.push_back(device);
- else if (IsVideoMediaType(device.type))
+ else if (IsVideoInputMediaType(device.type))
stream.video_devices.push_back(device);
else
NOTREACHED();
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 f0bbab260c4..e96bef4a410 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
@@ -60,7 +60,7 @@ TEST_F(MediaStreamDeviceObserverTest, GetNonScreenCaptureDevices) {
// OpenDevice request 2
base::RunLoop run_loop2;
mock_dispatcher_host_.OpenDevice(
- kRequestId2, "screen_capture", MEDIA_DESKTOP_VIDEO_CAPTURE,
+ kRequestId2, "screen_capture", MEDIA_GUM_DESKTOP_VIDEO_CAPTURE,
base::BindOnce(&MediaStreamDeviceObserverTest::OnDeviceOpened,
base::Unretained(this), run_loop2.QuitClosure()));
run_loop2.Run();
diff --git a/chromium/content/renderer/media/stream/media_stream_source.cc b/chromium/content/renderer/media/stream/media_stream_source.cc
index 3a795023c2a..419a0f73c77 100644
--- a/chromium/content/renderer/media/stream/media_stream_source.cc
+++ b/chromium/content/renderer/media/stream/media_stream_source.cc
@@ -9,6 +9,11 @@
namespace content {
+const char kMediaStreamSourceTab[] = "tab";
+const char kMediaStreamSourceScreen[] = "screen";
+const char kMediaStreamSourceDesktop[] = "desktop";
+const char kMediaStreamSourceSystem[] = "system";
+
const char MediaStreamSource::kSourceId[] = "sourceId";
MediaStreamSource::MediaStreamSource() {
diff --git a/chromium/content/renderer/media/stream/media_stream_source.h b/chromium/content/renderer/media/stream/media_stream_source.h
index ca0796068d8..92479abd057 100644
--- a/chromium/content/renderer/media/stream/media_stream_source.h
+++ b/chromium/content/renderer/media/stream/media_stream_source.h
@@ -14,6 +14,13 @@
namespace content {
+// Names for media stream source capture types.
+// These are values set via the "chromeMediaSource" constraint.
+CONTENT_EXPORT extern const char kMediaStreamSourceTab[];
+CONTENT_EXPORT extern const char kMediaStreamSourceScreen[]; /* video only */
+CONTENT_EXPORT extern const char kMediaStreamSourceDesktop[];
+CONTENT_EXPORT extern const char kMediaStreamSourceSystem[]; /* audio only */
+
class CONTENT_EXPORT MediaStreamSource
: public blink::WebMediaStreamSource::ExtraData {
public:
diff --git a/chromium/content/renderer/media/stream/media_stream_video_track.h b/chromium/content/renderer/media/stream/media_stream_video_track.h
index 09bc143c180..c46e29baf08 100644
--- a/chromium/content/renderer/media/stream/media_stream_video_track.h
+++ b/chromium/content/renderer/media/stream/media_stream_video_track.h
@@ -114,6 +114,8 @@ class CONTENT_EXPORT MediaStreamVideoTrack : public MediaStreamTrack {
friend class MediaStreamVideoSink;
FRIEND_TEST_ALL_PREFIXES(MediaStreamRemoteVideoSourceTest, StartTrack);
FRIEND_TEST_ALL_PREFIXES(MediaStreamRemoteVideoSourceTest, RemoteTrackStop);
+ FRIEND_TEST_ALL_PREFIXES(MediaStreamRemoteVideoSourceTest,
+ PreservesColorSpace);
FRIEND_TEST_ALL_PREFIXES(PepperToVideoTrackAdapterTest, PutFrame);
// Add |sink| to receive state changes on the main render thread and video
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 1f4094f216d..7b6cfe95d94 100644
--- a/chromium/content/renderer/media/stream/processed_local_audio_source.cc
+++ b/chromium/content/renderer/media/stream/processed_local_audio_source.cc
@@ -10,6 +10,8 @@
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/stringprintf.h"
+#include "build/build_config.h"
+#include "content/public/common/content_features.h"
#include "content/renderer/media/audio/audio_device_factory.h"
#include "content/renderer/media/stream/media_stream_audio_processor_options.h"
#include "content/renderer/media/stream/media_stream_constraints_util.h"
@@ -19,6 +21,7 @@
#include "content/renderer/render_frame_impl.h"
#include "media/base/channel_layout.h"
#include "media/base/sample_rates.h"
+#include "media/webrtc/webrtc_switches.h"
#include "third_party/webrtc/api/mediaconstraintsinterface.h"
#include "third_party/webrtc/media/base/mediachannel.h"
@@ -30,6 +33,14 @@ namespace {
// Used as an identifier for ProcessedLocalAudioSource::From().
void* const kProcessedLocalAudioSourceIdentifier =
const_cast<void**>(&kProcessedLocalAudioSourceIdentifier);
+
+bool ApmInAudioServiceEnabled() {
+#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
+ return base::FeatureList::IsEnabled(features::kWebRtcApmInAudioService);
+#else
+ return false;
+#endif
+}
} // namespace
ProcessedLocalAudioSource::ProcessedLocalAudioSource(
@@ -138,12 +149,11 @@ bool ProcessedLocalAudioSource::EnsureSourceIsStarted() {
WebRtcAudioDeviceImpl* const rtc_audio_device =
pc_factory_->GetWebRtcAudioDevice();
if (!rtc_audio_device) {
- WebRtcLogMessage("ProcessedLocalAudioSource::EnsureSourceIsStarted() fails "
- " because there is no WebRtcAudioDeviceImpl instance.");
+ WebRtcLogMessage(
+ "ProcessedLocalAudioSource::EnsureSourceIsStarted() fails"
+ " because there is no WebRtcAudioDeviceImpl instance.");
return false;
}
- audio_processor_ = new rtc::RefCountedObject<MediaStreamAudioProcessor>(
- audio_processing_properties_, rtc_audio_device);
// If KEYBOARD_MIC effect is set, change the layout to the corresponding
// layout that includes the keyboard mic.
@@ -191,20 +201,38 @@ bool ProcessedLocalAudioSource::EnsureSourceIsStarted() {
// ProcessedLocalAudioSource to the processor's output format.
media::AudioParameters params(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
channel_layout, device().input.sample_rate(),
- GetBufferSize(device().input.sample_rate()));
+ device().input.sample_rate() / 100);
params.set_effects(device().input.effects());
DCHECK(params.IsValid());
- audio_processor_->OnCaptureFormatChanged(params);
- SetFormat(audio_processor_->OutputFormat());
+ media::AudioSourceParameters source_params(device().session_id);
+ const bool use_remote_apm =
+ ApmInAudioServiceEnabled() &&
+ MediaStreamAudioProcessor::WouldModifyAudio(audio_processing_properties_);
+ if (use_remote_apm) {
+ audio_processor_proxy_ =
+ new rtc::RefCountedObject<AudioServiceAudioProcessorProxy>(
+ GetTaskRunner());
+ SetFormat(params);
+ // Add processing to the source.
+ source_params.processing = media::AudioSourceParameters::ProcessingConfig(
+ rtc_audio_device->GetAudioProcessingId(),
+ audio_processing_properties_.ToAudioProcessingSettings());
+ } else {
+ audio_processor_ = new rtc::RefCountedObject<MediaStreamAudioProcessor>(
+ audio_processing_properties_, rtc_audio_device);
+ params.set_frames_per_buffer(GetBufferSize(device().input.sample_rate()));
+ audio_processor_->OnCaptureFormatChanged(params);
+ SetFormat(audio_processor_->OutputFormat());
+ }
// Start the source.
- VLOG(1) << "Starting WebRTC audio source for consumption by render frame "
- << consumer_render_frame_id_ << " with input parameters={"
- << params.AsHumanReadableString() << "} and output parameters={"
- << GetAudioParameters().AsHumanReadableString() << '}';
+ DVLOG(1) << "Starting WebRTC audio source for consumption by render frame "
+ << consumer_render_frame_id_ << " with input parameters={"
+ << params.AsHumanReadableString() << "} and output parameters={"
+ << GetAudioParameters().AsHumanReadableString() << '}';
scoped_refptr<media::AudioCapturerSource> new_source =
AudioDeviceFactory::NewAudioCapturerSource(consumer_render_frame_id_,
- device().session_id);
+ source_params);
new_source->Initialize(params, this);
// We need to set the AGC control before starting the stream.
new_source->SetAutomaticGainControl(true);
@@ -233,10 +261,16 @@ void ProcessedLocalAudioSource::EnsureSourceIsStopped() {
source_to_stop->Stop();
// Stop the audio processor to avoid feeding render data into the processor.
- audio_processor_->Stop();
+ if (audio_processor_)
+ audio_processor_->Stop();
- VLOG(1) << "Stopped WebRTC audio pipeline for consumption by render frame "
- << consumer_render_frame_id_ << '.';
+ // Stop the proxy, if we have one, so as to detach from the processor
+ // controls.
+ if (audio_processor_proxy_)
+ audio_processor_proxy_->Stop();
+
+ DVLOG(1) << "Stopped WebRTC audio pipeline for consumption by render frame "
+ << consumer_render_frame_id_ << '.';
}
void ProcessedLocalAudioSource::SetVolume(int volume) {
@@ -265,6 +299,46 @@ void ProcessedLocalAudioSource::Capture(const media::AudioBus* audio_bus,
int audio_delay_milliseconds,
double volume,
bool key_pressed) {
+ if (audio_processor_) {
+ // The data must be processed here.
+ CaptureUsingProcessor(audio_bus, audio_delay_milliseconds, volume,
+ key_pressed);
+ } else {
+ // The audio is already processed in the audio service, just send it along.
+ level_calculator_.Calculate(*audio_bus, false);
+ DeliverDataToTracks(
+ *audio_bus, base::TimeTicks::Now() - base::TimeDelta::FromMilliseconds(
+ audio_delay_milliseconds));
+ }
+}
+
+void ProcessedLocalAudioSource::OnCaptureError(const std::string& message) {
+ WebRtcLogMessage("ProcessedLocalAudioSource::OnCaptureError: " + message);
+ StopSourceOnError(message);
+}
+
+void ProcessedLocalAudioSource::OnCaptureMuted(bool is_muted) {
+ SetMutedState(is_muted);
+}
+
+void ProcessedLocalAudioSource::OnCaptureProcessorCreated(
+ media::AudioProcessorControls* controls) {
+ DCHECK(audio_processor_proxy_);
+ audio_processor_proxy_->SetControls(controls);
+}
+
+void ProcessedLocalAudioSource::SetOutputDeviceForAec(
+ const std::string& output_device_id) {
+ DVLOG(1) << "ProcessedLocalAudioSource::SetOutputDeviceForAec()";
+ if (source_)
+ source_->SetOutputDeviceForAec(output_device_id);
+}
+
+void ProcessedLocalAudioSource::CaptureUsingProcessor(
+ const media::AudioBus* audio_bus,
+ int audio_delay_milliseconds,
+ double volume,
+ bool key_pressed) {
#if defined(OS_WIN) || defined(OS_MACOSX)
DCHECK_LE(volume, 1.0);
#elif (defined(OS_LINUX) && !defined(OS_CHROMEOS)) || defined(OS_OPENBSD)
@@ -339,27 +413,6 @@ void ProcessedLocalAudioSource::Capture(const media::AudioBus* audio_bus,
}
}
-void ProcessedLocalAudioSource::OnCaptureError(const std::string& message) {
- WebRtcLogMessage("ProcessedLocalAudioSource::OnCaptureError: " + message);
- StopSourceOnError(message);
-}
-
-void ProcessedLocalAudioSource::OnCaptureMuted(bool is_muted) {
- SetMutedState(is_muted);
-}
-
-media::AudioParameters ProcessedLocalAudioSource::GetInputFormat() const {
- return audio_processor_ ? audio_processor_->InputFormat()
- : media::AudioParameters();
-}
-
-void ProcessedLocalAudioSource::SetOutputDeviceForAec(
- const std::string& output_device_id) {
- DVLOG(1) << "ProcessedLocalAudioSource::SetOutputDeviceForAec()";
- if (source_)
- source_->SetOutputDeviceForAec(output_device_id);
-}
-
int ProcessedLocalAudioSource::GetBufferSize(int sample_rate) const {
DCHECK(GetTaskRunner()->BelongsToCurrentThread());
#if defined(OS_ANDROID)
@@ -369,7 +422,7 @@ int ProcessedLocalAudioSource::GetBufferSize(int sample_rate) const {
#endif
// If audio processing is turned on, require 10ms buffers.
- if (audio_processor_->has_audio_processing())
+ if (audio_processor_->has_audio_processing() || audio_processor_proxy_)
return (sample_rate / 100);
// If audio processing is off and the native hardware buffer size was
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 bb62af4dd71..5876c69c1a9 100644
--- a/chromium/content/renderer/media/stream/processed_local_audio_source.h
+++ b/chromium/content/renderer/media/stream/processed_local_audio_source.h
@@ -11,10 +11,12 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/synchronization/lock.h"
+#include "content/renderer/media/stream/audio_service_audio_processor_proxy.h"
#include "content/renderer/media/stream/media_stream_audio_level_calculator.h"
#include "content/renderer/media/stream/media_stream_audio_processor.h"
#include "content/renderer/media/stream/media_stream_audio_source.h"
#include "media/base/audio_capturer_source.h"
+#include "media/webrtc/audio_processor_controls.h"
#include "third_party/blink/public/platform/web_media_constraints.h"
namespace media {
@@ -63,11 +65,22 @@ class CONTENT_EXPORT ProcessedLocalAudioSource final
return audio_processing_properties_;
}
- // The following accessors are not valid until after the source is started
- // (when the first track is connected).
- const scoped_refptr<MediaStreamAudioProcessor>& audio_processor() const {
- return audio_processor_;
+ // The following accessors are valid after the source is started (when the
+ // first track is connected).
+ scoped_refptr<AudioProcessorInterface> audio_processor() const {
+ DCHECK(audio_processor_ || audio_processor_proxy_);
+ return audio_processor_
+ ? static_cast<scoped_refptr<AudioProcessorInterface>>(
+ audio_processor_)
+ : static_cast<scoped_refptr<AudioProcessorInterface>>(
+ audio_processor_proxy_);
}
+
+ bool has_audio_processing() const {
+ return audio_processor_proxy_ ||
+ (audio_processor_ && audio_processor_->has_audio_processing());
+ }
+
const scoped_refptr<MediaStreamAudioLevelCalculator::Level>& audio_level()
const {
return level_calculator_.level();
@@ -78,11 +91,6 @@ class CONTENT_EXPORT ProcessedLocalAudioSource final
int Volume() const;
int MaxVolume() const;
- // Audio parameters utilized by the source of the audio capturer.
- // TODO(phoglund): Think over the implications of this accessor and if we can
- // remove it.
- media::AudioParameters GetInputFormat() const;
-
void SetOutputDeviceForAec(const std::string& output_device_id);
protected:
@@ -100,8 +108,16 @@ class CONTENT_EXPORT ProcessedLocalAudioSource final
bool key_pressed) override;
void OnCaptureError(const std::string& message) override;
void OnCaptureMuted(bool is_muted) override;
+ void OnCaptureProcessorCreated(
+ media::AudioProcessorControls* controls) override;
private:
+ // Runs the audio through |audio_processor_| before sending it along.
+ void CaptureUsingProcessor(const media::AudioBus* audio_source,
+ int audio_delay_milliseconds,
+ double volume,
+ bool key_pressed);
+
// Helper function to get the source buffer size based on whether audio
// processing will take place.
int GetBufferSize(int sample_rate) const;
@@ -117,10 +133,15 @@ class CONTENT_EXPORT ProcessedLocalAudioSource final
// Callback that's called when the audio source has been initialized.
ConstraintsCallback started_callback_;
+ // At most one of |audio_processor_| and |audio_processor_proxy_| can be set.
+
// Audio processor doing processing like FIFO, AGC, AEC and NS. Its output
// data is in a unit of 10 ms data chunk.
scoped_refptr<MediaStreamAudioProcessor> audio_processor_;
+ // Proxy for the audio processor when it's run in the Audio Service process,
+ scoped_refptr<AudioServiceAudioProcessorProxy> audio_processor_proxy_;
+
// The device created by the AudioDeviceFactory in EnsureSourceIsStarted().
scoped_refptr<media::AudioCapturerSource> source_;
diff --git a/chromium/content/renderer/media/stream/track_audio_renderer.cc b/chromium/content/renderer/media/stream/track_audio_renderer.cc
index bcedaf56920..892a3108412 100644
--- a/chromium/content/renderer/media/stream/track_audio_renderer.cc
+++ b/chromium/content/renderer/media/stream/track_audio_renderer.cc
@@ -151,7 +151,7 @@ void TrackAudioRenderer::Start() {
DCHECK(!sink_);
sink_ = AudioDeviceFactory::NewAudioRendererSink(
AudioDeviceFactory::kSourceNonRtcAudioTrack, playout_render_frame_id_,
- session_id_, output_device_id_);
+ {session_id_, output_device_id_});
base::AutoLock auto_lock(thread_lock_);
prior_elapsed_render_time_ = base::TimeDelta();
@@ -253,7 +253,7 @@ void TrackAudioRenderer::SwitchOutputDevice(
scoped_refptr<media::AudioRendererSink> new_sink =
AudioDeviceFactory::NewAudioRendererSink(
AudioDeviceFactory::kSourceNonRtcAudioTrack, playout_render_frame_id_,
- session_id_, device_id);
+ {session_id_, device_id});
media::OutputDeviceStatus new_sink_status =
new_sink->GetOutputDeviceInfo().device_status();
@@ -344,7 +344,7 @@ void TrackAudioRenderer::ReconfigureSink(const media::AudioParameters& params) {
sink_started_ = false;
sink_ = AudioDeviceFactory::NewAudioRendererSink(
AudioDeviceFactory::kSourceNonRtcAudioTrack, playout_render_frame_id_,
- session_id_, output_device_id_);
+ {session_id_, output_device_id_});
MaybeStartSink();
}
diff --git a/chromium/content/renderer/media/stream/user_media_client_impl.cc b/chromium/content/renderer/media/stream/user_media_client_impl.cc
index bee0a486739..56cc10384ac 100644
--- a/chromium/content/renderer/media/stream/user_media_client_impl.cc
+++ b/chromium/content/renderer/media/stream/user_media_client_impl.cc
@@ -33,6 +33,21 @@ namespace {
static int g_next_request_id = 0;
+// The histogram counts the number of calls to the JS API
+// getUserMedia or getDisplayMedia().
+void UpdateAPICount(blink::WebUserMediaRequest::MediaType media_type) {
+ blink::WebRTCAPIName api_name = blink::WebRTCAPIName::kGetUserMedia;
+ switch (media_type) {
+ case blink::WebUserMediaRequest::MediaType::kUserMedia:
+ api_name = blink::WebRTCAPIName::kGetUserMedia;
+ break;
+ case blink::WebUserMediaRequest::MediaType::kDisplayMedia:
+ api_name = blink::WebRTCAPIName::kGetDisplayMedia;
+ break;
+ }
+ UpdateWebRTCMethodCount(api_name);
+}
+
} // namespace
UserMediaClientImpl::Request::Request(std::unique_ptr<UserMediaRequest> request)
@@ -124,10 +139,6 @@ UserMediaClientImpl::~UserMediaClientImpl() {
void UserMediaClientImpl::RequestUserMedia(
const blink::WebUserMediaRequest& web_request) {
- // Save histogram data so we can see how much GetUserMedia is used.
- // The histogram counts the number of calls to the JS API
- // webGetUserMedia.
- UpdateWebRTCMethodCount(blink::WebRTCAPIName::kGetUserMedia);
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!web_request.IsNull());
DCHECK(web_request.Audio() || web_request.Video());
@@ -138,6 +149,9 @@ void UserMediaClientImpl::RequestUserMedia(
static_cast<blink::WebFrame*>(
web_request.OwnerDocument().GetFrame()));
+ // Save histogram data so we can see how much GetUserMedia is used.
+ UpdateAPICount(web_request.MediaRequestType());
+
if (RenderThreadImpl::current()) {
RenderThreadImpl::current()->peer_connection_tracker()->TrackGetUserMedia(
web_request);
@@ -167,7 +181,7 @@ void UserMediaClientImpl::RequestUserMedia(
void UserMediaClientImpl::ApplyConstraints(
const blink::WebApplyConstraintsRequest& web_request) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- // TODO(guidou): Implement applyConstraints(). http://crbug.com/338503
+
pending_request_infos_.push_back(Request(web_request));
if (!is_processing_request_)
MaybeProcessNextRequestInfo();
diff --git a/chromium/content/renderer/media/stream/user_media_processor.cc b/chromium/content/renderer/media/stream/user_media_processor.cc
index bd5929a359b..150e73cdbbb 100644
--- a/chromium/content/renderer/media/stream/user_media_processor.cc
+++ b/chromium/content/renderer/media/stream/user_media_processor.cc
@@ -18,6 +18,7 @@
#include "base/task_runner_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/common/media/media_stream_controls.h"
+#include "content/public/common/media_stream_request.h"
#include "content/renderer/media/stream/local_media_stream_audio_source.h"
#include "content/renderer/media/stream/media_stream_audio_processor.h"
#include "content/renderer/media/stream/media_stream_audio_source.h"
@@ -53,22 +54,65 @@ using EchoCancellationType = AudioProcessingProperties::EchoCancellationType;
namespace {
-void CopyFirstString(const blink::StringConstraint& constraint,
- std::string* destination) {
- if (!constraint.Exact().IsEmpty())
- *destination = constraint.Exact()[0].Utf8();
-}
+void InitializeAudioTrackControls(const blink::WebUserMediaRequest& web_request,
+ TrackControls* track_controls) {
+ const blink::WebMediaConstraints& constraints =
+ web_request.AudioConstraints();
+ DCHECK(!constraints.IsNull());
+ track_controls->requested = true;
-bool IsDeviceSource(const std::string& source) {
- return source.empty();
+ MediaStreamType* stream_type = &track_controls->stream_type;
+ *stream_type = MEDIA_NO_SERVICE;
+
+ std::string source_constraint =
+ constraints.Basic().media_stream_source.Exact().IsEmpty()
+ ? std::string()
+ : constraints.Basic().media_stream_source.Exact()[0].Utf8();
+ if (!source_constraint.empty()) {
+ if (source_constraint == kMediaStreamSourceTab) {
+ *stream_type = MEDIA_GUM_TAB_AUDIO_CAPTURE;
+ } else if (source_constraint == kMediaStreamSourceDesktop ||
+ source_constraint == kMediaStreamSourceSystem) {
+ *stream_type = MEDIA_GUM_DESKTOP_AUDIO_CAPTURE;
+ }
+ } else {
+ *stream_type = MEDIA_DEVICE_AUDIO_CAPTURE;
+ }
}
-void InitializeTrackControls(const blink::WebMediaConstraints& constraints,
- TrackControls* track_controls) {
+void InitializeVideoTrackControls(const blink::WebUserMediaRequest& web_request,
+ TrackControls* track_controls) {
+ if (web_request.MediaRequestType() ==
+ blink::WebUserMediaRequest::MediaType::kDisplayMedia) {
+ track_controls->requested = true;
+ track_controls->stream_type = MEDIA_DISPLAY_VIDEO_CAPTURE;
+ return;
+ }
+
+ DCHECK_EQ(blink::WebUserMediaRequest::MediaType::kUserMedia,
+ web_request.MediaRequestType());
+ const blink::WebMediaConstraints& constraints =
+ web_request.VideoConstraints();
DCHECK(!constraints.IsNull());
track_controls->requested = true;
- CopyFirstString(constraints.Basic().media_stream_source,
- &track_controls->stream_source);
+
+ MediaStreamType* stream_type = &track_controls->stream_type;
+ *stream_type = MEDIA_NO_SERVICE;
+
+ std::string source_constraint =
+ constraints.Basic().media_stream_source.Exact().IsEmpty()
+ ? std::string()
+ : constraints.Basic().media_stream_source.Exact()[0].Utf8();
+ if (!source_constraint.empty()) {
+ if (source_constraint == kMediaStreamSourceTab) {
+ *stream_type = MEDIA_GUM_TAB_VIDEO_CAPTURE;
+ } else if (source_constraint == kMediaStreamSourceDesktop ||
+ source_constraint == kMediaStreamSourceScreen) {
+ *stream_type = MEDIA_GUM_DESKTOP_VIDEO_CAPTURE;
+ }
+ } else {
+ *stream_type = MEDIA_DEVICE_VIDEO_CAPTURE;
+ }
}
bool IsSameDevice(const MediaStreamDevice& device,
@@ -90,18 +134,6 @@ bool IsSameSource(const blink::WebMediaStreamSource& source,
return IsSameDevice(device, other_device);
}
-bool IsValidAudioContentSource(const std::string& source) {
- return source == kMediaStreamSourceTab ||
- source == kMediaStreamSourceDesktop ||
- source == kMediaStreamSourceSystem;
-}
-
-bool IsValidVideoContentSource(const std::string& source) {
- return source == kMediaStreamSourceTab ||
- source == kMediaStreamSourceDesktop ||
- source == kMediaStreamSourceScreen;
-}
-
void SurfaceAudioProcessingSettings(blink::WebMediaStreamSource* source) {
MediaStreamAudioSource* source_impl =
static_cast<MediaStreamAudioSource*>(source->GetExtraData());
@@ -432,14 +464,14 @@ void UserMediaProcessor::SetupAudioInput() {
DCHECK(current_request_info_->web_request().Audio());
auto& audio_controls = current_request_info_->stream_controls()->audio;
- InitializeTrackControls(
- current_request_info_->web_request().AudioConstraints(), &audio_controls);
- if (IsDeviceSource(audio_controls.stream_source)) {
+ InitializeAudioTrackControls(current_request_info_->web_request(),
+ &audio_controls);
+ if (IsDeviceMediaType(audio_controls.stream_type)) {
GetMediaDevicesDispatcher()->GetAudioInputCapabilities(base::BindOnce(
&UserMediaProcessor::SelectAudioDeviceSettings,
weak_factory_.GetWeakPtr(), current_request_info_->web_request()));
} else {
- if (!IsValidAudioContentSource(audio_controls.stream_source)) {
+ if (!IsAudioInputMediaType(audio_controls.stream_type)) {
blink::WebString failed_constraint_name =
blink::WebString::FromASCII(current_request_info_->web_request()
.AudioConstraints()
@@ -516,8 +548,8 @@ void UserMediaProcessor::SelectAudioSettings(
settings.hotword_enabled();
current_request_info_->SetAudioCaptureSettings(
settings,
- !IsDeviceSource(
- current_request_info_->stream_controls()->audio.stream_source));
+ !IsDeviceMediaType(
+ current_request_info_->stream_controls()->audio.stream_type));
// No further audio setup required. Continue with video.
SetupVideoInput();
@@ -531,15 +563,22 @@ void UserMediaProcessor::SetupVideoInput() {
GenerateStreamForCurrentRequestInfo();
return;
}
+
auto& video_controls = current_request_info_->stream_controls()->video;
- InitializeTrackControls(
- current_request_info_->web_request().VideoConstraints(), &video_controls);
- if (IsDeviceSource(video_controls.stream_source)) {
+ InitializeVideoTrackControls(current_request_info_->web_request(),
+ &video_controls);
+
+ if (video_controls.stream_type == MEDIA_DISPLAY_VIDEO_CAPTURE) {
+ SelectVideoContentSettings(false /* allow_device_id_constraint */);
+ return;
+ }
+
+ if (IsDeviceMediaType(video_controls.stream_type)) {
GetMediaDevicesDispatcher()->GetVideoInputCapabilities(base::BindOnce(
&UserMediaProcessor::SelectVideoDeviceSettings,
weak_factory_.GetWeakPtr(), current_request_info_->web_request()));
} else {
- if (!IsValidVideoContentSource(video_controls.stream_source)) {
+ if (!IsVideoInputMediaType(video_controls.stream_type)) {
blink::WebString failed_constraint_name =
blink::WebString::FromASCII(current_request_info_->web_request()
.VideoConstraints()
@@ -549,7 +588,7 @@ void UserMediaProcessor::SetupVideoInput() {
GetUserMediaRequestFailed(result, failed_constraint_name);
return;
}
- SelectVideoContentSettings();
+ SelectVideoContentSettings(true /* allow_device_id_constraint */);
}
}
@@ -565,8 +604,8 @@ void UserMediaProcessor::SelectVideoDeviceSettings(
return;
DCHECK(current_request_info_->stream_controls()->video.requested);
- DCHECK(IsDeviceSource(
- current_request_info_->stream_controls()->video.stream_source));
+ DCHECK(IsDeviceMediaType(
+ current_request_info_->stream_controls()->video.stream_type));
VideoDeviceCaptureCapabilities capabilities;
capabilities.device_capabilities = std::move(video_input_capabilities);
@@ -599,13 +638,14 @@ void UserMediaProcessor::SelectVideoDeviceSettings(
GenerateStreamForCurrentRequestInfo();
}
-void UserMediaProcessor::SelectVideoContentSettings() {
+void UserMediaProcessor::SelectVideoContentSettings(
+ bool allow_device_id_constraint) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(current_request_info_);
gfx::Size screen_size = GetScreenSize();
VideoCaptureSettings settings = SelectSettingsVideoContentCapture(
current_request_info_->web_request().VideoConstraints(),
- current_request_info_->stream_controls()->video.stream_source,
+ current_request_info_->stream_controls()->video.stream_type,
screen_size.width(), screen_size.height());
if (!settings.HasValue()) {
blink::WebString failed_constraint_name =
@@ -615,8 +655,10 @@ void UserMediaProcessor::SelectVideoContentSettings() {
failed_constraint_name);
return;
}
- current_request_info_->stream_controls()->video.device_id =
- settings.device_id();
+ if (allow_device_id_constraint) {
+ current_request_info_->stream_controls()->video.device_id =
+ settings.device_id();
+ }
current_request_info_->SetVideoCaptureSettings(settings,
true /* is_content_capture */);
GenerateStreamForCurrentRequestInfo();
diff --git a/chromium/content/renderer/media/stream/user_media_processor.h b/chromium/content/renderer/media/stream/user_media_processor.h
index 5e29c9b9f01..6b9e18f85e0 100644
--- a/chromium/content/renderer/media/stream/user_media_processor.h
+++ b/chromium/content/renderer/media/stream/user_media_processor.h
@@ -270,7 +270,7 @@ class CONTENT_EXPORT UserMediaProcessor
void FinalizeSelectVideoDeviceSettings(
const blink::WebUserMediaRequest& web_request,
const VideoCaptureSettings& settings);
- void SelectVideoContentSettings();
+ void SelectVideoContentSettings(bool allow_device_id_constraint);
void GenerateStreamForCurrentRequestInfo();
diff --git a/chromium/content/renderer/media/stream/webmediaplayer_ms.cc b/chromium/content/renderer/media/stream/webmediaplayer_ms.cc
index 2d13eb7cb58..45c8d7ee9d2 100644
--- a/chromium/content/renderer/media/stream/webmediaplayer_ms.cc
+++ b/chromium/content/renderer/media/stream/webmediaplayer_ms.cc
@@ -33,11 +33,12 @@
#include "media/base/video_types.h"
#include "media/blink/webmediaplayer_util.h"
#include "media/video/gpu_memory_buffer_video_frame_pool.h"
-#include "services/ui/public/cpp/gpu/context_provider_command_buffer.h"
+#include "services/ws/public/cpp/gpu/context_provider_command_buffer.h"
#include "third_party/blink/public/platform/web_media_player_client.h"
#include "third_party/blink/public/platform/web_media_player_source.h"
#include "third_party/blink/public/platform/web_rect.h"
#include "third_party/blink/public/platform/web_size.h"
+#include "third_party/blink/public/platform/web_surface_layer_bridge.h"
#include "third_party/blink/public/web/web_local_frame.h"
namespace {
@@ -262,7 +263,9 @@ WebMediaPlayerMS::WebMediaPlayerMS(
scoped_refptr<base::SingleThreadTaskRunner> media_task_runner,
scoped_refptr<base::TaskRunner> worker_task_runner,
media::GpuVideoAcceleratorFactories* gpu_factories,
- const blink::WebString& sink_id)
+ const blink::WebString& sink_id,
+ CreateSurfaceLayerBridgeCB create_bridge_callback,
+ bool surface_layer_for_video_enabled)
: frame_(frame),
network_state_(WebMediaPlayer::kNetworkStateEmpty),
ready_state_(WebMediaPlayer::kReadyStateHaveNothing),
@@ -282,7 +285,9 @@ WebMediaPlayerMS::WebMediaPlayerMS(
initial_audio_output_device_id_(sink_id.Utf8()),
volume_(1.0),
volume_multiplier_(1.0),
- should_play_upon_shown_(false) {
+ should_play_upon_shown_(false),
+ create_bridge_callback_(std::move(create_bridge_callback)),
+ surface_layer_for_video_enabled_(surface_layer_for_video_enabled) {
DVLOG(1) << __func__;
DCHECK(client);
DCHECK(delegate_);
@@ -301,8 +306,10 @@ WebMediaPlayerMS::~WebMediaPlayerMS() {
// Destruct compositor resources in the proper order.
get_client()->SetCcLayer(nullptr);
- if (video_layer_)
+ if (video_layer_) {
+ DCHECK(!surface_layer_for_video_enabled_);
video_layer_->StopUsingProvider();
+ }
if (frame_deliverer_)
io_task_runner_->DeleteSoon(FROM_HERE, frame_deliverer_.release());
@@ -418,6 +425,27 @@ blink::WebMediaPlayer::LoadTiming WebMediaPlayerMS::Load(
return blink::WebMediaPlayer::LoadTiming::kImmediate;
}
+void WebMediaPlayerMS::OnWebLayerUpdated() {}
+
+void WebMediaPlayerMS::RegisterContentsLayer(cc::Layer* layer) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(bridge_);
+
+ bridge_->SetContentsOpaque(opaque_);
+ client_->SetCcLayer(layer);
+}
+
+void WebMediaPlayerMS::UnregisterContentsLayer(cc::Layer* layer) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ // |client_| will unregister its cc::Layer if given a nullptr.
+ client_->SetCcLayer(nullptr);
+}
+
+void WebMediaPlayerMS::OnSurfaceIdUpdated(viz::SurfaceId surface_id) {
+ // TODO(apacible): Add implementation. See http://crbug/746182.
+ NOTIMPLEMENTED();
+}
+
void WebMediaPlayerMS::TrackAdded(const blink::WebMediaStreamTrack& track) {
Reload();
}
@@ -645,6 +673,13 @@ void WebMediaPlayerMS::ExitPictureInPicture(
// WebMediaPlayerMS. See http://crbug/746182.
}
+void WebMediaPlayerMS::SetPictureInPictureCustomControls(
+ const std::vector<blink::PictureInPictureControlInfo>& controls) {
+ NOTIMPLEMENTED();
+ // TODO(apacible): Implement after video in surfaces is supported for
+ // WebMediaPlayerMS. See http://crbug/746182.
+}
+
void WebMediaPlayerMS::RegisterPictureInPictureWindowResizeCallback(
blink::WebMediaPlayer::PipWindowResizedCallback) {
NOTIMPLEMENTED();
@@ -819,13 +854,13 @@ unsigned WebMediaPlayerMS::DroppedFrameCount() const {
return compositor_->dropped_frame_count();
}
-size_t WebMediaPlayerMS::AudioDecodedByteCount() const {
+uint64_t WebMediaPlayerMS::AudioDecodedByteCount() const {
DCHECK(thread_checker_.CalledOnValidThread());
NOTIMPLEMENTED();
return 0;
}
-size_t WebMediaPlayerMS::VideoDecodedByteCount() const {
+uint64_t WebMediaPlayerMS::VideoDecodedByteCount() const {
DCHECK(thread_checker_.CalledOnValidThread());
NOTIMPLEMENTED();
return 0;
@@ -956,11 +991,49 @@ bool WebMediaPlayerMS::CopyVideoTextureToPlatformTexture(
return false;
context_3d = media::Context3D(provider->ContextGL(), provider->GrContext());
DCHECK(context_3d.gl);
+
return video_renderer_.CopyVideoFrameTexturesToGLTexture(
context_3d, gl, video_frame.get(), target, texture, internal_format,
format, type, level, premultiply_alpha, flip_y);
}
+bool WebMediaPlayerMS::CopyVideoYUVDataToPlatformTexture(
+ gpu::gles2::GLES2Interface* gl,
+ unsigned target,
+ unsigned int texture,
+ unsigned internal_format,
+ unsigned format,
+ unsigned type,
+ int level,
+ bool premultiply_alpha,
+ bool flip_y,
+ int already_uploaded_id,
+ VideoFrameUploadMetadata* out_metadata) {
+ TRACE_EVENT0("media", "copyVideoYUVDataToPlatformTexture");
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ scoped_refptr<media::VideoFrame> video_frame =
+ compositor_->GetCurrentFrameWithoutUpdatingStatistics();
+
+ 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);
+}
+
bool WebMediaPlayerMS::TexImageImpl(TexImageFunctionID functionID,
unsigned target,
gpu::gles2::GLES2Interface* gl,
@@ -1006,6 +1079,15 @@ void WebMediaPlayerMS::OnFirstFrameReceived(media::VideoRotation video_rotation,
bool is_opaque) {
DVLOG(1) << __func__;
DCHECK(thread_checker_.CalledOnValidThread());
+
+ if (surface_layer_for_video_enabled_) {
+ DCHECK(!bridge_);
+
+ bridge_ = std::move(create_bridge_callback_)
+ .Run(this, compositor_->GetUpdateSubmissionStateCallback());
+ bridge_->CreateSurfaceLayer();
+ }
+
SetReadyState(WebMediaPlayer::kReadyStateHaveMetadata);
SetReadyState(WebMediaPlayer::kReadyStateHaveEnoughData);
@@ -1016,9 +1098,17 @@ void WebMediaPlayerMS::OnOpacityChanged(bool is_opaque) {
DVLOG(1) << __func__;
DCHECK(thread_checker_.CalledOnValidThread());
- // Opacity can be changed during the session without resetting
- // |video_layer_|.
- video_layer_->SetContentsOpaque(is_opaque);
+ opaque_ = is_opaque;
+
+ if (!bridge_) {
+ // Opacity can be changed during the session without resetting
+ // |video_layer_|.
+ video_layer_->SetContentsOpaque(opaque_);
+ } else {
+ DCHECK(bridge_);
+
+ bridge_->SetContentsOpaque(opaque_);
+ }
}
void WebMediaPlayerMS::OnRotationChanged(media::VideoRotation video_rotation,
@@ -1026,16 +1116,22 @@ void WebMediaPlayerMS::OnRotationChanged(media::VideoRotation video_rotation,
DVLOG(1) << __func__;
DCHECK(thread_checker_.CalledOnValidThread());
video_rotation_ = video_rotation;
+ opaque_ = is_opaque;
- // Keep the old |video_layer_| alive until SetCcLayer() is called with a new
- // pointer, as it may use the pointer from the last call.
- auto new_video_layer =
- cc::VideoLayer::Create(compositor_.get(), video_rotation);
- new_video_layer->SetContentsOpaque(is_opaque);
+ if (!bridge_) {
+ // Keep the old |video_layer_| alive until SetCcLayer() is called with a new
+ // pointer, as it may use the pointer from the last call.
+ auto new_video_layer =
+ cc::VideoLayer::Create(compositor_.get(), video_rotation);
+ new_video_layer->SetContentsOpaque(is_opaque);
- get_client()->SetCcLayer(new_video_layer.get());
+ get_client()->SetCcLayer(new_video_layer.get());
- video_layer_ = std::move(new_video_layer);
+ video_layer_ = std::move(new_video_layer);
+ } else if (bridge_->GetCcLayer()) {
+ // TODO(lethalantidote): Handle rotation.
+ bridge_->SetContentsOpaque(opaque_);
+ }
}
void WebMediaPlayerMS::RepaintInternal() {
diff --git a/chromium/content/renderer/media/stream/webmediaplayer_ms.h b/chromium/content/renderer/media/stream/webmediaplayer_ms.h
index 4af79567b43..8408a5d40b5 100644
--- a/chromium/content/renderer/media/stream/webmediaplayer_ms.h
+++ b/chromium/content/renderer/media/stream/webmediaplayer_ms.h
@@ -21,6 +21,7 @@
#include "media/video/gpu_video_accelerator_factories.h"
#include "third_party/blink/public/platform/web_media_player.h"
#include "third_party/blink/public/platform/web_media_stream.h"
+#include "third_party/blink/public/platform/web_surface_layer_bridge.h"
namespace blink {
class WebLocalFrame;
@@ -44,6 +45,11 @@ class GLES2Interface;
}
namespace content {
+using CreateSurfaceLayerBridgeCB =
+ base::OnceCallback<std::unique_ptr<blink::WebSurfaceLayerBridge>(
+ blink::WebSurfaceLayerBridgeObserver*,
+ cc::UpdateSubmissionStateCB)>;
+
class MediaStreamAudioRenderer;
class MediaStreamRendererFactory;
class MediaStreamVideoRenderer;
@@ -66,6 +72,7 @@ class CONTENT_EXPORT WebMediaPlayerMS
: public blink::WebMediaStreamObserver,
public blink::WebMediaPlayer,
public media::WebMediaPlayerDelegate::Observer,
+ public blink::WebSurfaceLayerBridgeObserver,
public base::SupportsWeakPtr<WebMediaPlayerMS> {
public:
// Construct a WebMediaPlayerMS with reference to the client, and
@@ -82,7 +89,9 @@ class CONTENT_EXPORT WebMediaPlayerMS
scoped_refptr<base::SingleThreadTaskRunner> media_task_runner,
scoped_refptr<base::TaskRunner> worker_task_runner,
media::GpuVideoAcceleratorFactories* gpu_factories,
- const blink::WebString& sink_id);
+ const blink::WebString& sink_id,
+ CreateSurfaceLayerBridgeCB create_bridge_callback,
+ bool surface_layer_for_video_enabled_);
~WebMediaPlayerMS() override;
@@ -91,6 +100,12 @@ class CONTENT_EXPORT WebMediaPlayerMS
const blink::WebMediaPlayerSource& source,
CORSMode cors_mode) override;
+ // WebSurfaceLayerBridgeObserver implementation.
+ void OnWebLayerUpdated() override;
+ void RegisterContentsLayer(cc::Layer* layer) override;
+ void UnregisterContentsLayer(cc::Layer* layer) override;
+ void OnSurfaceIdUpdated(viz::SurfaceId surface_id) override;
+
// Playback controls.
void Play() override;
void Pause() override;
@@ -101,6 +116,8 @@ class CONTENT_EXPORT WebMediaPlayerMS
blink::WebMediaPlayer::PipWindowOpenedCallback callback) override;
void ExitPictureInPicture(
blink::WebMediaPlayer::PipWindowClosedCallback callback) override;
+ void SetPictureInPictureCustomControls(
+ const std::vector<blink::PictureInPictureControlInfo>&) override;
void RegisterPictureInPictureWindowResizeCallback(
blink::WebMediaPlayer::PipWindowResizedCallback) override;
void SetSinkId(const blink::WebString& sink_id,
@@ -151,8 +168,8 @@ class CONTENT_EXPORT WebMediaPlayerMS
unsigned DecodedFrameCount() const override;
unsigned DroppedFrameCount() const override;
- size_t AudioDecodedByteCount() const override;
- size_t VideoDecodedByteCount() const override;
+ uint64_t AudioDecodedByteCount() const override;
+ uint64_t VideoDecodedByteCount() const override;
// WebMediaPlayerDelegate::Observer implementation.
void OnFrameHidden() override;
@@ -181,6 +198,19 @@ class CONTENT_EXPORT WebMediaPlayerMS
int already_uploaded_id,
VideoFrameUploadMetadata* out_metadata) override;
+ bool CopyVideoYUVDataToPlatformTexture(
+ gpu::gles2::GLES2Interface* gl,
+ unsigned target,
+ unsigned int texture,
+ unsigned internal_format,
+ unsigned format,
+ unsigned type,
+ int level,
+ bool premultiply_alpha,
+ bool flip_y,
+ int already_uploaded_id,
+ VideoFrameUploadMetadata* out_metadata) override;
+
bool TexImageImpl(TexImageFunctionID functionID,
unsigned target,
gpu::gles2::GLES2Interface* gl,
@@ -304,6 +334,18 @@ class CONTENT_EXPORT WebMediaPlayerMS
blink::WebString current_video_track_id_;
blink::WebString current_audio_track_id_;
+ CreateSurfaceLayerBridgeCB create_bridge_callback_;
+
+ // Whether the use of a surface layer instead of a video layer is enabled.
+ bool surface_layer_for_video_enabled_ = false;
+
+ // Owns the weblayer and obtains/maintains SurfaceIds for
+ // kUseSurfaceLayerForVideo feature.
+ std::unique_ptr<blink::WebSurfaceLayerBridge> bridge_;
+
+ // Whether the video is known to be opaque or not.
+ bool opaque_ = true;
+
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 c123ce1f0ec..02b2d8ddb0f 100644
--- a/chromium/content/renderer/media/stream/webmediaplayer_ms_compositor.cc
+++ b/chromium/content/renderer/media/stream/webmediaplayer_ms_compositor.cc
@@ -22,7 +22,7 @@
#include "media/base/video_util.h"
#include "media/filters/video_renderer_algorithm.h"
#include "media/renderers/paint_canvas_video_renderer.h"
-#include "services/ui/public/cpp/gpu/context_provider_command_buffer.h"
+#include "services/ws/public/cpp/gpu/context_provider_command_buffer.h"
#include "skia/ext/platform_canvas.h"
#include "third_party/blink/public/platform/web_media_stream.h"
#include "third_party/blink/public/platform/web_media_stream_source.h"
@@ -51,7 +51,7 @@ scoped_refptr<media::VideoFrame> CopyFrame(
media::PIXEL_FORMAT_I420, frame->coded_size(), frame->visible_rect(),
frame->natural_size(), frame->timestamp());
- ui::ContextProviderCommandBuffer* const provider =
+ ws::ContextProviderCommandBuffer* const provider =
RenderThreadImpl::current()->SharedMainThreadContextProvider().get();
if (!provider) {
// Return a black frame (yuv = {0, 0x80, 0x80}).
diff --git a/chromium/content/renderer/media/stream/webmediaplayer_ms_compositor.h b/chromium/content/renderer/media/stream/webmediaplayer_ms_compositor.h
index 002b4c413fe..921b0bb192a 100644
--- a/chromium/content/renderer/media/stream/webmediaplayer_ms_compositor.h
+++ b/chromium/content/renderer/media/stream/webmediaplayer_ms_compositor.h
@@ -16,6 +16,7 @@
#include "base/message_loop/message_loop.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread_checker.h"
+#include "cc/layers/surface_layer.h"
#include "cc/layers/video_frame_provider.h"
#include "content/common/content_export.h"
#include "media/base/media_log.h"
@@ -62,6 +63,11 @@ class CONTENT_EXPORT WebMediaPlayerMSCompositor
const blink::WebMediaStream& web_stream,
const base::WeakPtr<WebMediaPlayerMS>& player);
+ // Can be called from any thread.
+ cc::UpdateSubmissionStateCB GetUpdateSubmissionStateCallback() {
+ return update_submission_state_callback_;
+ }
+
void EnqueueFrame(scoped_refptr<media::VideoFrame> frame);
// Statistical data
@@ -182,6 +188,8 @@ class CONTENT_EXPORT WebMediaPlayerMSCompositor
std::map<base::TimeDelta, base::TimeTicks> timestamps_to_clock_times_;
+ cc::UpdateSubmissionStateCB update_submission_state_callback_;
+
// |current_frame_lock_| protects |current_frame_|, |rendering_frame_buffer_|,
// |dropped_frame_count_|, and |render_started_|.
base::Lock current_frame_lock_;
diff --git a/chromium/content/renderer/media/stream/webmediaplayer_ms_unittest.cc b/chromium/content/renderer/media/stream/webmediaplayer_ms_unittest.cc
index 5f7235954c0..065fc62abdf 100644
--- a/chromium/content/renderer/media/stream/webmediaplayer_ms_unittest.cc
+++ b/chromium/content/renderer/media/stream/webmediaplayer_ms_unittest.cc
@@ -26,6 +26,9 @@
#include "third_party/blink/public/platform/web_media_player_client.h"
#include "third_party/blink/public/platform/web_media_player_source.h"
+using ::testing::Return;
+using ::testing::StrictMock;
+
namespace content {
enum class FrameType {
@@ -35,6 +38,16 @@ enum class FrameType {
MIN_TYPE = TEST_BRAKE
};
+class MockSurfaceLayerBridge : public blink::WebSurfaceLayerBridge {
+ public:
+ MOCK_CONST_METHOD0(GetCcLayer, cc::Layer*());
+ MOCK_CONST_METHOD0(GetFrameSinkId, const viz::FrameSinkId&());
+ MOCK_CONST_METHOD0(GetSurfaceId, const viz::SurfaceId&());
+ MOCK_METHOD1(SetContentsOpaque, void(bool));
+ MOCK_METHOD0(CreateSurfaceLayer, void());
+ MOCK_METHOD0(ClearSurfaceId, void());
+};
+
using TestFrame = std::pair<FrameType, scoped_refptr<media::VideoFrame>>;
static const int kOddSizeOffset = 3;
@@ -90,6 +103,12 @@ class FakeWebMediaPlayerDelegate
EXPECT_EQ(delegate_id_, delegate_id);
}
+ void DidSetPictureInPictureCustomControls(
+ int delegate_id,
+ const std::vector<blink::PictureInPictureControlInfo>&) override {
+ EXPECT_EQ(delegate_id_, delegate_id);
+ }
+
void DidPictureInPictureSurfaceChange(int delegate_id,
const viz::SurfaceId&,
const gfx::Size&) override {
@@ -143,6 +162,8 @@ class FakeWebMediaPlayerDelegate
EXPECT_EQ(delegate_id_, delegate_id);
}
+ bool IsBackgroundMediaSuspendEnabled() override { return true; }
+
bool IsFrameHidden() override { return is_hidden_; }
bool IsFrameClosed() override { return false; }
@@ -485,26 +506,20 @@ class WebMediaPlayerMSTest
: render_factory_(new MockRenderFactory(message_loop_.task_runner(),
&message_loop_controller_)),
gpu_factories_(new media::MockGpuVideoAcceleratorFactories(nullptr)),
- player_(new WebMediaPlayerMS(
- nullptr,
- this,
- &delegate_,
- std::make_unique<media::MediaLog>(),
- std::unique_ptr<MediaStreamRendererFactory>(render_factory_),
- message_loop_.task_runner(),
- message_loop_.task_runner(),
- message_loop_.task_runner(),
- message_loop_.task_runner(),
- gpu_factories_.get(),
- blink::WebString())),
+ surface_layer_bridge_(
+ std::make_unique<StrictMock<MockSurfaceLayerBridge>>()),
layer_set_(false),
rendering_(false),
- background_rendering_(false) {}
+ background_rendering_(false) {
+ surface_layer_bridge_ptr_ = surface_layer_bridge_.get();
+ }
~WebMediaPlayerMSTest() override {
player_.reset();
base::RunLoop().RunUntilIdle();
}
+ void InitializeWebMediaPlayerMS(bool enable_surface_layer_for_video);
+
MockMediaStreamVideoRenderer* LoadAndGetFrameProvider(bool algorithm_enabled);
// Implementation of WebMediaPlayerClient
@@ -600,6 +615,12 @@ class WebMediaPlayerMSTest
MOCK_METHOD1(CheckSizeChanged, void(gfx::Size));
MOCK_CONST_METHOD0(CouldPlayIfEnoughData, bool());
+ std::unique_ptr<blink::WebSurfaceLayerBridge> CreateMockSurfaceLayerBridge(
+ blink::WebSurfaceLayerBridgeObserver*,
+ cc::UpdateSubmissionStateCB) {
+ return std::move(surface_layer_bridge_);
+ }
+
base::MessageLoop message_loop_;
MockRenderFactory* render_factory_;
std::unique_ptr<media::MockGpuVideoAcceleratorFactories> gpu_factories_;
@@ -610,6 +631,8 @@ class WebMediaPlayerMSTest
cc::Layer* layer_;
bool is_audio_element_ = false;
std::vector<base::OnceClosure> frame_ready_cbs_;
+ std::unique_ptr<StrictMock<MockSurfaceLayerBridge>> surface_layer_bridge_;
+ StrictMock<MockSurfaceLayerBridge>* surface_layer_bridge_ptr_ = nullptr;
private:
// Main function trying to ask WebMediaPlayerMS to submit a frame for
@@ -621,6 +644,19 @@ class WebMediaPlayerMSTest
bool background_rendering_;
};
+void WebMediaPlayerMSTest::InitializeWebMediaPlayerMS(
+ bool enable_surface_layer_for_video) {
+ player_ = std::make_unique<WebMediaPlayerMS>(
+ nullptr, this, &delegate_, std::make_unique<media::MediaLog>(),
+ std::unique_ptr<MediaStreamRendererFactory>(render_factory_),
+ message_loop_.task_runner(), message_loop_.task_runner(),
+ message_loop_.task_runner(), message_loop_.task_runner(),
+ gpu_factories_.get(), blink::WebString(),
+ base::BindRepeating(&WebMediaPlayerMSTest::CreateMockSurfaceLayerBridge,
+ base::Unretained(this)),
+ enable_surface_layer_for_video);
+}
+
MockMediaStreamVideoRenderer* WebMediaPlayerMSTest::LoadAndGetFrameProvider(
bool algorithm_enabled) {
EXPECT_FALSE(!!render_factory_->provider()) << "There should not be a "
@@ -734,6 +770,7 @@ void WebMediaPlayerMSTest::SizeChanged() {
}
TEST_F(WebMediaPlayerMSTest, NoDataDuringLoadForVideo) {
+ InitializeWebMediaPlayerMS(false);
EXPECT_CALL(*this, DoReadyStateChanged(
blink::WebMediaPlayer::kReadyStateHaveMetadata))
.Times(0);
@@ -751,6 +788,7 @@ TEST_F(WebMediaPlayerMSTest, NoDataDuringLoadForVideo) {
}
TEST_F(WebMediaPlayerMSTest, NoWaitForFrameForAudio) {
+ InitializeWebMediaPlayerMS(false);
is_audio_element_ = true;
scoped_refptr<MediaStreamAudioRenderer> audio_renderer(
new MockMediaStreamAudioRenderer());
@@ -777,6 +815,7 @@ TEST_F(WebMediaPlayerMSTest, NoWaitForFrameForAudio) {
}
TEST_F(WebMediaPlayerMSTest, NoWaitForFrameForAudioOnly) {
+ InitializeWebMediaPlayerMS(false);
render_factory_->set_support_video_renderer(false);
scoped_refptr<MediaStreamAudioRenderer> audio_renderer(
new MockMediaStreamAudioRenderer());
@@ -794,6 +833,8 @@ TEST_F(WebMediaPlayerMSTest, Playing_Normal) {
// and verifies that they are produced by WebMediaPlayerMS in appropriate
// order.
+ InitializeWebMediaPlayerMS(false);
+
MockMediaStreamVideoRenderer* provider = LoadAndGetFrameProvider(true);
int tokens[] = {0, 33, 66, 100, 133, 166, 200, 233, 266, 300,
@@ -824,6 +865,8 @@ TEST_F(WebMediaPlayerMSTest, Playing_ErrorFrame) {
// This tests sends a broken frame to WebMediaPlayerMS, and verifies
// OnSourceError function works as expected.
+ InitializeWebMediaPlayerMS(false);
+
MockMediaStreamVideoRenderer* provider = LoadAndGetFrameProvider(false);
const int kBrokenFrame = static_cast<int>(FrameType::BROKEN_FRAME);
@@ -851,6 +894,7 @@ TEST_F(WebMediaPlayerMSTest, Playing_ErrorFrame) {
}
TEST_P(WebMediaPlayerMSTest, PlayThenPause) {
+ InitializeWebMediaPlayerMS(false);
const bool opaque_frame = testing::get<0>(GetParam());
const bool odd_size_frame = testing::get<1>(GetParam());
// In the middle of this test, WebMediaPlayerMS::pause will be called, and we
@@ -892,6 +936,7 @@ TEST_P(WebMediaPlayerMSTest, PlayThenPause) {
}
TEST_P(WebMediaPlayerMSTest, PlayThenPauseThenPlay) {
+ InitializeWebMediaPlayerMS(false);
const bool opaque_frame = testing::get<0>(GetParam());
const bool odd_size_frame = testing::get<1>(GetParam());
// Similary to PlayAndPause test above, this one focuses on testing that
@@ -951,6 +996,7 @@ INSTANTIATE_TEST_CASE_P(,
// During this test, we check that when we send rotated video frames, it applies
// to player's natural size.
TEST_F(WebMediaPlayerMSTest, RotationChange) {
+ InitializeWebMediaPlayerMS(false);
MockMediaStreamVideoRenderer* provider = LoadAndGetFrameProvider(true);
const int kTestBrake = static_cast<int>(FrameType::TEST_BRAKE);
@@ -991,6 +1037,7 @@ TEST_F(WebMediaPlayerMSTest, RotationChange) {
// During this test, we check that web layer changes opacity according to the
// given frames.
TEST_F(WebMediaPlayerMSTest, OpacityChange) {
+ InitializeWebMediaPlayerMS(false);
MockMediaStreamVideoRenderer* provider = LoadAndGetFrameProvider(true);
// Push one opaque frame.
@@ -1035,6 +1082,7 @@ TEST_F(WebMediaPlayerMSTest, BackgroundRendering) {
// WebMediaPlayerMS without an explicit notification. We should expect that
// WebMediaPlayerMS can digest old frames, rather than piling frames up and
// explode.
+ InitializeWebMediaPlayerMS(false);
MockMediaStreamVideoRenderer* provider = LoadAndGetFrameProvider(true);
const int kTestBrake = static_cast<int>(FrameType::TEST_BRAKE);
@@ -1083,6 +1131,7 @@ TEST_F(WebMediaPlayerMSTest, FrameSizeChange) {
// During this test, the frame size of the input changes.
// We need to make sure, when sizeChanged() gets called, new size should be
// returned by GetCurrentSize().
+ InitializeWebMediaPlayerMS(false);
MockMediaStreamVideoRenderer* provider = LoadAndGetFrameProvider(true);
int tokens[] = {0, 33, 66, 100, 133, 166, 200, 233, 266, 300,
@@ -1110,7 +1159,8 @@ TEST_F(WebMediaPlayerMSTest, FrameSizeChange) {
// Tests that GpuMemoryBufferVideoFramePool is called in the expected sequence.
TEST_F(WebMediaPlayerMSTest, CreateHardwareFrames) {
- MockMediaStreamVideoRenderer* provider = LoadAndGetFrameProvider(true);
+ InitializeWebMediaPlayerMS(false);
+ MockMediaStreamVideoRenderer* provider = LoadAndGetFrameProvider(false);
SetGpuMemoryBufferVideoForTesting();
const int kTestBrake = static_cast<int>(FrameType::TEST_BRAKE);
@@ -1128,9 +1178,11 @@ TEST_F(WebMediaPlayerMSTest, CreateHardwareFrames) {
EXPECT_CALL(*this, DoReadyStateChanged(
blink::WebMediaPlayer::kReadyStateHaveEnoughData));
EXPECT_CALL(*this, CheckSizeChanged(provider->get_standard_size()));
+
+ // Run all the tasks that will assign current frame in
+ // WebMediaPlayerMSCompositor.
std::move(frame_ready_cbs_[0]).Run();
- message_loop_controller_.RunAndWaitForStatus(
- media::PipelineStatus::PIPELINE_OK);
+ base::RunLoop().RunUntilIdle();
auto frame = compositor_->GetCurrentFrameWithoutUpdatingStatistics();
ASSERT_TRUE(frame != nullptr);
@@ -1140,68 +1192,9 @@ TEST_F(WebMediaPlayerMSTest, CreateHardwareFrames) {
EXPECT_CALL(*this, DoStopRendering());
}
-// Hidden and closed trigger different events on Android and this test doesn't
-// cover that, see HiddenPlayerTests for specifics.
-#if !defined(OS_ANDROID)
-// Tests that GpuMemoryBufferVideoFramePool is not called when page is hidden.
-TEST_F(WebMediaPlayerMSTest, StopsCreatingHardwareFramesWhenHiddenOrClosed) {
- MockMediaStreamVideoRenderer* provider = LoadAndGetFrameProvider(true);
- SetGpuMemoryBufferVideoForTesting();
-
- const int kTestBrake = static_cast<int>(FrameType::TEST_BRAKE);
- static int tokens[] = {0, kTestBrake};
- std::vector<int> timestamps(tokens, tokens + sizeof(tokens) / sizeof(int));
- provider->QueueFrames(timestamps);
- 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, CheckSizeChanged(provider->get_standard_size()));
- message_loop_controller_.RunAndWaitForStatus(
- media::PipelineStatus::PIPELINE_OK);
- ASSERT_EQ(1u, frame_ready_cbs_.size());
- frame_ready_cbs_.clear();
-
- // Hidden should stop passing frames to GpuMemoryBufferVideoFramePool.
- player_->OnFrameHidden();
- provider->QueueFrames(timestamps, false);
- message_loop_controller_.RunAndWaitForStatus(
- media::PipelineStatus::PIPELINE_OK);
- ASSERT_EQ(0u, frame_ready_cbs_.size());
-
- // Shown should resume passing frames to GpuMemoryBufferVideoFramePool.
- player_->OnFrameShown();
- provider->QueueFrames(timestamps, false);
- message_loop_controller_.RunAndWaitForStatus(
- media::PipelineStatus::PIPELINE_OK);
- ASSERT_EQ(1u, frame_ready_cbs_.size());
- frame_ready_cbs_.clear();
-
- // Hidden should stop passing frames to GpuMemoryBufferVideoFramePool.
- player_->OnFrameClosed();
- provider->QueueFrames(timestamps, false);
- message_loop_controller_.RunAndWaitForStatus(
- media::PipelineStatus::PIPELINE_OK);
- ASSERT_EQ(0u, frame_ready_cbs_.size());
-
- // Shown should resume passing frames to GpuMemoryBufferVideoFramePool.
- player_->OnFrameShown();
- provider->QueueFrames(timestamps, false);
- message_loop_controller_.RunAndWaitForStatus(
- media::PipelineStatus::PIPELINE_OK);
- ASSERT_EQ(1u, frame_ready_cbs_.size());
-
- testing::Mock::VerifyAndClearExpectations(this);
-
- EXPECT_CALL(*this, DoSetCcLayer(false));
- EXPECT_CALL(*this, DoStopRendering());
-}
-#endif // !defined(OS_ANDROID)
-
#if defined(OS_ANDROID)
TEST_F(WebMediaPlayerMSTest, HiddenPlayerTests) {
+ InitializeWebMediaPlayerMS(false);
LoadAndGetFrameProvider(true);
// Hidden status should not affect playback.
diff --git a/chromium/content/renderer/media/video_capture_impl.cc b/chromium/content/renderer/media/video_capture_impl.cc
index edf50675310..77ed36bf3d7 100644
--- a/chromium/content/renderer/media/video_capture_impl.cc
+++ b/chromium/content/renderer/media/video_capture_impl.cc
@@ -41,6 +41,10 @@ struct VideoCaptureImpl::BufferContext
InitializeFromSharedMemory(
std::move(buffer_handle->get_shared_buffer_handle()));
break;
+ case VideoFrameBufferHandleType::READ_ONLY_SHMEM_REGION:
+ InitializeFromReadOnlyShmemRegion(
+ std::move(buffer_handle->get_read_only_shmem_region()));
+ break;
case VideoFrameBufferHandleType::SHARED_MEMORY_VIA_RAW_FILE_DESCRIPTOR:
NOTREACHED();
break;
@@ -51,8 +55,10 @@ struct VideoCaptureImpl::BufferContext
}
VideoFrameBufferHandleType buffer_type() const { return buffer_type_; }
- base::SharedMemory* shared_memory() { return shared_memory_.get(); }
+ base::SharedMemory* shared_memory() const { return shared_memory_.get(); }
size_t shared_memory_size() const { return shared_memory_size_; }
+ const void* read_only_shmem() const { return read_only_mapping_.memory(); }
+ size_t read_only_shmem_size() const { return read_only_mapping_.size(); }
const std::vector<gpu::MailboxHolder>& mailbox_holders() const {
return mailbox_holders_;
}
@@ -79,6 +85,13 @@ struct VideoCaptureImpl::BufferContext
}
}
+ void InitializeFromReadOnlyShmemRegion(
+ base::ReadOnlySharedMemoryRegion region) {
+ DCHECK(region.IsValid());
+ read_only_mapping_ = region.Map();
+ DCHECK(read_only_mapping_.IsValid());
+ }
+
void InitializeFromMailbox(
media::mojom::MailboxBufferHandleSetPtr mailbox_handles) {
DCHECK_EQ(media::VideoFrame::kMaxPlanes,
@@ -91,11 +104,14 @@ struct VideoCaptureImpl::BufferContext
VideoFrameBufferHandleType buffer_type_;
- // Only valid for |buffer_type_ == kSharedMemory|.
+ // Only valid for |buffer_type_ == SHARED_BUFFER_HANDLE|.
std::unique_ptr<base::SharedMemory> shared_memory_;
size_t shared_memory_size_;
- // Only valid for |buffer_type_ == kMailboxHolder|.
+ // Only valid for |buffer_type_ == READ_ONLY_SHMEM_REGION|.
+ base::ReadOnlySharedMemoryMapping read_only_mapping_;
+
+ // Only valid for |buffer_type_ == MAILBOX_HANDLES|.
std::vector<gpu::MailboxHolder> mailbox_holders_;
DISALLOW_COPY_AND_ASSIGN(BufferContext);
@@ -344,11 +360,19 @@ void VideoCaptureImpl::OnBufferReady(int32_t buffer_id,
frame = media::VideoFrame::WrapExternalSharedMemory(
static_cast<media::VideoPixelFormat>(info->pixel_format),
info->coded_size, info->visible_rect, info->visible_rect.size(),
- reinterpret_cast<uint8_t*>(buffer_context->shared_memory()->memory()),
+ static_cast<uint8_t*>(buffer_context->shared_memory()->memory()),
buffer_context->shared_memory_size(),
buffer_context->shared_memory()->handle(),
0 /* shared_memory_offset */, info->timestamp);
break;
+ case VideoFrameBufferHandleType::READ_ONLY_SHMEM_REGION:
+ frame = media::VideoFrame::WrapExternalData(
+ static_cast<media::VideoPixelFormat>(info->pixel_format),
+ info->coded_size, info->visible_rect, info->visible_rect.size(),
+ const_cast<uint8_t*>(
+ static_cast<const uint8_t*>(buffer_context->read_only_shmem())),
+ buffer_context->read_only_shmem_size(), info->timestamp);
+ break;
case VideoFrameBufferHandleType::SHARED_MEMORY_VIA_RAW_FILE_DESCRIPTOR:
NOTREACHED();
break;
@@ -402,7 +426,7 @@ void VideoCaptureImpl::OnAllClientsFinishedConsumingFrame(
double consumer_resource_utilization) {
DCHECK(io_thread_checker_.CalledOnValidThread());
-// Subtle race note: It's important that the |buffer| argument be
+// Subtle race note: It's important that the |buffer_context| argument be
// std::move()'ed to this method and never copied. This is so that the caller,
// DidFinishConsumingFrame(), does not implicitly retain a reference while it
// is running the trampoline callback on another thread. This is necessary to
@@ -499,7 +523,7 @@ media::mojom::VideoCaptureHost* VideoCaptureImpl::GetVideoCaptureHost() {
if (!video_capture_host_.get())
video_capture_host_.Bind(std::move(video_capture_host_info_));
return video_capture_host_.get();
-};
+}
// static
void VideoCaptureImpl::DidFinishConsumingFrame(
diff --git a/chromium/content/renderer/media/video_capture_impl_unittest.cc b/chromium/content/renderer/media/video_capture_impl_unittest.cc
index 634cb052872..251e4d78b3b 100644
--- a/chromium/content/renderer/media/video_capture_impl_unittest.cc
+++ b/chromium/content/renderer/media/video_capture_impl_unittest.cc
@@ -5,6 +5,7 @@
#include <stddef.h>
#include "base/macros.h"
+#include "base/memory/read_only_shared_memory_region.h"
#include "base/memory/shared_memory.h"
#include "base/test/scoped_task_environment.h"
#include "content/child/child_process.h"
@@ -146,12 +147,19 @@ class VideoCaptureImplTest : public ::testing::Test {
}
void SimulateOnBufferCreated(int buffer_id, const base::SharedMemory& shm) {
- media::mojom::VideoBufferHandlePtr buffer_handle =
- media::mojom::VideoBufferHandle::New();
- buffer_handle->set_shared_buffer_handle(mojo::WrapSharedMemoryHandle(
- shm.GetReadOnlyHandle(), shm.mapped_size(),
- mojo::UnwrappedSharedMemoryHandleProtection::kReadOnly));
- video_capture_impl_->OnNewBuffer(buffer_id, std::move(buffer_handle));
+ video_capture_impl_->OnNewBuffer(
+ buffer_id,
+ media::mojom::VideoBufferHandle::NewSharedBufferHandle(
+ mojo::WrapSharedMemoryHandle(
+ shm.GetReadOnlyHandle(), shm.mapped_size(),
+ mojo::UnwrappedSharedMemoryHandleProtection::kReadOnly)));
+ }
+
+ void SimulateReadOnlyBufferCreated(int buffer_id,
+ base::ReadOnlySharedMemoryRegion region) {
+ video_capture_impl_->OnNewBuffer(
+ buffer_id, media::mojom::VideoBufferHandle::NewReadOnlyShmemRegion(
+ std::move(region)));
}
void SimulateBufferReceived(int buffer_id, const gfx::Size& size) {
@@ -284,7 +292,7 @@ TEST_F(VideoCaptureImplTest, GetDeviceFormatsInUse) {
}
TEST_F(VideoCaptureImplTest, BufferReceived) {
- const int kBufferId = 11;
+ const int kArbitraryBufferId = 11;
base::SharedMemory shm;
const size_t frame_size = media::VideoFrame::AllocationSize(
@@ -296,20 +304,48 @@ TEST_F(VideoCaptureImplTest, BufferReceived) {
EXPECT_CALL(*this, OnFrameReady(_, _));
EXPECT_CALL(mock_video_capture_host_, DoStart(_, kSessionId, params_small_));
EXPECT_CALL(mock_video_capture_host_, Stop(_));
- EXPECT_CALL(mock_video_capture_host_, ReleaseBuffer(_, kBufferId, _))
+ EXPECT_CALL(mock_video_capture_host_, ReleaseBuffer(_, kArbitraryBufferId, _))
+ .Times(0);
+
+ StartCapture(0, params_small_);
+ SimulateOnBufferCreated(kArbitraryBufferId, shm);
+ SimulateBufferReceived(kArbitraryBufferId,
+ params_small_.requested_format.frame_size);
+ StopCapture(0);
+ SimulateBufferDestroyed(kArbitraryBufferId);
+
+ EXPECT_EQ(mock_video_capture_host_.released_buffer_count(), 0);
+}
+
+TEST_F(VideoCaptureImplTest, BufferReceived_ReadOnlyShmemRegion) {
+ const int kArbitraryBufferId = 11;
+
+ const size_t frame_size = media::VideoFrame::AllocationSize(
+ media::PIXEL_FORMAT_I420, params_small_.requested_format.frame_size);
+ base::MappedReadOnlyRegion shm =
+ base::ReadOnlySharedMemoryRegion::Create(frame_size);
+ ASSERT_TRUE(shm.IsValid());
+
+ EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_STARTED));
+ EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_STOPPED));
+ EXPECT_CALL(*this, OnFrameReady(_, _));
+ EXPECT_CALL(mock_video_capture_host_, DoStart(_, kSessionId, params_small_));
+ EXPECT_CALL(mock_video_capture_host_, Stop(_));
+ EXPECT_CALL(mock_video_capture_host_, ReleaseBuffer(_, kArbitraryBufferId, _))
.Times(0);
StartCapture(0, params_small_);
- SimulateOnBufferCreated(kBufferId, shm);
- SimulateBufferReceived(kBufferId, params_small_.requested_format.frame_size);
+ SimulateReadOnlyBufferCreated(kArbitraryBufferId, std::move(shm.region));
+ SimulateBufferReceived(kArbitraryBufferId,
+ params_small_.requested_format.frame_size);
StopCapture(0);
- SimulateBufferDestroyed(kBufferId);
+ SimulateBufferDestroyed(kArbitraryBufferId);
EXPECT_EQ(mock_video_capture_host_.released_buffer_count(), 0);
}
TEST_F(VideoCaptureImplTest, BufferReceivedAfterStop) {
- const int kBufferId = 12;
+ const int kArbitraryBufferId = 12;
base::SharedMemory shm;
const size_t frame_size = media::VideoFrame::AllocationSize(
@@ -321,14 +357,44 @@ TEST_F(VideoCaptureImplTest, BufferReceivedAfterStop) {
EXPECT_CALL(*this, OnFrameReady(_, _)).Times(0);
EXPECT_CALL(mock_video_capture_host_, DoStart(_, kSessionId, params_large_));
EXPECT_CALL(mock_video_capture_host_, Stop(_));
- EXPECT_CALL(mock_video_capture_host_, ReleaseBuffer(_, kBufferId, _));
+ EXPECT_CALL(mock_video_capture_host_,
+ ReleaseBuffer(_, kArbitraryBufferId, _));
StartCapture(0, params_large_);
- SimulateOnBufferCreated(kBufferId, shm);
+ SimulateOnBufferCreated(kArbitraryBufferId, shm);
StopCapture(0);
// A buffer received after StopCapture() triggers an instant ReleaseBuffer().
- SimulateBufferReceived(kBufferId, params_large_.requested_format.frame_size);
- SimulateBufferDestroyed(kBufferId);
+ SimulateBufferReceived(kArbitraryBufferId,
+ params_large_.requested_format.frame_size);
+ SimulateBufferDestroyed(kArbitraryBufferId);
+
+ EXPECT_EQ(mock_video_capture_host_.released_buffer_count(), 1);
+}
+
+TEST_F(VideoCaptureImplTest, BufferReceivedAfterStop_ReadOnlyShmemRegion) {
+ const int kArbitraryBufferId = 12;
+
+ const size_t frame_size = media::VideoFrame::AllocationSize(
+ media::PIXEL_FORMAT_I420, params_large_.requested_format.frame_size);
+ base::MappedReadOnlyRegion shm =
+ base::ReadOnlySharedMemoryRegion::Create(frame_size);
+ ASSERT_TRUE(shm.IsValid());
+
+ EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_STARTED));
+ EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_STOPPED));
+ EXPECT_CALL(*this, OnFrameReady(_, _)).Times(0);
+ EXPECT_CALL(mock_video_capture_host_, DoStart(_, kSessionId, params_large_));
+ EXPECT_CALL(mock_video_capture_host_, Stop(_));
+ EXPECT_CALL(mock_video_capture_host_,
+ ReleaseBuffer(_, kArbitraryBufferId, _));
+
+ StartCapture(0, params_large_);
+ SimulateReadOnlyBufferCreated(kArbitraryBufferId, std::move(shm.region));
+ StopCapture(0);
+ // A buffer received after StopCapture() triggers an instant ReleaseBuffer().
+ SimulateBufferReceived(kArbitraryBufferId,
+ params_large_.requested_format.frame_size);
+ SimulateBufferDestroyed(kArbitraryBufferId);
EXPECT_EQ(mock_video_capture_host_.released_buffer_count(), 1);
}
@@ -377,7 +443,7 @@ TEST_F(VideoCaptureImplTest, ErrorBeforeStop) {
}
TEST_F(VideoCaptureImplTest, BufferReceivedBeforeOnStarted) {
- const int kBufferId = 16;
+ const int kArbitraryBufferId = 16;
base::SharedMemory shm;
const size_t frame_size = media::VideoFrame::AllocationSize(
@@ -387,10 +453,46 @@ TEST_F(VideoCaptureImplTest, BufferReceivedBeforeOnStarted) {
InSequence s;
EXPECT_CALL(mock_video_capture_host_, DoStart(_, kSessionId, params_small_))
.WillOnce(DoNothing());
- EXPECT_CALL(mock_video_capture_host_, ReleaseBuffer(_, kBufferId, _));
+ EXPECT_CALL(mock_video_capture_host_,
+ ReleaseBuffer(_, kArbitraryBufferId, _));
+ StartCapture(0, params_small_);
+ SimulateOnBufferCreated(kArbitraryBufferId, shm);
+ SimulateBufferReceived(kArbitraryBufferId,
+ params_small_.requested_format.frame_size);
+
+ EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_STARTED));
+ EXPECT_CALL(mock_video_capture_host_, RequestRefreshFrame(_));
+ video_capture_impl_->OnStateChanged(media::mojom::VideoCaptureState::STARTED);
+
+ // Additional STARTED will cause RequestRefreshFrame a second time.
+ EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_STARTED));
+ EXPECT_CALL(mock_video_capture_host_, RequestRefreshFrame(_));
+ video_capture_impl_->OnStateChanged(media::mojom::VideoCaptureState::STARTED);
+
+ EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_STOPPED));
+ EXPECT_CALL(mock_video_capture_host_, Stop(_));
+ StopCapture(0);
+}
+
+TEST_F(VideoCaptureImplTest,
+ BufferReceivedBeforeOnStarted_ReadOnlyShmemRegion) {
+ const int kArbitraryBufferId = 16;
+
+ const size_t frame_size = media::VideoFrame::AllocationSize(
+ media::PIXEL_FORMAT_I420, params_small_.requested_format.frame_size);
+ base::MappedReadOnlyRegion shm =
+ base::ReadOnlySharedMemoryRegion::Create(frame_size);
+ ASSERT_TRUE(shm.IsValid());
+
+ InSequence s;
+ EXPECT_CALL(mock_video_capture_host_, DoStart(_, kSessionId, params_small_))
+ .WillOnce(DoNothing());
+ EXPECT_CALL(mock_video_capture_host_,
+ ReleaseBuffer(_, kArbitraryBufferId, _));
StartCapture(0, params_small_);
- SimulateOnBufferCreated(kBufferId, shm);
- SimulateBufferReceived(kBufferId, params_small_.requested_format.frame_size);
+ SimulateReadOnlyBufferCreated(kArbitraryBufferId, std::move(shm.region));
+ SimulateBufferReceived(kArbitraryBufferId,
+ params_small_.requested_format.frame_size);
EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_STARTED));
EXPECT_CALL(mock_video_capture_host_, RequestRefreshFrame(_));
diff --git a/chromium/content/renderer/media/webrtc/OWNERS b/chromium/content/renderer/media/webrtc/OWNERS
index 52da327acde..c85f7c53738 100644
--- a/chromium/content/renderer/media/webrtc/OWNERS
+++ b/chromium/content/renderer/media/webrtc/OWNERS
@@ -1,3 +1,4 @@
+orphis@chromium.org
sergeyu@chromium.org
per-file rtc_video_*=file://media/gpu/OWNERS
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 0e810df0728..a3869e8e4bd 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
@@ -13,6 +13,7 @@
#include "base/trace_event/trace_event.h"
#include "content/renderer/media/webrtc/track_observer.h"
#include "content/renderer/media/webrtc/webrtc_video_frame_adapter.h"
+#include "content/renderer/media/webrtc/webrtc_video_utils.h"
#include "media/base/bind_to_current_loop.h"
#include "media/base/timestamp_constants.h"
#include "media/base/video_frame.h"
@@ -22,25 +23,6 @@
namespace content {
-namespace {
-
-media::VideoRotation WebRTCToMediaVideoRotation(
- webrtc::VideoRotation rotation) {
- switch (rotation) {
- case webrtc::kVideoRotation_0:
- return media::VIDEO_ROTATION_0;
- case webrtc::kVideoRotation_90:
- return media::VIDEO_ROTATION_90;
- case webrtc::kVideoRotation_180:
- return media::VIDEO_ROTATION_180;
- case webrtc::kVideoRotation_270:
- return media::VIDEO_ROTATION_270;
- }
- return media::VIDEO_ROTATION_0;
-}
-
-} // anonymous namespace
-
// Internal class used for receiving frames from the webrtc track on a
// libjingle thread and forward it to the IO-thread.
class MediaStreamRemoteVideoSource::RemoteVideoSourceDelegate
@@ -192,7 +174,13 @@ void MediaStreamRemoteVideoSource::RemoteVideoSourceDelegate::OnFrame(
if (incoming_frame.rotation() != webrtc::kVideoRotation_0) {
video_frame->metadata()->SetRotation(
media::VideoFrameMetadata::ROTATION,
- WebRTCToMediaVideoRotation(incoming_frame.rotation()));
+ WebRtcToMediaVideoRotation(incoming_frame.rotation()));
+ }
+
+ if (incoming_frame.color_space().has_value()) {
+ video_frame->set_color_space(
+ WebRtcToMediaVideoColorSpace(incoming_frame.color_space().value())
+ .ToGfxColorSpace());
}
// Run render smoothness algorithm only when we don't have to render
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 e721651a012..89c42fff3dd 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
@@ -22,7 +22,9 @@
#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/web/web_heap.h"
+#include "third_party/webrtc/api/video/color_space.h"
#include "third_party/webrtc/api/video/i420_buffer.h"
+#include "ui/gfx/color_space.h"
namespace content {
@@ -37,6 +39,7 @@ class MediaStreamRemoteVideoSourceUnderTest
std::unique_ptr<TrackObserver> observer)
: MediaStreamRemoteVideoSource(std::move(observer)) {}
using MediaStreamRemoteVideoSource::SinkInterfaceForTesting;
+ using MediaStreamRemoteVideoSource::StartSourceImpl;
};
class MediaStreamRemoteVideoSourceTest
@@ -196,4 +199,39 @@ TEST_F(MediaStreamRemoteVideoSourceTest, RemoteTrackStop) {
track->RemoveSink(&sink);
}
+TEST_F(MediaStreamRemoteVideoSourceTest, PreservesColorSpace) {
+ std::unique_ptr<MediaStreamVideoTrack> track(CreateTrack());
+ MockMediaStreamVideoSink sink;
+ track->AddSink(&sink, sink.GetDeliverFrameCB(), false);
+
+ base::RunLoop run_loop;
+ EXPECT_CALL(sink, OnVideoFrame())
+ .WillOnce(RunClosure(run_loop.QuitClosure()));
+ rtc::scoped_refptr<webrtc::I420Buffer> buffer(
+ new rtc::RefCountedObject<webrtc::I420Buffer>(320, 240));
+ webrtc::ColorSpace kColorSpace(webrtc::ColorSpace::PrimaryID::kSMPTE240M,
+ webrtc::ColorSpace::TransferID::kSMPTE240M,
+ webrtc::ColorSpace::MatrixID::kSMPTE240M,
+ webrtc::ColorSpace::RangeID::kLimited);
+ const webrtc::VideoFrame& input_frame =
+ webrtc::VideoFrame::Builder()
+ .set_video_frame_buffer(buffer)
+ .set_timestamp_ms(0)
+ .set_rotation(webrtc::kVideoRotation_0)
+ .set_color_space(kColorSpace)
+ .build();
+ source()->SinkInterfaceForTesting()->OnFrame(input_frame);
+ run_loop.Run();
+
+ EXPECT_EQ(1, sink.number_of_frames());
+ scoped_refptr<media::VideoFrame> output_frame = sink.last_frame();
+ EXPECT_TRUE(output_frame);
+ EXPECT_TRUE(output_frame->ColorSpace() ==
+ gfx::ColorSpace(gfx::ColorSpace::PrimaryID::SMPTE240M,
+ gfx::ColorSpace::TransferID::SMPTE240M,
+ gfx::ColorSpace::MatrixID::SMPTE240M,
+ gfx::ColorSpace::RangeID::LIMITED));
+ track->RemoveSink(&sink);
+}
+
} // namespace content
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 32ec4d023d4..67999d0c42b 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
@@ -47,6 +47,7 @@ class MockWebRTCPeerConnectionHandlerClient
DidModifyTransceiversForMock(&web_transceivers, is_remote_description);
}
MOCK_METHOD1(DidAddRemoteDataChannel, void(blink::WebRTCDataChannelHandler*));
+ MOCK_METHOD1(DidNoteInterestingUsage, void(int));
MOCK_METHOD0(ReleasePeerConnectionHandler, void());
// Move-only arguments do not play nicely with MOCK, the workaround is to
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 d0c4b1b96f9..2d2cfb2223c 100644
--- a/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
+++ b/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
@@ -340,6 +340,19 @@ PeerConnectionDependencyFactory::CreatePeerConnection(
if (!GetPcFactory().get())
return nullptr;
+ std::unique_ptr<P2PPortAllocator> port_allocator =
+ CreatePortAllocator(web_frame);
+ return GetPcFactory()
+ ->CreatePeerConnection(config, std::move(port_allocator), nullptr,
+ observer)
+ .get();
+}
+
+std::unique_ptr<P2PPortAllocator>
+PeerConnectionDependencyFactory::CreatePortAllocator(
+ blink::WebLocalFrame* web_frame) {
+ DCHECK(web_frame);
+
// Copy the flag from Preference associated with this WebLocalFrame.
P2PPortAllocator::Config port_config;
uint16_t min_port = 0;
@@ -444,16 +457,13 @@ PeerConnectionDependencyFactory::CreatePeerConnection(
} else {
network_manager.reset(new EmptyNetworkManager(network_manager_));
}
- std::unique_ptr<P2PPortAllocator> port_allocator(new P2PPortAllocator(
+ auto port_allocator = std::make_unique<P2PPortAllocator>(
p2p_socket_dispatcher_, std::move(network_manager), socket_factory_.get(),
- port_config, requesting_origin));
+ port_config, requesting_origin);
if (IsValidPortRange(min_port, max_port))
port_allocator->SetPortRange(min_port, max_port);
- return GetPcFactory()
- ->CreatePeerConnection(config, std::move(port_allocator),
- nullptr, observer)
- .get();
+ return port_allocator;
}
scoped_refptr<webrtc::MediaStreamInterface>
@@ -520,22 +530,6 @@ void PeerConnectionDependencyFactory::TryScheduleStunProbeTrial() {
if (!cmd_line->HasSwitch(switches::kWebRtcStunProbeTrialParameter))
return;
- // The underneath IPC channel has to be connected before sending any IPC
- // message.
- if (!p2p_socket_dispatcher_->connected()) {
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE,
- base::BindOnce(
- &PeerConnectionDependencyFactory::TryScheduleStunProbeTrial,
- base::Unretained(this)),
- base::TimeDelta::FromSeconds(1));
- return;
- }
-
- // GetPcFactory could trigger an IPC message. If done before
- // |p2p_socket_dispatcher_| is connected, that'll put the
- // |p2p_socket_dispatcher_| in a bad state such that no other IPC message can
- // be processed.
GetPcFactory();
const std::string params =
@@ -604,6 +598,12 @@ PeerConnectionDependencyFactory::GetWebRtcWorkerThread() const {
: nullptr;
}
+rtc::Thread* PeerConnectionDependencyFactory::GetWebRtcWorkerThreadRtcThread()
+ const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ return chrome_worker_thread_.IsRunning() ? worker_thread_ : nullptr;
+}
+
scoped_refptr<base::SingleThreadTaskRunner>
PeerConnectionDependencyFactory::GetWebRtcSignalingThread() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
diff --git a/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.h b/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.h
index db7919fe1e5..39f6f9edec0 100644
--- a/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.h
+++ b/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.h
@@ -42,6 +42,7 @@ namespace content {
class IpcNetworkManager;
class IpcPacketSocketFactory;
+class P2PPortAllocator;
class WebRtcAudioDeviceImpl;
// Object factory for RTC PeerConnections.
@@ -81,6 +82,11 @@ class CONTENT_EXPORT PeerConnectionDependencyFactory
blink::WebLocalFrame* web_frame,
webrtc::PeerConnectionObserver* observer);
+ // Creates a PortAllocator that uses Chrome IPC sockets and enforces privacy
+ // controls according to the permissions granted on the page.
+ virtual std::unique_ptr<P2PPortAllocator> CreatePortAllocator(
+ blink::WebLocalFrame* web_frame);
+
// Creates a libjingle representation of a Session description. Used by a
// RTCPeerConnectionHandler instance.
virtual webrtc::SessionDescriptionInterface* CreateSessionDescription(
@@ -105,6 +111,8 @@ class CONTENT_EXPORT PeerConnectionDependencyFactory
void EnsureInitialized();
scoped_refptr<base::SingleThreadTaskRunner> GetWebRtcWorkerThread() const;
+ // TODO(bugs.webrtc.org/9419): Remove once WebRTC can be built as a component.
+ rtc::Thread* GetWebRtcWorkerThreadRtcThread() const;
virtual scoped_refptr<base::SingleThreadTaskRunner> GetWebRtcSignalingThread()
const;
diff --git a/chromium/content/renderer/media/webrtc/peer_connection_tracker.cc b/chromium/content/renderer/media/webrtc/peer_connection_tracker.cc
index 4566c247f7b..cfd1e8d81cb 100644
--- a/chromium/content/renderer/media/webrtc/peer_connection_tracker.cc
+++ b/chromium/content/renderer/media/webrtc/peer_connection_tracker.cc
@@ -48,10 +48,16 @@ static const char* SerializeBoolean(bool value) {
static std::string SerializeServers(
const std::vector<webrtc::PeerConnectionInterface::IceServer>& servers) {
std::string result = "[";
- for (size_t i = 0; i < servers.size(); ++i) {
- result += servers[i].uri;
- if (i != servers.size() - 1)
- result += ", ";
+ bool following = false;
+ for (const auto& server : servers) {
+ for (const auto& url : server.urls) {
+ if (following)
+ result += ", ";
+ else
+ following = true;
+
+ result += url;
+ }
}
result += "]";
return result;
diff --git a/chromium/content/renderer/media/webrtc/rtc_certificate.cc b/chromium/content/renderer/media/webrtc/rtc_certificate.cc
deleted file mode 100644
index 316b60216eb..00000000000
--- a/chromium/content/renderer/media/webrtc/rtc_certificate.cc
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright (c) 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/media/webrtc/rtc_certificate.h"
-
-#include <vector>
-
-#include "base/memory/ptr_util.h"
-#include "base/strings/string_util.h"
-#include "third_party/webrtc/rtc_base/sslidentity.h"
-#include "url/gurl.h"
-
-namespace content {
-
-RTCCertificate::RTCCertificate(
- const rtc::scoped_refptr<rtc::RTCCertificate>& certificate)
- : certificate_(certificate) {
- DCHECK(certificate_);
-}
-
-RTCCertificate::~RTCCertificate() {
-}
-
-std::unique_ptr<blink::WebRTCCertificate> RTCCertificate::ShallowCopy() const {
- return base::WrapUnique(new RTCCertificate(certificate_));
-}
-
-uint64_t RTCCertificate::Expires() const {
- return certificate_->Expires();
-}
-
-blink::WebVector<blink::WebRTCDtlsFingerprint> RTCCertificate::GetFingerprints()
- const {
- std::vector<blink::WebRTCDtlsFingerprint> fingerprints;
- std::unique_ptr<rtc::SSLCertificateStats> first_certificate_stats =
- certificate_->identity()->certificate().GetStats();
- for (rtc::SSLCertificateStats* certificate_stats =
- first_certificate_stats.get();
- certificate_stats; certificate_stats = certificate_stats->issuer.get()) {
- fingerprints.push_back(blink::WebRTCDtlsFingerprint(
- blink::WebString::FromUTF8(certificate_stats->fingerprint_algorithm),
- blink::WebString::FromUTF8(
- base::ToLowerASCII(certificate_stats->fingerprint))));
- }
- return blink::WebVector<blink::WebRTCDtlsFingerprint>(fingerprints);
-}
-
-blink::WebRTCCertificatePEM RTCCertificate::ToPEM() const {
- rtc::RTCCertificatePEM pem = certificate_->ToPEM();
- return blink::WebRTCCertificatePEM(
- blink::WebString::FromUTF8(pem.private_key()),
- blink::WebString::FromUTF8(pem.certificate()));
-}
-
-bool RTCCertificate::Equals(const blink::WebRTCCertificate& other) const {
- return *certificate_ ==
- *static_cast<const RTCCertificate&>(other).certificate_;
-}
-
-const rtc::scoped_refptr<rtc::RTCCertificate>&
-RTCCertificate::rtcCertificate() const {
- return certificate_;
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/media/webrtc/rtc_certificate.h b/chromium/content/renderer/media/webrtc/rtc_certificate.h
deleted file mode 100644
index 5210e8f40db..00000000000
--- a/chromium/content/renderer/media/webrtc/rtc_certificate.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright (c) 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_MEDIA_WEBRTC_RTC_CERTIFICATE_H_
-#define CONTENT_RENDERER_MEDIA_WEBRTC_RTC_CERTIFICATE_H_
-
-#include <stdint.h>
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "content/common/content_export.h"
-#include "third_party/blink/public/platform/web_rtc_certificate.h"
-#include "third_party/webrtc/rtc_base/rtccertificate.h"
-#include "third_party/webrtc/rtc_base/scoped_ref_ptr.h"
-
-namespace content {
-
-// Chromium's WebRTCCertificate implementation; wraps a rtc::scoped_refptr to an
-// rtc::RTCCertificate. This abstraction layer is necessary because blink does
-// not have direct access to WebRTC.
-class CONTENT_EXPORT RTCCertificate : public blink::WebRTCCertificate {
- public:
- RTCCertificate(const rtc::scoped_refptr<rtc::RTCCertificate>& certificate);
- ~RTCCertificate() override;
-
- // blink::WebRTCCertificate implementation.
- std::unique_ptr<blink::WebRTCCertificate> ShallowCopy() const override;
- uint64_t Expires() const override;
- blink::WebVector<blink::WebRTCDtlsFingerprint> GetFingerprints()
- const override;
- blink::WebRTCCertificatePEM ToPEM() const override;
- bool Equals(const blink::WebRTCCertificate& other) const override;
-
- const rtc::scoped_refptr<rtc::RTCCertificate>& rtcCertificate() const;
-
- private:
- rtc::scoped_refptr<rtc::RTCCertificate> certificate_;
-
- DISALLOW_COPY_AND_ASSIGN(RTCCertificate);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_MEDIA_WEBRTC_RTC_CERTIFICATE_H_
diff --git a/chromium/content/renderer/media/webrtc/rtc_certificate_generator.cc b/chromium/content/renderer/media/webrtc/rtc_certificate_generator.cc
index 4f5ff473c80..2b3924b4a22 100644
--- a/chromium/content/renderer/media/webrtc/rtc_certificate_generator.cc
+++ b/chromium/content/renderer/media/webrtc/rtc_certificate_generator.cc
@@ -12,7 +12,6 @@
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/renderer/media/webrtc/peer_connection_dependency_factory.h"
-#include "content/renderer/media/webrtc/rtc_certificate.h"
#include "content/renderer/render_thread_impl.h"
#include "media/media_buildflags.h"
#include "third_party/webrtc/rtc_base/rtccertificate.h"
@@ -91,15 +90,12 @@ class RTCCertificateGeneratorRequest
main_thread_->PostTask(
FROM_HERE,
base::BindOnce(&RTCCertificateGeneratorRequest::DoCallbackOnMainThread,
- this, std::move(observer),
- certificate
- ? std::make_unique<RTCCertificate>(certificate)
- : nullptr));
+ this, std::move(observer), certificate));
}
void DoCallbackOnMainThread(
CertificateCallbackPtr observer,
- std::unique_ptr<blink::WebRTCCertificate> certificate) {
+ rtc::scoped_refptr<rtc::RTCCertificate> certificate) {
DCHECK(main_thread_->BelongsToCurrentThread());
DCHECK(observer);
if (certificate)
@@ -155,7 +151,7 @@ bool RTCCertificateGenerator::IsSupportedKeyParams(
return WebRTCKeyParamsToKeyParams(key_params).IsValid();
}
-std::unique_ptr<blink::WebRTCCertificate> RTCCertificateGenerator::FromPEM(
+rtc::scoped_refptr<rtc::RTCCertificate> RTCCertificateGenerator::FromPEM(
blink::WebString pem_private_key,
blink::WebString pem_certificate) {
rtc::scoped_refptr<rtc::RTCCertificate> certificate =
@@ -163,7 +159,7 @@ std::unique_ptr<blink::WebRTCCertificate> RTCCertificateGenerator::FromPEM(
pem_private_key.Utf8(), pem_certificate.Utf8()));
if (!certificate)
return nullptr;
- return std::make_unique<RTCCertificate>(certificate);
+ return certificate;
}
} // namespace content
diff --git a/chromium/content/renderer/media/webrtc/rtc_certificate_generator.h b/chromium/content/renderer/media/webrtc/rtc_certificate_generator.h
index 5e29c7f62d4..f3fa2ce77f3 100644
--- a/chromium/content/renderer/media/webrtc/rtc_certificate_generator.h
+++ b/chromium/content/renderer/media/webrtc/rtc_certificate_generator.h
@@ -7,9 +7,9 @@
#include "base/macros.h"
#include "base/single_thread_task_runner.h"
-#include "third_party/blink/public/platform/web_rtc_certificate.h"
#include "third_party/blink/public/platform/web_rtc_certificate_generator.h"
#include "third_party/blink/public/platform/web_rtc_key_params.h"
+#include "third_party/webrtc/api/peerconnectioninterface.h"
namespace content {
@@ -32,7 +32,7 @@ class RTCCertificateGenerator : public blink::WebRTCCertificateGenerator {
std::unique_ptr<blink::WebRTCCertificateCallback> observer,
scoped_refptr<base::SingleThreadTaskRunner> task_runner) override;
bool IsSupportedKeyParams(const blink::WebRTCKeyParams& key_params) override;
- std::unique_ptr<blink::WebRTCCertificate> FromPEM(
+ rtc::scoped_refptr<rtc::RTCCertificate> FromPEM(
blink::WebString pem_private_key,
blink::WebString pem_certificate) override;
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 64bf108735c..15300aed087 100644
--- a/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler.cc
+++ b/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler.cc
@@ -30,7 +30,6 @@
#include "content/renderer/media/stream/media_stream_track.h"
#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_certificate.h"
#include "content/renderer/media/webrtc/rtc_data_channel_handler.h"
#include "content/renderer/media/webrtc/rtc_dtmf_sender_handler.h"
#include "content/renderer/media/webrtc/rtc_event_log_output_sink.h"
@@ -43,7 +42,6 @@
#include "media/base/media_switches.h"
#include "third_party/blink/public/platform/web_media_constraints.h"
#include "third_party/blink/public/platform/web_rtc_answer_options.h"
-#include "third_party/blink/public/platform/web_rtc_configuration.h"
#include "third_party/blink/public/platform/web_rtc_data_channel_init.h"
#include "third_party/blink/public/platform/web_rtc_ice_candidate.h"
#include "third_party/blink/public/platform/web_rtc_legacy_stats.h"
@@ -151,6 +149,16 @@ void RunClosureWithTrace(const base::Closure& closure,
closure.Run();
}
+void RunSynchronousOnceClosure(base::OnceClosure closure,
+ const char* trace_event_name,
+ base::WaitableEvent* event) {
+ {
+ TRACE_EVENT0("webrtc", trace_event_name);
+ std::move(closure).Run();
+ }
+ event->Signal();
+}
+
void RunSynchronousClosure(const base::Closure& closure,
const char* trace_event_name,
base::WaitableEvent* event) {
@@ -161,100 +169,24 @@ void RunSynchronousClosure(const base::Closure& closure,
event->Signal();
}
-void GetSdpAndTypeFromSessionDescription(
- const base::Callback<const webrtc::SessionDescriptionInterface*()>&
+// Initializes |web_description| if |description_callback| returns non-null,
+// otherwise does nothing.
+void GetWebRTCSessionDescriptionFromSessionDescriptionCallback(
+ base::OnceCallback<const webrtc::SessionDescriptionInterface*()>
description_callback,
- std::string* sdp, std::string* type) {
+ blink::WebRTCSessionDescription* web_description) {
const webrtc::SessionDescriptionInterface* description =
- description_callback.Run();
+ std::move(description_callback).Run();
if (description) {
- description->ToString(sdp);
- *type = description->type();
+ std::string sdp;
+ description->ToString(&sdp);
+ web_description->Initialize(blink::WebString::FromUTF8(description->type()),
+ blink::WebString::FromUTF8(sdp));
}
}
// Converter functions from Blink types to WebRTC types.
-// This function doesn't assume |webrtc_config| is empty. Any fields in
-// |blink_config| replace the corresponding fields in |webrtc_config|, but
-// fields that only exist in |webrtc_config| are left alone.
-void GetNativeRtcConfiguration(
- const blink::WebRTCConfiguration& blink_config,
- webrtc::PeerConnectionInterface::RTCConfiguration* webrtc_config) {
- DCHECK(webrtc_config);
-
- webrtc_config->servers.clear();
- for (const blink::WebRTCIceServer& blink_server : blink_config.ice_servers) {
- webrtc::PeerConnectionInterface::IceServer server;
- server.username = blink_server.username.Utf8();
- server.password = blink_server.credential.Utf8();
- server.uri = blink_server.url.GetString().Utf8();
- webrtc_config->servers.push_back(server);
- }
-
- switch (blink_config.ice_transport_policy) {
- case blink::WebRTCIceTransportPolicy::kRelay:
- webrtc_config->type = webrtc::PeerConnectionInterface::kRelay;
- break;
- case blink::WebRTCIceTransportPolicy::kAll:
- webrtc_config->type = webrtc::PeerConnectionInterface::kAll;
- break;
- default:
- NOTREACHED();
- }
-
- switch (blink_config.bundle_policy) {
- case blink::WebRTCBundlePolicy::kBalanced:
- webrtc_config->bundle_policy =
- webrtc::PeerConnectionInterface::kBundlePolicyBalanced;
- break;
- case blink::WebRTCBundlePolicy::kMaxBundle:
- webrtc_config->bundle_policy =
- webrtc::PeerConnectionInterface::kBundlePolicyMaxBundle;
- break;
- case blink::WebRTCBundlePolicy::kMaxCompat:
- webrtc_config->bundle_policy =
- webrtc::PeerConnectionInterface::kBundlePolicyMaxCompat;
- break;
- default:
- NOTREACHED();
- }
-
- switch (blink_config.rtcp_mux_policy) {
- case blink::WebRTCRtcpMuxPolicy::kNegotiate:
- webrtc_config->rtcp_mux_policy =
- webrtc::PeerConnectionInterface::kRtcpMuxPolicyNegotiate;
- break;
- case blink::WebRTCRtcpMuxPolicy::kRequire:
- webrtc_config->rtcp_mux_policy =
- webrtc::PeerConnectionInterface::kRtcpMuxPolicyRequire;
- break;
- default:
- NOTREACHED();
- }
-
- switch (blink_config.sdp_semantics) {
- case blink::WebRTCSdpSemantics::kPlanB:
- webrtc_config->sdp_semantics = webrtc::SdpSemantics::kPlanB;
- break;
- case blink::WebRTCSdpSemantics::kUnifiedPlan:
- webrtc_config->sdp_semantics = webrtc::SdpSemantics::kUnifiedPlan;
- break;
- case blink::WebRTCSdpSemantics::kDefault:
- NOTREACHED();
- }
-
- webrtc_config->certificates.clear();
- for (const std::unique_ptr<blink::WebRTCCertificate>& blink_certificate :
- blink_config.certificates) {
- webrtc_config->certificates.push_back(
- static_cast<RTCCertificate*>(blink_certificate.get())
- ->rtcCertificate());
- }
-
- webrtc_config->ice_candidate_pool_size = blink_config.ice_candidate_pool_size;
-}
-
absl::optional<bool> ConstraintToOptional(
const blink::WebMediaConstraints& constraints,
const blink::BooleanConstraint blink::WebMediaTrackConstraintSet::*picker) {
@@ -344,8 +276,10 @@ class CreateSessionDescriptionRequest
void OnSuccess(webrtc::SessionDescriptionInterface* desc) override {
if (!main_thread_->BelongsToCurrentThread()) {
main_thread_->PostTask(
- FROM_HERE, base::BindOnce(&CreateSessionDescriptionRequest::OnSuccess,
- this, desc));
+ FROM_HERE,
+ base::BindOnce(
+ &CreateSessionDescriptionRequest::OnSuccess,
+ rtc::scoped_refptr<CreateSessionDescriptionRequest>(this), desc));
return;
}
@@ -365,8 +299,11 @@ class CreateSessionDescriptionRequest
void OnFailure(webrtc::RTCError error) override {
if (!main_thread_->BelongsToCurrentThread()) {
main_thread_->PostTask(
- FROM_HERE, base::BindOnce(&CreateSessionDescriptionRequest::OnFailure,
- this, std::move(error)));
+ FROM_HERE,
+ base::BindOnce(
+ &CreateSessionDescriptionRequest::OnFailure,
+ rtc::scoped_refptr<CreateSessionDescriptionRequest>(this),
+ std::move(error)));
return;
}
@@ -443,7 +380,8 @@ class StatsResponse : public webrtc::StatsObserver {
main_thread_->PostTaskAndReply(
FROM_HERE,
- base::BindOnce(&StatsResponse::DeliverCallback, this,
+ base::BindOnce(&StatsResponse::DeliverCallback,
+ rtc::scoped_refptr<StatsResponse>(this),
base::Unretained(report_copies)),
base::BindOnce(&StatsResponse::DeleteReports,
base::Unretained(report_copies)));
@@ -694,26 +632,6 @@ bool IsRemoteStream(
return false;
}
-enum SdpSemanticRequested {
- kSdpSemanticRequestedDefault,
- kSdpSemanticRequestedPlanB,
- kSdpSemanticRequestedUnifiedPlan,
- kSdpSemanticRequestedMax
-};
-
-SdpSemanticRequested GetSdpSemanticRequested(
- blink::WebRTCSdpSemantics sdp_semantics) {
- switch (sdp_semantics) {
- case blink::WebRTCSdpSemantics::kDefault:
- return kSdpSemanticRequestedDefault;
- case blink::WebRTCSdpSemantics::kPlanB:
- return kSdpSemanticRequestedPlanB;
- case blink::WebRTCSdpSemantics::kUnifiedPlan:
- return kSdpSemanticRequestedUnifiedPlan;
- }
- NOTREACHED();
- return kSdpSemanticRequestedDefault;
-}
MediaStreamTrackMetrics::Kind MediaStreamTrackMetricsKind(
const blink::WebMediaStreamTrack& track) {
@@ -770,16 +688,13 @@ class RTCPeerConnectionHandler::WebRtcSetDescriptionObserverImpl
base::WeakPtr<PeerConnectionTracker> tracker,
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
PeerConnectionTracker::Action action,
- blink::WebRTCSdpSemantics sdp_semantics)
+ webrtc::SdpSemantics sdp_semantics)
: handler_(handler),
main_thread_(task_runner),
web_request_(web_request),
tracker_(tracker),
action_(action),
- sdp_semantics_(sdp_semantics) {
- DCHECK(sdp_semantics_ == blink::WebRTCSdpSemantics::kPlanB ||
- sdp_semantics_ == blink::WebRTCSdpSemantics::kUnifiedPlan);
- }
+ sdp_semantics_(sdp_semantics) {}
void OnSetDescriptionComplete(
webrtc::RTCError error,
@@ -799,10 +714,10 @@ class RTCPeerConnectionHandler::WebRtcSetDescriptionObserverImpl
// Process the rest of the state changes differently depending on SDP
// semantics.
- if (sdp_semantics_ == blink::WebRTCSdpSemantics::kPlanB) {
+ if (sdp_semantics_ == webrtc::SdpSemantics::kPlanB) {
ProcessStateChangesPlanB(std::move(states));
} else {
- DCHECK_EQ(sdp_semantics_, blink::WebRTCSdpSemantics::kUnifiedPlan);
+ DCHECK_EQ(sdp_semantics_, webrtc::SdpSemantics::kUnifiedPlan);
ProcessStateChangesUnifiedPlan(std::move(states));
}
@@ -840,7 +755,7 @@ class RTCPeerConnectionHandler::WebRtcSetDescriptionObserverImpl
}
void ProcessStateChangesPlanB(WebRtcSetDescriptionObserver::States states) {
- DCHECK_EQ(sdp_semantics_, blink::WebRTCSdpSemantics::kPlanB);
+ DCHECK_EQ(sdp_semantics_, webrtc::SdpSemantics::kPlanB);
// Determine which receivers have been removed before processing the
// removal as to not invalidate the iterator.
std::vector<RTCRtpReceiver*> removed_receivers;
@@ -887,7 +802,7 @@ class RTCPeerConnectionHandler::WebRtcSetDescriptionObserverImpl
void ProcessStateChangesUnifiedPlan(
WebRtcSetDescriptionObserver::States states) {
- DCHECK_EQ(sdp_semantics_, blink::WebRTCSdpSemantics::kUnifiedPlan);
+ DCHECK_EQ(sdp_semantics_, webrtc::SdpSemantics::kUnifiedPlan);
handler_->OnModifyTransceivers(
std::move(states.transceiver_states),
action_ == PeerConnectionTracker::ACTION_SET_REMOTE_DESCRIPTION);
@@ -898,7 +813,7 @@ class RTCPeerConnectionHandler::WebRtcSetDescriptionObserverImpl
blink::WebRTCVoidRequest web_request_;
base::WeakPtr<PeerConnectionTracker> tracker_;
PeerConnectionTracker::Action action_;
- blink::WebRTCSdpSemantics sdp_semantics_;
+ webrtc::SdpSemantics sdp_semantics_;
};
// Receives notifications from a PeerConnection object about state changes. The
@@ -1017,6 +932,21 @@ class RTCPeerConnectionHandler::Observer
}
}
+ void OnInterestingUsage(int usage_pattern) override {
+ main_thread_->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &RTCPeerConnectionHandler::Observer::OnInterestingUsageImpl, this,
+ usage_pattern));
+ }
+
+ void OnInterestingUsageImpl(int usage_pattern) {
+ DCHECK(main_thread_->BelongsToCurrentThread());
+ if (handler_) {
+ handler_->OnInterestingUsage(usage_pattern);
+ }
+ }
+
private:
const base::WeakPtr<RTCPeerConnectionHandler> handler_;
const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
@@ -1034,8 +964,6 @@ RTCPeerConnectionHandler::RTCPeerConnectionHandler(
track_adapter_map_(
new WebRtcMediaStreamTrackAdapterMap(dependency_factory_,
task_runner)),
- // This will be overwritten to the actual value used at Initialize().
- sdp_semantics_(blink::WebRTCSdpSemantics::kDefault),
task_runner_(std::move(task_runner)),
weak_factory_(this) {
CHECK(client_);
@@ -1063,9 +991,9 @@ void RTCPeerConnectionHandler::associateWithFrame(blink::WebLocalFrame* frame) {
}
bool RTCPeerConnectionHandler::Initialize(
- const blink::WebRTCConfiguration& server_configuration,
- const blink::WebMediaConstraints& options,
- blink::WebRTCSdpSemantics original_sdp_semantics_value) {
+ const webrtc::PeerConnectionInterface::RTCConfiguration&
+ server_configuration,
+ const blink::WebMediaConstraints& options) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
DCHECK(frame_);
@@ -1075,10 +1003,7 @@ bool RTCPeerConnectionHandler::Initialize(
peer_connection_tracker_ =
RenderThreadImpl::current()->peer_connection_tracker()->AsWeakPtr();
- sdp_semantics_ = server_configuration.sdp_semantics;
- DCHECK(sdp_semantics_ == blink::WebRTCSdpSemantics::kPlanB ||
- sdp_semantics_ == blink::WebRTCSdpSemantics::kUnifiedPlan);
- GetNativeRtcConfiguration(server_configuration, &configuration_);
+ configuration_ = server_configuration;
// Choose between RTC smoothness algorithm and prerenderer smoothing.
// Prerenderer smoothing is turned on if RTC smoothness is turned off.
@@ -1107,16 +1032,12 @@ bool RTCPeerConnectionHandler::Initialize(
options, frame_);
}
- UMA_HISTOGRAM_ENUMERATION(
- "WebRTC.PeerConnection.SdpSemanticRequested",
- GetSdpSemanticRequested(original_sdp_semantics_value),
- kSdpSemanticRequestedMax);
-
return true;
}
bool RTCPeerConnectionHandler::InitializeForTest(
- const blink::WebRTCConfiguration& server_configuration,
+ const webrtc::PeerConnectionInterface::RTCConfiguration&
+ server_configuration,
const blink::WebMediaConstraints& options,
const base::WeakPtr<PeerConnectionTracker>& peer_connection_tracker) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
@@ -1124,10 +1045,7 @@ bool RTCPeerConnectionHandler::InitializeForTest(
CHECK(!initialize_called_);
initialize_called_ = true;
- sdp_semantics_ = server_configuration.sdp_semantics;
- DCHECK(sdp_semantics_ == blink::WebRTCSdpSemantics::kPlanB ||
- sdp_semantics_ == blink::WebRTCSdpSemantics::kUnifiedPlan);
- GetNativeRtcConfiguration(server_configuration, &configuration_);
+ configuration_ = server_configuration;
peer_connection_observer_ =
new Observer(weak_factory_.GetWeakPtr(), task_runner_);
@@ -1280,10 +1198,10 @@ void RTCPeerConnectionHandler::SetLocalDescription(
new WebRtcSetDescriptionObserverImpl(
weak_factory_.GetWeakPtr(), request, peer_connection_tracker_,
task_runner_, PeerConnectionTracker::ACTION_SET_LOCAL_DESCRIPTION,
- sdp_semantics_));
+ configuration_.sdp_semantics));
bool surface_receivers_only =
- (sdp_semantics_ == blink::WebRTCSdpSemantics::kPlanB);
+ (configuration_.sdp_semantics == webrtc::SdpSemantics::kPlanB);
scoped_refptr<webrtc::SetSessionDescriptionObserver> webrtc_observer(
WebRtcSetLocalDescriptionObserverHandler::Create(
task_runner_, signaling_thread(), native_peer_connection_,
@@ -1349,10 +1267,10 @@ void RTCPeerConnectionHandler::SetRemoteDescription(
new WebRtcSetDescriptionObserverImpl(
weak_factory_.GetWeakPtr(), request, peer_connection_tracker_,
task_runner_, PeerConnectionTracker::ACTION_SET_REMOTE_DESCRIPTION,
- sdp_semantics_));
+ configuration_.sdp_semantics));
bool surface_receivers_only =
- (sdp_semantics_ == blink::WebRTCSdpSemantics::kPlanB);
+ (configuration_.sdp_semantics == webrtc::SdpSemantics::kPlanB);
rtc::scoped_refptr<webrtc::SetRemoteDescriptionObserverInterface>
webrtc_observer(WebRtcSetRemoteDescriptionObserverHandler::Create(
task_runner_, signaling_thread(),
@@ -1379,58 +1297,110 @@ blink::WebRTCSessionDescription RTCPeerConnectionHandler::LocalDescription() {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::localDescription");
- // Since local_description returns a pointer to a non-reference-counted object
- // that lives on the signaling thread, we cannot fetch a pointer to it and use
- // it directly here. Instead, we access the object completely on the signaling
- // thread.
- std::string sdp, type;
- base::Callback<const webrtc::SessionDescriptionInterface*()> description_cb =
- base::Bind(&webrtc::PeerConnectionInterface::local_description,
- native_peer_connection_);
- RunSynchronousClosureOnSignalingThread(
- base::Bind(&GetSdpAndTypeFromSessionDescription,
- std::move(description_cb), base::Unretained(&sdp),
- base::Unretained(&type)),
- "localDescription");
-
- return CreateWebKitSessionDescription(sdp, type);
+ base::OnceCallback<const webrtc::SessionDescriptionInterface*()>
+ description_cb =
+ base::BindOnce(&webrtc::PeerConnectionInterface::local_description,
+ native_peer_connection_);
+ return GetWebRTCSessionDescriptionOnSignalingThread(std::move(description_cb),
+ "localDescription");
}
blink::WebRTCSessionDescription RTCPeerConnectionHandler::RemoteDescription() {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::remoteDescription");
- // Since local_description returns a pointer to a non-reference-counted object
- // that lives on the signaling thread, we cannot fetch a pointer to it and use
- // it directly here. Instead, we access the object completely on the signaling
- // thread.
- std::string sdp, type;
- base::Callback<const webrtc::SessionDescriptionInterface*()> description_cb =
- base::Bind(&webrtc::PeerConnectionInterface::remote_description,
- native_peer_connection_);
- RunSynchronousClosureOnSignalingThread(
- base::Bind(&GetSdpAndTypeFromSessionDescription,
- std::move(description_cb), base::Unretained(&sdp),
- base::Unretained(&type)),
- "remoteDescription");
+ base::OnceCallback<const webrtc::SessionDescriptionInterface*()>
+ description_cb =
+ base::BindOnce(&webrtc::PeerConnectionInterface::remote_description,
+ native_peer_connection_);
+ return GetWebRTCSessionDescriptionOnSignalingThread(std::move(description_cb),
+ "remoteDescription");
+}
+
+blink::WebRTCSessionDescription
+RTCPeerConnectionHandler::CurrentLocalDescription() {
+ DCHECK(task_runner_->RunsTasksInCurrentSequence());
+ TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::currentLocalDescription");
+
+ base::OnceCallback<const webrtc::SessionDescriptionInterface*()>
+ description_cb = base::BindOnce(
+ &webrtc::PeerConnectionInterface::current_local_description,
+ native_peer_connection_);
+ return GetWebRTCSessionDescriptionOnSignalingThread(
+ std::move(description_cb), "currentLocalDescription");
+}
+
+blink::WebRTCSessionDescription
+RTCPeerConnectionHandler::CurrentRemoteDescription() {
+ DCHECK(task_runner_->RunsTasksInCurrentSequence());
+ TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::currentRemoteDescription");
+ base::OnceCallback<const webrtc::SessionDescriptionInterface*()>
+ description_cb = base::BindOnce(
+ &webrtc::PeerConnectionInterface::current_remote_description,
+ native_peer_connection_);
+ return GetWebRTCSessionDescriptionOnSignalingThread(
+ std::move(description_cb), "currentRemoteDescription");
+}
+
+blink::WebRTCSessionDescription
+RTCPeerConnectionHandler::PendingLocalDescription() {
+ DCHECK(task_runner_->RunsTasksInCurrentSequence());
+ TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::pendingLocalDescription");
+ base::OnceCallback<const webrtc::SessionDescriptionInterface*()>
+ description_cb = base::BindOnce(
+ &webrtc::PeerConnectionInterface::pending_local_description,
+ native_peer_connection_);
+ return GetWebRTCSessionDescriptionOnSignalingThread(
+ std::move(description_cb), "pendingLocalDescription");
+}
+
+blink::WebRTCSessionDescription
+RTCPeerConnectionHandler::PendingRemoteDescription() {
+ DCHECK(task_runner_->RunsTasksInCurrentSequence());
+ TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::pendingRemoteDescription");
+ base::OnceCallback<const webrtc::SessionDescriptionInterface*()>
+ description_cb = base::BindOnce(
+ &webrtc::PeerConnectionInterface::pending_remote_description,
+ native_peer_connection_);
+ return GetWebRTCSessionDescriptionOnSignalingThread(
+ std::move(description_cb), "pendingRemoteDescription");
+}
- return CreateWebKitSessionDescription(sdp, type);
+const webrtc::PeerConnectionInterface::RTCConfiguration&
+RTCPeerConnectionHandler::GetConfiguration() const {
+ return configuration_;
}
webrtc::RTCErrorType RTCPeerConnectionHandler::SetConfiguration(
- const blink::WebRTCConfiguration& blink_config) {
+ const webrtc::PeerConnectionInterface::RTCConfiguration& blink_config) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::setConfiguration");
- GetNativeRtcConfiguration(blink_config, &configuration_);
+
+ // Update the configuration with the potentially modified fields
+ webrtc::PeerConnectionInterface::RTCConfiguration new_configuration =
+ configuration_;
+ new_configuration.servers = blink_config.servers;
+ new_configuration.type = blink_config.type;
+ new_configuration.bundle_policy = blink_config.bundle_policy;
+ new_configuration.rtcp_mux_policy = blink_config.rtcp_mux_policy;
+ new_configuration.sdp_semantics = blink_config.sdp_semantics;
+ new_configuration.certificates = blink_config.certificates;
+ new_configuration.ice_candidate_pool_size =
+ blink_config.ice_candidate_pool_size;
if (peer_connection_tracker_)
- peer_connection_tracker_->TrackSetConfiguration(this, configuration_);
+ peer_connection_tracker_->TrackSetConfiguration(this, new_configuration);
webrtc::RTCError webrtc_error;
- bool ret =
- native_peer_connection_->SetConfiguration(configuration_, &webrtc_error);
+ bool ret = native_peer_connection_->SetConfiguration(new_configuration,
+ &webrtc_error);
// The boolean return value is made redundant by the error output param; just
// DCHECK that they're consistent.
DCHECK_EQ(ret, webrtc_error.type() == webrtc::RTCErrorType::NONE);
+
+ if (webrtc_error.ok()) {
+ configuration_ = new_configuration;
+ }
+
return webrtc_error.type();
}
@@ -1553,7 +1523,7 @@ webrtc::RTCErrorOr<std::unique_ptr<blink::WebRTCRtpTransceiver>>
RTCPeerConnectionHandler::AddTransceiverWithTrack(
const blink::WebMediaStreamTrack& web_track,
const webrtc::RtpTransceiverInit& init) {
- DCHECK_EQ(sdp_semantics_, blink::WebRTCSdpSemantics::kUnifiedPlan);
+ DCHECK_EQ(configuration_.sdp_semantics, webrtc::SdpSemantics::kUnifiedPlan);
DCHECK(task_runner_->RunsTasksInCurrentSequence());
std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref =
track_adapter_map_->GetOrCreateLocalTrackAdapter(web_track);
@@ -1600,7 +1570,7 @@ webrtc::RTCErrorOr<std::unique_ptr<blink::WebRTCRtpTransceiver>>
RTCPeerConnectionHandler::AddTransceiverWithKind(
std::string kind,
const webrtc::RtpTransceiverInit& init) {
- DCHECK_EQ(sdp_semantics_, blink::WebRTCSdpSemantics::kUnifiedPlan);
+ DCHECK_EQ(configuration_.sdp_semantics, webrtc::SdpSemantics::kUnifiedPlan);
DCHECK(task_runner_->RunsTasksInCurrentSequence());
cricket::MediaType media_type;
if (kind == webrtc::MediaStreamTrackInterface::kAudioKind) {
@@ -1692,7 +1662,7 @@ RTCPeerConnectionHandler::AddTrack(
auto transceiver_state = std::move(transceiver_states[0]);
std::unique_ptr<blink::WebRTCRtpTransceiver> web_transceiver;
- if (sdp_semantics_ == blink::WebRTCSdpSemantics::kPlanB) {
+ if (configuration_.sdp_semantics == webrtc::SdpSemantics::kPlanB) {
// Plan B: Create sender only.
DCHECK(transceiver_state.sender_state());
auto webrtc_sender = transceiver_state.sender_state()->webrtc_sender();
@@ -1705,7 +1675,7 @@ RTCPeerConnectionHandler::AddTrack(
web_transceiver = std::make_unique<RTCRtpSenderOnlyTransceiver>(
std::make_unique<RTCRtpSender>(*rtp_senders_.back().get()));
} else {
- DCHECK_EQ(sdp_semantics_, blink::WebRTCSdpSemantics::kUnifiedPlan);
+ DCHECK_EQ(configuration_.sdp_semantics, webrtc::SdpSemantics::kUnifiedPlan);
// Unified Plan: Create or recycle a transceiver.
auto transceiver = CreateOrUpdateTransceiver(std::move(transceiver_state));
web_transceiver = std::move(transceiver);
@@ -1735,10 +1705,11 @@ void RTCPeerConnectionHandler::AddTrackOnSignalingThread(
std::vector<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>> transceivers;
if (error_or_sender->ok()) {
auto sender = error_or_sender->value();
- if (sdp_semantics_ == blink::WebRTCSdpSemantics::kPlanB) {
+ if (configuration_.sdp_semantics == webrtc::SdpSemantics::kPlanB) {
transceivers = {new SurfaceSenderStateOnly(sender)};
} else {
- DCHECK_EQ(sdp_semantics_, blink::WebRTCSdpSemantics::kUnifiedPlan);
+ DCHECK_EQ(configuration_.sdp_semantics,
+ webrtc::SdpSemantics::kUnifiedPlan);
rtc::scoped_refptr<webrtc::RtpTransceiverInterface>
transceiver_for_sender = nullptr;
for (const auto& transceiver :
@@ -1760,7 +1731,7 @@ webrtc::RTCErrorOr<std::unique_ptr<blink::WebRTCRtpTransceiver>>
RTCPeerConnectionHandler::RemoveTrack(blink::WebRTCRtpSender* web_sender) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::RemoveTrack");
- if (sdp_semantics_ == blink::WebRTCSdpSemantics::kPlanB) {
+ if (configuration_.sdp_semantics == webrtc::SdpSemantics::kPlanB) {
if (RemoveTrackPlanB(web_sender)) {
// In Plan B, null indicates success.
std::unique_ptr<blink::WebRTCRtpTransceiver> web_transceiver = nullptr;
@@ -1770,13 +1741,13 @@ RTCPeerConnectionHandler::RemoveTrack(blink::WebRTCRtpSender* web_sender) {
// peerconnectioninterface.h is updated. https://crbug.com/webrtc/9534
return webrtc::RTCError(webrtc::RTCErrorType::INVALID_STATE);
}
- DCHECK_EQ(sdp_semantics_, blink::WebRTCSdpSemantics::kUnifiedPlan);
+ DCHECK_EQ(configuration_.sdp_semantics, webrtc::SdpSemantics::kUnifiedPlan);
return RemoveTrackUnifiedPlan(web_sender);
}
bool RTCPeerConnectionHandler::RemoveTrackPlanB(
blink::WebRTCRtpSender* web_sender) {
- DCHECK_EQ(sdp_semantics_, blink::WebRTCSdpSemantics::kPlanB);
+ DCHECK_EQ(configuration_.sdp_semantics, webrtc::SdpSemantics::kPlanB);
auto web_track = web_sender->Track();
auto it = FindSender(web_sender->Id());
if (it == rtp_senders_.end())
@@ -1810,7 +1781,7 @@ webrtc::RTCErrorOr<std::unique_ptr<blink::WebRTCRtpTransceiver>>
RTCPeerConnectionHandler::RemoveTrackUnifiedPlan(
blink::WebRTCRtpSender* web_sender) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
- DCHECK_EQ(sdp_semantics_, blink::WebRTCSdpSemantics::kUnifiedPlan);
+ DCHECK_EQ(configuration_.sdp_semantics, webrtc::SdpSemantics::kUnifiedPlan);
auto it = FindSender(web_sender->Id());
if (it == rtp_senders_.end())
return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER);
@@ -2122,7 +2093,7 @@ void RTCPeerConnectionHandler::OnRemoveReceiverPlanB(uintptr_t receiver_id) {
void RTCPeerConnectionHandler::OnModifyTransceivers(
std::vector<RtpTransceiverState> transceiver_states,
bool is_remote_description) {
- DCHECK_EQ(sdp_semantics_, blink::WebRTCSdpSemantics::kUnifiedPlan);
+ DCHECK_EQ(configuration_.sdp_semantics, webrtc::SdpSemantics::kUnifiedPlan);
std::vector<std::unique_ptr<blink::WebRTCRtpTransceiver>> web_transceivers(
transceiver_states.size());
PeerConnectionTracker::TransceiverUpdatedReason update_reason =
@@ -2216,6 +2187,10 @@ void RTCPeerConnectionHandler::OnIceCandidate(
client_->DidGenerateICECandidate(std::move(web_candidate));
}
+void RTCPeerConnectionHandler::OnInterestingUsage(int usage_pattern) {
+ client_->DidNoteInterestingUsage(usage_pattern);
+}
+
webrtc::SessionDescriptionInterface*
RTCPeerConnectionHandler::CreateNativeSessionDescription(
const std::string& sdp, const std::string& type,
@@ -2321,7 +2296,7 @@ size_t RTCPeerConnectionHandler::GetTransceiverIndex(
std::unique_ptr<RTCRtpTransceiver>
RTCPeerConnectionHandler::CreateOrUpdateTransceiver(
RtpTransceiverState transceiver_state) {
- DCHECK_EQ(sdp_semantics_, blink::WebRTCSdpSemantics::kUnifiedPlan);
+ DCHECK_EQ(configuration_.sdp_semantics, webrtc::SdpSemantics::kUnifiedPlan);
DCHECK(transceiver_state.is_initialized());
DCHECK(transceiver_state.sender_state());
DCHECK(transceiver_state.receiver_state());
@@ -2363,8 +2338,29 @@ RTCPeerConnectionHandler::signaling_thread() const {
return dependency_factory_->GetWebRtcSignalingThread();
}
+void RTCPeerConnectionHandler::RunSynchronousOnceClosureOnSignalingThread(
+ base::OnceClosure closure,
+ const char* trace_event_name) {
+ DCHECK(task_runner_->RunsTasksInCurrentSequence());
+ scoped_refptr<base::SingleThreadTaskRunner> thread(signaling_thread());
+ if (!thread.get() || thread->BelongsToCurrentThread()) {
+ TRACE_EVENT0("webrtc", trace_event_name);
+ std::move(closure).Run();
+ } else {
+ base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+ thread->PostTask(
+ FROM_HERE,
+ base::BindOnce(&RunSynchronousOnceClosure, std::move(closure),
+ base::Unretained(trace_event_name),
+ base::Unretained(&event)));
+ event.Wait();
+ }
+}
+
+// Deprecated version - uses a RepeatingCosure (aka old-style Closure)
void RTCPeerConnectionHandler::RunSynchronousClosureOnSignalingThread(
- const base::Closure& closure,
+ const base::RepeatingClosure& closure,
const char* trace_event_name) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
scoped_refptr<base::SingleThreadTaskRunner> thread(signaling_thread());
@@ -2382,6 +2378,27 @@ void RTCPeerConnectionHandler::RunSynchronousClosureOnSignalingThread(
}
}
+blink::WebRTCSessionDescription
+RTCPeerConnectionHandler::GetWebRTCSessionDescriptionOnSignalingThread(
+ base::OnceCallback<const webrtc::SessionDescriptionInterface*()>
+ description_cb,
+ const char* log_text) {
+ // Since the webrtc::PeerConnectionInterface::*_description() functions
+ // return a pointer to a non-reference-counted object that lives on the
+ // signaling thread, we cannot fetch a pointer to it and use it directly
+ // here.
+ // Instead, we access the object completely on the signaling thread.
+ // Initializing |description| on the signaling thread is safe because we
+ // own it and wait for it to be initialized here.
+
+ blink::WebRTCSessionDescription description; // IsNull() by default.
+ RunSynchronousOnceClosureOnSignalingThread(
+ base::BindOnce(&GetWebRTCSessionDescriptionFromSessionDescriptionCallback,
+ std::move(description_cb), base::Unretained(&description)),
+ log_text);
+ return description;
+}
+
void RTCPeerConnectionHandler::ReportICEState(
webrtc::PeerConnectionInterface::IceConnectionState new_state) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
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 74cb1b77c1a..091723acb64 100644
--- a/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler.h
+++ b/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler.h
@@ -26,7 +26,6 @@
#include "content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.h"
#include "ipc/ipc_platform_file.h"
#include "third_party/blink/public/platform/web_media_stream_source.h"
-#include "third_party/blink/public/platform/web_rtc_configuration.h"
#include "third_party/blink/public/platform/web_rtc_peer_connection_handler.h"
#include "third_party/blink/public/platform/web_rtc_stats_request.h"
#include "third_party/blink/public/platform/web_rtc_stats_response.h"
@@ -103,15 +102,15 @@ class CONTENT_EXPORT RTCPeerConnectionHandler
// Initialize method only used for unit test.
bool InitializeForTest(
- const blink::WebRTCConfiguration& server_configuration,
+ const webrtc::PeerConnectionInterface::RTCConfiguration&
+ server_configuration,
const blink::WebMediaConstraints& options,
const base::WeakPtr<PeerConnectionTracker>& peer_connection_tracker);
// blink::WebRTCPeerConnectionHandler implementation
- bool Initialize(
- const blink::WebRTCConfiguration& server_configuration,
- const blink::WebMediaConstraints& options,
- blink::WebRTCSdpSemantics original_sdp_semantics_value) override;
+ bool Initialize(const webrtc::PeerConnectionInterface::RTCConfiguration&
+ server_configuration,
+ const blink::WebMediaConstraints& options) override;
void CreateOffer(const blink::WebRTCSessionDescriptionRequest& request,
const blink::WebMediaConstraints& options) override;
@@ -132,9 +131,16 @@ class CONTENT_EXPORT RTCPeerConnectionHandler
blink::WebRTCSessionDescription LocalDescription() override;
blink::WebRTCSessionDescription RemoteDescription() override;
+ blink::WebRTCSessionDescription CurrentLocalDescription() override;
+ blink::WebRTCSessionDescription CurrentRemoteDescription() override;
+ blink::WebRTCSessionDescription PendingLocalDescription() override;
+ blink::WebRTCSessionDescription PendingRemoteDescription() override;
+ const webrtc::PeerConnectionInterface::RTCConfiguration& GetConfiguration()
+ const override;
webrtc::RTCErrorType SetConfiguration(
- const blink::WebRTCConfiguration& configuration) override;
+ const webrtc::PeerConnectionInterface::RTCConfiguration& configuration)
+ override;
bool AddICECandidate(
scoped_refptr<blink::WebRTCICECandidate> candidate) override;
bool AddICECandidate(
@@ -217,6 +223,7 @@ class CONTENT_EXPORT RTCPeerConnectionHandler
int sdp_mline_index,
int component,
int address_family);
+ void OnInterestingUsage(int usage_pattern);
private:
// Record info about the first SessionDescription from the local and
@@ -236,6 +243,11 @@ class CONTENT_EXPORT RTCPeerConnectionHandler
const std::string& type,
webrtc::SdpParseError* error);
+ blink::WebRTCSessionDescription GetWebRTCSessionDescriptionOnSignalingThread(
+ base::OnceCallback<const webrtc::SessionDescriptionInterface*()>
+ description_cb,
+ const char* log_text);
+
// Report to UMA whether an IceConnectionState has occurred. It only records
// the first occurrence of a given state.
void ReportICEState(
@@ -294,6 +306,8 @@ class CONTENT_EXPORT RTCPeerConnectionHandler
void RunSynchronousClosureOnSignalingThread(const base::Closure& closure,
const char* trace_event_name);
+ void RunSynchronousOnceClosureOnSignalingThread(base::OnceClosure closure,
+ const char* trace_event_name);
// Corresponds to the experimental RTCPeerConnection.id read-only attribute.
const std::string id_;
@@ -328,11 +342,7 @@ class CONTENT_EXPORT RTCPeerConnectionHandler
// In Plan B, senders and receivers are added or removed independently of one
// another. In Unified Plan, senders and receivers are created in pairs as
// transceivers. Transceivers may become inactive, but are never removed.
- // The value of this member affects the behavior of some methods and what
- // information is surfaced from webrtc. After Initialize(), this is the actual
- // mode used, meaning "kDefault" is no longer a valid value.
// TODO(hbos): Implement transceiver behaviors. https://crbug.com/777617
- blink::WebRTCSdpSemantics sdp_semantics_;
// Content layer correspondents of |webrtc::RtpSenderInterface|.
std::vector<std::unique_ptr<RTCRtpSender>> rtp_senders_;
// Content layer correspondents of |webrtc::RtpReceiverInterface|.
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 51a6af48d59..e281ec9de24 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
@@ -44,7 +44,6 @@
#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/platform/web_media_stream_track.h"
-#include "third_party/blink/public/platform/web_rtc_configuration.h"
#include "third_party/blink/public/platform/web_rtc_data_channel_handler.h"
#include "third_party/blink/public/platform/web_rtc_data_channel_init.h"
#include "third_party/blink/public/platform/web_rtc_dtmf_sender_handler.h"
@@ -279,8 +278,8 @@ class RTCPeerConnectionHandlerTest : public ::testing::Test {
mock_dependency_factory_.reset(new MockPeerConnectionDependencyFactory());
pc_handler_ = CreateRTCPeerConnectionHandlerUnderTest();
mock_tracker_.reset(new NiceMock<MockPeerConnectionTracker>());
- blink::WebRTCConfiguration config;
- config.sdp_semantics = blink::WebRTCSdpSemantics::kPlanB;
+ webrtc::PeerConnectionInterface::RTCConfiguration config;
+ config.sdp_semantics = webrtc::SdpSemantics::kPlanB;
blink::WebMediaConstraints constraints;
EXPECT_TRUE(pc_handler_->InitializeForTest(
config, constraints, mock_tracker_.get()->AsWeakPtr()));
@@ -704,7 +703,7 @@ TEST_F(RTCPeerConnectionHandlerTest, setLocalDescriptionParseError) {
pc_handler_->SetLocalDescription(request, description);
RunMessageLoopsUntilIdle();
// A description that failed to be applied shouldn't be stored.
- EXPECT_TRUE(pc_handler_->LocalDescription().Sdp().IsEmpty());
+ EXPECT_TRUE(pc_handler_->LocalDescription().IsNull());
}
TEST_F(RTCPeerConnectionHandlerTest, setRemoteDescription) {
@@ -760,26 +759,23 @@ TEST_F(RTCPeerConnectionHandlerTest, setRemoteDescriptionParseError) {
pc_handler_->SetRemoteDescription(request, description);
RunMessageLoopsUntilIdle();
// A description that failed to be applied shouldn't be stored.
- EXPECT_TRUE(pc_handler_->RemoteDescription().Sdp().IsEmpty());
+ EXPECT_TRUE(pc_handler_->RemoteDescription().IsNull());
}
TEST_F(RTCPeerConnectionHandlerTest, setConfiguration) {
- blink::WebRTCConfiguration config;
- config.sdp_semantics = blink::WebRTCSdpSemantics::kPlanB;
+ webrtc::PeerConnectionInterface::RTCConfiguration config;
+ config.sdp_semantics = webrtc::SdpSemantics::kPlanB;
EXPECT_CALL(*mock_tracker_.get(),
TrackSetConfiguration(pc_handler_.get(), _));
- // TODO(perkj): Test that the parameters in |config| can be translated when a
- // WebRTCConfiguration can be constructed. It's WebKit class and can't be
- // initialized from a test.
EXPECT_EQ(webrtc::RTCErrorType::NONE, pc_handler_->SetConfiguration(config));
}
// Test that when an error occurs in SetConfiguration, it's converted to a
// blink error and false is returned.
TEST_F(RTCPeerConnectionHandlerTest, setConfigurationError) {
- blink::WebRTCConfiguration config;
- config.sdp_semantics = blink::WebRTCSdpSemantics::kPlanB;
+ webrtc::PeerConnectionInterface::RTCConfiguration config;
+ config.sdp_semantics = webrtc::SdpSemantics::kPlanB;
mock_peer_connection_->set_setconfiguration_error_type(
webrtc::RTCErrorType::INVALID_MODIFICATION);
diff --git a/chromium/content/renderer/media/webrtc/rtc_rtp_receiver_unittest.cc b/chromium/content/renderer/media/webrtc/rtc_rtp_receiver_unittest.cc
index ebe77e3780c..4d4a13c3e5a 100644
--- a/chromium/content/renderer/media/webrtc/rtc_rtp_receiver_unittest.cc
+++ b/chromium/content/renderer/media/webrtc/rtc_rtp_receiver_unittest.cc
@@ -8,10 +8,10 @@
#include "base/logging.h"
#include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.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 "content/child/child_process.h"
#include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h"
#include "content/renderer/media/webrtc/mock_peer_connection_impl.h"
@@ -97,9 +97,10 @@ class RTCRtpReceiverTest : public ::testing::Test {
run_loop->Quit();
}
- // Message loop and child processes is needed for task queues and threading to
- // work, as is necessary to create tracks and adapters.
- base::MessageLoop message_loop_;
+ // Code under test expects to be run in a process with an initialized
+ // ChildProcess, which requires TaskScheduler, and a main-thread MessageLoop,
+ // which the ScopedTaskEnvironment also provides.
+ base::test::ScopedTaskEnvironment task_environment_;
ChildProcess child_process_;
std::unique_ptr<MockPeerConnectionDependencyFactory> dependency_factory_;
diff --git a/chromium/content/renderer/media/webrtc/rtc_rtp_sender_unittest.cc b/chromium/content/renderer/media/webrtc/rtc_rtp_sender_unittest.cc
index 0f3f27f9dad..8535d659593 100644
--- a/chromium/content/renderer/media/webrtc/rtc_rtp_sender_unittest.cc
+++ b/chromium/content/renderer/media/webrtc/rtc_rtp_sender_unittest.cc
@@ -7,9 +7,9 @@
#include <memory>
#include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
+#include "base/test/scoped_task_environment.h"
#include "build/build_config.h"
#include "content/child/child_process.h"
#include "content/renderer/media/stream/media_stream_audio_source.h"
@@ -136,9 +136,10 @@ class RTCRtpSenderTest : public ::testing::Test {
return *result_holder;
}
- // Message loop and child processes is needed for task queues and threading to
- // work, as is necessary to create tracks and adapters.
- base::MessageLoop message_loop_;
+ // Code under test expects to be run in a process with an initialized
+ // ChildProcess, which requires TaskScheduler, and a main-thread MessageLoop,
+ // which the ScopedTaskEnvironment also provides.
+ base::test::ScopedTaskEnvironment task_environment_;
ChildProcess child_process_;
std::unique_ptr<MockPeerConnectionDependencyFactory> dependency_factory_;
diff --git a/chromium/content/renderer/media/webrtc/rtc_stats.cc b/chromium/content/renderer/media/webrtc/rtc_stats.cc
index a24ef5bc613..8471bdb9bca 100644
--- a/chromium/content/renderer/media/webrtc/rtc_stats.cc
+++ b/chromium/content/renderer/media/webrtc/rtc_stats.cc
@@ -322,8 +322,8 @@ void RTCStatsCollectorCallbackImpl::OnStatsDelivered(
main_thread_->PostTask(
FROM_HERE,
base::BindOnce(
- &RTCStatsCollectorCallbackImpl::OnStatsDeliveredOnMainThread, this,
- report));
+ &RTCStatsCollectorCallbackImpl::OnStatsDeliveredOnMainThread,
+ rtc::scoped_refptr<RTCStatsCollectorCallbackImpl>(this), report));
}
void RTCStatsCollectorCallbackImpl::OnStatsDeliveredOnMainThread(
diff --git a/chromium/content/renderer/media/webrtc/rtc_video_decoder_adapter.cc b/chromium/content/renderer/media/webrtc/rtc_video_decoder_adapter.cc
new file mode 100644
index 00000000000..e64ad90561a
--- /dev/null
+++ b/chromium/content/renderer/media/webrtc/rtc_video_decoder_adapter.cc
@@ -0,0 +1,395 @@
+// 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/renderer/media/webrtc/rtc_video_decoder_adapter.h"
+
+#include <algorithm>
+
+#include "base/bind.h"
+#include "base/command_line.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/memory/ptr_util.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/sequenced_task_runner.h"
+#include "base/single_thread_task_runner.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "build/build_config.h"
+#include "content/renderer/media/render_media_log.h"
+#include "content/renderer/media/webrtc/webrtc_video_frame_adapter.h"
+#include "media/base/media_log.h"
+#include "media/base/media_util.h"
+#include "media/base/video_types.h"
+#include "media/video/gpu_video_accelerator_factories.h"
+#include "third_party/webrtc/api/video/video_frame.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/refcount.h"
+#include "third_party/webrtc/rtc_base/refcountedobject.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 {
+
+namespace {
+
+// Any reasonable size, will be overridden by the decoder anyway.
+//
+// TODO(sandersd): DXVA VDA does not compute a visible rect itself; we should
+// not enable RTCVideoDecoderAdapter on Windows until that is fixed.
+// https://crbug.com/869660.
+const gfx::Size kDefaultSize(640, 480);
+
+// Assumed pixel format of the encoded content. WebRTC doesn't tell us, and in
+// practice the decoders ignore it. We're going with generic 4:2:0.
+const media::VideoPixelFormat kDefaultPixelFormat = media::PIXEL_FORMAT_I420;
+
+// Maximum number of buffers that we will queue in |pending_buffers_|.
+const int32_t kMaxPendingBuffers = 8;
+
+// Maximum number of timestamps that will be maintained in |decode_timestamps_|.
+// Really only needs to be a bit larger than the maximum reorder distance (which
+// is presumably 0 for WebRTC), but being larger doesn't hurt much.
+const int32_t kMaxDecodeHistory = 32;
+
+// Maximum number of consecutive frames that can fail to decode before
+// requesting fallback to software decode.
+const int32_t kMaxConsecutiveErrors = 5;
+
+// Map webrtc::VideoCodecType to media::VideoCodec.
+media::VideoCodec ToVideoCodec(webrtc::VideoCodecType video_codec_type) {
+ switch (video_codec_type) {
+ case webrtc::kVideoCodecVP8:
+ return media::kCodecVP8;
+ case webrtc::kVideoCodecVP9:
+ return media::kCodecVP9;
+ case webrtc::kVideoCodecH264:
+ return media::kCodecH264;
+ default:
+ return media::kUnknownVideoCodec;
+ }
+}
+
+// Map webrtc::VideoCodecType to a guess for media::VideoCodecProfile.
+media::VideoCodecProfile GuessVideoCodecProfile(
+ webrtc::VideoCodecType video_codec_type) {
+ switch (video_codec_type) {
+ case webrtc::kVideoCodecVP8:
+ return media::VP8PROFILE_ANY;
+ case webrtc::kVideoCodecVP9:
+ return media::VP9PROFILE_PROFILE0;
+ case webrtc::kVideoCodecH264:
+ return media::H264PROFILE_BASELINE;
+ default:
+ return media::VIDEO_CODEC_PROFILE_UNKNOWN;
+ }
+}
+
+void FinishWait(base::WaitableEvent* waiter, bool* result_out, bool result) {
+ DVLOG(3) << __func__ << "(" << result << ")";
+ *result_out = result;
+ waiter->Signal();
+}
+
+} // namespace
+
+// static
+std::unique_ptr<RTCVideoDecoderAdapter> RTCVideoDecoderAdapter::Create(
+ webrtc::VideoCodecType video_codec_type,
+ media::GpuVideoAcceleratorFactories* gpu_factories,
+ CreateVideoDecoderCB create_video_decoder_cb) {
+ DVLOG(1) << __func__ << "(" << video_codec_type << ")";
+
+#if defined(OS_WIN)
+ // Do not use hardware decoding for H.264 on Win7, due to high latency.
+ // See https://crbug.com/webrtc/5717.
+ if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableWin7WebRtcHWH264Decoding) &&
+ video_codec_type == webrtc::kVideoCodecH264 &&
+ base::win::GetVersion() == base::win::VERSION_WIN7) {
+ DVLOG(1) << "H.264 HW decoding is not supported on Win7";
+ return nullptr;
+ }
+#endif // defined(OS_WIN)
+
+ // Short circuit known-unsupported codecs.
+ if (ToVideoCodec(video_codec_type) == media::kUnknownVideoCodec)
+ return nullptr;
+
+ std::unique_ptr<RTCVideoDecoderAdapter> rtc_video_decoder_adapter =
+ base::WrapUnique(new RTCVideoDecoderAdapter(
+ gpu_factories->GetTaskRunner(), std::move(create_video_decoder_cb),
+ video_codec_type));
+
+ // Synchronously verify that the decoder can be initialized.
+ if (!rtc_video_decoder_adapter->InitializeSync()) {
+ DeleteSoonOnMediaThread(std::move(rtc_video_decoder_adapter),
+ gpu_factories);
+ return nullptr;
+ }
+
+ return rtc_video_decoder_adapter;
+}
+
+// static
+void RTCVideoDecoderAdapter::DeleteSoonOnMediaThread(
+ std::unique_ptr<webrtc::VideoDecoder> rtc_video_decoder_adapter,
+ media::GpuVideoAcceleratorFactories* gpu_factories) {
+ gpu_factories->GetTaskRunner()->DeleteSoon(
+ FROM_HERE, std::move(rtc_video_decoder_adapter));
+}
+
+RTCVideoDecoderAdapter::RTCVideoDecoderAdapter(
+ scoped_refptr<base::SingleThreadTaskRunner> media_task_runner,
+ CreateVideoDecoderCB create_video_decoder_cb,
+ webrtc::VideoCodecType video_codec_type)
+ : media_task_runner_(std::move(media_task_runner)),
+ create_video_decoder_cb_(std::move(create_video_decoder_cb)),
+ video_codec_type_(video_codec_type),
+ weak_this_factory_(this) {
+ DVLOG(1) << __func__;
+ DETACH_FROM_THREAD(decoding_thread_checker_);
+ weak_this_ = weak_this_factory_.GetWeakPtr();
+}
+
+RTCVideoDecoderAdapter::~RTCVideoDecoderAdapter() {
+ DVLOG(1) << __func__;
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
+}
+
+bool RTCVideoDecoderAdapter::InitializeSync() {
+ DVLOG(3) << __func__;
+ DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
+
+ bool result = false;
+ base::WaitableEvent waiter(base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+ media::VideoDecoder::InitCB init_cb =
+ base::BindRepeating(&FinishWait, &waiter, &result);
+ if (media_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&RTCVideoDecoderAdapter::InitializeOnMediaThread,
+ base::Unretained(this), std::move(init_cb)))) {
+ waiter.Wait();
+ }
+ return result;
+}
+
+int32_t RTCVideoDecoderAdapter::InitDecode(
+ const webrtc::VideoCodec* codec_settings,
+ int32_t number_of_cores) {
+ DVLOG(1) << __func__;
+ DCHECK_CALLED_ON_VALID_THREAD(decoding_thread_checker_);
+ DCHECK_EQ(video_codec_type_, codec_settings->codecType);
+
+ base::AutoLock auto_lock(lock_);
+ UMA_HISTOGRAM_BOOLEAN("Media.RTCVideoDecoderInitDecodeSuccess", !has_error_);
+ return has_error_ ? WEBRTC_VIDEO_CODEC_UNINITIALIZED : WEBRTC_VIDEO_CODEC_OK;
+}
+
+int32_t RTCVideoDecoderAdapter::Decode(
+ const webrtc::EncodedImage& input_image,
+ bool missing_frames,
+ const webrtc::CodecSpecificInfo* codec_specific_info,
+ int64_t render_time_ms) {
+ DVLOG(2) << __func__;
+ DCHECK_CALLED_ON_VALID_THREAD(decoding_thread_checker_);
+
+#if defined(OS_WIN)
+ // Hardware VP9 decoders don't handle more than one spatial layer. Fall back
+ // to software decoding. See https://crbug.com/webrtc/9304.
+ if (codec_specific_info &&
+ codec_specific_info->codecType == webrtc::kVideoCodecVP9 &&
+ codec_specific_info->codecSpecific.VP9.ss_data_available &&
+ codec_specific_info->codecSpecific.VP9.num_spatial_layers > 1) {
+ return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
+ }
+#endif // defined(OS_WIN)
+
+ if (missing_frames || !input_image._completeFrame) {
+ DVLOG(2) << "Missing or incomplete frames";
+ // We probably can't handle broken frames. Request a key frame.
+ return WEBRTC_VIDEO_CODEC_ERROR;
+ }
+
+ // Convert to media::DecoderBuffer.
+ // TODO(sandersd): What is |render_time_ms|?
+ scoped_refptr<media::DecoderBuffer> buffer =
+ media::DecoderBuffer::CopyFrom(input_image._buffer, input_image._length);
+ buffer->set_timestamp(
+ base::TimeDelta::FromMicroseconds(input_image._timeStamp));
+
+ // Queue for decoding.
+ {
+ base::AutoLock auto_lock(lock_);
+ if (has_error_)
+ return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
+ if (pending_buffers_.size() >= kMaxPendingBuffers) {
+ // We are severely behind. Drop pending buffers and request a keyframe to
+ // catch up as quickly as possible.
+ DVLOG(2) << "Pending buffers overflow";
+ if (++consecutive_error_count_ > kMaxConsecutiveErrors) {
+ pending_buffers_.clear();
+ decode_timestamps_.clear();
+ return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
+ }
+ pending_buffers_.clear();
+ return WEBRTC_VIDEO_CODEC_ERROR;
+ }
+ pending_buffers_.push_back(std::move(buffer));
+ }
+ media_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&RTCVideoDecoderAdapter::DecodeOnMediaThread, weak_this_));
+
+ return WEBRTC_VIDEO_CODEC_OK;
+}
+
+int32_t RTCVideoDecoderAdapter::RegisterDecodeCompleteCallback(
+ webrtc::DecodedImageCallback* callback) {
+ DVLOG(2) << __func__;
+ DCHECK_CALLED_ON_VALID_THREAD(decoding_thread_checker_);
+ DCHECK(callback);
+
+ base::AutoLock auto_lock(lock_);
+ decode_complete_callback_ = callback;
+ return has_error_ ? WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE
+ : WEBRTC_VIDEO_CODEC_OK;
+}
+
+int32_t RTCVideoDecoderAdapter::Release() {
+ DVLOG(1) << __func__;
+ DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
+
+ base::AutoLock auto_lock(lock_);
+ pending_buffers_.clear();
+ decode_timestamps_.clear();
+ return has_error_ ? WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE
+ : WEBRTC_VIDEO_CODEC_OK;
+}
+
+const char* RTCVideoDecoderAdapter::ImplementationName() const {
+ return "ExternalDecoder";
+}
+
+void RTCVideoDecoderAdapter::InitializeOnMediaThread(
+ media::VideoDecoder::InitCB init_cb) {
+ DVLOG(3) << __func__;
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
+
+ // TODO(sandersd): Plumb a real log sink here so that we can contribute to the
+ // media-internals UI. The current log just discards all messages.
+ media_log_ = std::make_unique<media::MediaLog>();
+
+ video_decoder_ = create_video_decoder_cb_.Run(media_log_.get());
+ if (!video_decoder_) {
+ media_task_runner_->PostTask(FROM_HERE,
+ base::BindRepeating(init_cb, false));
+ return;
+ }
+
+ // We don't know much about the media that is coming.
+ media::VideoDecoderConfig config(
+ ToVideoCodec(video_codec_type_),
+ GuessVideoCodecProfile(video_codec_type_), kDefaultPixelFormat,
+ media::COLOR_SPACE_UNSPECIFIED, media::VIDEO_ROTATION_0, kDefaultSize,
+ gfx::Rect(kDefaultSize), kDefaultSize, media::EmptyExtraData(),
+ media::Unencrypted());
+
+ // In practice this is ignored by hardware decoders.
+ bool low_delay = true;
+
+ // Encryption is not supported.
+ media::CdmContext* cdm_context = nullptr;
+ media::VideoDecoder::WaitingForDecryptionKeyCB waiting_cb;
+
+ media::VideoDecoder::OutputCB output_cb =
+ base::BindRepeating(&RTCVideoDecoderAdapter::OnOutput, weak_this_);
+
+ video_decoder_->Initialize(config, low_delay, cdm_context, std::move(init_cb),
+ std::move(output_cb), std::move(waiting_cb));
+}
+
+void RTCVideoDecoderAdapter::DecodeOnMediaThread() {
+ DVLOG(4) << __func__;
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
+
+ int max_decode_requests = video_decoder_->GetMaxDecodeRequests();
+ while (outstanding_decode_requests_ < max_decode_requests) {
+ scoped_refptr<media::DecoderBuffer> buffer;
+ {
+ base::AutoLock auto_lock(lock_);
+
+ // Take the first pending buffer.
+ if (pending_buffers_.empty())
+ return;
+ buffer = pending_buffers_.front();
+ pending_buffers_.pop_front();
+
+ // Record the timestamp.
+ while (decode_timestamps_.size() >= kMaxDecodeHistory)
+ decode_timestamps_.pop_front();
+ decode_timestamps_.push_back(buffer->timestamp());
+ }
+
+ // Submit for decoding.
+ outstanding_decode_requests_++;
+ video_decoder_->Decode(
+ std::move(buffer),
+ base::BindRepeating(&RTCVideoDecoderAdapter::OnDecodeDone, weak_this_));
+ }
+}
+
+void RTCVideoDecoderAdapter::OnDecodeDone(media::DecodeStatus status) {
+ DVLOG(3) << __func__ << "(" << status << ")";
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
+
+ outstanding_decode_requests_--;
+
+ if (status == media::DecodeStatus::DECODE_ERROR) {
+ DVLOG(2) << "Entering permanent error state";
+ UMA_HISTOGRAM_ENUMERATION("Media.RTCVideoDecoderError",
+ media::VideoDecodeAccelerator::PLATFORM_FAILURE,
+ media::VideoDecodeAccelerator::ERROR_MAX + 1);
+
+ base::AutoLock auto_lock(lock_);
+ has_error_ = true;
+ pending_buffers_.clear();
+ decode_timestamps_.clear();
+ return;
+ }
+
+ DecodeOnMediaThread();
+}
+
+void RTCVideoDecoderAdapter::OnOutput(
+ const 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);
+
+ base::AutoLock auto_lock(lock_);
+
+ if (std::find(decode_timestamps_.begin(), decode_timestamps_.end(),
+ frame->timestamp()) == decode_timestamps_.end()) {
+ DVLOG(2) << "Discarding frame with timestamp " << frame->timestamp();
+ return;
+ }
+
+ // Assumes that Decoded() can be safely called with the lock held, which
+ // apparently it can be because RTCVideoDecoder does the same.
+ DCHECK(decode_complete_callback_);
+ decode_complete_callback_->Decoded(rtc_frame);
+ consecutive_error_count_ = 0;
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/media/webrtc/rtc_video_decoder_adapter.h b/chromium/content/renderer/media/webrtc/rtc_video_decoder_adapter.h
new file mode 100644
index 00000000000..e7c6c8cc1e5
--- /dev/null
+++ b/chromium/content/renderer/media/webrtc/rtc_video_decoder_adapter.h
@@ -0,0 +1,137 @@
+// 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_RENDERER_MEDIA_WEBRTC_RTC_VIDEO_DECODER_ADAPTER_H_
+#define CONTENT_RENDERER_MEDIA_WEBRTC_RTC_VIDEO_DECODER_ADAPTER_H_
+
+#include <memory>
+
+#include "base/callback_forward.h"
+#include "base/containers/circular_deque.h"
+#include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/synchronization/lock.h"
+#include "base/threading/thread_checker.h"
+#include "content/common/content_export.h"
+#include "media/base/decode_status.h"
+#include "media/base/video_codecs.h"
+#include "media/base/video_decoder.h"
+#include "third_party/webrtc/modules/video_coding/include/video_codec_interface.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace base {
+class SingleThreadTaskRunner;
+} // namespace base
+
+namespace media {
+class DecoderBuffer;
+class GpuVideoAcceleratorFactories;
+class MediaLog;
+class VideoFrame;
+} // namespace media
+
+namespace content {
+
+// This class decodes video for WebRTC using a media::VideoDecoder. In
+// particular, either GpuVideoDecoder or MojoVideoDecoder are used to provide
+// access to hardware decoding in the GPU process.
+//
+// Lifecycle methods are called on the WebRTC worker thread. Decoding happens on
+// a WebRTC DecodingThread, which is an rtc::PlatformThread owend by WebRTC; it
+// does not have a TaskRunner.
+//
+// To stop decoding, WebRTC stops the DecodingThread and then calls Release() on
+// the worker. Calling the DecodedImageCallback after the DecodingThread is
+// stopped is illegal but, because we decode on the media thread, there is no
+// way to synchronize this correctly.
+class CONTENT_EXPORT RTCVideoDecoderAdapter : public webrtc::VideoDecoder {
+ public:
+ using CreateVideoDecoderCB =
+ base::RepeatingCallback<std::unique_ptr<media::VideoDecoder>(
+ media::MediaLog*)>;
+
+ // Creates and initializes an RTCVideoDecoderAdapter. Returns nullptr if
+ // |video_codec_type| cannot be supported.
+ // Called on the worker thread.
+ static std::unique_ptr<RTCVideoDecoderAdapter> Create(
+ webrtc::VideoCodecType video_codec_type,
+ media::GpuVideoAcceleratorFactories* gpu_factories,
+ CreateVideoDecoderCB create_video_decoder_cb);
+
+ // Called on the worker thread.
+ static void DeleteSoonOnMediaThread(
+ std::unique_ptr<webrtc::VideoDecoder> rtc_video_decoder_adapter,
+ media::GpuVideoAcceleratorFactories* gpu_factories);
+
+ // Called on |media_task_runner_|.
+ ~RTCVideoDecoderAdapter() override;
+
+ // webrtc::VideoDecoder implementation.
+ // Called on the DecodingThread.
+ int32_t InitDecode(const webrtc::VideoCodec* codec_settings,
+ int32_t number_of_cores) override;
+ // Called on the DecodingThread.
+ int32_t RegisterDecodeCompleteCallback(
+ webrtc::DecodedImageCallback* callback) override;
+ // Called on the DecodingThread.
+ int32_t Decode(const webrtc::EncodedImage& input_image,
+ bool missing_frames,
+ const webrtc::CodecSpecificInfo* codec_specific_info,
+ int64_t render_time_ms) override;
+ // Called on the worker thread.
+ int32_t Release() override;
+ // Called on the worker thread and on the DecodingThread.
+ const char* ImplementationName() const override;
+
+ private:
+ // |create_video_decoder_cb| will always be called on |media_task_runner|.
+ // Called on the worker thread.
+ RTCVideoDecoderAdapter(
+ scoped_refptr<base::SingleThreadTaskRunner> media_task_runner,
+ CreateVideoDecoderCB create_video_decoder_cb,
+ webrtc::VideoCodecType video_codec_type);
+
+ bool InitializeSync();
+ void InitializeOnMediaThread(media::VideoDecoder::InitCB init_cb);
+ void DecodeOnMediaThread();
+ void OnDecodeDone(media::DecodeStatus status);
+ void OnOutput(const scoped_refptr<media::VideoFrame>& frame);
+
+ // Construction parameters.
+ scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_;
+ CreateVideoDecoderCB create_video_decoder_cb_;
+ webrtc::VideoCodecType video_codec_type_;
+
+ // Media thread members.
+ // |media_log_| must outlive |video_decoder_| because it is passed as a raw
+ // pointer.
+ std::unique_ptr<media::MediaLog> media_log_;
+ std::unique_ptr<media::VideoDecoder> video_decoder_;
+ int32_t outstanding_decode_requests_ = 0;
+
+ // Shared members.
+ base::Lock lock_;
+ int32_t consecutive_error_count_ = 0;
+ bool has_error_ = false;
+ webrtc::DecodedImageCallback* decode_complete_callback_ = nullptr;
+ // Requests that have not been submitted to the decoder yet.
+ base::circular_deque<scoped_refptr<media::DecoderBuffer>> pending_buffers_;
+ // Record of timestamps that have been sent to be decoded. Removing a
+ // timestamp will cause the frame to be dropped when it is output.
+ base::circular_deque<base::TimeDelta> decode_timestamps_;
+
+ // Thread management.
+ THREAD_CHECKER(worker_thread_checker_);
+ THREAD_CHECKER(decoding_thread_checker_);
+
+ base::WeakPtr<RTCVideoDecoderAdapter> weak_this_;
+ base::WeakPtrFactory<RTCVideoDecoderAdapter> weak_this_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(RTCVideoDecoderAdapter);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_MEDIA_WEBRTC_RTC_VIDEO_DECODER_ADAPTER_H_
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
new file mode 100644
index 00000000000..1b0c4e1e6d7
--- /dev/null
+++ b/chromium/content/renderer/media/webrtc/rtc_video_decoder_adapter_unittest.cc
@@ -0,0 +1,276 @@
+// 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 <memory>
+#include <vector>
+
+#include <stdint.h>
+
+#include "base/callback_forward.h"
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/memory/ptr_util.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/test/mock_callback.h"
+#include "base/test/scoped_task_environment.h"
+#include "base/threading/thread.h"
+#include "base/time/time.h"
+#include "content/renderer/media/webrtc/rtc_video_decoder_adapter.h"
+#include "gpu/command_buffer/common/mailbox.h"
+#include "media/base/decode_status.h"
+#include "media/base/gmock_callback_support.h"
+#include "media/base/media_util.h"
+#include "media/base/video_decoder.h"
+#include "media/base/video_decoder_config.h"
+#include "media/base/video_frame.h"
+#include "media/base/video_types.h"
+#include "media/video/mock_gpu_video_accelerator_factories.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/size.h"
+
+using ::testing::_;
+using ::testing::AtLeast;
+using ::testing::DoAll;
+using ::testing::Mock;
+using ::testing::Return;
+using ::testing::SaveArg;
+using ::testing::StrictMock;
+
+namespace content {
+
+namespace {
+
+class MockVideoDecoder : public media::VideoDecoder {
+ public:
+ std::string GetDisplayName() const override { return "MockVideoDecoder"; }
+ MOCK_METHOD6(
+ Initialize,
+ void(const media::VideoDecoderConfig& config,
+ bool low_delay,
+ media::CdmContext* cdm_context,
+ const InitCB& init_cb,
+ const OutputCB& output_cb,
+ const WaitingForDecryptionKeyCB& waiting_for_decryption_key_cb));
+ MOCK_METHOD2(Decode,
+ void(scoped_refptr<media::DecoderBuffer> buffer,
+ const DecodeCB&));
+ MOCK_METHOD1(Reset, void(const base::RepeatingClosure&));
+ bool NeedsBitstreamConversion() const override { return false; }
+ bool CanReadWithoutStalling() const override { return true; }
+ int GetMaxDecodeRequests() const override { return 1; }
+};
+
+// Wraps a callback as a webrtc::DecodedImageCallback.
+class DecodedImageCallback : public webrtc::DecodedImageCallback {
+ public:
+ DecodedImageCallback(
+ base::RepeatingCallback<void(const webrtc::VideoFrame&)> callback)
+ : callback_(callback) {}
+
+ int32_t Decoded(webrtc::VideoFrame& decodedImage) override {
+ callback_.Run(decodedImage);
+ // TODO(sandersd): Does the return value matter? RTCVideoDecoder
+ // ignores it.
+ return 0;
+ }
+
+ private:
+ base::RepeatingCallback<void(const webrtc::VideoFrame&)> callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(DecodedImageCallback);
+};
+
+} // namespace
+
+class RTCVideoDecoderAdapterTest : public ::testing::Test {
+ public:
+ RTCVideoDecoderAdapterTest()
+ : media_thread_("Media Thread"),
+ gpu_factories_(nullptr),
+ decoded_image_callback_(decoded_cb_.Get()) {
+ media_thread_.Start();
+ ON_CALL(gpu_factories_, GetTaskRunner())
+ .WillByDefault(Return(media_thread_.task_runner()));
+ EXPECT_CALL(gpu_factories_, GetTaskRunner()).Times(AtLeast(0));
+ owned_video_decoder_ = std::make_unique<StrictMock<MockVideoDecoder>>();
+ video_decoder_ = owned_video_decoder_.get();
+ }
+
+ ~RTCVideoDecoderAdapterTest() {
+ if (!rtc_video_decoder_adapter_)
+ return;
+
+ RTCVideoDecoderAdapter::DeleteSoonOnMediaThread(
+ std::move(rtc_video_decoder_adapter_), &gpu_factories_);
+ media_thread_.FlushForTesting();
+ }
+
+ protected:
+ std::unique_ptr<media::VideoDecoder> CreateVideoDecoder(
+ media::MediaLog* media_log) {
+ DCHECK(owned_video_decoder_);
+ return std::move(owned_video_decoder_);
+ }
+
+ bool BasicSetup() {
+ if (!CreateAndInitialize())
+ return false;
+ if (InitDecode() != WEBRTC_VIDEO_CODEC_OK)
+ return false;
+ if (RegisterDecodeCompleteCallback() != WEBRTC_VIDEO_CODEC_OK)
+ return false;
+ return true;
+ }
+
+ bool BasicTeardown() {
+ if (Release() != WEBRTC_VIDEO_CODEC_OK)
+ return false;
+ return true;
+ }
+
+ bool CreateAndInitialize(bool init_cb_result = true) {
+ EXPECT_CALL(*video_decoder_, Initialize(_, _, _, _, _, _))
+ .WillOnce(DoAll(SaveArg<4>(&output_cb_),
+ media::RunCallback<3>(init_cb_result)));
+ rtc_video_decoder_adapter_ = RTCVideoDecoderAdapter::Create(
+ webrtc::kVideoCodecVP9, &gpu_factories_,
+ base::BindRepeating(&RTCVideoDecoderAdapterTest::CreateVideoDecoder,
+ base::Unretained(this)));
+ return !!rtc_video_decoder_adapter_;
+ }
+
+ int32_t InitDecode() {
+ webrtc::VideoCodec codec_settings;
+ codec_settings.codecType = webrtc::kVideoCodecVP9;
+ return rtc_video_decoder_adapter_->InitDecode(&codec_settings, 1);
+ }
+
+ int32_t RegisterDecodeCompleteCallback() {
+ return rtc_video_decoder_adapter_->RegisterDecodeCompleteCallback(
+ &decoded_image_callback_);
+ }
+
+ int32_t Decode(uint32_t timestamp) {
+ uint8_t buf[] = {0};
+ webrtc::EncodedImage input_image(&buf[0], 1, 1);
+ input_image._completeFrame = true;
+ input_image._timeStamp = timestamp;
+ return rtc_video_decoder_adapter_->Decode(input_image, false, nullptr, 0);
+ }
+
+ void FinishDecode(uint32_t timestamp) {
+ media_thread_.task_runner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&RTCVideoDecoderAdapterTest::FinishDecodeOnMediaThread,
+ base::Unretained(this), timestamp));
+ }
+
+ void FinishDecodeOnMediaThread(uint32_t timestamp) {
+ DCHECK(media_thread_.task_runner()->BelongsToCurrentThread());
+ gpu::MailboxHolder mailbox_holders[media::VideoFrame::kMaxPlanes];
+ mailbox_holders[0].mailbox = gpu::Mailbox::Generate();
+ scoped_refptr<media::VideoFrame> frame =
+ media::VideoFrame::WrapNativeTextures(
+ media::PIXEL_FORMAT_ARGB, mailbox_holders,
+ media::VideoFrame::ReleaseMailboxCB(), gfx::Size(640, 360),
+ gfx::Rect(640, 360), gfx::Size(640, 360),
+ base::TimeDelta::FromMicroseconds(timestamp));
+ output_cb_.Run(std::move(frame));
+ }
+
+ int32_t Release() { return rtc_video_decoder_adapter_->Release(); }
+
+ base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::Thread media_thread_;
+
+ // Owned by |rtc_video_decoder_adapter_|.
+ StrictMock<MockVideoDecoder>* video_decoder_ = nullptr;
+
+ StrictMock<base::MockCallback<
+ base::RepeatingCallback<void(const webrtc::VideoFrame&)>>>
+ decoded_cb_;
+
+ private:
+ StrictMock<media::MockGpuVideoAcceleratorFactories> gpu_factories_;
+ std::unique_ptr<RTCVideoDecoderAdapter> rtc_video_decoder_adapter_;
+ std::unique_ptr<StrictMock<MockVideoDecoder>> owned_video_decoder_;
+ DecodedImageCallback decoded_image_callback_;
+ media::VideoDecoder::OutputCB output_cb_;
+
+ DISALLOW_COPY_AND_ASSIGN(RTCVideoDecoderAdapterTest);
+};
+
+TEST_F(RTCVideoDecoderAdapterTest, Lifecycle) {
+ ASSERT_TRUE(BasicSetup());
+ ASSERT_TRUE(BasicTeardown());
+}
+
+TEST_F(RTCVideoDecoderAdapterTest, InitializationFailure) {
+ ASSERT_FALSE(CreateAndInitialize(false));
+}
+
+TEST_F(RTCVideoDecoderAdapterTest, Decode) {
+ ASSERT_TRUE(BasicSetup());
+
+ EXPECT_CALL(*video_decoder_, Decode(_, _))
+ .WillOnce(media::RunCallback<1>(media::DecodeStatus::OK));
+
+ ASSERT_EQ(Decode(0), WEBRTC_VIDEO_CODEC_OK);
+
+ EXPECT_CALL(decoded_cb_, Run(_));
+ FinishDecode(0);
+ media_thread_.FlushForTesting();
+}
+
+TEST_F(RTCVideoDecoderAdapterTest, Decode_Error) {
+ ASSERT_TRUE(BasicSetup());
+
+ EXPECT_CALL(*video_decoder_, Decode(_, _))
+ .WillOnce(media::RunCallback<1>(media::DecodeStatus::DECODE_ERROR));
+
+ ASSERT_EQ(Decode(0), WEBRTC_VIDEO_CODEC_OK);
+ media_thread_.FlushForTesting();
+
+ ASSERT_EQ(Decode(1), WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE);
+}
+
+TEST_F(RTCVideoDecoderAdapterTest, Decode_Hang_Short) {
+ ASSERT_TRUE(BasicSetup());
+
+ // Ignore Decode() calls.
+ EXPECT_CALL(*video_decoder_, Decode(_, _)).Times(AtLeast(1));
+
+ for (int counter = 0; counter < 10; counter++) {
+ int32_t result = Decode(counter);
+ if (result == WEBRTC_VIDEO_CODEC_ERROR) {
+ ASSERT_GT(counter, 2);
+ return;
+ }
+ media_thread_.FlushForTesting();
+ }
+
+ FAIL();
+}
+
+TEST_F(RTCVideoDecoderAdapterTest, Decode_Hang_Long) {
+ ASSERT_TRUE(BasicSetup());
+
+ // Ignore Decode() calls.
+ EXPECT_CALL(*video_decoder_, Decode(_, _)).Times(AtLeast(1));
+
+ for (int counter = 0; counter < 100; counter++) {
+ int32_t result = Decode(counter);
+ if (result == WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE) {
+ ASSERT_GT(counter, 10);
+ return;
+ }
+ media_thread_.FlushForTesting();
+ }
+
+ FAIL();
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/media/webrtc/rtc_video_encoder.cc b/chromium/content/renderer/media/webrtc/rtc_video_encoder.cc
index 69f49db28bc..fc6985e7f86 100644
--- a/chromium/content/renderer/media/webrtc/rtc_video_encoder.cc
+++ b/chromium/content/renderer/media/webrtc/rtc_video_encoder.cc
@@ -63,7 +63,7 @@ webrtc::VideoCodecType ProfileToWebRtcVideoCodecType(
return webrtc::kVideoCodecH264;
}
NOTREACHED() << "Invalid profile " << GetProfileName(profile);
- return webrtc::kVideoCodecUnknown;
+ return webrtc::kVideoCodecGeneric;
}
// Populates struct webrtc::RTPFragmentationHeader for H264 codec.
@@ -322,8 +322,13 @@ void RTCVideoEncoder::Impl::CreateAndInitializeVEA(
return;
}
input_visible_size_ = input_visible_size;
- if (!video_encoder_->Initialize(media::PIXEL_FORMAT_I420, input_visible_size_,
- profile, bitrate * 1000, this)) {
+ const media::VideoEncodeAccelerator::Config config(
+ media::PIXEL_FORMAT_I420, input_visible_size_, profile, bitrate * 1000,
+ base::nullopt, base::nullopt,
+ video_content_type_ == webrtc::VideoContentType::SCREENSHARE
+ ? media::VideoEncodeAccelerator::Config::ContentType::kDisplay
+ : media::VideoEncodeAccelerator::Config::ContentType::kCamera);
+ if (!video_encoder_->Initialize(config, this)) {
LogAndNotifyError(FROM_HERE, "Error initializing video_encoder",
media::VideoEncodeAccelerator::kInvalidArgumentError);
return;
@@ -555,9 +560,9 @@ void RTCVideoEncoder::Impl::BitstreamBufferReady(
capture_timestamp_ms = current_time_ms;
}
- webrtc::EncodedImage image(
- reinterpret_cast<uint8_t*>(output_buffer->memory()),
- metadata.payload_size_bytes, output_buffer->mapped_size());
+ webrtc::EncodedImage image(static_cast<uint8_t*>(output_buffer->memory()),
+ metadata.payload_size_bytes,
+ output_buffer->mapped_size());
image._encodedWidth = input_visible_size_.width();
image._encodedHeight = input_visible_size_.height();
image._timeStamp = rtp_timestamp.value();
@@ -653,7 +658,7 @@ void RTCVideoEncoder::Impl::EncodeOneFrame() {
frame = media::VideoFrame::WrapExternalSharedMemory(
media::PIXEL_FORMAT_I420, input_frame_coded_size_,
gfx::Rect(input_visible_size_), input_visible_size_,
- reinterpret_cast<uint8_t*>(input_buffer->memory()),
+ static_cast<uint8_t*>(input_buffer->memory()),
input_buffer->mapped_size(), input_buffer->handle(), 0, timestamp);
if (!frame.get()) {
LogAndNotifyError(FROM_HERE, "failed to create frame",
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 2d142d5aa82..460fe992b7c 100644
--- a/chromium/content/renderer/media/webrtc/rtc_video_encoder_unittest.cc
+++ b/chromium/content/renderer/media/webrtc/rtc_video_encoder_unittest.cc
@@ -77,7 +77,7 @@ class RTCVideoEncoderTest
EXPECT_CALL(*mock_gpu_factories_.get(), DoCreateVideoEncodeAccelerator())
.WillRepeatedly(Return(mock_vea));
- EXPECT_CALL(*mock_vea, Initialize(_, _, _, _, _))
+ EXPECT_CALL(*mock_vea, Initialize(_, _))
.WillOnce(Invoke(this, &RTCVideoEncoderTest::Initialize));
EXPECT_CALL(*mock_vea, UseOutputBitstreamBuffer(_)).Times(AtLeast(3));
EXPECT_CALL(*mock_vea, Destroy()).Times(1);
@@ -129,15 +129,12 @@ class RTCVideoEncoderTest
}
// media::VideoEncodeAccelerator implementation.
- bool Initialize(media::VideoPixelFormat input_format,
- const gfx::Size& input_visible_size,
- media::VideoCodecProfile output_profile,
- uint32_t initial_bitrate,
+ bool Initialize(const media::VideoEncodeAccelerator::Config& config,
media::VideoEncodeAccelerator::Client* client) {
DVLOG(3) << __func__;
client_ = client;
- client_->RequireBitstreamBuffers(0, input_visible_size,
- input_visible_size.GetArea());
+ client_->RequireBitstreamBuffers(0, config.input_visible_size,
+ config.input_visible_size.GetArea());
return true;
}
diff --git a/chromium/content/renderer/media/webrtc/stun_field_trial.h b/chromium/content/renderer/media/webrtc/stun_field_trial.h
index 24c6dfc76fd..5843731a46a 100644
--- a/chromium/content/renderer/media/webrtc/stun_field_trial.h
+++ b/chromium/content/renderer/media/webrtc/stun_field_trial.h
@@ -18,7 +18,7 @@
#include "content/renderer/p2p/network_list_observer.h"
#include "third_party/webrtc/p2p/stunprober/stunprober.h"
#include "third_party/webrtc/rtc_base/network.h"
-#include "third_party/webrtc/rtc_base/sigslot.h"
+#include "third_party/webrtc/rtc_base/third_party/sigslot/sigslot.h"
namespace rtc {
class PacketSocketFactory;
diff --git a/chromium/content/renderer/media/webrtc/webrtc_audio_device_impl.cc b/chromium/content/renderer/media/webrtc/webrtc_audio_device_impl.cc
index f0e7046d201..d6dba457e4b 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_audio_device_impl.cc
+++ b/chromium/content/renderer/media/webrtc/webrtc_audio_device_impl.cc
@@ -21,7 +21,8 @@ using media::ChannelLayout;
namespace content {
WebRtcAudioDeviceImpl::WebRtcAudioDeviceImpl()
- : audio_transport_callback_(nullptr),
+ : audio_processing_id_(base::UnguessableToken::Create()),
+ audio_transport_callback_(nullptr),
output_delay_ms_(0),
initialized_(false),
playing_(false),
@@ -130,6 +131,10 @@ void WebRtcAudioDeviceImpl::SetOutputDeviceForAec(
}
}
+base::UnguessableToken WebRtcAudioDeviceImpl::GetAudioProcessingId() const {
+ return audio_processing_id_;
+}
+
int32_t WebRtcAudioDeviceImpl::RegisterAudioCallback(
webrtc::AudioTransport* audio_callback) {
DVLOG(1) << "WebRtcAudioDeviceImpl::RegisterAudioCallback()";
@@ -318,34 +323,6 @@ int32_t WebRtcAudioDeviceImpl::MinMicrophoneVolume(uint32_t* min_volume) const {
return 0;
}
-int32_t WebRtcAudioDeviceImpl::StereoPlayoutIsAvailable(bool* available) const {
- DCHECK(initialized_);
- // This method is called during initialization on the signaling thread and
- // then later on the worker thread. Due to this we cannot DCHECK on what
- // thread we're on since it might incorrectly initialize the
- // worker_thread_checker_.
- base::AutoLock auto_lock(lock_);
- *available = renderer_ && renderer_->channels() == 2;
- return 0;
-}
-
-int32_t WebRtcAudioDeviceImpl::StereoRecordingIsAvailable(
- bool* available) const {
- DCHECK(initialized_);
- // This method is called during initialization on the signaling thread and
- // then later on the worker thread. Due to this we cannot DCHECK on what
- // thread we're on since it might incorrectly initialize the
- // worker_thread_checker_.
-
- // TODO(xians): These kind of hardware methods do not make much sense since we
- // support multiple sources. Remove or figure out new APIs for such methods.
- base::AutoLock auto_lock(lock_);
- if (capturers_.empty())
- return -1;
- *available = (capturers_.back()->GetInputFormat().channels() == 2);
- return 0;
-}
-
int32_t WebRtcAudioDeviceImpl::PlayoutDelay(uint16_t* delay_ms) const {
DCHECK(worker_thread_checker_.CalledOnValidThread());
base::AutoLock auto_lock(lock_);
diff --git a/chromium/content/renderer/media/webrtc/webrtc_audio_device_impl.h b/chromium/content/renderer/media/webrtc/webrtc_audio_device_impl.h
index 9a6d343cf15..4f3f1ac0d0c 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_audio_device_impl.h
+++ b/chromium/content/renderer/media/webrtc/webrtc_audio_device_impl.h
@@ -18,6 +18,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/threading/thread_checker.h"
+#include "base/unguessable_token.h"
#include "content/common/content_export.h"
#include "content/renderer/media/webrtc/webrtc_audio_device_not_impl.h"
#include "ipc/ipc_platform_file.h"
@@ -67,6 +68,10 @@ class WebRtcAudioRendererSource {
// Callback to notify the client of the output device the renderer is using.
virtual void SetOutputDeviceForAec(const std::string& output_device_id) = 0;
+ // Returns the UnguessableToken used to connect this stream to an input stream
+ // for echo cancellation.
+ virtual base::UnguessableToken GetAudioProcessingId() const = 0;
+
protected:
virtual ~WebRtcAudioRendererSource() {}
};
@@ -159,8 +164,6 @@ class CONTENT_EXPORT WebRtcAudioDeviceImpl : public WebRtcAudioDeviceNotImpl,
int32_t MaxMicrophoneVolume(uint32_t* max_volume) const override;
int32_t MinMicrophoneVolume(uint32_t* min_volume) const override;
- int32_t StereoPlayoutIsAvailable(bool* available) const override;
- int32_t StereoRecordingIsAvailable(bool* available) const override;
int32_t PlayoutDelay(uint16_t* delay_ms) const override;
public:
@@ -186,11 +189,6 @@ class CONTENT_EXPORT WebRtcAudioDeviceImpl : public WebRtcAudioDeviceNotImpl,
return renderer_;
}
- private:
- typedef std::list<ProcessedLocalAudioSource*> CapturerList;
- typedef std::list<WebRtcPlayoutDataSource::Sink*> PlayoutDataSinkList;
- class RenderBuffer;
-
// WebRtcAudioRendererSource implementation.
// Called on the AudioOutputDevice worker thread.
@@ -203,11 +201,18 @@ class CONTENT_EXPORT WebRtcAudioDeviceImpl : public WebRtcAudioDeviceNotImpl,
void RemoveAudioRenderer(WebRtcAudioRenderer* renderer) override;
void AudioRendererThreadStopped() override;
void SetOutputDeviceForAec(const std::string& output_device_id) override;
+ base::UnguessableToken GetAudioProcessingId() const override;
// WebRtcPlayoutDataSource implementation.
void AddPlayoutSink(WebRtcPlayoutDataSource::Sink* sink) override;
void RemovePlayoutSink(WebRtcPlayoutDataSource::Sink* sink) override;
+ private:
+ using CapturerList = std::list<ProcessedLocalAudioSource*>;
+ using PlayoutDataSinkList = std::list<WebRtcPlayoutDataSource::Sink*>;
+
+ class RenderBuffer;
+
// Used to check methods that run on the main render thread.
base::ThreadChecker main_thread_checker_;
// Used to check methods that are called on libjingle's signaling thread.
@@ -215,6 +220,8 @@ class CONTENT_EXPORT WebRtcAudioDeviceImpl : public WebRtcAudioDeviceNotImpl,
base::ThreadChecker worker_thread_checker_;
base::ThreadChecker audio_renderer_thread_checker_;
+ const base::UnguessableToken audio_processing_id_;
+
// List of captures which provides access to the native audio input layer
// in the browser process. The last capturer in this list is considered the
// "default capturer" by the methods implementing the
diff --git a/chromium/content/renderer/media/webrtc/webrtc_audio_device_not_impl.cc b/chromium/content/renderer/media/webrtc/webrtc_audio_device_not_impl.cc
index 800da351a60..315439ee400 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_audio_device_not_impl.cc
+++ b/chromium/content/renderer/media/webrtc/webrtc_audio_device_not_impl.cc
@@ -121,6 +121,12 @@ int32_t WebRtcAudioDeviceNotImpl::MicrophoneMute(bool* enabled) const {
return 0;
}
+int32_t WebRtcAudioDeviceNotImpl::StereoPlayoutIsAvailable(
+ bool* available) const {
+ *available = false;
+ return 0;
+}
+
int32_t WebRtcAudioDeviceNotImpl::SetStereoPlayout(bool enable) {
return 0;
}
@@ -129,6 +135,12 @@ int32_t WebRtcAudioDeviceNotImpl::StereoPlayout(bool* enabled) const {
return 0;
}
+int32_t WebRtcAudioDeviceNotImpl::StereoRecordingIsAvailable(
+ bool* available) const {
+ *available = false;
+ return 0;
+}
+
int32_t WebRtcAudioDeviceNotImpl::SetStereoRecording(bool enable) {
return 0;
}
diff --git a/chromium/content/renderer/media/webrtc/webrtc_audio_device_not_impl.h b/chromium/content/renderer/media/webrtc/webrtc_audio_device_not_impl.h
index 02ba0987d98..17b42ef2015 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_audio_device_not_impl.h
+++ b/chromium/content/renderer/media/webrtc/webrtc_audio_device_not_impl.h
@@ -61,7 +61,9 @@ class CONTENT_EXPORT WebRtcAudioDeviceNotImpl
int32_t MicrophoneMuteIsAvailable(bool* available) override;
int32_t SetMicrophoneMute(bool enable) override;
int32_t MicrophoneMute(bool* enabled) const override;
+ int32_t StereoPlayoutIsAvailable(bool* available) const override;
int32_t SetStereoPlayout(bool enable) override;
+ int32_t StereoRecordingIsAvailable(bool* available) const override;
int32_t StereoPlayout(bool* enabled) const override;
int32_t SetStereoRecording(bool enable) override;
int32_t StereoRecording(bool* enabled) const override;
diff --git a/chromium/content/renderer/media/webrtc/webrtc_audio_renderer.cc b/chromium/content/renderer/media/webrtc/webrtc_audio_renderer.cc
index c1ea561596d..4d8da5ed05f 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_audio_renderer.cc
+++ b/chromium/content/renderer/media/webrtc/webrtc_audio_renderer.cc
@@ -196,9 +196,10 @@ bool WebRtcAudioRenderer::Initialize(WebRtcAudioRendererSource* source) {
DCHECK(!source_);
}
+ media::AudioSinkParameters sink_params(session_id_, output_device_id_);
+ sink_params.processing_id = source->GetAudioProcessingId();
sink_ = AudioDeviceFactory::NewAudioRendererSink(
- AudioDeviceFactory::kSourceWebRtc, source_render_frame_id_, session_id_,
- output_device_id_);
+ AudioDeviceFactory::kSourceWebRtc, source_render_frame_id_, sink_params);
if (sink_->GetOutputDeviceInfo().device_status() !=
media::OUTPUT_DEVICE_STATUS_OK) {
@@ -384,10 +385,12 @@ void WebRtcAudioRenderer::SwitchOutputDevice(
DCHECK_NE(state_, UNINITIALIZED);
}
+ media::AudioSinkParameters sink_params(session_id_, device_id);
+ sink_params.processing_id = source_->GetAudioProcessingId();
scoped_refptr<media::AudioRendererSink> new_sink =
AudioDeviceFactory::NewAudioRendererSink(
AudioDeviceFactory::kSourceWebRtc, source_render_frame_id_,
- session_id_, device_id);
+ sink_params);
media::OutputDeviceStatus status =
new_sink->GetOutputDeviceInfo().device_status();
if (status != media::OUTPUT_DEVICE_STATUS_OK) {
@@ -534,8 +537,10 @@ void WebRtcAudioRenderer::UpdateSourceVolume(
// object is an exception (bug?). So, to work around that, we need to make
// sure we call SetVolume on the signaling thread.
signaling_thread_->PostTask(
- FROM_HERE, base::BindOnce(&webrtc::AudioSourceInterface::SetVolume,
- source, volume));
+ FROM_HERE,
+ base::BindOnce(&webrtc::AudioSourceInterface::SetVolume,
+ rtc::scoped_refptr<webrtc::AudioSourceInterface>(source),
+ volume));
} else {
source->SetVolume(volume);
}
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 e3e2cce259b..273bac1d183 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_audio_renderer_unittest.cc
+++ b/chromium/content/renderer/media/webrtc/webrtc_audio_renderer_unittest.cc
@@ -49,6 +49,7 @@ class MockAudioRendererSource : public WebRtcAudioRendererSource {
MOCK_METHOD1(RemoveAudioRenderer, void(WebRtcAudioRenderer* renderer));
MOCK_METHOD0(AudioRendererThreadStopped, void());
MOCK_METHOD1(SetOutputDeviceForAec, void(const std::string&));
+ MOCK_CONST_METHOD0(GetAudioProcessingId, base::UnguessableToken());
};
} // namespace
@@ -70,56 +71,63 @@ class WebRtcAudioRendererTest : public testing::Test,
blink::WebVector<blink::WebMediaStreamTrack> dummy_tracks;
stream_.Initialize(blink::WebString::FromUTF8("new stream"), dummy_tracks,
dummy_tracks);
+ EXPECT_CALL(*source_.get(), GetAudioProcessingId())
+ .WillRepeatedly(Return(*kAudioProcessingId));
}
void SetupRenderer(const std::string& device_id) {
renderer_ = new WebRtcAudioRenderer(message_loop_->task_runner(), stream_,
1, 1, device_id);
- EXPECT_CALL(*this, MockCreateAudioRendererSink(
- AudioDeviceFactory::kSourceWebRtc, _, _, device_id));
+ EXPECT_CALL(
+ *this, MockCreateAudioRendererSink(AudioDeviceFactory::kSourceWebRtc, _,
+ _, device_id, _));
EXPECT_CALL(*source_.get(), SetOutputDeviceForAec(device_id));
EXPECT_TRUE(renderer_->Initialize(source_.get()));
renderer_proxy_ = renderer_->CreateSharedAudioRendererProxy(stream_);
}
- MOCK_METHOD1(CreateAudioCapturerSource,
- scoped_refptr<media::AudioCapturerSource>(int));
- MOCK_METHOD3(CreateFinalAudioRendererSink,
- scoped_refptr<media::AudioRendererSink>(int,
- int,
- const std::string&));
- MOCK_METHOD4(
- CreateSwitchableAudioRendererSink,
- scoped_refptr<media::SwitchableAudioRendererSink>(SourceType,
- int,
- int,
- const std::string&));
- MOCK_METHOD4(MockCreateAudioRendererSink,
- void(SourceType, int, int, const std::string&));
+ MOCK_METHOD2(CreateAudioCapturerSource,
+ scoped_refptr<media::AudioCapturerSource>(
+ int,
+ const media::AudioSourceParameters&));
+ MOCK_METHOD2(CreateFinalAudioRendererSink,
+ scoped_refptr<media::AudioRendererSink>(
+ int,
+ const media::AudioSinkParameters&));
+ MOCK_METHOD3(CreateSwitchableAudioRendererSink,
+ scoped_refptr<media::SwitchableAudioRendererSink>(
+ SourceType,
+ int,
+ const media::AudioSinkParameters&));
+ MOCK_METHOD5(MockCreateAudioRendererSink,
+ void(SourceType,
+ int,
+ int,
+ const std::string&,
+ const base::Optional<base::UnguessableToken>&));
scoped_refptr<media::AudioRendererSink> CreateAudioRendererSink(
SourceType source_type,
int render_frame_id,
- int session_id,
- const std::string& device_id) override {
+ const media::AudioSinkParameters& params) override {
mock_sink_ = new media::MockAudioRendererSink(
- device_id,
- device_id == kInvalidOutputDeviceId
+ params.device_id,
+ params.device_id == kInvalidOutputDeviceId
? media::OUTPUT_DEVICE_STATUS_ERROR_INTERNAL
: media::OUTPUT_DEVICE_STATUS_OK,
media::AudioParameters(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
media::CHANNEL_LAYOUT_STEREO,
kHardwareSampleRate, kHardwareBufferSize));
- if (device_id != kInvalidOutputDeviceId) {
+ if (params.device_id != kInvalidOutputDeviceId) {
EXPECT_CALL(*mock_sink_.get(), Start());
EXPECT_CALL(*mock_sink_.get(), Play());
} else {
EXPECT_CALL(*mock_sink_.get(), Stop());
}
- MockCreateAudioRendererSink(source_type, render_frame_id, session_id,
- device_id);
+ MockCreateAudioRendererSink(source_type, render_frame_id, params.session_id,
+ params.device_id, params.processing_id);
return mock_sink_;
}
@@ -132,6 +140,8 @@ class WebRtcAudioRendererTest : public testing::Test,
blink::WebHeap::CollectAllGarbageForTesting();
}
+ const base::Optional<base::UnguessableToken> kAudioProcessingId =
+ base::UnguessableToken::Create();
std::unique_ptr<base::MessageLoopForIO> message_loop_;
scoped_refptr<media::MockAudioRendererSink> mock_sink_;
std::unique_ptr<MockAudioRendererSource> source_;
@@ -235,9 +245,9 @@ TEST_F(WebRtcAudioRendererTest, SwitchOutputDevice) {
renderer_proxy_->Start();
EXPECT_CALL(*mock_sink_.get(), Stop());
- EXPECT_CALL(*this,
- MockCreateAudioRendererSink(AudioDeviceFactory::kSourceWebRtc, _,
- _, kOtherOutputDeviceId));
+ EXPECT_CALL(*this, MockCreateAudioRendererSink(
+ AudioDeviceFactory::kSourceWebRtc, _, _,
+ kOtherOutputDeviceId, kAudioProcessingId));
EXPECT_CALL(*source_.get(), AudioRendererThreadStopped());
EXPECT_CALL(*source_.get(), SetOutputDeviceForAec(kOtherOutputDeviceId));
EXPECT_CALL(*this, MockSwitchDeviceCallback(media::OUTPUT_DEVICE_STATUS_OK));
@@ -262,9 +272,9 @@ TEST_F(WebRtcAudioRendererTest, SwitchOutputDeviceInvalidDevice) {
auto original_sink = mock_sink_;
renderer_proxy_->Start();
- EXPECT_CALL(*this,
- MockCreateAudioRendererSink(AudioDeviceFactory::kSourceWebRtc, _,
- _, kInvalidOutputDeviceId));
+ EXPECT_CALL(*this, MockCreateAudioRendererSink(
+ AudioDeviceFactory::kSourceWebRtc, _, _,
+ kInvalidOutputDeviceId, kAudioProcessingId));
EXPECT_CALL(*this, MockSwitchDeviceCallback(
media::OUTPUT_DEVICE_STATUS_ERROR_INTERNAL));
base::RunLoop loop;
@@ -285,9 +295,9 @@ TEST_F(WebRtcAudioRendererTest, InitializeWithInvalidDevice) {
renderer_ = new WebRtcAudioRenderer(message_loop_->task_runner(), stream_, 1,
1, kInvalidOutputDeviceId);
- EXPECT_CALL(*this,
- MockCreateAudioRendererSink(AudioDeviceFactory::kSourceWebRtc, _,
- _, kInvalidOutputDeviceId));
+ EXPECT_CALL(*this, MockCreateAudioRendererSink(
+ AudioDeviceFactory::kSourceWebRtc, _, _,
+ kInvalidOutputDeviceId, kAudioProcessingId));
EXPECT_FALSE(renderer_->Initialize(source_.get()));
diff --git a/chromium/content/renderer/media/webrtc/webrtc_audio_sink.cc b/chromium/content/renderer/media/webrtc/webrtc_audio_sink.cc
index b5a59a0e32e..81becdc4569 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_audio_sink.cc
+++ b/chromium/content/renderer/media/webrtc/webrtc_audio_sink.cc
@@ -32,7 +32,7 @@ WebRtcAudioSink::~WebRtcAudioSink() {
}
void WebRtcAudioSink::SetAudioProcessor(
- scoped_refptr<MediaStreamAudioProcessor> processor) {
+ scoped_refptr<webrtc::AudioProcessorInterface> processor) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(processor.get());
adapter_->set_processor(std::move(processor));
@@ -94,7 +94,7 @@ void WebRtcAudioSink::DeliverRebufferedAudio(const media::AudioBus& audio_bus,
namespace {
// TODO(miu): MediaStreamAudioProcessor destructor requires this nonsense.
void DereferenceOnMainThread(
- const scoped_refptr<MediaStreamAudioProcessor>& processor) {}
+ const scoped_refptr<webrtc::AudioProcessorInterface>& processor) {}
} // namespace
WebRtcAudioSink::Adapter::Adapter(
diff --git a/chromium/content/renderer/media/webrtc/webrtc_audio_sink.h b/chromium/content/renderer/media/webrtc/webrtc_audio_sink.h
index fee1d51f999..a5667cc3537 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_audio_sink.h
+++ b/chromium/content/renderer/media/webrtc/webrtc_audio_sink.h
@@ -22,6 +22,7 @@
#include "content/renderer/media/stream/media_stream_audio_processor.h"
#include "media/base/audio_parameters.h"
#include "media/base/audio_push_fifo.h"
+#include "third_party/webrtc/api/mediastreaminterface.h"
#include "third_party/webrtc/pc/mediastreamtrack.h"
namespace content {
@@ -57,7 +58,8 @@ class CONTENT_EXPORT WebRtcAudioSink : public MediaStreamAudioSink {
// source. This is passed via the Adapter to libjingle. This method may only
// be called once, before the audio data flow starts, and before any calls to
// GetAudioProcessor() might be made.
- void SetAudioProcessor(scoped_refptr<MediaStreamAudioProcessor> processor);
+ void SetAudioProcessor(
+ scoped_refptr<webrtc::AudioProcessorInterface> processor);
// MediaStreamSink override.
void OnEnabledChanged(bool enabled) override;
@@ -78,7 +80,8 @@ class CONTENT_EXPORT WebRtcAudioSink : public MediaStreamAudioSink {
// These setters are called before the audio data flow starts, and before
// any methods called on the signaling thread reference these objects.
- void set_processor(scoped_refptr<MediaStreamAudioProcessor> processor) {
+ void set_processor(
+ scoped_refptr<webrtc::AudioProcessorInterface> processor) {
audio_processor_ = std::move(processor);
}
void set_level(
@@ -124,7 +127,7 @@ class CONTENT_EXPORT WebRtcAudioSink : public MediaStreamAudioSink {
// The audio processsor that applies audio post-processing on the source
// audio. This is null if there is no audio processing taking place
// upstream. This must be set before calls to GetAudioProcessor() are made.
- scoped_refptr<MediaStreamAudioProcessor> audio_processor_;
+ scoped_refptr<webrtc::AudioProcessorInterface> audio_processor_;
// Thread-safe accessor to current audio signal level. This may be null, if
// not applicable to the current use case. This must be set before calls to
diff --git a/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter.cc b/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter.cc
index a20adaaae7b..92d4065c2e2 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter.cc
+++ b/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter.cc
@@ -157,9 +157,9 @@ void WebRtcMediaStreamTrackAdapter::InitializeLocalAudioTrack(
// The sink only grabs stats from the audio processor. Stats are only
// available if audio processing is turned on. Therefore, only provide the
// sink a reference to the processor if audio processing is turned on.
- if (auto processor = media_stream_source->audio_processor()) {
- if (processor->has_audio_processing())
- local_track_audio_sink_->SetAudioProcessor(processor);
+ if (media_stream_source->has_audio_processing()) {
+ local_track_audio_sink_->SetAudioProcessor(
+ media_stream_source->audio_processor());
}
}
native_track->AddSink(local_track_audio_sink_.get());
diff --git a/chromium/content/renderer/media/webrtc/webrtc_set_description_observer_unittest.cc b/chromium/content/renderer/media/webrtc/webrtc_set_description_observer_unittest.cc
index c2f7dc786b0..c33a3559e13 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_set_description_observer_unittest.cc
+++ b/chromium/content/renderer/media/webrtc/webrtc_set_description_observer_unittest.cc
@@ -21,8 +21,8 @@
#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
#include "third_party/blink/public/web/web_heap.h"
#include "third_party/webrtc/api/peerconnectioninterface.h"
+#include "third_party/webrtc/api/test/mock_peerconnectioninterface.h"
#include "third_party/webrtc/media/base/fakemediaengine.h"
-#include "third_party/webrtc/pc/test/mock_peerconnection.h"
using ::testing::Return;
@@ -66,9 +66,7 @@ class WebRtcSetDescriptionObserverForTest
class WebRtcSetRemoteDescriptionObserverHandlerTest : public ::testing::Test {
public:
void SetUp() override {
- pc_ = new webrtc::MockPeerConnection(new webrtc::FakePeerConnectionFactory(
- std::unique_ptr<cricket::MediaEngineInterface>(
- new cricket::FakeMediaEngine())));
+ pc_ = new webrtc::MockPeerConnectionInterface;
dependency_factory_.reset(new MockPeerConnectionDependencyFactory());
main_thread_ = blink::scheduler::GetSingleThreadTaskRunnerForTesting();
scoped_refptr<WebRtcMediaStreamTrackAdapterMap> map =
@@ -107,7 +105,7 @@ class WebRtcSetRemoteDescriptionObserverHandlerTest : public ::testing::Test {
base::test::ScopedTaskEnvironment scoped_task_environment_;
ChildProcess child_process_;
- scoped_refptr<webrtc::MockPeerConnection> pc_;
+ scoped_refptr<webrtc::MockPeerConnectionInterface> pc_;
std::unique_ptr<MockPeerConnectionDependencyFactory> dependency_factory_;
scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
scoped_refptr<WebRtcSetDescriptionObserverForTest> observer_;
diff --git a/chromium/content/renderer/media/webrtc/webrtc_uma_histograms_unittest.cc b/chromium/content/renderer/media/webrtc/webrtc_uma_histograms_unittest.cc
index 3f7a4fa4363..b0c44b875f6 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_uma_histograms_unittest.cc
+++ b/chromium/content/renderer/media/webrtc/webrtc_uma_histograms_unittest.cc
@@ -20,38 +20,37 @@ class MockPerSessionWebRTCAPIMetrics : public PerSessionWebRTCAPIMetrics {
MOCK_METHOD1(LogUsage, void(blink::WebRTCAPIName));
};
-TEST(PerSessionWebRTCAPIMetrics, NoCallOngoingGetUserMedia) {
- MockPerSessionWebRTCAPIMetrics metrics;
- EXPECT_CALL(metrics, LogUsage(_)).Times(1);
- metrics.LogUsageOnlyOnce(blink::WebRTCAPIName::kGetUserMedia);
-}
+class PerSessionWebRTCAPIMetricsTest
+ : public testing::Test,
+ public testing::WithParamInterface<blink::WebRTCAPIName> {
+ public:
+ PerSessionWebRTCAPIMetricsTest() = default;
+ ~PerSessionWebRTCAPIMetricsTest() override = default;
-TEST(PerSessionWebRTCAPIMetrics, CallOngoingGetUserMedia) {
+ protected:
MockPerSessionWebRTCAPIMetrics metrics;
- metrics.IncrementStreamCounter();
- EXPECT_CALL(metrics, LogUsage(blink::WebRTCAPIName::kGetUserMedia)).Times(1);
- metrics.LogUsageOnlyOnce(blink::WebRTCAPIName::kGetUserMedia);
-}
+};
-TEST(PerSessionWebRTCAPIMetrics, NoCallOngoingGetMediaDevices) {
- MockPerSessionWebRTCAPIMetrics metrics;
- EXPECT_CALL(metrics, LogUsage(_)).Times(1);
- metrics.LogUsageOnlyOnce(blink::WebRTCAPIName::kEnumerateDevices);
+TEST_P(PerSessionWebRTCAPIMetricsTest, NoCallOngoing) {
+ blink::WebRTCAPIName api_name = GetParam();
+ EXPECT_CALL(metrics, LogUsage(api_name)).Times(1);
+ metrics.LogUsageOnlyOnce(api_name);
}
-TEST(PerSessionWebRTCAPIMetrics, CallOngoingGetMediaDevices) {
- MockPerSessionWebRTCAPIMetrics metrics;
+TEST_P(PerSessionWebRTCAPIMetricsTest, CallOngoing) {
+ blink::WebRTCAPIName api_name = GetParam();
metrics.IncrementStreamCounter();
- EXPECT_CALL(metrics, LogUsage(blink::WebRTCAPIName::kEnumerateDevices))
- .Times(1);
- metrics.LogUsageOnlyOnce(blink::WebRTCAPIName::kEnumerateDevices);
+ EXPECT_CALL(metrics, LogUsage(api_name)).Times(1);
+ metrics.LogUsageOnlyOnce(api_name);
}
-TEST(PerSessionWebRTCAPIMetrics, NoCallOngoingRTCPeerConnection) {
- MockPerSessionWebRTCAPIMetrics metrics;
- EXPECT_CALL(metrics, LogUsage(blink::WebRTCAPIName::kRTCPeerConnection));
- metrics.LogUsageOnlyOnce(blink::WebRTCAPIName::kRTCPeerConnection);
-}
+INSTANTIATE_TEST_CASE_P(
+ PerSessionWebRTCAPIMetricsTest,
+ PerSessionWebRTCAPIMetricsTest,
+ ::testing::ValuesIn({blink::WebRTCAPIName::kGetUserMedia,
+ blink::WebRTCAPIName::kGetDisplayMedia,
+ blink::WebRTCAPIName::kEnumerateDevices,
+ blink::WebRTCAPIName::kRTCPeerConnection}));
TEST(PerSessionWebRTCAPIMetrics, NoCallOngoingMultiplePC) {
MockPerSessionWebRTCAPIMetrics metrics;
diff --git a/chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc b/chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc
index 57ae21ee241..d00e437c8fe 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc
+++ b/chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc
@@ -194,28 +194,7 @@ void WebRtcVideoCapturerAdapter::SetContentHint(
}
bool WebRtcVideoCapturerAdapter::IsScreencast() const {
- // IsScreencast() is misleading since content hints were added to
- // MediaStreamTracks. What IsScreencast() really signals is whether or not
- // video frames should ever be scaled before being handed over to WebRTC.
- // TODO(pbos): Remove the need for IsScreencast() -> ShouldAdaptResolution()
- // by inlining VideoCapturer::AdaptFrame() and removing it from VideoCapturer.
- return !ShouldAdaptResolution();
-}
-
-bool WebRtcVideoCapturerAdapter::ShouldAdaptResolution() const {
- DCHECK(thread_checker_.CalledOnValidThread());
- if (content_hint_ ==
- blink::WebMediaStreamTrack::ContentHintType::kVideoMotion) {
- return true;
- }
- if (content_hint_ ==
- blink::WebMediaStreamTrack::ContentHintType::kVideoDetail ||
- content_hint_ ==
- blink::WebMediaStreamTrack::ContentHintType::kVideoText) {
- return false;
- }
- // Screencast does not adapt by default.
- return !is_screencast_;
+ return is_screencast_;
}
bool WebRtcVideoCapturerAdapter::GetBestCaptureFormat(
diff --git a/chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter.h b/chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter.h
index f51e39593ab..921b373e690 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter.h
+++ b/chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter.h
@@ -56,8 +56,6 @@ class CONTENT_EXPORT WebRtcVideoCapturerAdapter
cricket::VideoFormat* best_format) override;
bool IsScreencast() const override;
- bool ShouldAdaptResolution() const;
-
// |thread_checker_| is bound to the libjingle worker thread.
base::ThreadChecker thread_checker_;
diff --git a/chromium/content/renderer/media/webrtc/webrtc_video_utils.cc b/chromium/content/renderer/media/webrtc/webrtc_video_utils.cc
new file mode 100644
index 00000000000..0c7662f4131
--- /dev/null
+++ b/chromium/content/renderer/media/webrtc/webrtc_video_utils.cc
@@ -0,0 +1,177 @@
+// 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/renderer/media/webrtc/webrtc_video_utils.h"
+
+namespace content {
+
+media::VideoRotation WebRtcToMediaVideoRotation(
+ webrtc::VideoRotation rotation) {
+ switch (rotation) {
+ case webrtc::kVideoRotation_0:
+ return media::VIDEO_ROTATION_0;
+ case webrtc::kVideoRotation_90:
+ return media::VIDEO_ROTATION_90;
+ case webrtc::kVideoRotation_180:
+ return media::VIDEO_ROTATION_180;
+ case webrtc::kVideoRotation_270:
+ return media::VIDEO_ROTATION_270;
+ }
+ return media::VIDEO_ROTATION_0;
+}
+
+media::VideoColorSpace WebRtcToMediaVideoColorSpace(
+ const webrtc::ColorSpace& color_space) {
+ media::VideoColorSpace::PrimaryID primaries =
+ media::VideoColorSpace::PrimaryID::INVALID;
+ switch (color_space.primaries()) {
+ case webrtc::ColorSpace::PrimaryID::kBT709:
+ primaries = media::VideoColorSpace::PrimaryID::BT709;
+ break;
+ case webrtc::ColorSpace::PrimaryID::kBT470M:
+ primaries = media::VideoColorSpace::PrimaryID::BT470M;
+ break;
+ case webrtc::ColorSpace::PrimaryID::kBT470BG:
+ primaries = media::VideoColorSpace::PrimaryID::BT470BG;
+ break;
+ case webrtc::ColorSpace::PrimaryID::kSMPTE170M:
+ primaries = media::VideoColorSpace::PrimaryID::SMPTE170M;
+ break;
+ case webrtc::ColorSpace::PrimaryID::kSMPTE240M:
+ primaries = media::VideoColorSpace::PrimaryID::SMPTE240M;
+ break;
+ case webrtc::ColorSpace::PrimaryID::kFILM:
+ primaries = media::VideoColorSpace::PrimaryID::FILM;
+ break;
+ case webrtc::ColorSpace::PrimaryID::kBT2020:
+ primaries = media::VideoColorSpace::PrimaryID::BT2020;
+ break;
+ case webrtc::ColorSpace::PrimaryID::kSMPTEST428:
+ primaries = media::VideoColorSpace::PrimaryID::SMPTEST428_1;
+ break;
+ case webrtc::ColorSpace::PrimaryID::kSMPTEST431:
+ primaries = media::VideoColorSpace::PrimaryID::SMPTEST431_2;
+ break;
+ case webrtc::ColorSpace::PrimaryID::kSMPTEST432:
+ primaries = media::VideoColorSpace::PrimaryID::SMPTEST432_1;
+ break;
+ case webrtc::ColorSpace::PrimaryID::kJEDECP22:
+ primaries = media::VideoColorSpace::PrimaryID::EBU_3213_E;
+ break;
+ case webrtc::ColorSpace::PrimaryID::kInvalid:
+ default:
+ break;
+ }
+
+ media::VideoColorSpace::TransferID transfer =
+ media::VideoColorSpace::TransferID::INVALID;
+ switch (color_space.transfer()) {
+ case webrtc::ColorSpace::TransferID::kBT709:
+ transfer = media::VideoColorSpace::TransferID::BT709;
+ break;
+ case webrtc::ColorSpace::TransferID::kGAMMA22:
+ transfer = media::VideoColorSpace::TransferID::GAMMA22;
+ break;
+ case webrtc::ColorSpace::TransferID::kGAMMA28:
+ transfer = media::VideoColorSpace::TransferID::GAMMA28;
+ break;
+ case webrtc::ColorSpace::TransferID::kSMPTE170M:
+ transfer = media::VideoColorSpace::TransferID::SMPTE170M;
+ break;
+ case webrtc::ColorSpace::TransferID::kSMPTE240M:
+ transfer = media::VideoColorSpace::TransferID::SMPTE240M;
+ break;
+ case webrtc::ColorSpace::TransferID::kLINEAR:
+ transfer = media::VideoColorSpace::TransferID::LINEAR;
+ break;
+ case webrtc::ColorSpace::TransferID::kLOG:
+ transfer = media::VideoColorSpace::TransferID::LOG;
+ break;
+ case webrtc::ColorSpace::TransferID::kLOG_SQRT:
+ transfer = media::VideoColorSpace::TransferID::LOG_SQRT;
+ break;
+ case webrtc::ColorSpace::TransferID::kIEC61966_2_4:
+ transfer = media::VideoColorSpace::TransferID::IEC61966_2_4;
+ break;
+ case webrtc::ColorSpace::TransferID::kBT1361_ECG:
+ transfer = media::VideoColorSpace::TransferID::BT1361_ECG;
+ break;
+ case webrtc::ColorSpace::TransferID::kIEC61966_2_1:
+ transfer = media::VideoColorSpace::TransferID::IEC61966_2_1;
+ break;
+ case webrtc::ColorSpace::TransferID::kBT2020_10:
+ transfer = media::VideoColorSpace::TransferID::BT2020_10;
+ break;
+ case webrtc::ColorSpace::TransferID::kBT2020_12:
+ transfer = media::VideoColorSpace::TransferID::BT2020_12;
+ break;
+ case webrtc::ColorSpace::TransferID::kSMPTEST2084:
+ transfer = media::VideoColorSpace::TransferID::SMPTEST2084;
+ break;
+ case webrtc::ColorSpace::TransferID::kSMPTEST428:
+ transfer = media::VideoColorSpace::TransferID::SMPTEST428_1;
+ break;
+ case webrtc::ColorSpace::TransferID::kARIB_STD_B67:
+ transfer = media::VideoColorSpace::TransferID::ARIB_STD_B67;
+ break;
+ case webrtc::ColorSpace::TransferID::kInvalid:
+ default:
+ break;
+ }
+
+ media::VideoColorSpace::MatrixID matrix =
+ media::VideoColorSpace::MatrixID::INVALID;
+ switch (color_space.matrix()) {
+ case webrtc::ColorSpace::MatrixID::kRGB:
+ matrix = media::VideoColorSpace::MatrixID::RGB;
+ break;
+ case webrtc::ColorSpace::MatrixID::kBT709:
+ matrix = media::VideoColorSpace::MatrixID::BT709;
+ break;
+ case webrtc::ColorSpace::MatrixID::kFCC:
+ matrix = media::VideoColorSpace::MatrixID::FCC;
+ break;
+ case webrtc::ColorSpace::MatrixID::kBT470BG:
+ matrix = media::VideoColorSpace::MatrixID::BT470BG;
+ break;
+ case webrtc::ColorSpace::MatrixID::kSMPTE170M:
+ matrix = media::VideoColorSpace::MatrixID::SMPTE170M;
+ break;
+ case webrtc::ColorSpace::MatrixID::kSMPTE240M:
+ matrix = media::VideoColorSpace::MatrixID::SMPTE240M;
+ break;
+ case webrtc::ColorSpace::MatrixID::kYCOCG:
+ matrix = media::VideoColorSpace::MatrixID::YCOCG;
+ break;
+ case webrtc::ColorSpace::MatrixID::kBT2020_NCL:
+ matrix = media::VideoColorSpace::MatrixID::BT2020_NCL;
+ break;
+ case webrtc::ColorSpace::MatrixID::kBT2020_CL:
+ matrix = media::VideoColorSpace::MatrixID::BT2020_CL;
+ break;
+ case webrtc::ColorSpace::MatrixID::kSMPTE2085:
+ matrix = media::VideoColorSpace::MatrixID::YDZDX;
+ break;
+ case webrtc::ColorSpace::MatrixID::kInvalid:
+ default:
+ break;
+ }
+
+ gfx::ColorSpace::RangeID range = gfx::ColorSpace::RangeID::INVALID;
+ switch (color_space.range()) {
+ case webrtc::ColorSpace::RangeID::kLimited:
+ range = gfx::ColorSpace::RangeID::LIMITED;
+ break;
+ case webrtc::ColorSpace::RangeID::kFull:
+ range = gfx::ColorSpace::RangeID::FULL;
+ break;
+ case webrtc::ColorSpace::RangeID::kInvalid:
+ default:
+ break;
+ }
+
+ return media::VideoColorSpace(primaries, transfer, matrix, range);
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/media/webrtc/webrtc_video_utils.h b/chromium/content/renderer/media/webrtc/webrtc_video_utils.h
new file mode 100644
index 00000000000..1d91b2a4607
--- /dev/null
+++ b/chromium/content/renderer/media/webrtc/webrtc_video_utils.h
@@ -0,0 +1,25 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_VIDEO_UTILS_H_
+#define CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_VIDEO_UTILS_H_
+
+#include "media/base/video_color_space.h"
+#include "media/base/video_rotation.h"
+#include "third_party/webrtc/api/video/color_space.h"
+#include "third_party/webrtc/api/video/video_rotation.h"
+
+namespace content {
+
+// This file has helper methods for conversion between chromium types and
+// webrtc/api/video types.
+
+media::VideoRotation WebRtcToMediaVideoRotation(webrtc::VideoRotation rotation);
+
+media::VideoColorSpace WebRtcToMediaVideoColorSpace(
+ const webrtc::ColorSpace& color_space);
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_VIDEO_UTILS_H_
diff --git a/chromium/content/renderer/media/webrtc_local_audio_source_provider.cc b/chromium/content/renderer/media/webrtc_local_audio_source_provider.cc
index 8087bd2db3b..1a3c58facd4 100644
--- a/chromium/content/renderer/media/webrtc_local_audio_source_provider.cc
+++ b/chromium/content/renderer/media/webrtc_local_audio_source_provider.cc
@@ -39,10 +39,11 @@ WebRtcLocalAudioSourceProvider::WebRtcLocalAudioSourceProvider(
blink::WebLocalFrame::FrameForCurrentContext();
RenderFrame* const render_frame = RenderFrame::FromWebFrame(web_frame);
if (render_frame) {
- int sample_rate = AudioDeviceFactory::GetOutputDeviceInfo(
- render_frame->GetRoutingID(), 0, std::string())
- .output_params()
- .sample_rate();
+ int sample_rate =
+ AudioDeviceFactory::GetOutputDeviceInfo(render_frame->GetRoutingID(),
+ media::AudioSinkParameters())
+ .output_params()
+ .sample_rate();
sink_params_.Reset(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
media::CHANNEL_LAYOUT_STEREO, sample_rate,
kWebAudioRenderBufferSize);
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
index 6a05c12fd96..6fc91036161 100644
--- 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
@@ -49,6 +49,8 @@ class MockWebMediaPlayer : public blink::WebMediaPlayer,
void SetVolume(double) override {}
void EnterPictureInPicture(PipWindowOpenedCallback) override {}
void ExitPictureInPicture(PipWindowClosedCallback) override {}
+ void SetPictureInPictureCustomControls(
+ const std::vector<blink::PictureInPictureControlInfo>&) override {}
void RegisterPictureInPictureWindowResizeCallback(
PipWindowResizedCallback) override {}
blink::WebTimeRanges Buffered() const override {
@@ -81,8 +83,8 @@ class MockWebMediaPlayer : public blink::WebMediaPlayer,
unsigned DecodedFrameCount() const override { return 0; }
unsigned DroppedFrameCount() const override { return 0; }
unsigned CorruptedFrameCount() const override { return 0; }
- size_t AudioDecodedByteCount() const override { return 0; }
- size_t VideoDecodedByteCount() 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& paint_rectangle,
diff --git a/chromium/content/renderer/media_recorder/vea_encoder.cc b/chromium/content/renderer/media_recorder/vea_encoder.cc
index 269eabb0069..faedb367ddd 100644
--- a/chromium/content/renderer/media_recorder/vea_encoder.cc
+++ b/chromium/content/renderer/media_recorder/vea_encoder.cc
@@ -34,6 +34,23 @@ const uint32_t kMaxKeyframeInterval = 100;
} // anonymous namespace
+scoped_refptr<VEAEncoder> VEAEncoder::Create(
+ const VideoTrackRecorder::OnEncodedVideoCB& on_encoded_video_callback,
+ const VideoTrackRecorder::OnErrorCB& on_error_callback,
+ int32_t bits_per_second,
+ media::VideoCodecProfile codec,
+ const gfx::Size& size,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
+ auto encoder = base::WrapRefCounted(
+ new VEAEncoder(on_encoded_video_callback, on_error_callback,
+ bits_per_second, codec, size, std::move(task_runner)));
+ encoder->encoding_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&VEAEncoder::ConfigureEncoderOnEncodingTaskRunner, encoder,
+ size));
+ return encoder;
+}
+
VEAEncoder::VEAEncoder(
const VideoTrackRecorder::OnEncodedVideoCB& on_encoded_video_callback,
const VideoTrackRecorder::OnErrorCB& on_error_callback,
@@ -55,14 +72,14 @@ VEAEncoder::VEAEncoder(
DCHECK(gpu_factories_);
DCHECK_GE(size.width(), kVEAEncoderMinResolutionWidth);
DCHECK_GE(size.height(), kVEAEncoderMinResolutionHeight);
-
- encoding_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&VEAEncoder::ConfigureEncoderOnEncodingTaskRunner, this,
- size));
}
VEAEncoder::~VEAEncoder() {
+ if (encoding_task_runner_->BelongsToCurrentThread()) {
+ DestroyOnEncodingTaskRunner();
+ return;
+ }
+
base::WaitableEvent release_waiter(
base::WaitableEvent::ResetPolicy::MANUAL,
base::WaitableEvent::InitialState::NOT_SIGNALED);
@@ -116,7 +133,7 @@ void VEAEncoder::BitstreamBufferReady(
base::SharedMemory* output_buffer =
output_buffers_[bitstream_buffer_id].get();
std::unique_ptr<std::string> data(new std::string);
- data->append(reinterpret_cast<char*>(output_buffer->memory()),
+ data->append(static_cast<char*>(output_buffer->memory()),
metadata.payload_size_bytes);
const auto front_frame = frames_in_encode_.front();
@@ -214,7 +231,7 @@ void VEAEncoder::EncodeOnEncodingTaskRunner(scoped_refptr<VideoFrame> frame,
video_frame = media::VideoFrame::WrapExternalSharedMemory(
media::PIXEL_FORMAT_I420, vea_requested_input_coded_size_,
gfx::Rect(input_visible_size_), input_visible_size_,
- reinterpret_cast<uint8_t*>(input_buffer->memory()),
+ static_cast<uint8_t*>(input_buffer->memory()),
input_buffer->mapped_size(), input_buffer->handle(), 0,
frame->timestamp());
if (!video_frame) {
@@ -254,18 +271,18 @@ void VEAEncoder::ConfigureEncoderOnEncodingTaskRunner(const gfx::Size& size) {
input_visible_size_ = size;
vea_requested_input_coded_size_ = gfx::Size();
video_encoder_ = gpu_factories_->CreateVideoEncodeAccelerator();
- if (!video_encoder_ ||
- !video_encoder_->Initialize(media::PIXEL_FORMAT_I420, input_visible_size_,
- codec_, bits_per_second_, this)) {
+ const media::VideoEncodeAccelerator::Config config(
+ media::PIXEL_FORMAT_I420, input_visible_size_, codec_, bits_per_second_);
+ if (!video_encoder_ || !video_encoder_->Initialize(config, this))
NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
- }
}
void VEAEncoder::DestroyOnEncodingTaskRunner(
base::WaitableEvent* async_waiter) {
DCHECK(encoding_task_runner_->BelongsToCurrentThread());
video_encoder_.reset();
- async_waiter->Signal();
+ if (async_waiter)
+ async_waiter->Signal();
}
} // namespace content
diff --git a/chromium/content/renderer/media_recorder/vea_encoder.h b/chromium/content/renderer/media_recorder/vea_encoder.h
index 3d06e593f91..2ef80c76338 100644
--- a/chromium/content/renderer/media_recorder/vea_encoder.h
+++ b/chromium/content/renderer/media_recorder/vea_encoder.h
@@ -29,7 +29,7 @@ namespace content {
class VEAEncoder final : public VideoTrackRecorder::Encoder,
public media::VideoEncodeAccelerator::Client {
public:
- VEAEncoder(
+ static scoped_refptr<VEAEncoder> Create(
const VideoTrackRecorder::OnEncodedVideoCB& on_encoded_video_callback,
const VideoTrackRecorder::OnErrorCB& on_error_callback,
int32_t bits_per_second,
@@ -52,6 +52,14 @@ class VEAEncoder final : public VideoTrackRecorder::Encoder,
using VideoParamsAndTimestamp =
std::pair<media::WebmMuxer::VideoParameters, base::TimeTicks>;
+ VEAEncoder(
+ const VideoTrackRecorder::OnEncodedVideoCB& on_encoded_video_callback,
+ const VideoTrackRecorder::OnErrorCB& on_error_callback,
+ int32_t bits_per_second,
+ media::VideoCodecProfile codec,
+ const gfx::Size& size,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+
void UseOutputBitstreamBufferId(int32_t bitstream_buffer_id);
void FrameFinished(std::unique_ptr<base::SharedMemory> shm);
@@ -62,7 +70,7 @@ class VEAEncoder final : public VideoTrackRecorder::Encoder,
void ConfigureEncoderOnEncodingTaskRunner(const gfx::Size& size);
- void DestroyOnEncodingTaskRunner(base::WaitableEvent* async_waiter);
+ void DestroyOnEncodingTaskRunner(base::WaitableEvent* async_waiter = nullptr);
media::GpuVideoAcceleratorFactories* const gpu_factories_;
diff --git a/chromium/content/renderer/media_recorder/video_track_recorder.cc b/chromium/content/renderer/media_recorder/video_track_recorder.cc
index c2e59536231..c7fb3465bac 100644
--- a/chromium/content/renderer/media_recorder/video_track_recorder.cc
+++ b/chromium/content/renderer/media_recorder/video_track_recorder.cc
@@ -24,7 +24,7 @@
#include "media/base/video_util.h"
#include "media/filters/context_3d.h"
#include "media/renderers/paint_canvas_video_renderer.h"
-#include "services/ui/public/cpp/gpu/context_provider_command_buffer.h"
+#include "services/ws/public/cpp/gpu/context_provider_command_buffer.h"
#include "skia/ext/platform_canvas.h"
#include "third_party/libyuv/include/libyuv.h"
#include "ui/gfx/geometry/size.h"
@@ -163,6 +163,23 @@ media::VideoCodecProfile CodecEnumerator::CodecIdToVEAProfile(CodecId codec) {
} // anonymous namespace
+VideoTrackRecorder::Counter::Counter() : count_(0u), weak_factory_(this) {}
+
+VideoTrackRecorder::Counter::~Counter() = default;
+
+void VideoTrackRecorder::Counter::IncreaseCount() {
+ count_++;
+}
+
+void VideoTrackRecorder::Counter::DecreaseCount() {
+ count_--;
+}
+
+base::WeakPtr<VideoTrackRecorder::Counter>
+VideoTrackRecorder::Counter::GetWeakPtr() {
+ return weak_factory_.GetWeakPtr();
+}
+
VideoTrackRecorder::Encoder::Encoder(
const OnEncodedVideoCB& on_encoded_video_callback,
int32_t bits_per_second,
@@ -173,7 +190,7 @@ VideoTrackRecorder::Encoder::Encoder(
paused_(false),
on_encoded_video_callback_(on_encoded_video_callback),
bits_per_second_(bits_per_second),
- num_frames_in_encode_(0) {
+ num_frames_in_encode_(std::make_unique<VideoTrackRecorder::Counter>()) {
DCHECK(!on_encoded_video_callback_.is_null());
if (encoding_task_runner_)
return;
@@ -184,6 +201,10 @@ VideoTrackRecorder::Encoder::Encoder(
VideoTrackRecorder::Encoder::~Encoder() {
main_task_runner_->DeleteSoon(FROM_HERE, video_renderer_.release());
+ if (origin_task_runner_ && !origin_task_runner_->BelongsToCurrentThread()) {
+ origin_task_runner_->DeleteSoon(FROM_HERE,
+ std::move(num_frames_in_encode_));
+ }
}
void VideoTrackRecorder::Encoder::StartFrameEncode(
@@ -204,7 +225,7 @@ void VideoTrackRecorder::Encoder::StartFrameEncode(
return;
}
- if (num_frames_in_encode_ > kMaxNumberOfFramesInEncode) {
+ if (num_frames_in_encode_->count() > kMaxNumberOfFramesInEncode) {
DLOG(WARNING) << "Too many frames are queued up. Dropping this one.";
return;
}
@@ -226,9 +247,13 @@ void VideoTrackRecorder::Encoder::StartFrameEncode(
video_frame, video_frame->format(), video_frame->visible_rect(),
video_frame->natural_size());
}
- wrapped_frame->AddDestructionObserver(media::BindToCurrentLoop(base::Bind(
- &VideoTrackRecorder::Encoder::FrameReleased, this, video_frame)));
- ++num_frames_in_encode_;
+ 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)));
+ num_frames_in_encode_->IncreaseCount();
encoding_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&Encoder::EncodeOnEncodingTaskRunner, this,
@@ -243,7 +268,7 @@ void VideoTrackRecorder::Encoder::RetrieveFrameOnMainThread(
scoped_refptr<media::VideoFrame> frame;
// |context_provider| is null if the GPU process has crashed or isn't there.
- ui::ContextProviderCommandBuffer* const context_provider =
+ ws::ContextProviderCommandBuffer* const context_provider =
RenderThreadImpl::current()->SharedMainThreadContextProvider().get();
if (!context_provider) {
// Send black frames (yuv = {0, 127, 127}).
@@ -349,12 +374,6 @@ bool VideoTrackRecorder::Encoder::CanEncodeAlphaChannel() {
return false;
}
-void VideoTrackRecorder::Encoder::FrameReleased(
- const scoped_refptr<VideoFrame>& frame) {
- DCHECK(origin_task_runner_->BelongsToCurrentThread());
- --num_frames_in_encode_;
-}
-
// static
VideoTrackRecorder::CodecId VideoTrackRecorder::GetPreferredCodecId() {
return GetCodecEnumerator()->GetPreferredCodecId();
@@ -377,7 +396,7 @@ VideoTrackRecorder::VideoTrackRecorder(
int32_t bits_per_second,
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner)
: track_(track),
- paused_before_init_(false),
+ should_pause_encoder_on_initialization_(false),
main_task_runner_(std::move(main_task_runner)),
weak_ptr_factory_(this) {
DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
@@ -407,7 +426,7 @@ void VideoTrackRecorder::Pause() {
if (encoder_)
encoder_->SetPaused(true);
else
- paused_before_init_ = true;
+ should_pause_encoder_on_initialization_ = true;
}
void VideoTrackRecorder::Resume() {
@@ -415,7 +434,7 @@ void VideoTrackRecorder::Resume() {
if (encoder_)
encoder_->SetPaused(false);
else
- paused_before_init_ = false;
+ should_pause_encoder_on_initialization_ = false;
}
void VideoTrackRecorder::OnVideoFrameForTesting(
@@ -454,7 +473,7 @@ void VideoTrackRecorder::InitializeEncoder(
input_size.height())) {
UMA_HISTOGRAM_BOOLEAN("Media.MediaRecorder.VEAUsed", true);
const auto vea_profile = GetCodecEnumerator()->CodecIdToVEAProfile(codec);
- encoder_ = new VEAEncoder(
+ encoder_ = VEAEncoder::Create(
on_encoded_video_callback,
media::BindToCurrentLoop(base::Bind(&VideoTrackRecorder::OnError,
weak_ptr_factory_.GetWeakPtr())),
@@ -479,8 +498,8 @@ void VideoTrackRecorder::InitializeEncoder(
}
}
- if (paused_before_init_)
- encoder_->SetPaused(paused_before_init_);
+ if (should_pause_encoder_on_initialization_)
+ encoder_->SetPaused(should_pause_encoder_on_initialization_);
// StartFrameEncode() will be called on Render IO thread.
MediaStreamVideoSink::ConnectToTrack(
diff --git a/chromium/content/renderer/media_recorder/video_track_recorder.h b/chromium/content/renderer/media_recorder/video_track_recorder.h
index 73160800518..63244ef87a4 100644
--- a/chromium/content/renderer/media_recorder/video_track_recorder.h
+++ b/chromium/content/renderer/media_recorder/video_track_recorder.h
@@ -69,6 +69,22 @@ class CONTENT_EXPORT VideoTrackRecorder : public MediaStreamVideoSink {
bool is_key_frame)>;
using OnErrorCB = base::Closure;
+ // Wraps a counter in a class in order to enable use of base::WeakPtr<>.
+ // See https://crbug.com/859610 for why this was added.
+ class Counter {
+ public:
+ Counter();
+ ~Counter();
+ uint32_t count() const { return count_; }
+ void IncreaseCount();
+ void DecreaseCount();
+ base::WeakPtr<Counter> GetWeakPtr();
+
+ private:
+ uint32_t count_;
+ base::WeakPtrFactory<Counter> weak_factory_;
+ };
+
// Base class to describe a generic Encoder, encapsulating all actual encoder
// (re)configurations, encoding and delivery of received frames. This class is
// ref-counted to allow the MediaStreamVideoTrack to hold a reference to it
@@ -118,6 +134,13 @@ class CONTENT_EXPORT VideoTrackRecorder : public MediaStreamVideoSink {
friend class base::RefCountedThreadSafe<Encoder>;
friend class VideoTrackRecorderTest;
+ // This destructor may run on either |main_task_runner|,
+ // |encoding_task_runner|, or |origin_task_runner_|. Main ownership lies
+ // with VideoTrackRecorder. Shared ownership is handed out to
+ // asynchronous tasks running on |encoding_task_runner| for encoding. Shared
+ // ownership is also handed out to a MediaStreamVideoTrack which pushes
+ // frames on |origin_task_runner_|. Each of these may end up being the last
+ // reference.
virtual ~Encoder();
virtual void EncodeOnEncodingTaskRunner(
@@ -150,7 +173,8 @@ class CONTENT_EXPORT VideoTrackRecorder : public MediaStreamVideoSink {
const int32_t bits_per_second_;
// Number of frames that we keep the reference alive for encode.
- uint32_t num_frames_in_encode_;
+ // Operated and released exclusively on |origin_task_runner_|.
+ std::unique_ptr<Counter> num_frames_in_encode_;
// Used to retrieve incoming opaque VideoFrames (i.e. VideoFrames backed by
// textures). Created on-demand on |main_task_runner_|.
@@ -203,8 +227,7 @@ class CONTENT_EXPORT VideoTrackRecorder : public MediaStreamVideoSink {
base::TimeTicks capture_time)>
initialize_encoder_callback_;
- // Used to track the paused state during the initialization process.
- bool paused_before_init_;
+ bool should_pause_encoder_on_initialization_;
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
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 2eecab58c8c..286089354ee 100644
--- a/chromium/content/renderer/media_recorder/video_track_recorder_unittest.cc
+++ b/chromium/content/renderer/media_recorder/video_track_recorder_unittest.cc
@@ -17,6 +17,7 @@
#include "base/single_thread_task_runner.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_task_environment.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "content/child/child_process.h"
#include "content/renderer/media/stream/media_stream_video_track.h"
#include "content/renderer/media/stream/mock_media_stream_video_source.h"
@@ -92,6 +93,9 @@ class VideoTrackRecorderTest
blink_source_.Reset();
video_track_recorder_.reset();
blink::WebHeap::CollectAllGarbageForTesting();
+ // VideoTrackRecorder::Encoder::~Encoder may post a DeleteSoon(), which
+ // may cause ASAN to detect a memory leak if we don't wait.
+ scoped_task_environment_.RunUntilIdle();
}
void InitializeRecorder(VideoTrackRecorder::CodecId codec) {
@@ -137,7 +141,7 @@ class VideoTrackRecorderTest
}
uint32_t NumFramesInEncode() {
- return video_track_recorder_->encoder_->num_frames_in_encode_;
+ return video_track_recorder_->encoder_->num_frames_in_encode_->count();
}
// A ChildProcess is needed to fool the Tracks and Sources into believing they
diff --git a/chromium/content/renderer/message_delivery_policy.h b/chromium/content/renderer/message_delivery_policy.h
deleted file mode 100644
index 4ad9b2f1a11..00000000000
--- a/chromium/content/renderer/message_delivery_policy.h
+++ /dev/null
@@ -1,25 +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_MESSAGE_DELIVERY_POLICY_H_
-#define CONTENT_RENDERER_MESSAGE_DELIVERY_POLICY_H_
-
-namespace content {
-
-enum MessageDeliveryPolicy {
- // If a commit was requested before the message was enqueued the message
- // will be delivered with the swap corresponding to that commit. Otherwise
- // the message will be sent immediately using regular IPC.
- // If the commit is aborted or optimized out the message is sent using regular
- // IPC.
- MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE,
- // The message will be delivered with the next swap.
- // If the swap is optimized out, the message is sent using regular IPC.
- // If the swap fails the message remains enqueued.
- MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP,
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_MESSAGE_DELIVERY_POLICY_H_
diff --git a/chromium/content/renderer/mojo/blink_interface_registry_impl.cc b/chromium/content/renderer/mojo/blink_interface_registry_impl.cc
index 34113b87bee..36d10c45fef 100644
--- a/chromium/content/renderer/mojo/blink_interface_registry_impl.cc
+++ b/chromium/content/renderer/mojo/blink_interface_registry_impl.cc
@@ -13,7 +13,7 @@ namespace content {
BlinkInterfaceRegistryImpl::BlinkInterfaceRegistryImpl(
base::WeakPtr<service_manager::BinderRegistry> interface_registry,
- base::WeakPtr<AssociatedInterfaceRegistryImpl>
+ base::WeakPtr<blink::AssociatedInterfaceRegistry>
associated_interface_registry)
: interface_registry_(interface_registry),
associated_interface_registry_(associated_interface_registry) {}
diff --git a/chromium/content/renderer/mojo/blink_interface_registry_impl.h b/chromium/content/renderer/mojo/blink_interface_registry_impl.h
index fbee9230c84..4a5c0d358ee 100644
--- a/chromium/content/renderer/mojo/blink_interface_registry_impl.h
+++ b/chromium/content/renderer/mojo/blink_interface_registry_impl.h
@@ -8,8 +8,8 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
-#include "content/common/associated_interface_registry_impl.h"
#include "services/service_manager/public/cpp/binder_registry.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
#include "third_party/blink/public/platform/interface_registry.h"
namespace content {
@@ -18,7 +18,7 @@ class BlinkInterfaceRegistryImpl final : public blink::InterfaceRegistry {
public:
BlinkInterfaceRegistryImpl(
base::WeakPtr<service_manager::BinderRegistry> interface_registry,
- base::WeakPtr<AssociatedInterfaceRegistryImpl>
+ base::WeakPtr<blink::AssociatedInterfaceRegistry>
associated_interface_registry);
~BlinkInterfaceRegistryImpl();
@@ -33,7 +33,7 @@ class BlinkInterfaceRegistryImpl final : public blink::InterfaceRegistry {
private:
const base::WeakPtr<service_manager::BinderRegistry> interface_registry_;
- const base::WeakPtr<AssociatedInterfaceRegistryImpl>
+ const base::WeakPtr<blink::AssociatedInterfaceRegistry>
associated_interface_registry_;
DISALLOW_COPY_AND_ASSIGN(BlinkInterfaceRegistryImpl);
diff --git a/chromium/content/renderer/mus/BUILD.gn b/chromium/content/renderer/mus/BUILD.gn
index 3fbd6316fec..391e93c5422 100644
--- a/chromium/content/renderer/mus/BUILD.gn
+++ b/chromium/content/renderer/mus/BUILD.gn
@@ -31,8 +31,8 @@ static_library("mus") {
"//content/public/child:child_sources",
"//media/mojo/interfaces:remoting",
"//services/service_manager/public/cpp",
- "//services/ui/public/cpp",
- "//services/ui/public/interfaces",
+ "//services/ws/public/cpp",
+ "//services/ws/public/mojom",
"//third_party/blink/public:blink",
"//ui/events:events",
"//ui/events:events_base",
diff --git a/chromium/content/renderer/mus/mus_embedded_frame.cc b/chromium/content/renderer/mus/mus_embedded_frame.cc
index e0fdd265386..4f6b4ad3169 100644
--- a/chromium/content/renderer/mus/mus_embedded_frame.cc
+++ b/chromium/content/renderer/mus/mus_embedded_frame.cc
@@ -13,8 +13,8 @@
#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/ui/public/cpp/property_type_converters.h"
-#include "services/ui/public/interfaces/window_manager.mojom.h"
+#include "services/ws/public/cpp/property_type_converters.h"
+#include "services/ws/public/mojom/window_manager.mojom.h"
namespace content {
namespace {
@@ -64,7 +64,7 @@ void MusEmbeddedFrame::SetWindowBounds(
MusEmbeddedFrame::MusEmbeddedFrame(
RendererWindowTreeClient* renderer_window_tree_client,
MusEmbeddedFrameDelegate* delegate,
- ui::ClientSpecificId window_id,
+ ws::ClientSpecificId window_id,
const base::UnguessableToken& token)
: renderer_window_tree_client_(renderer_window_tree_client),
delegate_(delegate),
@@ -81,7 +81,7 @@ void MusEmbeddedFrame::CreateChildWindowAndEmbed(
const base::UnguessableToken& token) {
// Set a name for debugging.
base::flat_map<std::string, std::vector<uint8_t>> properties;
- properties[ui::mojom::WindowManager::kName_Property] =
+ 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(),
@@ -108,7 +108,7 @@ uint32_t MusEmbeddedFrame::GetAndAdvanceNextChangeId() {
return renderer_window_tree_client_->GetAndAdvanceNextChangeId();
}
-ui::mojom::WindowTree* MusEmbeddedFrame::window_tree() {
+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();
diff --git a/chromium/content/renderer/mus/mus_embedded_frame.h b/chromium/content/renderer/mus/mus_embedded_frame.h
index 3639c8af1ef..a6ad8fece7d 100644
--- a/chromium/content/renderer/mus/mus_embedded_frame.h
+++ b/chromium/content/renderer/mus/mus_embedded_frame.h
@@ -10,10 +10,10 @@
#include "base/macros.h"
#include "base/unguessable_token.h"
#include "components/viz/common/surfaces/local_surface_id.h"
-#include "services/ui/common/types.h"
+#include "services/ws/common/types.h"
#include "ui/gfx/geometry/rect.h"
-namespace ui {
+namespace ws {
namespace mojom {
class WindowTree;
}
@@ -52,7 +52,7 @@ class MusEmbeddedFrame {
MusEmbeddedFrame(RendererWindowTreeClient* renderer_window_tree_client,
MusEmbeddedFrameDelegate* delegate,
- ui::ClientSpecificId window_id,
+ ws::ClientSpecificId window_id,
const base::UnguessableToken& token);
// Called once the WindowTree has been obtained. This is only called if
@@ -68,11 +68,11 @@ class MusEmbeddedFrame {
uint32_t GetAndAdvanceNextChangeId();
- ui::mojom::WindowTree* window_tree();
+ ws::mojom::WindowTree* window_tree();
RendererWindowTreeClient* renderer_window_tree_client_;
MusEmbeddedFrameDelegate* delegate_;
- const ui::ClientSpecificId window_id_;
+ const ws::ClientSpecificId window_id_;
std::unique_ptr<PendingState> pending_state_;
diff --git a/chromium/content/renderer/mus/render_widget_window_tree_client_factory.cc b/chromium/content/renderer/mus/render_widget_window_tree_client_factory.cc
index bda28e54de3..ab490b37092 100644
--- a/chromium/content/renderer/mus/render_widget_window_tree_client_factory.cc
+++ b/chromium/content/renderer/mus/render_widget_window_tree_client_factory.cc
@@ -18,7 +18,7 @@
#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/ui/public/interfaces/window_tree.mojom.h"
+#include "services/ws/public/mojom/window_tree.mojom.h"
#include "url/gurl.h"
namespace content {
@@ -27,7 +27,7 @@ namespace {
void BindMusConnectionOnMainThread(
uint32_t routing_id,
- ui::mojom::WindowTreeClientRequest request,
+ ws::mojom::WindowTreeClientRequest request,
mojom::RenderWidgetWindowTreeClientRequest
render_widget_window_tree_client_request) {
RendererWindowTreeClient::CreateIfNecessary(routing_id);
@@ -64,7 +64,7 @@ class RenderWidgetWindowTreeClientFactoryImpl
// mojom::RenderWidgetWindowTreeClientFactory implementation.
void CreateWindowTreeClientForRenderWidget(
uint32_t routing_id,
- ui::mojom::WindowTreeClientRequest request,
+ ws::mojom::WindowTreeClientRequest request,
mojom::RenderWidgetWindowTreeClientRequest
render_widget_window_tree_client_request) override {
main_thread_task_runner_->PostTask(
diff --git a/chromium/content/renderer/mus/renderer_window_tree_client.cc b/chromium/content/renderer/mus/renderer_window_tree_client.cc
index ee2d0c21ea8..4eef295478b 100644
--- a/chromium/content/renderer/mus/renderer_window_tree_client.cc
+++ b/chromium/content/renderer/mus/renderer_window_tree_client.cc
@@ -32,7 +32,7 @@ base::LazyInstance<ConnectionMap>::Leaky g_connections =
// static
void RendererWindowTreeClient::CreateIfNecessary(int routing_id) {
- if (features::IsAshInBrowserProcess() || Get(routing_id))
+ if (!features::IsUsingWindowService() || Get(routing_id))
return;
RendererWindowTreeClient* connection =
new RendererWindowTreeClient(routing_id);
@@ -53,7 +53,7 @@ RendererWindowTreeClient* RendererWindowTreeClient::Get(int routing_id) {
}
void RendererWindowTreeClient::Bind(
- ui::mojom::WindowTreeClientRequest request,
+ ws::mojom::WindowTreeClientRequest request,
mojom::RenderWidgetWindowTreeClientRequest
render_widget_window_tree_client_request) {
// Bind() may be called multiple times.
@@ -175,7 +175,7 @@ void RendererWindowTreeClient::Embed(uint32_t frame_routing_id,
void RendererWindowTreeClient::OnEmbedFromToken(
const base::UnguessableToken& token,
- ui::mojom::WindowDataPtr root,
+ ws::mojom::WindowDataPtr root,
int64_t display_id,
const base::Optional<viz::LocalSurfaceId>& local_surface_id) {
// Renderers don't use ScheduleEmbedForExistingClient(), so this path should
@@ -188,10 +188,10 @@ void RendererWindowTreeClient::DestroyFrame(uint32_t frame_routing_id) {
}
void RendererWindowTreeClient::OnEmbed(
- ui::mojom::WindowDataPtr root,
- ui::mojom::WindowTreePtr tree,
+ ws::mojom::WindowDataPtr root,
+ ws::mojom::WindowTreePtr tree,
int64_t display_id,
- ui::Id focused_window_id,
+ ws::Id focused_window_id,
bool drawn,
const base::Optional<viz::LocalSurfaceId>& local_surface_id) {
const bool is_reembed = tree_.is_bound();
@@ -220,24 +220,24 @@ void RendererWindowTreeClient::OnEmbed(
}
}
-void RendererWindowTreeClient::OnEmbeddedAppDisconnected(ui::Id window_id) {
+void RendererWindowTreeClient::OnEmbeddedAppDisconnected(ws::Id window_id) {
// TODO(sad): Embedded mus-client (oopif) is gone. Figure out what to do.
}
-void RendererWindowTreeClient::OnUnembed(ui::Id window_id) {
+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(ui::Id new_capture_window_id,
- ui::Id old_capture_window_id) {}
+void RendererWindowTreeClient::OnCaptureChanged(ws::Id new_capture_window_id,
+ ws::Id old_capture_window_id) {}
void RendererWindowTreeClient::OnFrameSinkIdAllocated(
- ui::Id window_id,
+ 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::IsAshInBrowserProcess())
+ if (!features::IsUsingWindowService())
return;
for (MusEmbeddedFrame* embedded_frame : embedded_frames_) {
@@ -251,7 +251,7 @@ void RendererWindowTreeClient::OnFrameSinkIdAllocated(
void RendererWindowTreeClient::OnTopLevelCreated(
uint32_t change_id,
- ui::mojom::WindowDataPtr data,
+ ws::mojom::WindowDataPtr data,
int64_t display_id,
bool drawn,
const base::Optional<viz::LocalSurfaceId>& local_surface_id) {
@@ -259,65 +259,58 @@ void RendererWindowTreeClient::OnTopLevelCreated(
}
void RendererWindowTreeClient::OnWindowBoundsChanged(
- ui::Id window_id,
+ ws::Id window_id,
const gfx::Rect& old_bounds,
const gfx::Rect& new_bounds,
const base::Optional<viz::LocalSurfaceId>& local_surface_id) {}
void RendererWindowTreeClient::OnWindowTransformChanged(
- ui::Id window_id,
+ ws::Id window_id,
const gfx::Transform& old_transform,
const gfx::Transform& new_transform) {}
-void RendererWindowTreeClient::OnClientAreaChanged(
- ui::Id window_id,
- const gfx::Insets& new_client_area,
- const std::vector<gfx::Rect>& new_additional_client_areas) {}
-
void RendererWindowTreeClient::OnTransientWindowAdded(
- ui::Id window_id,
- ui::Id transient_window_id) {}
+ ws::Id window_id,
+ ws::Id transient_window_id) {}
void RendererWindowTreeClient::OnTransientWindowRemoved(
- ui::Id window_id,
- ui::Id transient_window_id) {}
+ ws::Id window_id,
+ ws::Id transient_window_id) {}
void RendererWindowTreeClient::OnWindowHierarchyChanged(
- ui::Id window_id,
- ui::Id old_parent_id,
- ui::Id new_parent_id,
- std::vector<ui::mojom::WindowDataPtr> windows) {}
+ ws::Id window_id,
+ ws::Id old_parent_id,
+ ws::Id new_parent_id,
+ std::vector<ws::mojom::WindowDataPtr> windows) {}
void RendererWindowTreeClient::OnWindowReordered(
- ui::Id window_id,
- ui::Id relative_window_id,
- ui::mojom::OrderDirection direction) {}
+ ws::Id window_id,
+ ws::Id relative_window_id,
+ ws::mojom::OrderDirection direction) {}
-void RendererWindowTreeClient::OnWindowDeleted(ui::Id window_id) {
+void RendererWindowTreeClient::OnWindowDeleted(ws::Id window_id) {
// See comments on OnUnembed() for why we do nothing here.
}
-void RendererWindowTreeClient::OnWindowVisibilityChanged(ui::Id window_id,
+void RendererWindowTreeClient::OnWindowVisibilityChanged(ws::Id window_id,
bool visible) {}
-void RendererWindowTreeClient::OnWindowOpacityChanged(ui::Id window_id,
+void RendererWindowTreeClient::OnWindowOpacityChanged(ws::Id window_id,
float old_opacity,
float new_opacity) {}
-void RendererWindowTreeClient::OnWindowParentDrawnStateChanged(ui::Id window_id,
+void RendererWindowTreeClient::OnWindowParentDrawnStateChanged(ws::Id window_id,
bool drawn) {}
void RendererWindowTreeClient::OnWindowSharedPropertyChanged(
- ui::Id window_id,
+ ws::Id window_id,
const std::string& name,
const base::Optional<std::vector<uint8_t>>& new_data) {}
void RendererWindowTreeClient::OnWindowInputEvent(
uint32_t event_id,
- ui::Id window_id,
+ ws::Id window_id,
int64_t display_id,
- ui::Id display_root_window_id,
- const gfx::PointF& event_location_in_screen_pixel_layout,
std::unique_ptr<ui::Event> event,
bool matches_pointer_watcher) {
NOTREACHED();
@@ -325,20 +318,20 @@ void RendererWindowTreeClient::OnWindowInputEvent(
void RendererWindowTreeClient::OnPointerEventObserved(
std::unique_ptr<ui::Event> event,
- ui::Id window_id,
+ ws::Id window_id,
int64_t display_id) {
NOTREACHED();
}
-void RendererWindowTreeClient::OnWindowFocused(ui::Id focused_window_id) {}
+void RendererWindowTreeClient::OnWindowFocused(ws::Id focused_window_id) {}
-void RendererWindowTreeClient::OnWindowCursorChanged(ui::Id window_id,
+void RendererWindowTreeClient::OnWindowCursorChanged(ws::Id window_id,
ui::CursorData cursor) {}
void RendererWindowTreeClient::OnWindowSurfaceChanged(
- ui::Id window_id,
+ ws::Id window_id,
const viz::SurfaceInfo& surface_info) {
- DCHECK(!features::IsAshInBrowserProcess());
+ DCHECK(features::IsUsingWindowService());
for (MusEmbeddedFrame* embedded_frame : embedded_frames_) {
if (embedded_frame->window_id_ == window_id) {
embedded_frame->delegate_->OnMusEmbeddedFrameSurfaceChanged(surface_info);
@@ -350,21 +343,21 @@ void RendererWindowTreeClient::OnWindowSurfaceChanged(
void RendererWindowTreeClient::OnDragDropStart(
const base::flat_map<std::string, std::vector<uint8_t>>& mime_data) {}
-void RendererWindowTreeClient::OnDragEnter(ui::Id window_id,
+void RendererWindowTreeClient::OnDragEnter(ws::Id window_id,
uint32_t event_flags,
const gfx::Point& position,
uint32_t effect_bitmask,
OnDragEnterCallback callback) {}
-void RendererWindowTreeClient::OnDragOver(ui::Id window_id,
+void RendererWindowTreeClient::OnDragOver(ws::Id window_id,
uint32_t event_flags,
const gfx::Point& position,
uint32_t effect_bitmask,
OnDragOverCallback callback) {}
-void RendererWindowTreeClient::OnDragLeave(ui::Id window_id) {}
+void RendererWindowTreeClient::OnDragLeave(ws::Id window_id) {}
-void RendererWindowTreeClient::OnCompleteDrop(ui::Id window_id,
+void RendererWindowTreeClient::OnCompleteDrop(ws::Id window_id,
uint32_t event_flags,
const gfx::Point& position,
uint32_t effect_bitmask,
@@ -378,6 +371,9 @@ void RendererWindowTreeClient::OnPerformDragDropCompleted(
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
@@ -386,14 +382,9 @@ void RendererWindowTreeClient::OnChangeCompleted(uint32_t change_id,
// controls the visibility of the root frame).
}
-void RendererWindowTreeClient::RequestClose(ui::Id window_id) {}
-
-void RendererWindowTreeClient::GetWindowManager(
- mojo::AssociatedInterfaceRequest<ui::mojom::WindowManager> internal) {
- NOTREACHED();
-}
+void RendererWindowTreeClient::RequestClose(ws::Id window_id) {}
void RendererWindowTreeClient::GetScreenProviderObserver(
- ui::mojom::ScreenProviderObserverAssociatedRequest observer) {}
+ ws::mojom::ScreenProviderObserverAssociatedRequest observer) {}
} // namespace content
diff --git a/chromium/content/renderer/mus/renderer_window_tree_client.h b/chromium/content/renderer/mus/renderer_window_tree_client.h
index 5309e209efd..8a9352f388e 100644
--- a/chromium/content/renderer/mus/renderer_window_tree_client.h
+++ b/chromium/content/renderer/mus/renderer_window_tree_client.h
@@ -14,8 +14,8 @@
#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/ui/common/types.h"
-#include "services/ui/public/interfaces/window_tree.mojom.h"
+#include "services/ws/common/types.h"
+#include "services/ws/public/mojom/window_tree.mojom.h"
#include "ui/gfx/geometry/rect.h"
namespace base {
@@ -40,9 +40,9 @@ class MusEmbeddedFrame;
class MusEmbeddedFrameDelegate;
class RenderFrameProxy;
-// ui.mojom.WindowTreeClient implementation for RenderWidget. This lives and
+// ws::mojom::WindowTreeClient implementation for RenderWidget. This lives and
// operates on the renderer's main thread.
-class RendererWindowTreeClient : public ui::mojom::WindowTreeClient,
+class RendererWindowTreeClient : public ws::mojom::WindowTreeClient,
public mojom::RenderWidgetWindowTreeClient {
public:
// Creates a RendererWindowTreeClient instance for the RenderWidget instance
@@ -59,7 +59,7 @@ class RendererWindowTreeClient : public ui::mojom::WindowTreeClient,
// TODO(sky): make RenderWidget own RendererWindowTreeClient.
static RendererWindowTreeClient* Get(int routing_id);
- void Bind(ui::mojom::WindowTreeClientRequest request,
+ void Bind(ws::mojom::WindowTreeClientRequest request,
mojom::RenderWidgetWindowTreeClientRequest
render_widget_window_tree_client_request);
@@ -79,7 +79,7 @@ class RendererWindowTreeClient : public ui::mojom::WindowTreeClient,
LayerTreeFrameSinkCallback callback);
// Creates a new MusEmbeddedFrame. |token| is an UnguessableToken that was
- // registered for an embedding with mus (specifically ui::mojom::WindowTree).
+ // registered for an embedding with mus (specifically ws::mojom::WindowTree).
std::unique_ptr<MusEmbeddedFrame> CreateMusEmbeddedFrame(
MusEmbeddedFrameDelegate* mus_embedded_frame_delegate,
const base::UnguessableToken& token);
@@ -105,98 +105,91 @@ class RendererWindowTreeClient : public ui::mojom::WindowTreeClient,
const base::UnguessableToken& token) override;
void DestroyFrame(uint32_t frame_routing_id) override;
- // ui::mojom::WindowTreeClient:
+ // 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 OnEmbed(
- ui::mojom::WindowDataPtr root,
- ui::mojom::WindowTreePtr tree,
+ ws::mojom::WindowDataPtr root,
+ ws::mojom::WindowTreePtr tree,
int64_t display_id,
- ui::Id focused_window_id,
+ ws::Id focused_window_id,
bool drawn,
const base::Optional<viz::LocalSurfaceId>& local_surface_id) override;
void OnEmbedFromToken(
const base::UnguessableToken& token,
- ui::mojom::WindowDataPtr root,
+ ws::mojom::WindowDataPtr root,
int64_t display_id,
const base::Optional<viz::LocalSurfaceId>& local_surface_id) override;
- void OnEmbeddedAppDisconnected(ui::Id window_id) override;
- void OnUnembed(ui::Id window_id) override;
- void OnCaptureChanged(ui::Id new_capture_window_id,
- ui::Id old_capture_window_id) override;
- void OnFrameSinkIdAllocated(ui::Id window_id,
+ 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,
- ui::mojom::WindowDataPtr data,
+ ws::mojom::WindowDataPtr data,
int64_t display_id,
bool drawn,
const base::Optional<viz::LocalSurfaceId>& local_surface_id) override;
void OnWindowBoundsChanged(
- ui::Id window_id,
+ ws::Id window_id,
const gfx::Rect& old_bounds,
const gfx::Rect& new_bounds,
const base::Optional<viz::LocalSurfaceId>& local_frame_id) override;
- void OnWindowTransformChanged(ui::Id window_id,
+ void OnWindowTransformChanged(ws::Id window_id,
const gfx::Transform& old_transform,
const gfx::Transform& new_transform) override;
- void OnClientAreaChanged(
- ui::Id window_id,
- const gfx::Insets& new_client_area,
- const std::vector<gfx::Rect>& new_additional_client_areas) override;
- void OnTransientWindowAdded(ui::Id window_id,
- ui::Id transient_window_id) override;
- void OnTransientWindowRemoved(ui::Id window_id,
- ui::Id transient_window_id) 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(
- ui::Id window_id,
- ui::Id old_parent_id,
- ui::Id new_parent_id,
- std::vector<ui::mojom::WindowDataPtr> windows) override;
- void OnWindowReordered(ui::Id window_id,
- ui::Id relative_window_id,
- ui::mojom::OrderDirection direction) override;
- void OnWindowDeleted(ui::Id window_id) override;
- void OnWindowVisibilityChanged(ui::Id window_id, bool visible) override;
- void OnWindowOpacityChanged(ui::Id window_id,
+ 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 OnWindowOpacityChanged(ws::Id window_id,
float old_opacity,
float new_opacity) override;
- void OnWindowParentDrawnStateChanged(ui::Id window_id, bool drawn) override;
+ void OnWindowParentDrawnStateChanged(ws::Id window_id, bool drawn) override;
void OnWindowSharedPropertyChanged(
- ui::Id window_id,
+ ws::Id window_id,
const std::string& name,
const base::Optional<std::vector<uint8_t>>& new_data) override;
- void OnWindowInputEvent(
- uint32_t event_id,
- ui::Id window_id,
- int64_t display_id,
- ui::Id display_root_window_id,
- const gfx::PointF& event_location_in_screen_pixel_layout,
- std::unique_ptr<ui::Event> event,
- bool matches_pointer_watcher) override;
+ void OnWindowInputEvent(uint32_t event_id,
+ ws::Id window_id,
+ int64_t display_id,
+ std::unique_ptr<ui::Event> event,
+ bool matches_pointer_watcher) override;
void OnPointerEventObserved(std::unique_ptr<ui::Event> event,
- ui::Id window_id,
+ ws::Id window_id,
int64_t display_id) override;
- void OnWindowFocused(ui::Id focused_window_id) override;
- void OnWindowCursorChanged(ui::Id window_id, ui::CursorData cursor) override;
- void OnWindowSurfaceChanged(ui::Id window_id,
+ void OnWindowFocused(ws::Id focused_window_id) override;
+ void OnWindowCursorChanged(ws::Id window_id, ui::CursorData cursor) override;
+ void OnWindowSurfaceChanged(ws::Id window_id,
const viz::SurfaceInfo& surface_info) override;
void OnDragDropStart(const base::flat_map<std::string, std::vector<uint8_t>>&
mime_data) override;
- void OnDragEnter(ui::Id window_id,
+ void OnDragEnter(ws::Id window_id,
uint32_t event_flags,
const gfx::Point& position,
uint32_t effect_bitmask,
OnDragEnterCallback callback) override;
- void OnDragOver(ui::Id window_id,
+ void OnDragOver(ws::Id window_id,
uint32_t event_flags,
const gfx::Point& position,
uint32_t effect_bitmask,
OnDragOverCallback callback) override;
- void OnDragLeave(ui::Id window_id) override;
- void OnCompleteDrop(ui::Id window_id,
+ void OnDragLeave(ws::Id window_id) override;
+ void OnCompleteDrop(ws::Id window_id,
uint32_t event_flags,
const gfx::Point& position,
uint32_t effect_bitmask,
@@ -205,25 +198,23 @@ class RendererWindowTreeClient : public ui::mojom::WindowTreeClient,
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(ui::Id window_id) override;
- void GetWindowManager(
- mojo::AssociatedInterfaceRequest<ui::mojom::WindowManager> internal)
- override;
+ void RequestClose(ws::Id window_id) override;
void GetScreenProviderObserver(
- ui::mojom::ScreenProviderObserverAssociatedRequest observer) override;
+ ws::mojom::ScreenProviderObserverAssociatedRequest observer) override;
const int routing_id_;
- ui::Id root_window_id_ = 0u;
+ 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_;
- ui::mojom::WindowTreePtr tree_;
- mojo::Binding<ui::mojom::WindowTreeClient> binding_;
+ ws::mojom::WindowTreePtr tree_;
+ mojo::Binding<ws::mojom::WindowTreeClient> binding_;
mojo::Binding<mojom::RenderWidgetWindowTreeClient>
render_widget_window_tree_client_binding_;
- ui::ClientSpecificId next_window_id_ = 0;
+ ws::ClientSpecificId next_window_id_ = 0;
uint32_t next_change_id_ = 0;
// Set of MusEmbeddedFrames. They are owned by the corresponding
diff --git a/chromium/content/renderer/navigation_client.cc b/chromium/content/renderer/navigation_client.cc
index 209968171ba..a9d8f5771bf 100644
--- a/chromium/content/renderer/navigation_client.cc
+++ b/chromium/content/renderer/navigation_client.cc
@@ -23,7 +23,8 @@ void NavigationClient::CommitNavigation(
subresource_overrides,
mojom::ControllerServiceWorkerInfoPtr controller_service_worker_info,
network::mojom::URLLoaderFactoryPtr prefetch_loader_factory,
- const base::UnguessableToken& devtools_navigation_token) {
+ const base::UnguessableToken& devtools_navigation_token,
+ CommitNavigationCallback callback) {
// TODO(ahemery): The reset should be done when the navigation did commit
// (meaning at a later stage). This is not currently possible because of
// race conditions leading to the early deletion of NavigationRequest would
@@ -35,7 +36,7 @@ void NavigationClient::CommitNavigation(
std::move(subresource_overrides),
std::move(controller_service_worker_info),
std::move(prefetch_loader_factory), devtools_navigation_token,
- mojom::FrameNavigationControl::CommitNavigationCallback());
+ std::move(callback));
}
void NavigationClient::CommitFailedNavigation(
@@ -44,12 +45,12 @@ void NavigationClient::CommitFailedNavigation(
bool has_stale_copy_in_cache,
int error_code,
const base::Optional<std::string>& error_page_content,
- std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loaders) {
+ std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loaders,
+ CommitFailedNavigationCallback callback) {
ResetDisconnectionHandler();
render_frame_->CommitFailedNavigation(
common_params, request_params, has_stale_copy_in_cache, error_code,
- error_page_content, std::move(subresource_loaders),
- mojom::FrameNavigationControl::CommitFailedNavigationCallback());
+ error_page_content, std::move(subresource_loaders), std::move(callback));
}
void NavigationClient::Bind(mojom::NavigationClientAssociatedRequest request) {
diff --git a/chromium/content/renderer/navigation_client.h b/chromium/content/renderer/navigation_client.h
index 3f535c5d1e8..b8f8d69d127 100644
--- a/chromium/content/renderer/navigation_client.h
+++ b/chromium/content/renderer/navigation_client.h
@@ -28,14 +28,16 @@ class NavigationClient : mojom::NavigationClient {
subresource_overrides,
mojom::ControllerServiceWorkerInfoPtr controller_service_worker_info,
network::mojom::URLLoaderFactoryPtr prefetch_loader_factory,
- const base::UnguessableToken& devtools_navigation_token) override;
+ const base::UnguessableToken& devtools_navigation_token,
+ CommitNavigationCallback callback) override;
void CommitFailedNavigation(
const CommonNavigationParams& common_params,
const RequestNavigationParams& request_params,
bool has_stale_copy_in_cache,
int error_code,
const base::Optional<std::string>& error_page_content,
- std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loaders) override;
+ std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loaders,
+ CommitFailedNavigationCallback callback) override;
void Bind(mojom::NavigationClientAssociatedRequest request);
diff --git a/chromium/content/renderer/p2p/empty_network_manager.h b/chromium/content/renderer/p2p/empty_network_manager.h
index 1ecb6a80fb4..35df4d1df2c 100644
--- a/chromium/content/renderer/p2p/empty_network_manager.h
+++ b/chromium/content/renderer/p2p/empty_network_manager.h
@@ -10,7 +10,7 @@
#include "base/threading/thread_checker.h"
#include "content/common/content_export.h"
#include "third_party/webrtc/rtc_base/network.h"
-#include "third_party/webrtc/rtc_base/sigslot.h"
+#include "third_party/webrtc/rtc_base/third_party/sigslot/sigslot.h"
namespace rtc {
class IPAddress;
diff --git a/chromium/content/renderer/p2p/filtering_network_manager.h b/chromium/content/renderer/p2p/filtering_network_manager.h
index 99d5ef50dd3..16ef60d3647 100644
--- a/chromium/content/renderer/p2p/filtering_network_manager.h
+++ b/chromium/content/renderer/p2p/filtering_network_manager.h
@@ -12,7 +12,7 @@
#include "content/common/content_export.h"
#include "content/renderer/p2p/network_manager_uma.h"
#include "third_party/webrtc/rtc_base/network.h"
-#include "third_party/webrtc/rtc_base/sigslot.h"
+#include "third_party/webrtc/rtc_base/third_party/sigslot/sigslot.h"
#include "url/gurl.h"
namespace media {
diff --git a/chromium/content/renderer/p2p/host_address_request.cc b/chromium/content/renderer/p2p/host_address_request.cc
index 221e46b9367..0b0c8747e53 100644
--- a/chromium/content/renderer/p2p/host_address_request.cc
+++ b/chromium/content/renderer/p2p/host_address_request.cc
@@ -7,9 +7,7 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/location.h"
-#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
-#include "content/common/p2p_messages.h"
#include "content/renderer/p2p/socket_dispatcher.h"
#include "jingle/glue/utils.h"
@@ -17,78 +15,37 @@ namespace content {
P2PAsyncAddressResolver::P2PAsyncAddressResolver(
P2PSocketDispatcher* dispatcher)
- : dispatcher_(dispatcher),
- ipc_task_runner_(dispatcher->task_runner()),
- delegate_task_runner_(base::ThreadTaskRunnerHandle::Get()),
- state_(STATE_CREATED),
- request_id_(0),
- registered_(false) {
+ : dispatcher_(dispatcher), state_(STATE_CREATED) {
AddRef(); // Balanced in Destroy().
}
P2PAsyncAddressResolver::~P2PAsyncAddressResolver() {
DCHECK(state_ == STATE_CREATED || state_ == STATE_FINISHED);
- DCHECK(!registered_);
}
void P2PAsyncAddressResolver::Start(const rtc::SocketAddress& host_name,
const DoneCallback& done_callback) {
- DCHECK(delegate_task_runner_->BelongsToCurrentThread());
+ DCHECK(thread_checker_.CalledOnValidThread());
DCHECK_EQ(STATE_CREATED, state_);
state_ = STATE_SENT;
- ipc_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&P2PAsyncAddressResolver::DoSendRequest, this,
- host_name, done_callback));
+ done_callback_ = done_callback;
+ dispatcher_->GetP2PSocketManager()->GetHostAddress(
+ host_name.hostname(), base::BindOnce(&P2PAsyncAddressResolver::OnResponse,
+ base::Unretained(this)));
}
void P2PAsyncAddressResolver::Cancel() {
- DCHECK(delegate_task_runner_->BelongsToCurrentThread());
+ DCHECK(thread_checker_.CalledOnValidThread());
- if (state_ != STATE_FINISHED) {
+ if (state_ != STATE_FINISHED)
state_ = STATE_FINISHED;
- ipc_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&P2PAsyncAddressResolver::DoUnregister, this));
- }
- done_callback_.Reset();
-}
-
-void P2PAsyncAddressResolver::DoSendRequest(
- const rtc::SocketAddress& host_name,
- const DoneCallback& done_callback) {
- DCHECK(ipc_task_runner_->BelongsToCurrentThread());
-
- done_callback_ = done_callback;
- request_id_ = dispatcher_->RegisterHostAddressRequest(this);
- registered_ = true;
- dispatcher_->SendP2PMessage(
- new P2PHostMsg_GetHostAddress(host_name.hostname(), request_id_));
-}
-void P2PAsyncAddressResolver::DoUnregister() {
- DCHECK(ipc_task_runner_->BelongsToCurrentThread());
- if (registered_) {
- dispatcher_->UnregisterHostAddressRequest(request_id_);
- registered_ = false;
- }
+ done_callback_.Reset();
}
void P2PAsyncAddressResolver::OnResponse(const net::IPAddressList& addresses) {
- DCHECK(ipc_task_runner_->BelongsToCurrentThread());
- DCHECK(registered_);
-
- dispatcher_->UnregisterHostAddressRequest(request_id_);
- registered_ = false;
-
- delegate_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&P2PAsyncAddressResolver::DeliverResponse, this,
- addresses));
-}
-
-void P2PAsyncAddressResolver::DeliverResponse(
- const net::IPAddressList& addresses) {
- DCHECK(delegate_task_runner_->BelongsToCurrentThread());
+ DCHECK(thread_checker_.CalledOnValidThread());
if (state_ == STATE_SENT) {
state_ = STATE_FINISHED;
base::ResetAndReturn(&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 2f2ecac37b5..8811f78de5d 100644
--- a/chromium/content/renderer/p2p/host_address_request.h
+++ b/chromium/content/renderer/p2p/host_address_request.h
@@ -12,14 +12,11 @@
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
#include "content/common/content_export.h"
#include "net/base/ip_address.h"
#include "third_party/webrtc/rtc_base/asyncresolverinterface.h"
-namespace base {
-class SingleThreadTaskRunner;
-} // namespace base
-
namespace content {
class P2PSocketDispatcher;
@@ -51,23 +48,13 @@ class P2PAsyncAddressResolver
virtual ~P2PAsyncAddressResolver();
- void DoSendRequest(const rtc::SocketAddress& host_name,
- const DoneCallback& done_callback);
- void DoUnregister();
void OnResponse(const net::IPAddressList& address);
- void DeliverResponse(const net::IPAddressList& address);
P2PSocketDispatcher* dispatcher_;
- scoped_refptr<base::SingleThreadTaskRunner> ipc_task_runner_;
- scoped_refptr<base::SingleThreadTaskRunner> delegate_task_runner_;
+ base::ThreadChecker thread_checker_;
// State must be accessed from delegate thread only.
State state_;
-
- // Accessed on the IPC thread only.
- int32_t request_id_;
- bool registered_;
- std::vector<rtc::IPAddress> addresses_;
DoneCallback done_callback_;
DISALLOW_COPY_AND_ASSIGN(P2PAsyncAddressResolver);
diff --git a/chromium/content/renderer/p2p/ipc_socket_factory.cc b/chromium/content/renderer/p2p/ipc_socket_factory.cc
index d38d76a1c44..3384c6cce22 100644
--- a/chromium/content/renderer/p2p/ipc_socket_factory.cc
+++ b/chromium/content/renderer/p2p/ipc_socket_factory.cc
@@ -32,26 +32,26 @@ namespace {
const int kDefaultNonSetOptionValue = -1;
-bool IsTcpClientSocket(P2PSocketType type) {
- return (type == P2P_SOCKET_STUN_TCP_CLIENT) ||
- (type == P2P_SOCKET_TCP_CLIENT) ||
- (type == P2P_SOCKET_STUN_SSLTCP_CLIENT) ||
- (type == P2P_SOCKET_SSLTCP_CLIENT) ||
- (type == P2P_SOCKET_TLS_CLIENT) ||
- (type == P2P_SOCKET_STUN_TLS_CLIENT);
+bool IsTcpClientSocket(network::P2PSocketType type) {
+ return (type == network::P2P_SOCKET_STUN_TCP_CLIENT) ||
+ (type == network::P2P_SOCKET_TCP_CLIENT) ||
+ (type == network::P2P_SOCKET_STUN_SSLTCP_CLIENT) ||
+ (type == network::P2P_SOCKET_SSLTCP_CLIENT) ||
+ (type == network::P2P_SOCKET_TLS_CLIENT) ||
+ (type == network::P2P_SOCKET_STUN_TLS_CLIENT);
}
bool JingleSocketOptionToP2PSocketOption(rtc::Socket::Option option,
- P2PSocketOption* ipc_option) {
+ network::P2PSocketOption* ipc_option) {
switch (option) {
case rtc::Socket::OPT_RCVBUF:
- *ipc_option = P2P_SOCKET_OPT_RCVBUF;
+ *ipc_option = network::P2P_SOCKET_OPT_RCVBUF;
break;
case rtc::Socket::OPT_SNDBUF:
- *ipc_option = P2P_SOCKET_OPT_SNDBUF;
+ *ipc_option = network::P2P_SOCKET_OPT_SNDBUF;
break;
case rtc::Socket::OPT_DSCP:
- *ipc_option = P2P_SOCKET_OPT_DSCP;
+ *ipc_option = network::P2P_SOCKET_OPT_DSCP;
break;
case rtc::Socket::OPT_DONTFRAGMENT:
case rtc::Socket::OPT_NODELAY:
@@ -90,8 +90,8 @@ class IpcPacketSocket : public rtc::AsyncPacketSocket,
typedef std::list<InFlightPacketRecord> InFlightPacketList;
// Always takes ownership of client even if initialization fails.
- bool Init(P2PSocketType type,
- P2PSocketClientImpl* client,
+ bool Init(network::P2PSocketType type,
+ std::unique_ptr<P2PSocketClientImpl> client,
const rtc::SocketAddress& local_address,
uint16_t min_port,
uint16_t max_port,
@@ -117,12 +117,14 @@ class IpcPacketSocket : public rtc::AsyncPacketSocket,
// P2PSocketClientDelegate implementation.
void OnOpen(const net::IPEndPoint& local_address,
const net::IPEndPoint& remote_address) override;
- void OnIncomingTcpConnection(const net::IPEndPoint& address,
- P2PSocketClient* client) override;
- void OnSendComplete(const P2PSendPacketMetrics& send_metrics) override;
+ void OnIncomingTcpConnection(
+ const net::IPEndPoint& address,
+ std::unique_ptr<P2PSocketClient> client) override;
+ void OnSendComplete(
+ const network::P2PSendPacketMetrics& send_metrics) override;
void OnError() override;
void OnDataReceived(const net::IPEndPoint& address,
- const std::vector<char>& data,
+ const std::vector<int8_t>& data,
const base::TimeTicks& timestamp) override;
private:
@@ -143,19 +145,19 @@ class IpcPacketSocket : public rtc::AsyncPacketSocket,
// |in_flight_packet_records_|.
void TraceSendThrottlingState() const;
- void InitAcceptedTcp(P2PSocketClient* client,
+ void InitAcceptedTcp(std::unique_ptr<P2PSocketClient> client,
const rtc::SocketAddress& local_address,
const rtc::SocketAddress& remote_address);
- int DoSetOption(P2PSocketOption option, int value);
+ int DoSetOption(network::P2PSocketOption option, int value);
- P2PSocketType type_;
+ network::P2PSocketType type_;
// Used to verify that a method runs on the thread that created this socket.
base::ThreadChecker thread_checker_;
// Corresponding P2P socket client.
- scoped_refptr<P2PSocketClient> client_;
+ std::unique_ptr<P2PSocketClient> client_;
// Local address is allocated by the browser process, and the
// renderer side doesn't know the address until it receives OnOpen()
@@ -187,7 +189,7 @@ class IpcPacketSocket : public rtc::AsyncPacketSocket,
// Current error code. Valid when state_ == IS_ERROR.
int error_;
- int options_[P2P_SOCKET_OPT_MAX];
+ int options_[network::P2P_SOCKET_OPT_MAX];
// Track the maximum and current consecutive bytes discarded due to not enough
// send_bytes_available_.
@@ -229,7 +231,7 @@ class AsyncAddressResolverImpl : public rtc::AsyncResolverInterface {
};
IpcPacketSocket::IpcPacketSocket()
- : type_(P2P_SOCKET_UDP),
+ : type_(network::P2P_SOCKET_UDP),
state_(IS_UNINITIALIZED),
send_bytes_available_(kMaximumInFlightBytes),
writable_signal_expected_(false),
@@ -239,7 +241,7 @@ IpcPacketSocket::IpcPacketSocket()
packets_discarded_(0),
total_packets_(0) {
static_assert(kMaximumInFlightBytes > 0, "would send at zero rate");
- std::fill_n(options_, static_cast<int> (P2P_SOCKET_OPT_MAX),
+ std::fill_n(options_, static_cast<int>(network::P2P_SOCKET_OPT_MAX),
kDefaultNonSetOptionValue);
}
@@ -273,8 +275,8 @@ void IpcPacketSocket::IncrementDiscardCounters(size_t bytes_discarded) {
}
}
-bool IpcPacketSocket::Init(P2PSocketType type,
- P2PSocketClientImpl* client,
+bool IpcPacketSocket::Init(network::P2PSocketType type,
+ std::unique_ptr<P2PSocketClientImpl> client,
const rtc::SocketAddress& local_address,
uint16_t min_port,
uint16_t max_port,
@@ -283,7 +285,8 @@ bool IpcPacketSocket::Init(P2PSocketType type,
DCHECK_EQ(state_, IS_UNINITIALIZED);
type_ = type;
- client_ = client;
+ auto* client_ptr = client.get();
+ client_ = std::move(client);
local_address_ = local_address;
remote_address_ = remote_address;
state_ = IS_OPENING;
@@ -312,21 +315,22 @@ bool IpcPacketSocket::Init(P2PSocketType type,
// We need to send both resolved and unresolved address in Init. Unresolved
// address will be used in case of TLS for certificate hostname matching.
// Certificate will be tied to domain name not to IP address.
- P2PHostAndIPEndPoint remote_info(remote_address.hostname(), remote_endpoint);
+ network::P2PHostAndIPEndPoint remote_info(remote_address.hostname(),
+ remote_endpoint);
- client->Init(type, local_endpoint, min_port, max_port, remote_info, this);
+ client_ptr->Init(type, local_endpoint, min_port, max_port, remote_info, this);
return true;
}
void IpcPacketSocket::InitAcceptedTcp(
- P2PSocketClient* client,
+ std::unique_ptr<P2PSocketClient> client,
const rtc::SocketAddress& local_address,
const rtc::SocketAddress& remote_address) {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK_EQ(state_, IS_UNINITIALIZED);
- client_ = client;
+ client_ = std::move(client);
local_address_ = local_address;
remote_address_ = remote_address;
state_ = IS_OPEN;
@@ -418,8 +422,8 @@ int IpcPacketSocket::SendTo(const void *data, size_t data_size,
send_bytes_available_ -= data_size;
- const char* data_char = reinterpret_cast<const char*>(data);
- std::vector<char> data_vector(data_char, data_char + data_size);
+ const int8_t* data_char = reinterpret_cast<const int8_t*>(data);
+ std::vector<int8_t> data_vector(data_char, data_char + data_size);
uint64_t packet_id = client_->Send(address_chrome, data_vector, options);
// Ensure packet_id is not 0. It can't be the case according to
@@ -471,7 +475,7 @@ rtc::AsyncPacketSocket::State IpcPacketSocket::GetState() const {
}
int IpcPacketSocket::GetOption(rtc::Socket::Option option, int* value) {
- P2PSocketOption p2p_socket_option = P2P_SOCKET_OPT_MAX;
+ network::P2PSocketOption p2p_socket_option = network::P2P_SOCKET_OPT_MAX;
if (!JingleSocketOptionToP2PSocketOption(option, &p2p_socket_option)) {
// unsupported option.
return -1;
@@ -484,7 +488,7 @@ int IpcPacketSocket::GetOption(rtc::Socket::Option option, int* value) {
int IpcPacketSocket::SetOption(rtc::Socket::Option option, int value) {
DCHECK(thread_checker_.CalledOnValidThread());
- P2PSocketOption p2p_socket_option = P2P_SOCKET_OPT_MAX;
+ network::P2PSocketOption p2p_socket_option = network::P2P_SOCKET_OPT_MAX;
if (!JingleSocketOptionToP2PSocketOption(option, &p2p_socket_option)) {
// Option is not supported.
return -1;
@@ -499,7 +503,7 @@ int IpcPacketSocket::SetOption(rtc::Socket::Option option, int value) {
return 0;
}
-int IpcPacketSocket::DoSetOption(P2PSocketOption option, int value) {
+int IpcPacketSocket::DoSetOption(network::P2PSocketOption option, int value) {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK_EQ(state_, IS_OPEN);
@@ -532,9 +536,9 @@ void IpcPacketSocket::OnOpen(const net::IPEndPoint& local_address,
TraceSendThrottlingState();
// Set all pending options if any.
- for (int i = 0; i < P2P_SOCKET_OPT_MAX; ++i) {
+ for (int i = 0; i < network::P2P_SOCKET_OPT_MAX; ++i) {
if (options_[i] != kDefaultNonSetOptionValue)
- DoSetOption(static_cast<P2PSocketOption> (i), options_[i]);
+ DoSetOption(static_cast<network::P2PSocketOption>(i), options_[i]);
}
SignalAddressReady(this, local_address_);
@@ -562,7 +566,7 @@ void IpcPacketSocket::OnOpen(const net::IPEndPoint& local_address,
void IpcPacketSocket::OnIncomingTcpConnection(
const net::IPEndPoint& address,
- P2PSocketClient* client) {
+ std::unique_ptr<P2PSocketClient> client) {
DCHECK(thread_checker_.CalledOnValidThread());
std::unique_ptr<IpcPacketSocket> socket(new IpcPacketSocket());
@@ -572,11 +576,12 @@ void IpcPacketSocket::OnIncomingTcpConnection(
// Always expect correct IPv4 address to be allocated.
NOTREACHED();
}
- socket->InitAcceptedTcp(client, local_address_, remote_address);
+ socket->InitAcceptedTcp(std::move(client), local_address_, remote_address);
SignalNewConnection(this, socket.release());
}
-void IpcPacketSocket::OnSendComplete(const P2PSendPacketMetrics& send_metrics) {
+void IpcPacketSocket::OnSendComplete(
+ const network::P2PSendPacketMetrics& send_metrics) {
DCHECK(thread_checker_.CalledOnValidThread());
CHECK(!in_flight_packet_records_.empty());
@@ -624,7 +629,7 @@ void IpcPacketSocket::OnError() {
}
void IpcPacketSocket::OnDataReceived(const net::IPEndPoint& address,
- const std::vector<char>& data,
+ const std::vector<int8_t>& data,
const base::TimeTicks& timestamp) {
DCHECK(thread_checker_.CalledOnValidThread());
@@ -644,8 +649,8 @@ void IpcPacketSocket::OnDataReceived(const net::IPEndPoint& address,
}
rtc::PacketTime packet_time(timestamp.ToInternalValue(), 0);
- SignalReadPacket(this, &data[0], data.size(), address_lj,
- packet_time);
+ SignalReadPacket(this, reinterpret_cast<const char*>(&data[0]), data.size(),
+ address_lj, packet_time);
}
AsyncAddressResolverImpl::AsyncAddressResolverImpl(
@@ -727,11 +732,11 @@ rtc::AsyncPacketSocket* IpcPacketSocketFactory::CreateUdpSocket(
const rtc::SocketAddress& local_address,
uint16_t min_port,
uint16_t max_port) {
- P2PSocketClientImpl* socket_client =
- new P2PSocketClientImpl(socket_dispatcher_, traffic_annotation_);
+ auto socket_client = std::make_unique<P2PSocketClientImpl>(
+ socket_dispatcher_, traffic_annotation_);
std::unique_ptr<IpcPacketSocket> socket(new IpcPacketSocket());
- if (!socket->Init(P2P_SOCKET_UDP, socket_client, local_address, min_port,
- max_port, rtc::SocketAddress())) {
+ if (!socket->Init(network::P2P_SOCKET_UDP, std::move(socket_client),
+ local_address, min_port, max_port, rtc::SocketAddress())) {
return nullptr;
}
return socket.release();
@@ -746,13 +751,14 @@ rtc::AsyncPacketSocket* IpcPacketSocketFactory::CreateServerTcpSocket(
if (opts & rtc::PacketSocketFactory::OPT_SSLTCP)
return nullptr;
- P2PSocketType type = (opts & rtc::PacketSocketFactory::OPT_STUN) ?
- P2P_SOCKET_STUN_TCP_SERVER : P2P_SOCKET_TCP_SERVER;
- P2PSocketClientImpl* socket_client =
- new P2PSocketClientImpl(socket_dispatcher_, traffic_annotation_);
+ network::P2PSocketType type = (opts & rtc::PacketSocketFactory::OPT_STUN)
+ ? network::P2P_SOCKET_STUN_TCP_SERVER
+ : network::P2P_SOCKET_TCP_SERVER;
+ auto socket_client = std::make_unique<P2PSocketClientImpl>(
+ socket_dispatcher_, traffic_annotation_);
std::unique_ptr<IpcPacketSocket> socket(new IpcPacketSocket());
- if (!socket->Init(type, socket_client, local_address, min_port, max_port,
- rtc::SocketAddress())) {
+ if (!socket->Init(type, std::move(socket_client), local_address, min_port,
+ max_port, rtc::SocketAddress())) {
return nullptr;
}
return socket.release();
@@ -763,21 +769,25 @@ rtc::AsyncPacketSocket* IpcPacketSocketFactory::CreateClientTcpSocket(
const rtc::SocketAddress& remote_address,
const rtc::ProxyInfo& proxy_info,
const std::string& user_agent, int opts) {
- P2PSocketType type;
+ network::P2PSocketType type;
if (opts & rtc::PacketSocketFactory::OPT_SSLTCP) {
- type = (opts & rtc::PacketSocketFactory::OPT_STUN) ?
- P2P_SOCKET_STUN_SSLTCP_CLIENT : P2P_SOCKET_SSLTCP_CLIENT;
+ type = (opts & rtc::PacketSocketFactory::OPT_STUN)
+ ? network::P2P_SOCKET_STUN_SSLTCP_CLIENT
+ : network::P2P_SOCKET_SSLTCP_CLIENT;
} else if (opts & rtc::PacketSocketFactory::OPT_TLS) {
- type = (opts & rtc::PacketSocketFactory::OPT_STUN) ?
- P2P_SOCKET_STUN_TLS_CLIENT : P2P_SOCKET_TLS_CLIENT;
+ type = (opts & rtc::PacketSocketFactory::OPT_STUN)
+ ? network::P2P_SOCKET_STUN_TLS_CLIENT
+ : network::P2P_SOCKET_TLS_CLIENT;
} else {
- type = (opts & rtc::PacketSocketFactory::OPT_STUN) ?
- P2P_SOCKET_STUN_TCP_CLIENT : P2P_SOCKET_TCP_CLIENT;
+ type = (opts & rtc::PacketSocketFactory::OPT_STUN)
+ ? network::P2P_SOCKET_STUN_TCP_CLIENT
+ : network::P2P_SOCKET_TCP_CLIENT;
}
- P2PSocketClientImpl* socket_client =
- new P2PSocketClientImpl(socket_dispatcher_, traffic_annotation_);
+ auto socket_client = std::make_unique<P2PSocketClientImpl>(
+ socket_dispatcher_, traffic_annotation_);
std::unique_ptr<IpcPacketSocket> socket(new IpcPacketSocket());
- if (!socket->Init(type, socket_client, local_address, 0, 0, remote_address))
+ if (!socket->Init(type, std::move(socket_client), local_address, 0, 0,
+ remote_address))
return nullptr;
return socket.release();
}
diff --git a/chromium/content/renderer/p2p/socket_client.h b/chromium/content/renderer/p2p/socket_client.h
index 575d9af5213..fc92d51322d 100644
--- a/chromium/content/renderer/p2p/socket_client.h
+++ b/chromium/content/renderer/p2p/socket_client.h
@@ -9,9 +9,8 @@
#include <vector>
-#include "base/memory/ref_counted.h"
-#include "content/common/p2p_socket_type.h"
#include "net/base/ip_endpoint.h"
+#include "services/network/public/cpp/p2p_socket_type.h"
namespace rtc {
struct PacketOptions;
@@ -22,17 +21,17 @@ namespace content {
class P2PSocketClientDelegate;
// P2P socket that routes all calls over IPC.
-// Note that while ref-counting is thread-safe, all methods must be
-// called on the same thread.
-class P2PSocketClient : public base::RefCountedThreadSafe<P2PSocketClient> {
+class P2PSocketClient {
public:
+ virtual ~P2PSocketClient() {}
+
// Send the |data| to the |address| using Differentiated Services Code Point
// |dscp|. Return value is the unique packet_id for this packet.
virtual uint64_t Send(const net::IPEndPoint& address,
- const std::vector<char>& data,
+ const std::vector<int8_t>& data,
const rtc::PacketOptions& options) = 0;
- virtual void SetOption(P2PSocketOption option, int value) = 0;
+ virtual void SetOption(network::P2PSocketOption option, int value) = 0;
// Must be called before the socket is destroyed.
virtual void Close() = 0;
@@ -42,11 +41,6 @@ class P2PSocketClient : public base::RefCountedThreadSafe<P2PSocketClient> {
protected:
P2PSocketClient() {}
- virtual ~P2PSocketClient() {}
-
- private:
- // Calls destructor.
- friend class base::RefCountedThreadSafe<P2PSocketClient>;
};
} // namespace content
diff --git a/chromium/content/renderer/p2p/socket_client_delegate.h b/chromium/content/renderer/p2p/socket_client_delegate.h
index 4652bb7d15c..680e6f2f84b 100644
--- a/chromium/content/renderer/p2p/socket_client_delegate.h
+++ b/chromium/content/renderer/p2p/socket_client_delegate.h
@@ -7,9 +7,8 @@
#include <vector>
-#include "base/memory/ref_counted.h"
-#include "content/common/p2p_socket_type.h"
#include "net/base/ip_endpoint.h"
+#include "services/network/public/cpp/p2p_socket_type.h"
namespace content {
@@ -27,18 +26,20 @@ class P2PSocketClientDelegate {
// For a socket that is listening on incoming TCP connectsion, this
// function is called when a new client connects.
- virtual void OnIncomingTcpConnection(const net::IPEndPoint& address,
- P2PSocketClient* client) = 0;
+ virtual void OnIncomingTcpConnection(
+ const net::IPEndPoint& address,
+ std::unique_ptr<P2PSocketClient> client) = 0;
// Called once for each Send() call after the send is complete.
- virtual void OnSendComplete(const P2PSendPacketMetrics& send_metrics) = 0;
+ virtual void OnSendComplete(
+ const network::P2PSendPacketMetrics& send_metrics) = 0;
// Called if an non-retryable error occurs.
virtual void OnError() = 0;
// Called when data is received on the socket.
virtual void OnDataReceived(const net::IPEndPoint& address,
- const std::vector<char>& data,
+ const std::vector<int8_t>& data,
const base::TimeTicks& timestamp) = 0;
};
diff --git a/chromium/content/renderer/p2p/socket_client_impl.cc b/chromium/content/renderer/p2p/socket_client_impl.cc
index 4bc68c80628..2b0de5c4a0e 100644
--- a/chromium/content/renderer/p2p/socket_client_impl.cc
+++ b/chromium/content/renderer/p2p/socket_client_impl.cc
@@ -9,11 +9,11 @@
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
-#include "content/common/p2p_messages.h"
#include "content/renderer/p2p/socket_client_delegate.h"
#include "content/renderer/p2p/socket_dispatcher.h"
#include "content/renderer/render_thread_impl.h"
#include "crypto/random.h"
+#include "services/network/public/cpp/p2p_param_traits.h"
namespace {
@@ -32,14 +32,13 @@ P2PSocketClientImpl::P2PSocketClientImpl(
P2PSocketDispatcher* dispatcher,
const net::NetworkTrafficAnnotationTag& traffic_annotation)
: dispatcher_(dispatcher),
- ipc_task_runner_(dispatcher->task_runner()),
- delegate_task_runner_(base::ThreadTaskRunnerHandle::Get()),
socket_id_(0),
delegate_(nullptr),
state_(STATE_UNINITIALIZED),
traffic_annotation_(traffic_annotation),
random_socket_id_(0),
- next_packet_id_(0) {
+ next_packet_id_(0),
+ binding_(this) {
crypto::RandBytes(&random_socket_id_, sizeof(random_socket_id_));
}
@@ -47,46 +46,33 @@ P2PSocketClientImpl::~P2PSocketClientImpl() {
CHECK(state_ == STATE_CLOSED || state_ == STATE_UNINITIALIZED);
}
-void P2PSocketClientImpl::Init(P2PSocketType type,
- const net::IPEndPoint& local_address,
- uint16_t min_port,
- uint16_t max_port,
- const P2PHostAndIPEndPoint& remote_address,
- P2PSocketClientDelegate* delegate) {
- DCHECK(delegate_task_runner_->BelongsToCurrentThread());
+void P2PSocketClientImpl::Init(
+ network::P2PSocketType type,
+ const net::IPEndPoint& local_address,
+ uint16_t min_port,
+ uint16_t max_port,
+ const network::P2PHostAndIPEndPoint& remote_address,
+ P2PSocketClientDelegate* delegate) {
+ DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(delegate);
// |delegate_| is only accessesed on |delegate_message_loop_|.
delegate_ = delegate;
- ipc_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&P2PSocketClientImpl::DoInit, this, type, local_address,
- min_port, max_port, remote_address));
-}
-
-void P2PSocketClientImpl::DoInit(P2PSocketType type,
- const net::IPEndPoint& local_address,
- uint16_t min_port,
- uint16_t max_port,
- const P2PHostAndIPEndPoint& remote_address) {
DCHECK_EQ(state_, STATE_UNINITIALIZED);
state_ = STATE_OPENING;
- socket_id_ = dispatcher_->RegisterClient(this);
- dispatcher_->SendP2PMessage(new P2PHostMsg_CreateSocket(
- type, socket_id_, local_address, P2PPortRange(min_port, max_port),
- remote_address));
+ network::mojom::P2PSocketClientPtr socket_client;
+ binding_.Bind(mojo::MakeRequest(&socket_client));
+ binding_.set_connection_error_handler(base::Bind(
+ &P2PSocketClientImpl::OnConnectionError, base::Unretained(this)));
+ dispatcher_->GetP2PSocketManager()->CreateSocket(
+ type, local_address, network::P2PPortRange(min_port, max_port),
+ remote_address, std::move(socket_client), mojo::MakeRequest(&socket_));
}
uint64_t P2PSocketClientImpl::Send(const net::IPEndPoint& address,
- const std::vector<char>& data,
+ const std::vector<int8_t>& data,
const rtc::PacketOptions& options) {
uint64_t unique_id = GetUniqueId(random_socket_id_, ++next_packet_id_);
- if (!ipc_task_runner_->BelongsToCurrentThread()) {
- ipc_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&P2PSocketClientImpl::SendWithPacketId, this,
- address, data, options, unique_id));
- return unique_id;
- }
// Can send data only when the socket is open.
DCHECK(state_ == STATE_OPEN || state_ == STATE_ERROR);
@@ -98,50 +84,28 @@ uint64_t P2PSocketClientImpl::Send(const net::IPEndPoint& address,
}
void P2PSocketClientImpl::SendWithPacketId(const net::IPEndPoint& address,
- const std::vector<char>& data,
+ const std::vector<int8_t>& data,
const rtc::PacketOptions& options,
uint64_t packet_id) {
TRACE_EVENT_ASYNC_BEGIN0("p2p", "Send", packet_id);
- dispatcher_->SendP2PMessage(new P2PHostMsg_Send(
- socket_id_, data, P2PPacketInfo(address, options, packet_id),
- net::MutableNetworkTrafficAnnotationTag(traffic_annotation_)));
+ socket_->Send(data, network::P2PPacketInfo(address, options, packet_id),
+ net::MutableNetworkTrafficAnnotationTag(traffic_annotation_));
}
-void P2PSocketClientImpl::SetOption(P2PSocketOption option,
+void P2PSocketClientImpl::SetOption(network::P2PSocketOption option,
int value) {
- if (!ipc_task_runner_->BelongsToCurrentThread()) {
- ipc_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&P2PSocketClientImpl::SetOption, this, option, value));
- return;
- }
-
DCHECK(state_ == STATE_OPEN || state_ == STATE_ERROR);
- if (state_ == STATE_OPEN) {
- dispatcher_->SendP2PMessage(new P2PHostMsg_SetOption(socket_id_,
- option, value));
- }
+ if (state_ == STATE_OPEN)
+ socket_->SetOption(option, value);
}
void P2PSocketClientImpl::Close() {
- DCHECK(delegate_task_runner_->BelongsToCurrentThread());
+ DCHECK(thread_checker_.CalledOnValidThread());
delegate_ = nullptr;
-
- ipc_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&P2PSocketClientImpl::DoClose, this));
-}
-
-void P2PSocketClientImpl::DoClose() {
- DCHECK(ipc_task_runner_->BelongsToCurrentThread());
- if (dispatcher_) {
- if (state_ == STATE_OPEN || state_ == STATE_OPENING ||
- state_ == STATE_ERROR) {
- dispatcher_->SendP2PMessage(new P2PHostMsg_DestroySocket(socket_id_));
- }
- dispatcher_->UnregisterClient(socket_id_);
- }
+ if (socket_)
+ socket_.reset();
state_ = STATE_CLOSED;
}
@@ -151,114 +115,63 @@ int P2PSocketClientImpl::GetSocketID() const {
}
void P2PSocketClientImpl::SetDelegate(P2PSocketClientDelegate* delegate) {
- DCHECK(delegate_task_runner_->BelongsToCurrentThread());
+ DCHECK(thread_checker_.CalledOnValidThread());
delegate_ = delegate;
}
-void P2PSocketClientImpl::OnSocketCreated(
- const net::IPEndPoint& local_address,
- const net::IPEndPoint& remote_address) {
- DCHECK(ipc_task_runner_->BelongsToCurrentThread());
- DCHECK_EQ(state_, STATE_OPENING);
+void P2PSocketClientImpl::SocketCreated(const net::IPEndPoint& local_address,
+ const net::IPEndPoint& remote_address) {
state_ = STATE_OPEN;
-
- delegate_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&P2PSocketClientImpl::DeliverOnSocketCreated,
- this, local_address, remote_address));
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (delegate_)
+ delegate_->OnOpen(local_address, remote_address);
}
-void P2PSocketClientImpl::DeliverOnSocketCreated(
- const net::IPEndPoint& local_address,
- const net::IPEndPoint& remote_address) {
- DCHECK(delegate_task_runner_->BelongsToCurrentThread());
+void P2PSocketClientImpl::SendComplete(
+ const network::P2PSendPacketMetrics& send_metrics) {
+ DCHECK(thread_checker_.CalledOnValidThread());
if (delegate_)
- delegate_->OnOpen(local_address, remote_address);
+ delegate_->OnSendComplete(send_metrics);
}
-void P2PSocketClientImpl::OnIncomingTcpConnection(
- const net::IPEndPoint& address) {
- DCHECK(ipc_task_runner_->BelongsToCurrentThread());
+void P2PSocketClientImpl::IncomingTcpConnection(
+ const net::IPEndPoint& socket_address,
+ network::mojom::P2PSocketPtr socket,
+ network::mojom::P2PSocketClientRequest client_request) {
DCHECK_EQ(state_, STATE_OPEN);
- scoped_refptr<P2PSocketClientImpl> new_client =
- new P2PSocketClientImpl(dispatcher_, traffic_annotation_);
- new_client->socket_id_ = dispatcher_->RegisterClient(new_client.get());
+ auto new_client =
+ std::make_unique<P2PSocketClientImpl>(dispatcher_, traffic_annotation_);
new_client->state_ = STATE_OPEN;
- new_client->delegate_task_runner_ = delegate_task_runner_;
- dispatcher_->SendP2PMessage(new P2PHostMsg_AcceptIncomingTcpConnection(
- socket_id_, address, new_client->socket_id_));
+ network::mojom::P2PSocketClientPtr socket_client;
+ new_client->socket_ = std::move(socket);
+ new_client->binding_.Bind(std::move(client_request));
+ new_client->binding_.set_connection_error_handler(base::Bind(
+ &P2PSocketClientImpl::OnConnectionError, base::Unretained(this)));
- delegate_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&P2PSocketClientImpl::DeliverOnIncomingTcpConnection, this,
- address, new_client));
-}
-
-void P2PSocketClientImpl::DeliverOnIncomingTcpConnection(
- const net::IPEndPoint& address,
- scoped_refptr<P2PSocketClient> new_client) {
- DCHECK(delegate_task_runner_->BelongsToCurrentThread());
+ DCHECK(thread_checker_.CalledOnValidThread());
if (delegate_) {
- delegate_->OnIncomingTcpConnection(address, new_client.get());
+ delegate_->OnIncomingTcpConnection(socket_address, std::move(new_client));
} else {
// Just close the socket if there is no delegate to accept it.
new_client->Close();
}
}
-void P2PSocketClientImpl::OnSendComplete(
- const P2PSendPacketMetrics& send_metrics) {
- DCHECK(ipc_task_runner_->BelongsToCurrentThread());
-
- delegate_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&P2PSocketClientImpl::DeliverOnSendComplete,
- this, send_metrics));
-}
-
-void P2PSocketClientImpl::DeliverOnSendComplete(
- const P2PSendPacketMetrics& send_metrics) {
- DCHECK(delegate_task_runner_->BelongsToCurrentThread());
+void P2PSocketClientImpl::DataReceived(const net::IPEndPoint& socket_address,
+ const std::vector<int8_t>& data,
+ base::TimeTicks timestamp) {
+ DCHECK_EQ(STATE_OPEN, state_);
+ DCHECK(thread_checker_.CalledOnValidThread());
if (delegate_)
- delegate_->OnSendComplete(send_metrics);
+ delegate_->OnDataReceived(socket_address, data, timestamp);
}
-void P2PSocketClientImpl::OnError() {
- DCHECK(ipc_task_runner_->BelongsToCurrentThread());
+void P2PSocketClientImpl::OnConnectionError() {
state_ = STATE_ERROR;
-
- delegate_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&P2PSocketClientImpl::DeliverOnError, this));
-}
-
-void P2PSocketClientImpl::DeliverOnError() {
- DCHECK(delegate_task_runner_->BelongsToCurrentThread());
if (delegate_)
delegate_->OnError();
}
-void P2PSocketClientImpl::OnDataReceived(const net::IPEndPoint& address,
- const std::vector<char>& data,
- const base::TimeTicks& timestamp) {
- DCHECK(ipc_task_runner_->BelongsToCurrentThread());
- DCHECK_EQ(STATE_OPEN, state_);
- delegate_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&P2PSocketClientImpl::DeliverOnDataReceived,
- this, address, data, timestamp));
-}
-
-void P2PSocketClientImpl::DeliverOnDataReceived(
- const net::IPEndPoint& address, const std::vector<char>& data,
- const base::TimeTicks& timestamp) {
- DCHECK(delegate_task_runner_->BelongsToCurrentThread());
- if (delegate_)
- delegate_->OnDataReceived(address, data, timestamp);
-}
-
-void P2PSocketClientImpl::Detach() {
- DCHECK(ipc_task_runner_->BelongsToCurrentThread());
- dispatcher_ = nullptr;
- OnError();
-}
-
} // namespace content
diff --git a/chromium/content/renderer/p2p/socket_client_impl.h b/chromium/content/renderer/p2p/socket_client_impl.h
index b447548dbf1..cb9bb37be94 100644
--- a/chromium/content/renderer/p2p/socket_client_impl.h
+++ b/chromium/content/renderer/p2p/socket_client_impl.h
@@ -11,13 +11,15 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "content/common/p2p_socket_type.h"
+#include "base/threading/thread_checker.h"
#include "content/renderer/p2p/socket_client.h"
+#include "mojo/public/cpp/bindings/binding.h"
#include "net/base/ip_endpoint.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
+#include "services/network/public/cpp/p2p_socket_type.h"
+#include "services/network/public/mojom/p2p.mojom.h"
namespace base {
-class SingleThreadTaskRunner;
class TimeTicks;
} // namespace base
@@ -25,36 +27,35 @@ namespace content {
class P2PSocketDispatcher;
-// P2P socket that routes all calls over IPC.
+// P2P socket that routes all calls over Mojo.
//
-// The object runs on two threads: IPC thread and delegate thread. The
-// IPC thread is used to interact with P2PSocketDispatcher. All
-// callbacks to the user of this class are called on the delegate
-// thread which is specified in Init().
-class P2PSocketClientImpl : public P2PSocketClient {
+// The object runs on the WebRTC worker thread.
+class P2PSocketClientImpl : public P2PSocketClient,
+ public network::mojom::P2PSocketClient {
public:
- explicit P2PSocketClientImpl(
+ P2PSocketClientImpl(
P2PSocketDispatcher* dispatcher,
const net::NetworkTrafficAnnotationTag& traffic_annotation);
+ ~P2PSocketClientImpl() override;
// Initialize socket of the specified |type| and connected to the
// specified |address|. |address| matters only when |type| is set to
// P2P_SOCKET_TCP_CLIENT.
- virtual void Init(P2PSocketType type,
+ virtual void Init(network::P2PSocketType type,
const net::IPEndPoint& local_address,
uint16_t min_port,
uint16_t max_port,
- const P2PHostAndIPEndPoint& remote_address,
+ const network::P2PHostAndIPEndPoint& remote_address,
P2PSocketClientDelegate* delegate);
// Send the |data| to the |address| using Differentiated Services Code Point
// |dscp|. Return value is the unique packet_id for this packet.
uint64_t Send(const net::IPEndPoint& address,
- const std::vector<char>& data,
+ const std::vector<int8_t>& data,
const rtc::PacketOptions& options) override;
// Setting socket options.
- void SetOption(P2PSocketOption option, int value) override;
+ void SetOption(network::P2PSocketOption option, int value) override;
// Must be called before the socket is destroyed. The delegate may
// not be called after |closed_task| is executed.
@@ -75,53 +76,29 @@ class P2PSocketClientImpl : public P2PSocketClient {
friend class P2PSocketDispatcher;
- ~P2PSocketClientImpl() override;
-
- // Message handlers that run on IPC thread.
- void OnSocketCreated(const net::IPEndPoint& local_address,
- const net::IPEndPoint& remote_address);
- void OnIncomingTcpConnection(const net::IPEndPoint& address);
- void OnSendComplete(const P2PSendPacketMetrics& send_metrics);
- void OnError();
- void OnDataReceived(const net::IPEndPoint& address,
- const std::vector<char>& data,
- const base::TimeTicks& timestamp);
-
- // Proxy methods that deliver messages to the delegate thread.
- void DeliverOnSocketCreated(const net::IPEndPoint& local_address,
- const net::IPEndPoint& remote_address);
- void DeliverOnIncomingTcpConnection(
- const net::IPEndPoint& address,
- scoped_refptr<P2PSocketClient> new_client);
- void DeliverOnSendComplete(const P2PSendPacketMetrics& send_metrics);
- void DeliverOnError();
- void DeliverOnDataReceived(const net::IPEndPoint& address,
- const std::vector<char>& data,
- const base::TimeTicks& timestamp);
-
// Helper function to be called by Send to handle different threading
// condition.
void SendWithPacketId(const net::IPEndPoint& address,
- const std::vector<char>& data,
+ const std::vector<int8_t>& data,
const rtc::PacketOptions& options,
uint64_t packet_id);
- // Scheduled on the IPC thread to finish initialization.
- void DoInit(P2PSocketType type,
- const net::IPEndPoint& local_address,
- uint16_t min_port,
- uint16_t max_port,
- const P2PHostAndIPEndPoint& remote_address);
-
- // Scheduled on the IPC thread to finish closing the connection.
- void DoClose();
+ // network::mojom::P2PSocketClient interface.
+ void SocketCreated(const net::IPEndPoint& local_address,
+ const net::IPEndPoint& remote_address) override;
+ void SendComplete(const network::P2PSendPacketMetrics& send_metrics) override;
+ void IncomingTcpConnection(
+ const net::IPEndPoint& socket_address,
+ network::mojom::P2PSocketPtr socket,
+ network::mojom::P2PSocketClientRequest client_request) override;
+ void DataReceived(const net::IPEndPoint& socket_address,
+ const std::vector<int8_t>& data,
+ base::TimeTicks timestamp) override;
- // Called by the dispatcher when it is destroyed.
- void Detach();
+ void OnConnectionError();
P2PSocketDispatcher* dispatcher_;
- scoped_refptr<base::SingleThreadTaskRunner> ipc_task_runner_;
- scoped_refptr<base::SingleThreadTaskRunner> delegate_task_runner_;
+ base::ThreadChecker thread_checker_;
int socket_id_;
P2PSocketClientDelegate* delegate_;
State state_;
@@ -131,6 +108,9 @@ class P2PSocketClientImpl : public P2PSocketClient {
uint32_t random_socket_id_;
uint32_t next_packet_id_;
+ network::mojom::P2PSocketPtr socket_;
+ mojo::Binding<network::mojom::P2PSocketClient> binding_;
+
DISALLOW_COPY_AND_ASSIGN(P2PSocketClientImpl);
};
diff --git a/chromium/content/renderer/p2p/socket_dispatcher.cc b/chromium/content/renderer/p2p/socket_dispatcher.cc
index 7459bef41d9..ce4ed09485c 100644
--- a/chromium/content/renderer/p2p/socket_dispatcher.cc
+++ b/chromium/content/renderer/p2p/socket_dispatcher.cc
@@ -7,36 +7,37 @@
#include "base/bind.h"
#include "base/memory/ref_counted.h"
#include "content/child/child_process.h"
-#include "content/common/p2p_messages.h"
-#include "content/renderer/p2p/host_address_request.h"
+#include "content/child/child_thread_impl.h"
+#include "content/public/common/service_names.mojom.h"
#include "content/renderer/p2p/network_list_observer.h"
#include "content/renderer/p2p/socket_client_impl.h"
#include "content/renderer/render_view_impl.h"
-#include "ipc/ipc_sender.h"
+#include "services/network/public/cpp/p2p_param_traits.h"
+#include "services/service_manager/public/cpp/connector.h"
namespace content {
-P2PSocketDispatcher::P2PSocketDispatcher(
- base::SingleThreadTaskRunner* ipc_task_runner)
- : ipc_task_runner_(ipc_task_runner),
- network_notifications_started_(false),
+P2PSocketDispatcher::P2PSocketDispatcher()
+ : main_task_runner_(base::ThreadTaskRunnerHandle::Get()),
network_list_observers_(
new base::ObserverListThreadSafe<NetworkListObserver>()),
- sender_(nullptr) {}
+ network_notification_client_binding_(this) {
+ network::mojom::P2PSocketManagerPtr p2p_socket_manager;
+ p2p_socket_manager_request_ = mojo::MakeRequest(&p2p_socket_manager);
+ thread_safe_p2p_socket_manager_ =
+ network::mojom::ThreadSafeP2PSocketManagerPtr::Create(
+ std::move(p2p_socket_manager));
+}
P2PSocketDispatcher::~P2PSocketDispatcher() {
- network_list_observers_->AssertEmpty();
- for (base::IDMap<P2PSocketClientImpl*>::iterator i(&clients_); !i.IsAtEnd();
- i.Advance()) {
- i.GetCurrentValue()->Detach();
- }
}
void P2PSocketDispatcher::AddNetworkListObserver(
NetworkListObserver* network_list_observer) {
network_list_observers_->AddObserver(network_list_observer);
- network_notifications_started_ = true;
- SendP2PMessage(new P2PHostMsg_StartNetworkNotifications());
+ main_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&P2PSocketDispatcher::RequestNetworkEventsIfNecessary, this));
}
void P2PSocketDispatcher::RemoveNetworkListObserver(
@@ -44,160 +45,46 @@ void P2PSocketDispatcher::RemoveNetworkListObserver(
network_list_observers_->RemoveObserver(network_list_observer);
}
-void P2PSocketDispatcher::Send(IPC::Message* message) {
- DCHECK(ipc_task_runner_->BelongsToCurrentThread());
- if (!sender_) {
- DLOG(WARNING) << "P2PSocketDispatcher::Send() - Sender closed.";
- delete message;
- return;
- }
-
- sender_->Send(message);
-}
-
-bool P2PSocketDispatcher::OnMessageReceived(const IPC::Message& message) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(P2PSocketDispatcher, message)
- IPC_MESSAGE_HANDLER(P2PMsg_NetworkListChanged, OnNetworkListChanged)
- IPC_MESSAGE_HANDLER(P2PMsg_GetHostAddressResult, OnGetHostAddressResult)
- IPC_MESSAGE_HANDLER(P2PMsg_OnSocketCreated, OnSocketCreated)
- IPC_MESSAGE_HANDLER(P2PMsg_OnIncomingTcpConnection, OnIncomingTcpConnection)
- IPC_MESSAGE_HANDLER(P2PMsg_OnSendComplete, OnSendComplete)
- IPC_MESSAGE_HANDLER(P2PMsg_OnError, OnError)
- IPC_MESSAGE_HANDLER(P2PMsg_OnDataReceived, OnDataReceived)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-void P2PSocketDispatcher::OnFilterAdded(IPC::Channel* channel) {
- DVLOG(1) << "P2PSocketDispatcher::OnFilterAdded()";
- sender_ = channel;
-}
-
-void P2PSocketDispatcher::OnFilterRemoved() {
- sender_ = nullptr;
-}
-
-void P2PSocketDispatcher::OnChannelConnected(int32_t peer_id) {
- connected_ = true;
-}
-
-void P2PSocketDispatcher::OnChannelClosing() {
- sender_ = nullptr;
- connected_ = false;
-}
-
-base::SingleThreadTaskRunner* P2PSocketDispatcher::task_runner() {
- return ipc_task_runner_.get();
-}
-
-int P2PSocketDispatcher::RegisterClient(P2PSocketClientImpl* client) {
- DCHECK(ipc_task_runner_->BelongsToCurrentThread());
- return clients_.Add(client);
-}
-
-void P2PSocketDispatcher::UnregisterClient(int id) {
- DCHECK(ipc_task_runner_->BelongsToCurrentThread());
- clients_.Remove(id);
-}
-
-void P2PSocketDispatcher::SendP2PMessage(IPC::Message* msg) {
- if (!ipc_task_runner_->BelongsToCurrentThread()) {
- ipc_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&P2PSocketDispatcher::Send, this, msg));
- return;
- }
- Send(msg);
-}
-
-int P2PSocketDispatcher::RegisterHostAddressRequest(
- P2PAsyncAddressResolver* request) {
- DCHECK(ipc_task_runner_->BelongsToCurrentThread());
- return host_address_requests_.Add(request);
+network::mojom::P2PSocketManager* P2PSocketDispatcher::GetP2PSocketManager() {
+ main_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&P2PSocketDispatcher::RequestInterfaceIfNecessary, this));
+ return thread_safe_p2p_socket_manager_->get();
}
-void P2PSocketDispatcher::UnregisterHostAddressRequest(int id) {
- DCHECK(ipc_task_runner_->BelongsToCurrentThread());
- host_address_requests_.Remove(id);
-}
-
-void P2PSocketDispatcher::OnNetworkListChanged(
- const net::NetworkInterfaceList& networks,
+void P2PSocketDispatcher::NetworkListChanged(
+ const std::vector<net::NetworkInterface>& networks,
const net::IPAddress& default_ipv4_local_address,
const net::IPAddress& default_ipv6_local_address) {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ networks_ = networks;
+ default_ipv4_local_address_ = default_ipv4_local_address;
+ default_ipv6_local_address_ = default_ipv6_local_address;
network_list_observers_->Notify(
FROM_HERE, &NetworkListObserver::OnNetworkListChanged, networks,
default_ipv4_local_address, default_ipv6_local_address);
}
-void P2PSocketDispatcher::OnGetHostAddressResult(
- int32_t request_id,
- const net::IPAddressList& addresses) {
- P2PAsyncAddressResolver* request = host_address_requests_.Lookup(request_id);
- if (!request) {
- DVLOG(1) << "Received P2P message for socket that doesn't exist.";
+void P2PSocketDispatcher::RequestInterfaceIfNecessary() {
+ if (!p2p_socket_manager_request_.is_pending())
return;
- }
-
- request->OnResponse(addresses);
-}
-
-void P2PSocketDispatcher::OnSocketCreated(
- int socket_id,
- const net::IPEndPoint& local_address,
- const net::IPEndPoint& remote_address) {
- P2PSocketClientImpl* client = GetClient(socket_id);
- if (client) {
- client->OnSocketCreated(local_address, remote_address);
- }
-}
-
-void P2PSocketDispatcher::OnIncomingTcpConnection(
- int socket_id, const net::IPEndPoint& address) {
- P2PSocketClientImpl* client = GetClient(socket_id);
- if (client) {
- client->OnIncomingTcpConnection(address);
- }
-}
-
-void P2PSocketDispatcher::OnSendComplete(
- int socket_id,
- const P2PSendPacketMetrics& send_metrics) {
- P2PSocketClientImpl* client = GetClient(socket_id);
- if (client) {
- client->OnSendComplete(send_metrics);
- }
-}
-
-void P2PSocketDispatcher::OnError(int socket_id) {
- P2PSocketClientImpl* client = GetClient(socket_id);
- if (client) {
- client->OnError();
- }
-}
-
-void P2PSocketDispatcher::OnDataReceived(
- int socket_id, const net::IPEndPoint& address,
- const std::vector<char>& data,
- const base::TimeTicks& timestamp) {
- P2PSocketClientImpl* client = GetClient(socket_id);
- if (client) {
- client->OnDataReceived(address, data, timestamp);
- }
-}
-P2PSocketClientImpl* P2PSocketDispatcher::GetClient(int socket_id) {
- P2PSocketClientImpl* client = clients_.Lookup(socket_id);
- if (client == nullptr) {
- // This may happen if the socket was closed, but the browser side
- // hasn't processed the close message by the time it sends the
- // message to the renderer.
- DVLOG(1) << "Received P2P message for socket that doesn't exist.";
- return nullptr;
+ ChildThreadImpl::current()->GetConnector()->BindInterface(
+ mojom::kBrowserServiceName, std::move(p2p_socket_manager_request_));
+}
+
+void P2PSocketDispatcher::RequestNetworkEventsIfNecessary() {
+ if (network_notification_client_binding_.is_bound()) {
+ network_list_observers_->Notify(
+ FROM_HERE, &NetworkListObserver::OnNetworkListChanged, networks_,
+ default_ipv4_local_address_, default_ipv6_local_address_);
+ } else {
+ network::mojom::P2PNetworkNotificationClientPtr network_notification_client;
+ network_notification_client_binding_.Bind(
+ mojo::MakeRequest(&network_notification_client));
+ GetP2PSocketManager()->StartNetworkNotifications(
+ std::move(network_notification_client));
}
-
- return client;
}
} // namespace content
diff --git a/chromium/content/renderer/p2p/socket_dispatcher.h b/chromium/content/renderer/p2p/socket_dispatcher.h
index 785f1bb0861..70b2696be52 100644
--- a/chromium/content/renderer/p2p/socket_dispatcher.h
+++ b/chromium/content/renderer/p2p/socket_dispatcher.h
@@ -27,35 +27,35 @@
#include "base/callback_forward.h"
#include "base/compiler_specific.h"
-#include "base/containers/id_map.h"
#include "base/macros.h"
+#include "base/memory/ref_counted.h"
#include "base/observer_list_threadsafe.h"
#include "base/synchronization/lock.h"
#include "content/common/content_export.h"
-#include "content/common/p2p_socket_type.h"
#include "content/renderer/p2p/network_list_manager.h"
-#include "ipc/message_filter.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/thread_safe_interface_ptr.h"
#include "net/base/ip_address.h"
#include "net/base/network_interfaces.h"
+#include "services/network/public/cpp/p2p_socket_type.h"
+#include "services/network/public/mojom/p2p.mojom.h"
namespace base {
class SingleThreadTaskRunner;
} // namespace base
-namespace net {
-class IPEndPoint;
-} // namespace net
-
namespace content {
class NetworkListObserver;
-class P2PAsyncAddressResolver;
-class P2PSocketClientImpl;
-class CONTENT_EXPORT P2PSocketDispatcher : public IPC::MessageFilter,
- public NetworkListManager {
+// This class is created on the main thread, but is used primarily on the
+// WebRTC worker threads.
+class CONTENT_EXPORT P2PSocketDispatcher
+ : public base::RefCountedThreadSafe<P2PSocketDispatcher>,
+ public NetworkListManager,
+ public network::mojom::P2PNetworkNotificationClient {
public:
- explicit P2PSocketDispatcher(base::SingleThreadTaskRunner* ipc_task_runner);
+ P2PSocketDispatcher();
// NetworkListManager interface:
void AddNetworkListObserver(
@@ -63,67 +63,38 @@ class CONTENT_EXPORT P2PSocketDispatcher : public IPC::MessageFilter,
void RemoveNetworkListObserver(
NetworkListObserver* network_list_observer) override;
- bool connected() { return connected_; }
+ network::mojom::P2PSocketManager* GetP2PSocketManager();
+
+ private:
+ friend class base::RefCountedThreadSafe<P2PSocketDispatcher>;
- protected:
~P2PSocketDispatcher() override;
- private:
- friend class P2PAsyncAddressResolver;
- friend class P2PSocketClientImpl;
-
- // Send a message asynchronously.
- virtual void Send(IPC::Message* message);
-
- // IPC::MessageFilter override. Called on IO thread.
- bool OnMessageReceived(const IPC::Message& message) override;
- void OnFilterAdded(IPC::Channel* channel) override;
- void OnFilterRemoved() override;
- void OnChannelClosing() override;
- void OnChannelConnected(int32_t peer_pid) override;
-
- base::SingleThreadTaskRunner* task_runner();
-
- // Called by P2PSocketClient.
- int RegisterClient(P2PSocketClientImpl* client);
- void UnregisterClient(int id);
- void SendP2PMessage(IPC::Message* msg);
-
- // Called by DnsRequest.
- int RegisterHostAddressRequest(P2PAsyncAddressResolver* request);
- void UnregisterHostAddressRequest(int id);
-
- // Incoming message handlers.
- void OnNetworkListChanged(const net::NetworkInterfaceList& networks,
- const net::IPAddress& default_ipv4_local_address,
- const net::IPAddress& default_ipv6_local_address);
- void OnGetHostAddressResult(int32_t request_id,
- const net::IPAddressList& addresses);
- void OnSocketCreated(int socket_id,
- const net::IPEndPoint& local_address,
- const net::IPEndPoint& remote_address);
- void OnIncomingTcpConnection(int socket_id, const net::IPEndPoint& address);
- void OnSendComplete(int socket_id, const P2PSendPacketMetrics& send_metrics);
- void OnError(int socket_id);
- void OnDataReceived(int socket_id, const net::IPEndPoint& address,
- const std::vector<char>& data,
- const base::TimeTicks& timestamp);
-
- P2PSocketClientImpl* GetClient(int socket_id);
-
- scoped_refptr<base::SingleThreadTaskRunner> ipc_task_runner_;
- base::IDMap<P2PSocketClientImpl*> clients_;
-
- base::IDMap<P2PAsyncAddressResolver*> host_address_requests_;
-
- bool network_notifications_started_;
+ // network::mojom::P2PNetworkNotificationClient interface.
+ void NetworkListChanged(
+ const std::vector<net::NetworkInterface>& networks,
+ const net::IPAddress& default_ipv4_local_address,
+ const net::IPAddress& default_ipv6_local_address) override;
+
+ void RequestInterfaceIfNecessary();
+ void RequestNetworkEventsIfNecessary();
+
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
+
scoped_refptr<base::ObserverListThreadSafe<NetworkListObserver>>
network_list_observers_;
- IPC::Sender* sender_;
+ network::mojom::P2PSocketManagerRequest p2p_socket_manager_request_;
+ scoped_refptr<network::mojom::ThreadSafeP2PSocketManagerPtr>
+ thread_safe_p2p_socket_manager_;
+
+ // Cached from last |NetworkListChanged| call.
+ std::vector<net::NetworkInterface> networks_;
+ net::IPAddress default_ipv4_local_address_;
+ net::IPAddress default_ipv6_local_address_;
- // To indicate whether IPC could be invoked on this dispatcher.
- bool connected_ = false;
+ mojo::Binding<network::mojom::P2PNetworkNotificationClient>
+ network_notification_client_binding_;
DISALLOW_COPY_AND_ASSIGN(P2PSocketDispatcher);
};
diff --git a/chromium/content/renderer/pepper/host_globals.cc b/chromium/content/renderer/pepper/host_globals.cc
index 0b631a0f7db..5ef70b58473 100644
--- a/chromium/content/renderer/pepper/host_globals.cc
+++ b/chromium/content/renderer/pepper/host_globals.cc
@@ -10,8 +10,8 @@
#include "base/logging.h"
#include "base/rand_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task/post_task.h"
#include "base/task_runner.h"
-#include "base/task_scheduler/post_task.h"
#include "content/public/common/content_switches.h"
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
#include "content/renderer/pepper/plugin_module.h"
diff --git a/chromium/content/renderer/pepper/pepper_broker_unittest.cc b/chromium/content/renderer/pepper/pepper_broker_unittest.cc
index 4012be98d68..af2f082e464 100644
--- a/chromium/content/renderer/pepper/pepper_broker_unittest.cc
+++ b/chromium/content/renderer/pepper/pepper_broker_unittest.cc
@@ -3,13 +3,13 @@
// found in the LICENSE file.
#include "content/renderer/pepper/pepper_broker.h"
-#include "base/message_loop/message_loop.h"
#if defined(OS_POSIX)
#include <fcntl.h>
#include <sys/socket.h>
#endif // defined(OS_POSIX)
+#include "base/test/scoped_task_environment.h"
#include "build/build_config.h"
#include "content/test/mock_render_process.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -18,7 +18,10 @@ namespace content {
class PepperBrokerTest : public ::testing::Test {
protected:
- base::MessageLoopForIO message_loop_;
+ PepperBrokerTest()
+ : task_environment_(
+ base::test::ScopedTaskEnvironment::MainThreadType::IO) {}
+ base::test::ScopedTaskEnvironment task_environment_;
// We need a render process for ppapi::proxy::ProxyChannel to work.
MockRenderProcess mock_process_;
};
diff --git a/chromium/content/renderer/pepper/pepper_file_chooser_host.cc b/chromium/content/renderer/pepper/pepper_file_chooser_host.cc
index 014049a6873..9c93b39c851 100644
--- a/chromium/content/renderer/pepper/pepper_file_chooser_host.cc
+++ b/chromium/content/renderer/pepper/pepper_file_chooser_host.cc
@@ -155,7 +155,7 @@ int32_t PepperFileChooserHost::OnShow(
RenderFrameImpl* render_frame = static_cast<RenderFrameImpl*>(
renderer_ppapi_host_->GetRenderFrameForInstance(pp_instance()));
- if (!render_frame || !render_frame->ScheduleFileChooser(params, handler_)) {
+ if (!render_frame || !render_frame->RunFileChooser(params, handler_)) {
delete handler_;
handler_ = nullptr;
return PP_ERROR_NOACCESS;
diff --git a/chromium/content/renderer/pepper/pepper_file_system_host.cc b/chromium/content/renderer/pepper/pepper_file_system_host.cc
index dcf0df79372..53915dfd0d7 100644
--- a/chromium/content/renderer/pepper/pepper_file_system_host.cc
+++ b/chromium/content/renderer/pepper/pepper_file_system_host.cc
@@ -7,6 +7,7 @@
#include "base/bind.h"
#include "base/callback.h"
#include "content/common/pepper_file_util.h"
+#include "content/public/common/service_names.mojom.h"
#include "content/public/renderer/render_view.h"
#include "content/public/renderer/renderer_ppapi_host.h"
#include "content/renderer/fileapi/file_system_dispatcher.h"
@@ -18,6 +19,8 @@
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/shared_impl/file_system_util.h"
#include "ppapi/shared_impl/file_type_conversion.h"
+#include "services/service_manager/public/cpp/connector.h"
+#include "storage/common/fileapi/file_system_type_converters.h"
#include "storage/common/fileapi/file_system_util.h"
#include "third_party/blink/public/web/web_document.h"
#include "third_party/blink/public/web/web_local_frame.h"
@@ -66,7 +69,12 @@ bool PepperFileSystemHost::IsFileSystemHost() { return true; }
void PepperFileSystemHost::DidOpenFileSystem(
const std::string& /* name_unused */,
- const GURL& root) {
+ const GURL& root,
+ base::File::Error error) {
+ if (error != base::File::FILE_OK) {
+ DidFailOpenFileSystem(error);
+ return;
+ }
opened_ = true;
root_url_ = root;
reply_context_.params.set_result(PP_OK);
@@ -99,13 +107,11 @@ int32_t PepperFileSystemHost::OnHostMsgOpen(
if (!document_url.is_valid())
return PP_ERROR_FAILED;
- FileSystemDispatcher* file_system_dispatcher =
- RenderThreadImpl::current()->file_system_dispatcher();
reply_context_ = context->MakeReplyMessageContext();
- file_system_dispatcher->OpenFileSystem(
- document_url.GetOrigin(), file_system_type,
- base::Bind(&PepperFileSystemHost::DidOpenFileSystem, AsWeakPtr()),
- base::Bind(&PepperFileSystemHost::DidFailOpenFileSystem, AsWeakPtr()));
+ GetFileSystemManager().Open(
+ document_url.GetOrigin(),
+ mojo::ConvertTo<blink::mojom::FileSystemType>(file_system_type),
+ base::BindOnce(&PepperFileSystemHost::DidOpenFileSystem, AsWeakPtr()));
return PP_OK_COMPLETIONPENDING;
}
@@ -138,4 +144,12 @@ int32_t PepperFileSystemHost::OnHostMsgInitIsolatedFileSystem(
return PP_OK;
}
+blink::mojom::FileSystemManager& PepperFileSystemHost::GetFileSystemManager() {
+ if (!file_system_manager_) {
+ ChildThreadImpl::current()->GetConnector()->BindInterface(
+ mojom::kBrowserServiceName, mojo::MakeRequest(&file_system_manager_));
+ }
+ return *file_system_manager_;
+}
+
} // namespace content
diff --git a/chromium/content/renderer/pepper/pepper_file_system_host.h b/chromium/content/renderer/pepper/pepper_file_system_host.h
index 88a64219706..9017bc258cc 100644
--- a/chromium/content/renderer/pepper/pepper_file_system_host.h
+++ b/chromium/content/renderer/pepper/pepper_file_system_host.h
@@ -16,6 +16,7 @@
#include "ppapi/c/private/ppb_isolated_file_system_private.h"
#include "ppapi/host/host_message_context.h"
#include "ppapi/host/resource_host.h"
+#include "third_party/blink/public/mojom/filesystem/file_system.mojom.h"
#include "url/gurl.h"
namespace content {
@@ -56,7 +57,9 @@ class PepperFileSystemHost
private:
// Callback for OpenFileSystem.
- void DidOpenFileSystem(const std::string& name_unused, const GURL& root);
+ void DidOpenFileSystem(const std::string& name_unused,
+ const GURL& root,
+ base::File::Error error);
void DidFailOpenFileSystem(base::File::Error error);
int32_t OnHostMsgOpen(ppapi::host::HostMessageContext* context,
@@ -66,6 +69,8 @@ class PepperFileSystemHost
const std::string& fsid,
PP_IsolatedFileSystemType_Private type);
+ blink::mojom::FileSystemManager& GetFileSystemManager();
+
RendererPpapiHost* renderer_ppapi_host_;
ppapi::host::ReplyMessageContext reply_context_;
@@ -73,6 +78,7 @@ class PepperFileSystemHost
bool opened_; // whether open is successful.
GURL root_url_;
bool called_open_; // whether open has been called.
+ blink::mojom::FileSystemManagerPtr file_system_manager_;
DISALLOW_COPY_AND_ASSIGN(PepperFileSystemHost);
};
diff --git a/chromium/content/renderer/pepper/pepper_graphics_2d_host.cc b/chromium/content/renderer/pepper/pepper_graphics_2d_host.cc
index 5110e1478a8..5e3c8da0265 100644
--- a/chromium/content/renderer/pepper/pepper_graphics_2d_host.cc
+++ b/chromium/content/renderer/pepper/pepper_graphics_2d_host.cc
@@ -44,7 +44,7 @@
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/shared_impl/ppb_view_shared.h"
#include "ppapi/thunk/enter.h"
-#include "services/ui/public/cpp/gpu/context_provider_command_buffer.h"
+#include "services/ws/public/cpp/gpu/context_provider_command_buffer.h"
#include "skia/ext/platform_canvas.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "third_party/khronos/GLES2/gl2ext.h"
diff --git a/chromium/content/renderer/pepper/pepper_platform_audio_input.cc b/chromium/content/renderer/pepper/pepper_platform_audio_input.cc
index 97629b7c3c7..fe4a9778901 100644
--- a/chromium/content/renderer/pepper/pepper_platform_audio_input.cc
+++ b/chromium/content/renderer/pepper/pepper_platform_audio_input.cc
@@ -176,8 +176,8 @@ void PepperPlatformAudioInput::InitializeOnIOThread(int session_id) {
DCHECK(io_task_runner_->BelongsToCurrentThread());
if (ipc_startup_state_ != kStopped)
- ipc_ = AudioInputIPCFactory::get()->CreateAudioInputIPC(render_frame_id_,
- session_id);
+ ipc_ = AudioInputIPCFactory::get()->CreateAudioInputIPC(
+ render_frame_id_, media::AudioSourceParameters(session_id));
if (!ipc_)
return;
diff --git a/chromium/content/renderer/pepper/pepper_platform_audio_output.cc b/chromium/content/renderer/pepper/pepper_platform_audio_output.cc
index fcc69c75eae..3e5586da8c9 100644
--- a/chromium/content/renderer/pepper/pepper_platform_audio_output.cc
+++ b/chromium/content/renderer/pepper/pepper_platform_audio_output.cc
@@ -154,7 +154,7 @@ void PepperPlatformAudioOutput::InitializeOnIOThread(
const media::AudioParameters& params) {
DCHECK(io_task_runner_->BelongsToCurrentThread());
if (ipc_)
- ipc_->CreateStream(this, params);
+ ipc_->CreateStream(this, params, base::nullopt);
}
void PepperPlatformAudioOutput::StartPlaybackOnIOThread() {
diff --git a/chromium/content/renderer/pepper/pepper_platform_audio_output_dev.cc b/chromium/content/renderer/pepper/pepper_platform_audio_output_dev.cc
index 7c7f53aab6e..3120c80ede4 100644
--- a/chromium/content/renderer/pepper/pepper_platform_audio_output_dev.cc
+++ b/chromium/content/renderer/pepper/pepper_platform_audio_output_dev.cc
@@ -290,9 +290,9 @@ void PepperPlatformAudioOutputDev::RequestDeviceAuthorizationOnIOThread() {
auth_timeout_action_.reset(new base::OneShotTimer());
auth_timeout_action_->Start(
FROM_HERE, auth_timeout_,
- base::Bind(&PepperPlatformAudioOutputDev::OnDeviceAuthorized, this,
- media::OUTPUT_DEVICE_STATUS_ERROR_TIMED_OUT,
- media::AudioParameters(), std::string()));
+ base::BindOnce(&PepperPlatformAudioOutputDev::OnDeviceAuthorized, this,
+ media::OUTPUT_DEVICE_STATUS_ERROR_TIMED_OUT,
+ media::AudioParameters(), std::string()));
}
}
@@ -310,7 +310,7 @@ void PepperPlatformAudioOutputDev::CreateStreamOnIOThread(
case IDLE:
if (did_receive_auth_.IsSignaled() && device_id_.empty()) {
state_ = CREATING_STREAM;
- ipc_->CreateStream(this, params);
+ ipc_->CreateStream(this, params, base::nullopt);
} else {
RequestDeviceAuthorizationOnIOThread();
start_on_authorized_ = true;
@@ -323,7 +323,7 @@ void PepperPlatformAudioOutputDev::CreateStreamOnIOThread(
case AUTHORIZED:
state_ = CREATING_STREAM;
- ipc_->CreateStream(this, params);
+ ipc_->CreateStream(this, params, base::nullopt);
start_on_authorized_ = false;
break;
diff --git a/chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc b/chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc
index 8e7653afc9d..6cde87d05de 100644
--- a/chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc
+++ b/chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc
@@ -125,6 +125,7 @@
#include "third_party/khronos/GLES2/gl2.h"
#include "ui/events/blink/blink_event_util.h"
#include "ui/events/blink/web_input_event.h"
+#include "ui/events/keycodes/dom/dom_code.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/image/image_skia_rep.h"
@@ -135,8 +136,8 @@
#if BUILDFLAG(ENABLE_PRINTING)
// nogncheck because dependency on //printing is conditional upon
// enable_basic_printing flags.
+#include "printing/metafile_skia.h" // nogncheck
#include "printing/metafile_skia_wrapper.h" // nogncheck
-#include "printing/pdf_metafile_skia.h" // nogncheck
#endif
#if defined(OS_CHROMEOS)
@@ -373,7 +374,7 @@ class PluginInstanceLockTarget : public MouseLockDispatcher::LockTarget {
};
void PrintPDFOutput(PP_Resource print_output,
- printing::PdfMetafileSkia* metafile) {
+ printing::MetafileSkia* metafile) {
#if BUILDFLAG(ENABLE_PRINTING)
DCHECK(metafile);
@@ -486,9 +487,8 @@ PPB_Gamepad_API* PepperPluginInstanceImpl::GamepadImpl::AsPPB_Gamepad_API() {
void PepperPluginInstanceImpl::GamepadImpl::Sample(
PP_Instance instance,
PP_GamepadsSampleData* data) {
- device::Gamepads gamepads_data;
- RenderThreadImpl::current()->SampleGamepads(&gamepads_data);
- ppapi::ConvertDeviceGamepadData(gamepads_data, data);
+ // This gamepad singleton resource method should not be called
+ NOTREACHED();
}
PepperPluginInstanceImpl::PepperPluginInstanceImpl(
@@ -1019,7 +1019,7 @@ bool PepperPluginInstanceImpl::
// Set the composition target.
for (size_t i = 0; i < ime_text_spans.size(); ++i) {
if (ime_text_spans[i].thickness ==
- ui::mojom::ImeTextSpanThickness::kThick) {
+ ws::mojom::ImeTextSpanThickness::kThick) {
std::vector<uint32_t>::iterator it =
std::find(event.composition_segment_offsets.begin(),
event.composition_segment_offsets.end(),
@@ -1549,7 +1549,8 @@ void PepperPluginInstanceImpl::SelectAll() {
static const ui::EventFlags kPlatformModifier = ui::EF_CONTROL_DOWN;
// Synthesize a ctrl + a key event to send to the plugin and let it sort out
// the event. See also https://crbug.com/739529.
- ui::KeyEvent char_event(L'A', ui::VKEY_A, kPlatformModifier);
+ ui::KeyEvent char_event(L'A', ui::VKEY_A, ui::DomCode::NONE,
+ kPlatformModifier);
// Also synthesize a key up event to look more like a real key press.
// Otherwise the plugin will not do all the required work to keep the renderer
@@ -2005,7 +2006,7 @@ void PepperPluginInstanceImpl::PrintPage(int page_number,
DCHECK(plugin_print_interface_);
// |canvas| should always have an associated metafile.
- printing::PdfMetafileSkia* metafile =
+ printing::MetafileSkia* metafile =
printing::MetafileSkiaWrapper::GetMetafileFromCanvas(canvas);
DCHECK(metafile);
@@ -2426,7 +2427,7 @@ void PepperPluginInstanceImpl::SimulateImeSetCompositionEvent(
ime_text_span.start_offset = offsets[i];
ime_text_span.end_offset = offsets[i + 1];
if (input_event.composition_target_segment == static_cast<int32_t>(i - 2))
- ime_text_span.thickness = ui::mojom::ImeTextSpanThickness::kThick;
+ ime_text_span.thickness = ws::mojom::ImeTextSpanThickness::kThick;
ime_text_spans.push_back(ime_text_span);
}
@@ -2610,7 +2611,7 @@ uint32_t PepperPluginInstanceImpl::GetAudioHardwareOutputSampleRate(
PP_Instance instance) {
return render_frame() ? AudioDeviceFactory::GetOutputDeviceInfo(
render_frame()->GetRoutingID(),
- 0 /* session_id */, std::string() /* device_id */)
+ media::AudioSinkParameters())
.output_params()
.sample_rate()
: 0;
@@ -2620,8 +2621,7 @@ uint32_t PepperPluginInstanceImpl::GetAudioHardwareOutputBufferSize(
PP_Instance instance) {
return render_frame() ? AudioDeviceFactory::GetOutputDeviceInfo(
render_frame()->GetRoutingID(),
- 0 /* session_id */, std::string() /* device_id */
- )
+ media::AudioSinkParameters())
.output_params()
.frames_per_buffer()
: 0;
@@ -2655,20 +2655,19 @@ void PepperPluginInstanceImpl::NumberOfFindResultsChanged(
// them.
if (find_identifier_ == -1)
return;
- if (render_frame_) {
- render_frame_->ReportFindInPageMatchCount(find_identifier_, total,
- PP_ToBool(final_result));
- }
+ if (!container_)
+ return;
+ container_->ReportFindInPageMatchCount(find_identifier_, total,
+ PP_ToBool(final_result));
}
void PepperPluginInstanceImpl::SelectedFindResultChanged(PP_Instance instance,
int32_t index) {
if (find_identifier_ == -1)
return;
- if (render_frame_) {
- render_frame_->ReportFindInPageSelection(find_identifier_, index + 1,
- blink::WebRect());
- }
+ if (!container_)
+ return;
+ container_->ReportFindInPageSelection(find_identifier_, index + 1);
}
void PepperPluginInstanceImpl::SetTickmarks(PP_Instance instance,
diff --git a/chromium/content/renderer/pepper/pepper_plugin_instance_impl.h b/chromium/content/renderer/pepper/pepper_plugin_instance_impl.h
index 757177607ca..af9f4f4995a 100644
--- a/chromium/content/renderer/pepper/pepper_plugin_instance_impl.h
+++ b/chromium/content/renderer/pepper/pepper_plugin_instance_impl.h
@@ -99,7 +99,7 @@ class ScopedPPVar;
}
namespace printing {
-class PdfMetafileSkia;
+class MetafileSkia;
}
namespace content {
@@ -791,7 +791,7 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
//
// The metafile to save into, which is guaranteed to be valid between a
// successful PrintBegin call and a PrintEnd call.
- printing::PdfMetafileSkia* metafile_;
+ printing::MetafileSkia* metafile_;
// An array of page ranges.
std::vector<PP_PrintPageNumberRange_Dev> ranges_;
diff --git a/chromium/content/renderer/pepper/pepper_plugin_registry.cc b/chromium/content/renderer/pepper/pepper_plugin_registry.cc
index 6a885b4b1fa..73ddbac0b5b 100644
--- a/chromium/content/renderer/pepper/pepper_plugin_registry.cc
+++ b/chromium/content/renderer/pepper/pepper_plugin_registry.cc
@@ -28,9 +28,9 @@ PepperPluginRegistry* PepperPluginRegistry::GetInstance() {
const PepperPluginInfo* PepperPluginRegistry::GetInfoForPlugin(
const WebPluginInfo& info) {
- for (size_t i = 0; i < plugin_list_.size(); ++i) {
- if (info.path == plugin_list_[i].path)
- return &plugin_list_[i];
+ for (const auto& plugin : plugin_list_) {
+ if (info.path == plugin.path)
+ return &plugin;
}
// We did not find the plugin in our list. But wait! the plugin can also
// be a latecomer, as it happens with pepper flash. This information
@@ -117,16 +117,13 @@ void PepperPluginRegistry::Initialize() {
// initialization. If we bail out (in the continue clauses) before saving
// the initialized module, it will still try to unregister itself in its
// destructor.
- for (size_t i = 0; i < plugin_list_.size(); i++) {
- const PepperPluginInfo& current = plugin_list_[i];
+ for (const auto& current : plugin_list_) {
if (current.is_out_of_process)
continue; // Out of process plugins need no special pre-initialization.
- scoped_refptr<PluginModule> module =
- new PluginModule(current.name,
- current.version,
- current.path,
- ppapi::PpapiPermissions(current.permissions));
+ auto module = base::MakeRefCounted<PluginModule>(
+ current.name, current.version, current.path,
+ ppapi::PpapiPermissions(current.permissions));
AddLiveModule(current.path, base::Optional<url::Origin>(), module.get());
if (current.is_internal) {
if (!module->InitAsInternalPlugin(current.internal_entry_points)) {
diff --git a/chromium/content/renderer/pepper/pepper_url_loader_host.cc b/chromium/content/renderer/pepper/pepper_url_loader_host.cc
index 681130e7db9..b4a262c9203 100644
--- a/chromium/content/renderer/pepper/pepper_url_loader_host.cc
+++ b/chromium/content/renderer/pepper/pepper_url_loader_host.cc
@@ -260,7 +260,9 @@ int32_t PepperURLLoaderHost::InternalOnHostMsgOpen(
DCHECK(web_request.GetSkipServiceWorker());
WebAssociatedURLLoaderOptions options;
- if (!has_universal_access_) {
+ if (has_universal_access_) {
+ options.grant_universal_access = true;
+ } else {
// All other HTTP requests are untrusted.
options.untrusted_http = true;
if (filled_in_request_data.allow_cross_origin_requests) {
diff --git a/chromium/content/renderer/pepper/pepper_video_encoder_host.cc b/chromium/content/renderer/pepper/pepper_video_encoder_host.cc
index 8c3565b2b23..cf8e6333142 100644
--- a/chromium/content/renderer/pepper/pepper_video_encoder_host.cc
+++ b/chromium/content/renderer/pepper/pepper_video_encoder_host.cc
@@ -266,10 +266,10 @@ int32_t PepperVideoEncoderHost::OnHostMsgInitialize(
return PP_ERROR_NOTSUPPORTED;
initialize_reply_context_ = context->MakeReplyMessageContext();
- if (encoder_->Initialize(media_input_format_, input_size, media_profile,
- initial_bitrate, this)) {
+ const media::VideoEncodeAccelerator::Config config(
+ media_input_format_, input_size, media_profile, initial_bitrate);
+ if (encoder_->Initialize(config, this))
return PP_OK_COMPLETIONPENDING;
- }
initialize_reply_context_ = ppapi::host::ReplyMessageContext();
Close();
diff --git a/chromium/content/renderer/pepper/plugin_instance_throttler_impl.h b/chromium/content/renderer/pepper/plugin_instance_throttler_impl.h
index b98f914e2d4..3fbcdecee14 100644
--- a/chromium/content/renderer/pepper/plugin_instance_throttler_impl.h
+++ b/chromium/content/renderer/pepper/plugin_instance_throttler_impl.h
@@ -113,7 +113,7 @@ class CONTENT_EXPORT PluginInstanceThrottlerImpl
bool audio_throttled_;
base::DelayTimer audio_throttled_frame_timeout_;
- base::ObserverList<Observer> observer_list_;
+ base::ObserverList<Observer>::Unchecked observer_list_;
base::WeakPtrFactory<PluginInstanceThrottlerImpl> weak_factory_;
diff --git a/chromium/content/renderer/pepper/plugin_module.cc b/chromium/content/renderer/pepper/plugin_module.cc
index 48954c1da95..7f3d594f71b 100644
--- a/chromium/content/renderer/pepper/plugin_module.cc
+++ b/chromium/content/renderer/pepper/plugin_module.cc
@@ -110,7 +110,6 @@
#include "ppapi/c/private/ppb_find_private.h"
#include "ppapi/c/private/ppb_flash.h"
#include "ppapi/c/private/ppb_flash_clipboard.h"
-#include "ppapi/c/private/ppb_flash_device_id.h"
#include "ppapi/c/private/ppb_flash_drm.h"
#include "ppapi/c/private/ppb_flash_file.h"
#include "ppapi/c/private/ppb_flash_font_file.h"
diff --git a/chromium/content/renderer/pepper/url_request_info_util.cc b/chromium/content/renderer/pepper/url_request_info_util.cc
index f5b4028d7fa..5108a428a42 100644
--- a/chromium/content/renderer/pepper/url_request_info_util.cc
+++ b/chromium/content/renderer/pepper/url_request_info_util.cc
@@ -9,7 +9,7 @@
#include "base/logging.h"
#include "base/strings/string_util.h"
-#include "content/common/fileapi/file_system_messages.h"
+#include "content/public/common/service_names.mojom.h"
#include "content/renderer/loader/request_extra_data.h"
#include "content/renderer/pepper/host_globals.h"
#include "content/renderer/pepper/pepper_file_ref_renderer_host.h"
@@ -24,6 +24,8 @@
#include "ppapi/shared_impl/url_request_info_data.h"
#include "ppapi/shared_impl/var.h"
#include "ppapi/thunk/enter.h"
+#include "services/service_manager/public/cpp/connector.h"
+#include "third_party/blink/public/mojom/filesystem/file_system.mojom.h"
#include "third_party/blink/public/platform/file_path_conversion.h"
#include "third_party/blink/public/platform/web_data.h"
#include "third_party/blink/public/platform/web_feature.mojom.h"
@@ -49,6 +51,13 @@ namespace content {
namespace {
+blink::mojom::FileSystemManagerPtr GetFileSystemManager() {
+ blink::mojom::FileSystemManagerPtr file_system_manager_ptr;
+ ChildThreadImpl::current()->GetConnector()->BindInterface(
+ mojom::kBrowserServiceName, mojo::MakeRequest(&file_system_manager_ptr));
+ return file_system_manager_ptr;
+}
+
// Appends the file ref given the Resource pointer associated with it to the
// given HTTP body, returning true on success.
bool AppendFileRefToBody(PP_Instance instance,
@@ -78,9 +87,8 @@ bool AppendFileRefToBody(PP_Instance instance,
case PP_FILESYSTEMTYPE_LOCALPERSISTENT:
// TODO(kinuko): remove this sync IPC when we fully support
// AppendURLRange for FileSystem URL.
- RenderThreadImpl::current()->Send(
- new FileSystemHostMsg_SyncGetPlatformPath(
- file_ref_host->GetFileSystemURL(), &platform_path));
+ GetFileSystemManager()->GetPlatformPath(file_ref_host->GetFileSystemURL(),
+ &platform_path);
break;
case PP_FILESYSTEMTYPE_EXTERNAL:
platform_path = file_ref_host->GetExternalFilePath();
diff --git a/chromium/content/renderer/pepper/video_decoder_shim.cc b/chromium/content/renderer/pepper/video_decoder_shim.cc
index ca39cdef7d7..ac45730b1c3 100644
--- a/chromium/content/renderer/pepper/video_decoder_shim.cc
+++ b/chromium/content/renderer/pepper/video_decoder_shim.cc
@@ -35,7 +35,7 @@
#include "media/video/picture.h"
#include "media/video/video_decode_accelerator.h"
#include "ppapi/c/pp_errors.h"
-#include "services/ui/public/cpp/gpu/context_provider_command_buffer.h"
+#include "services/ws/public/cpp/gpu/context_provider_command_buffer.h"
#include "third_party/skia/include/gpu/GrTypes.h"
namespace content {
@@ -60,7 +60,7 @@ bool IsCodecSupported(media::VideoCodec codec) {
// YUV->RGB converter class using a shader and FBO.
class VideoDecoderShim::YUVConverter {
public:
- YUVConverter(scoped_refptr<ui::ContextProviderCommandBuffer>);
+ YUVConverter(scoped_refptr<ws::ContextProviderCommandBuffer>);
~YUVConverter();
bool Initialize();
void Convert(const scoped_refptr<media::VideoFrame>& frame, GLuint tex_out);
@@ -71,7 +71,7 @@ class VideoDecoderShim::YUVConverter {
GLuint CreateProgram(const char* name, GLuint vshader, GLuint fshader);
GLuint CreateTexture();
- scoped_refptr<ui::ContextProviderCommandBuffer> context_provider_;
+ scoped_refptr<ws::ContextProviderCommandBuffer> context_provider_;
gpu::gles2::GLES2Interface* gl_;
GLuint frame_buffer_;
GLuint vertex_buffer_;
@@ -101,7 +101,7 @@ class VideoDecoderShim::YUVConverter {
};
VideoDecoderShim::YUVConverter::YUVConverter(
- scoped_refptr<ui::ContextProviderCommandBuffer> context_provider)
+ scoped_refptr<ws::ContextProviderCommandBuffer> context_provider)
: context_provider_(std::move(context_provider)),
gl_(context_provider_->ContextGL()),
frame_buffer_(0),
@@ -390,16 +390,22 @@ void VideoDecoderShim::YUVConverter::Convert(
};
yuv_adjust = yuv_adjust_constrained;
+ // TODO(hubbe): Should default to 709
yuv_matrix = yuv_to_rgb_rec601;
- int result;
- if (frame->metadata()->GetInteger(media::VideoFrameMetadata::COLOR_SPACE,
- &result)) {
- if (result == media::COLOR_SPACE_JPEG) {
- yuv_matrix = yuv_to_rgb_jpeg;
- yuv_adjust = yuv_adjust_full;
- } else if (result == media::COLOR_SPACE_HD_REC709) {
- yuv_matrix = yuv_to_rgb_rec709;
+ SkYUVColorSpace sk_yuv_color_space;
+ if (frame->ColorSpace().ToSkYUVColorSpace(&sk_yuv_color_space)) {
+ switch (sk_yuv_color_space) {
+ case kJPEG_SkYUVColorSpace:
+ yuv_matrix = yuv_to_rgb_jpeg;
+ yuv_adjust = yuv_adjust_full;
+ break;
+ case kRec709_SkYUVColorSpace:
+ yuv_matrix = yuv_to_rgb_rec709;
+ break;
+ case kRec601_SkYUVColorSpace:
+ // Current default.
+ break;
}
}
diff --git a/chromium/content/renderer/pepper/video_decoder_shim.h b/chromium/content/renderer/pepper/video_decoder_shim.h
index 44a1b6d4f00..40b69d58bf4 100644
--- a/chromium/content/renderer/pepper/video_decoder_shim.h
+++ b/chromium/content/renderer/pepper/video_decoder_shim.h
@@ -22,7 +22,7 @@ namespace base {
class SingleThreadTaskRunner;
}
-namespace ui {
+namespace ws {
class ContextProviderCommandBuffer;
}
@@ -79,7 +79,7 @@ class VideoDecoderShim : public media::VideoDecodeAccelerator {
PepperVideoDecoderHost* host_;
scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_;
- scoped_refptr<ui::ContextProviderCommandBuffer> context_provider_;
+ scoped_refptr<ws::ContextProviderCommandBuffer> context_provider_;
// The current decoded frame size.
gfx::Size texture_size_;
diff --git a/chromium/content/renderer/pepper/video_encoder_shim.cc b/chromium/content/renderer/pepper/video_encoder_shim.cc
index a8ce1b77691..0c2d9e7442a 100644
--- a/chromium/content/renderer/pepper/video_encoder_shim.cc
+++ b/chromium/content/renderer/pepper/video_encoder_shim.cc
@@ -97,10 +97,7 @@ class VideoEncoderShim::EncoderImpl {
explicit EncoderImpl(const base::WeakPtr<VideoEncoderShim>& shim);
~EncoderImpl();
- void Initialize(media::VideoPixelFormat input_format,
- const gfx::Size& input_visible_size,
- media::VideoCodecProfile output_profile,
- uint32_t initial_bitrate);
+ void Initialize(const media::VideoEncodeAccelerator::Config& config);
void Encode(const scoped_refptr<media::VideoFrame>& frame,
bool force_keyframe);
void UseOutputBitstreamBuffer(const media::BitstreamBuffer& buffer,
@@ -158,23 +155,19 @@ VideoEncoderShim::EncoderImpl::~EncoderImpl() {
vpx_codec_destroy(&encoder_);
}
-void VideoEncoderShim::EncoderImpl::Initialize(
- media::VideoPixelFormat input_format,
- const gfx::Size& input_visible_size,
- media::VideoCodecProfile output_profile,
- uint32_t initial_bitrate) {
- gfx::Size coded_size =
- media::VideoFrame::PlaneSize(input_format, 0, input_visible_size);
+void VideoEncoderShim::EncoderImpl::Initialize(const Config& config) {
+ gfx::Size coded_size = media::VideoFrame::PlaneSize(
+ config.input_format, 0, config.input_visible_size);
// Only VP9 profile 0 is supported by PPAPI at the moment. VP9 profiles 1-3
// are not supported due to backward compatibility.
- DCHECK_NE(output_profile, media::VP9PROFILE_PROFILE1);
- DCHECK_NE(output_profile, media::VP9PROFILE_PROFILE2);
- DCHECK_NE(output_profile, media::VP9PROFILE_PROFILE3);
+ DCHECK_NE(config.output_profile, media::VP9PROFILE_PROFILE1);
+ DCHECK_NE(config.output_profile, media::VP9PROFILE_PROFILE2);
+ DCHECK_NE(config.output_profile, media::VP9PROFILE_PROFILE3);
vpx_codec_iface_t* vpx_codec;
int32_t min_quantizer, max_quantizer, cpu_used;
- GetVpxCodecParameters(output_profile, &vpx_codec, &min_quantizer,
+ GetVpxCodecParameters(config.output_profile, &vpx_codec, &min_quantizer,
&max_quantizer, &cpu_used);
// Populate encoder configuration with default values.
@@ -183,15 +176,15 @@ void VideoEncoderShim::EncoderImpl::Initialize(
return;
}
- config_.g_w = input_visible_size.width();
- config_.g_h = input_visible_size.height();
+ config_.g_w = config.input_visible_size.width();
+ config_.g_h = config.input_visible_size.height();
framerate_ = config_.g_timebase.den;
config_.g_lag_in_frames = 0;
config_.g_timebase.num = 1;
config_.g_timebase.den = base::Time::kMicrosecondsPerSecond;
- config_.rc_target_bitrate = initial_bitrate / 1000;
+ config_.rc_target_bitrate = config.initial_bitrate / 1000;
config_.rc_min_quantizer = min_quantizer;
config_.rc_max_quantizer = max_quantizer;
// Do not saturate CPU utilization just for encoding. On a lower-end system
@@ -202,10 +195,10 @@ void VideoEncoderShim::EncoderImpl::Initialize(
// Use Q/CQ mode if no target bitrate is given. Note that in the VP8/CQ case
// the meaning of rc_target_bitrate changes to target maximum rate.
- if (initial_bitrate == 0) {
- if (output_profile == media::VP9PROFILE_PROFILE0) {
+ if (config.initial_bitrate == 0) {
+ if (config.output_profile == media::VP9PROFILE_PROFILE0) {
config_.rc_end_usage = VPX_Q;
- } else if (output_profile == media::VP8PROFILE_ANY) {
+ } else if (config.output_profile == media::VP8PROFILE_ANY) {
config_.rc_end_usage = VPX_CQ;
config_.rc_target_bitrate = kVp8MaxCQBitrate;
}
@@ -230,7 +223,7 @@ void VideoEncoderShim::EncoderImpl::Initialize(
return;
}
- if (output_profile == media::VP9PROFILE_PROFILE0) {
+ if (config.output_profile == media::VP9PROFILE_PROFILE0) {
if (vpx_codec_control(&encoder_, VP9E_SET_AQ_MODE,
kVp9AqModeCyclicRefresh) != VPX_CODEC_OK) {
NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
@@ -408,26 +401,21 @@ VideoEncoderShim::GetSupportedProfiles() {
}
bool VideoEncoderShim::Initialize(
- media::VideoPixelFormat input_format,
- const gfx::Size& input_visible_size,
- media::VideoCodecProfile output_profile,
- uint32_t initial_bitrate,
+ const media::VideoEncodeAccelerator::Config& config,
media::VideoEncodeAccelerator::Client* client) {
DCHECK(RenderThreadImpl::current());
DCHECK_EQ(client, host_);
- if (input_format != media::PIXEL_FORMAT_I420)
+ if (config.input_format != media::PIXEL_FORMAT_I420)
return false;
- if (output_profile != media::VP8PROFILE_ANY &&
- output_profile != media::VP9PROFILE_PROFILE0)
+ if (config.output_profile != media::VP8PROFILE_ANY &&
+ config.output_profile != media::VP9PROFILE_PROFILE0)
return false;
media_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&VideoEncoderShim::EncoderImpl::Initialize,
- base::Unretained(encoder_impl_.get()), input_format,
- input_visible_size, output_profile, initial_bitrate));
+ FROM_HERE, base::BindOnce(&VideoEncoderShim::EncoderImpl::Initialize,
+ base::Unretained(encoder_impl_.get()), config));
return true;
}
diff --git a/chromium/content/renderer/pepper/video_encoder_shim.h b/chromium/content/renderer/pepper/video_encoder_shim.h
index e48700b1d21..771fa5ea3d3 100644
--- a/chromium/content/renderer/pepper/video_encoder_shim.h
+++ b/chromium/content/renderer/pepper/video_encoder_shim.h
@@ -39,10 +39,7 @@ class VideoEncoderShim : public media::VideoEncodeAccelerator {
// media::VideoEncodeAccelerator implementation.
media::VideoEncodeAccelerator::SupportedProfiles GetSupportedProfiles()
override;
- bool Initialize(media::VideoPixelFormat input_format,
- const gfx::Size& input_visible_size,
- media::VideoCodecProfile output_profile,
- uint32_t initial_bitrate,
+ bool Initialize(const media::VideoEncodeAccelerator::Config& config,
media::VideoEncodeAccelerator::Client* client) override;
void Encode(const scoped_refptr<media::VideoFrame>& frame,
bool force_keyframe) override;
diff --git a/chromium/content/renderer/render_frame_impl.cc b/chromium/content/renderer/render_frame_impl.cc
index 9571ea0233e..52270733e64 100644
--- a/chromium/content/renderer/render_frame_impl.cc
+++ b/chromium/content/renderer/render_frame_impl.cc
@@ -38,15 +38,14 @@
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task/post_task.h"
#include "base/task_runner_util.h"
-#include "base/task_scheduler/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "cc/base/switches.h"
#include "content/common/accessibility_messages.h"
-#include "content/common/associated_interface_provider_impl.h"
#include "content/common/associated_interfaces.mojom.h"
#include "content/common/content_constants_internal.h"
#include "content/common/content_security_policy/content_security_policy.h"
@@ -168,7 +167,7 @@
#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"
-#include "services/ui/public/cpp/gpu/context_provider_command_buffer.h"
+#include "services/ws/public/cpp/gpu/context_provider_command_buffer.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
#include "third_party/blink/public/common/frame/sandbox_flags.h"
#include "third_party/blink/public/common/frame/user_activation_update_type.h"
@@ -199,7 +198,7 @@
#include "third_party/blink/public/web/web_context_features.h"
#include "third_party/blink/public/web/web_document.h"
#include "third_party/blink/public/web/web_element_collection.h"
-#include "third_party/blink/public/web/web_find_options.h"
+#include "third_party/blink/public/web/web_file_chooser_completion.h"
#include "third_party/blink/public/web/web_frame_owner_properties.h"
#include "third_party/blink/public/web/web_frame_serializer.h"
#include "third_party/blink/public/web/web_frame_serializer_cache_control_policy.h"
@@ -239,6 +238,7 @@
#endif
#if defined(OS_WIN)
+#include "base/debug/invalid_access_win.h"
#include "base/process/kill.h"
#elif defined(OS_POSIX)
#include <signal.h>
@@ -264,7 +264,6 @@ using blink::WebElement;
using blink::WebElementCollection;
using blink::WebExternalPopupMenu;
using blink::WebExternalPopupMenuClient;
-using blink::WebFindOptions;
using blink::WebFrame;
using blink::WebFrameLoadType;
using blink::WebFrameSerializer;
@@ -467,6 +466,15 @@ WebURLRequest CreateURLRequestForNavigation(
}
}
+ if (common_params.post_data) {
+ request.SetHTTPBody(GetWebHTTPBodyForRequestBody(*common_params.post_data));
+ if (!request_params.post_content_type.empty()) {
+ request.AddHTTPHeaderField(
+ WebString::FromASCII(net::HttpRequestHeaders::kContentType),
+ WebString::FromASCII(request_params.post_content_type));
+ }
+ }
+
if (!web_referrer.IsEmpty() ||
common_params.referrer.policy != blink::kWebReferrerPolicyDefault) {
request.SetHTTPReferrer(web_referrer, common_params.referrer.policy);
@@ -489,7 +497,8 @@ WebURLRequest CreateURLRequestForNavigation(
CommonNavigationParams MakeCommonNavigationParams(
const blink::WebLocalFrameClient::NavigationPolicyInfo& info,
- int load_flags) {
+ int load_flags,
+ base::TimeTicks input_start) {
Referrer referrer(
GURL(info.url_request.HttpHeaderField(WebString::FromUTF8("Referer"))
.Latin1()),
@@ -537,7 +546,8 @@ CommonNavigationParams MakeCommonNavigationParams(
info.url_request.GetNavigationCSP().self_source.has_value()
? base::Optional<CSPSource>(BuildCSPSource(
info.url_request.GetNavigationCSP().self_source.value()))
- : base::nullopt);
+ : base::nullopt,
+ input_start);
}
WebFrameLoadType NavigationTypeToLoadType(
@@ -810,7 +820,8 @@ std::unique_ptr<DocumentState> BuildDocumentState() {
// pending_navigation_params in a valid state. Callback should probably not be
// a part of PendingNavigationParams.
std::unique_ptr<DocumentState> BuildDocumentStateFromPending(
- PendingNavigationParams* pending_navigation_params) {
+ PendingNavigationParams* pending_navigation_params,
+ const network::ResourceResponseHead* head) {
std::unique_ptr<DocumentState> document_state(new DocumentState());
InternalDocumentStateData* internal_data =
InternalDocumentStateData::FromDocumentState(document_state.get());
@@ -846,6 +857,18 @@ std::unique_ptr<DocumentState> BuildDocumentStateFromPending(
document_state->set_can_load_local_resources(
request_params.can_load_local_resources);
+ if (head) {
+ if (head->headers)
+ internal_data->set_http_status_code(head->headers->response_code());
+ document_state->set_was_fetched_via_spdy(head->was_fetched_via_spdy);
+ document_state->set_was_alpn_negotiated(head->was_alpn_negotiated);
+ document_state->set_alpn_negotiated_protocol(
+ head->alpn_negotiated_protocol);
+ document_state->set_was_alternate_protocol_available(
+ head->was_alternate_protocol_available);
+ document_state->set_connection_info(head->connection_info);
+ }
+
bool load_data = !common_params.base_url_for_data_url.is_empty() &&
!common_params.history_url_for_data_url.is_empty() &&
common_params.url.SchemeIs(url::kDataScheme);
@@ -900,8 +923,9 @@ void ApplyFilePathAlias(blink::WebURLRequest* request) {
// Packs all navigation timings sent by the browser to a blink understandable
// format, blink::WebNavigationTimings.
blink::WebNavigationTimings BuildNavigationTimings(
- const base::TimeTicks& navigation_start,
- const NavigationTiming& browser_navigation_timings) {
+ base::TimeTicks navigation_start,
+ const NavigationTiming& browser_navigation_timings,
+ base::TimeTicks input_start) {
blink::WebNavigationTimings renderer_navigation_timings;
// Sanitizes the navigation_start timestamp for browser-initiated navigations,
@@ -923,9 +947,39 @@ blink::WebNavigationTimings BuildNavigationTimings(
renderer_navigation_timings.fetch_start =
browser_navigation_timings.fetch_start;
+ renderer_navigation_timings.input_start = input_start;
+
return renderer_navigation_timings;
}
+// Packs all loading data sent by the browser to a blink understandable
+// format, blink::WebNavigationParams.
+std::unique_ptr<blink::WebNavigationParams> BuildNavigationParams(
+ const CommonNavigationParams& common_params,
+ const RequestNavigationParams& request_params,
+ std::unique_ptr<blink::WebServiceWorkerNetworkProvider>
+ service_worker_network_provider) {
+ std::unique_ptr<blink::WebNavigationParams> navigation_params =
+ std::make_unique<blink::WebNavigationParams>();
+ navigation_params->navigation_timings = BuildNavigationTimings(
+ common_params.navigation_start, request_params.navigation_timing,
+ common_params.input_start);
+
+ if (common_params.source_location.has_value()) {
+ navigation_params->source_location.url =
+ WebString::FromLatin1(common_params.source_location->url);
+ navigation_params->source_location.line_number =
+ common_params.source_location->line_number;
+ navigation_params->source_location.column_number =
+ common_params.source_location->column_number;
+ }
+
+ navigation_params->is_user_activated = request_params.was_activated;
+ navigation_params->service_worker_network_provider =
+ std::move(service_worker_network_provider);
+ return navigation_params;
+}
+
} // namespace
class RenderFrameImpl::FrameURLLoaderFactory
@@ -951,11 +1005,9 @@ class RenderFrameImpl::FrameURLLoaderFactory
scoped_refptr<network::SharedURLLoaderFactory> loader_factory =
frame_->GetLoaderFactoryBundle();
if (request.GetRequestContext() == WebURLRequest::kRequestContextPrefetch &&
- frame_->prefetch_loader_factory_) {
+ frame_->prefetch_shared_loader_factory_) {
// The frame should be alive when this factory is used.
- loader_factory =
- base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
- frame_->prefetch_loader_factory_.get());
+ loader_factory = frame_->prefetch_shared_loader_factory_;
}
return std::make_unique<WebURLLoaderImpl>(
RenderThreadImpl::current()->resource_dispatcher(),
@@ -1063,6 +1115,15 @@ void HandleChromeDebugURL(const GURL& url) {
CHECK(false);
}
+#if defined(OS_WIN)
+ if (url == kChromeUIHeapCorruptionCrashURL) {
+ LOG(ERROR)
+ << "Intentionally causing heap corruption because user navigated to "
+ << url.spec();
+ base::debug::win::TerminateWithHeapCorruption();
+ }
+#endif
+
#if DCHECK_IS_ON()
if (url == kChromeUICrashDcheckURL) {
LOG(ERROR) << "Intentionally causing DCHECK because user navigated to "
@@ -1077,14 +1138,6 @@ void HandleChromeDebugURL(const GURL& url) {
#endif // ADDRESS_SANITIZER
}
-struct RenderFrameImpl::PendingFileChooser {
- PendingFileChooser(const FileChooserParams& p,
- blink::WebFileChooserCompletion* c)
- : params(p), completion(c) {}
- FileChooserParams params;
- blink::WebFileChooserCompletion* completion; // MAY BE NULL to skip callback.
-};
-
const std::string& UniqueNameForWebFrame(blink::WebFrame* frame) {
return frame->IsWebLocalFrame()
? RenderFrameImpl::FromWebFrame(frame)->unique_name()
@@ -1515,13 +1568,13 @@ mojom::FrameHost* RenderFrameImpl::GetFrameHost() {
}
RenderFrameImpl::~RenderFrameImpl() {
+ if (prefetch_shared_loader_factory_)
+ prefetch_shared_loader_factory_->Detach();
+
// If file chooser is still waiting for answer, dispatch empty answer.
- while (!file_chooser_completions_.empty()) {
- if (file_chooser_completions_.front()->completion) {
- file_chooser_completions_.front()->completion->DidChooseFile(
- WebVector<WebString>());
- }
- file_chooser_completions_.pop_front();
+ if (file_chooser_completion_) {
+ file_chooser_completion_->DidChooseFile(WebVector<WebString>());
+ file_chooser_completion_ = nullptr;
}
for (auto& observer : observers_)
@@ -1607,6 +1660,8 @@ void RenderFrameImpl::Initialize() {
enabled_bindings_ |= BINDINGS_POLICY_DOM_AUTOMATION;
if (command_line.HasSwitch(switches::kStatsCollectionController))
enabled_bindings_ |= BINDINGS_POLICY_STATS_COLLECTION;
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService))
+ frame_request_blocker_ = base::MakeRefCounted<FrameRequestBlocker>();
}
void RenderFrameImpl::InitializeBlameContext(RenderFrameImpl* parent_frame) {
@@ -1911,7 +1966,6 @@ bool RenderFrameImpl::OnMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(FrameMsg_GetSerializedHtmlWithLocalLinks,
OnGetSerializedHtmlWithLocalLinks)
IPC_MESSAGE_HANDLER(FrameMsg_SerializeAsMHTML, OnSerializeAsMHTML)
- IPC_MESSAGE_HANDLER(FrameMsg_Find, OnFind)
IPC_MESSAGE_HANDLER(FrameMsg_EnableViewSourceMode, OnEnableViewSourceMode)
IPC_MESSAGE_HANDLER(FrameMsg_SuppressFurtherDialogs,
OnSuppressFurtherDialogs)
@@ -1941,7 +1995,14 @@ bool RenderFrameImpl::OnMessageReceived(const IPC::Message& msg) {
void RenderFrameImpl::OnAssociatedInterfaceRequest(
const std::string& interface_name,
mojo::ScopedInterfaceEndpointHandle handle) {
- associated_interfaces_.BindRequest(interface_name, std::move(handle));
+ if (!associated_interfaces_.TryBindInterface(interface_name, &handle)) {
+ for (auto& observer : observers_) {
+ if (observer.OnAssociatedInterfaceRequestForFrame(interface_name,
+ &handle)) {
+ return;
+ }
+ }
+ }
}
void RenderFrameImpl::BindEngagement(
@@ -2324,8 +2385,7 @@ void RenderFrameImpl::HandleJavascriptExecutionResult(
void RenderFrameImpl::OnVisualStateRequest(uint64_t id) {
GetRenderWidget()->QueueMessage(
- new FrameHostMsg_VisualStateResponse(routing_id_, id),
- MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE);
+ new FrameHostMsg_VisualStateResponse(routing_id_, id));
}
void RenderFrameImpl::OnSetAccessibilityMode(ui::AXMode new_mode) {
@@ -2339,10 +2399,6 @@ void RenderFrameImpl::OnSetAccessibilityMode(ui::AXMode new_mode) {
render_accessibility_ = new RenderAccessibilityImpl(this, new_mode);
} else if (!new_mode.has_mode(ui::AXMode::kWebContents) &&
old_mode.has_mode(ui::AXMode::kWebContents)) {
- // Note: this isn't called automatically by the destructor because
- // there'd be no point in calling it in frame teardown, only if there's
- // an accessibility mode change but the frame is persisting.
- render_accessibility_->DisableAccessibility();
delete render_accessibility_;
render_accessibility_ = nullptr;
}
@@ -2449,8 +2505,27 @@ void RenderFrameImpl::OnCheckCompleted() {
frame_->CheckCompleted();
}
-void RenderFrameImpl::OnPostMessageEvent(
- const FrameMsg_PostMessage_Params& params) {
+void RenderFrameImpl::OnPostMessageEvent(FrameMsg_PostMessage_Params params) {
+ // This function is called on the per-thread task runner via legacy IPC. From
+ // the investigation of task duration on some web sites [1], this IPC message
+ // processing is one of the heaviest tasks. Use a per-frame task runner
+ // instead to get more efficient scheduing.
+ // [1] http://bit.ly/2MqaXfw
+ //
+ // TODO(hajimehoshi): Replace this legacy IPC usage with Mojo after message
+ // ordering is controllable.
+
+ // Ensure the message data is owned by |params| itself so that the data is
+ // live even after moved.
+ params.message->data.EnsureDataIsOwned();
+
+ frame_->GetTaskRunner(blink::TaskType::kPostedMessage)
+ ->PostTask(FROM_HERE,
+ base::BindOnce(&RenderFrameImpl::PostMessageEvent,
+ weak_factory_.GetWeakPtr(), std::move(params)));
+}
+
+void RenderFrameImpl::PostMessageEvent(FrameMsg_PostMessage_Params params) {
// Find the source frame if it exists.
WebFrame* source_frame = nullptr;
if (params.source_routing_id != MSG_ROUTING_NONE) {
@@ -2541,36 +2616,6 @@ bool RenderFrameImpl::RunJavaScriptDialog(JavaScriptDialogType type,
return success;
}
-bool RenderFrameImpl::ScheduleFileChooser(
- const FileChooserParams& params,
- blink::WebFileChooserCompletion* completion) {
- static const size_t kMaximumPendingFileChooseRequests = 4;
-
- // Do not open the file dialog in a hidden RenderFrame.
- if (IsHidden())
- return false;
-
- if (file_chooser_completions_.size() > kMaximumPendingFileChooseRequests) {
- // This sanity check prevents too many file choose requests from getting
- // queued which could DoS the user. Getting these is most likely a
- // programming error (there are many ways to DoS the user so it's not
- // considered a "real" security check), either in JS requesting many file
- // choosers to pop up, or in a plugin.
- //
- // TODO(brettw): We might possibly want to require a user gesture to open
- // a file picker, which will address this issue in a better way.
- return false;
- }
-
- file_chooser_completions_.push_back(
- std::make_unique<PendingFileChooser>(params, completion));
- if (file_chooser_completions_.size() == 1) {
- // Actually show the browse dialog when this is the first request.
- Send(new FrameHostMsg_RunFileChooser(routing_id_, params));
- }
- return true;
-}
-
void RenderFrameImpl::DidFailProvisionalLoadInternal(
const WebURLError& error,
blink::WebHistoryCommitType commit_type,
@@ -2619,19 +2664,34 @@ void RenderFrameImpl::DidFailProvisionalLoadInternal(
CommitNavigationCallback()));
}
+ // The |pending_navigation_params_| are reset in DidCreateDocumentLoader.
+ // We might not have |pending_navigation_params_| here, if failing after
+ // creating the DocumentLoader. This can happen if there's no byte in the
+ // response and the network connection gets closed. In that case, the
+ // provisional load does not commit and we get a DidFailProvisionalLoad.
std::unique_ptr<DocumentState> document_state;
- // If we sent a successful navigation to commit but for whatever reason the
- // commit was interrupted we might end up with empty
- // |pending_navigation_params_| here. For example, if
- // there's no byte in the response and the network connection gets closed. In
- // that case, the provisional load does not commit and we get a
- // DidFailProvisionalLoad.
- if (pending_navigation_params_)
- document_state =
- BuildDocumentStateFromPending(pending_navigation_params_.get());
-
+ std::unique_ptr<blink::WebNavigationParams> navigation_params;
+ if (pending_navigation_params_) {
+ document_state = BuildDocumentStateFromPending(
+ pending_navigation_params_.get(), nullptr);
+ // We might come here after we've already created
+ // ServiceWorkerNetworkProvider in CommitNavigation, and if that's the case
+ // we shouldn't reuse the same request_params (which confuses the
+ // ServiceWorker backend due to double-creation for the same provider_id).
+ // Code below will result in creating a SWNetworkProvider with an invalid
+ // ID but it should be fine as it's only used for showing an error page.
+ // TODO(ahemery): We should probably move the existing one down
+ // into the failed page instead of recreating a new one.
+ navigation_params = BuildNavigationParams(
+ pending_navigation_params_->common_params,
+ pending_navigation_params_->request_params,
+ BuildServiceWorkerNetworkProviderForNavigation(
+ nullptr /* request_params */,
+ nullptr /* controller_service_worker_info */));
+ }
LoadNavigationErrorPage(failed_request, error, replace, nullptr,
- error_page_content, std::move(document_state));
+ error_page_content, std::move(navigation_params),
+ std::move(document_state));
}
void RenderFrameImpl::LoadNavigationErrorPage(
@@ -2640,30 +2700,8 @@ void RenderFrameImpl::LoadNavigationErrorPage(
bool replace,
HistoryEntry* entry,
const base::Optional<std::string>& error_page_content,
+ std::unique_ptr<blink::WebNavigationParams> navigation_params,
std::unique_ptr<blink::WebDocumentLoader::ExtraData> navigation_data) {
- blink::WebFrameLoadType frame_load_type =
- entry ? blink::WebFrameLoadType::kBackForward
- : blink::WebFrameLoadType::kStandard;
- const blink::WebHistoryItem& history_item =
- entry ? entry->root() : blink::WebHistoryItem();
-
- // Requests blocked by the X-Frame-Options HTTP response header don't display
- // error pages but a blank page instead.
- // TODO(alexmos, mkwst, arthursonzogni): This block can be removed once error
- // pages are refactored. See crbug.com/588314 and crbug.com/622385.
- if (error.reason() == net::ERR_BLOCKED_BY_RESPONSE) {
- // Do not preserve the history item for blocked navigations, since we will
- // not attempt to reload it later. Also, it is important that the document
- // sequence number is not preserved, so that other navigations will not be
- // considered same-document with this data URL.
- const blink::WebHistoryItem& blank_history_item = blink::WebHistoryItem();
- frame_load_type = blink::WebFrameLoadType::kStandard;
- LoadNavigationErrorPageInternal("", GURL("data:,"), WebURL(), replace,
- frame_load_type, blank_history_item,
- std::move(navigation_data));
- return;
- }
-
std::string error_html;
if (error_page_content.has_value()) {
error_html = error_page_content.value();
@@ -2673,9 +2711,9 @@ void RenderFrameImpl::LoadNavigationErrorPage(
GetContentClient()->renderer()->PrepareErrorPage(
this, failed_request, error, &error_html, nullptr);
}
- LoadNavigationErrorPageInternal(error_html, GURL(kUnreachableWebDataURL),
- error.url(), replace, frame_load_type,
- history_item, std::move(navigation_data));
+ LoadNavigationErrorPageInternal(error_html, error.url(), replace, entry,
+ std::move(navigation_params),
+ std::move(navigation_data), &failed_request);
}
void RenderFrameImpl::LoadNavigationErrorPageForHttpStatusError(
@@ -2684,35 +2722,47 @@ void RenderFrameImpl::LoadNavigationErrorPageForHttpStatusError(
int http_status,
bool replace,
HistoryEntry* entry,
+ std::unique_ptr<blink::WebNavigationParams> navigation_params,
std::unique_ptr<blink::WebDocumentLoader::ExtraData> navigation_data) {
- blink::WebFrameLoadType frame_load_type =
- entry ? blink::WebFrameLoadType::kBackForward
- : blink::WebFrameLoadType::kStandard;
- const blink::WebHistoryItem& history_item =
- entry ? entry->root() : blink::WebHistoryItem();
-
std::string error_html;
GetContentClient()->renderer()->PrepareErrorPageForHttpStatusError(
this, failed_request, unreachable_url, http_status, &error_html, nullptr);
- std::unique_ptr<DocumentState> document_state(BuildDocumentState());
- LoadNavigationErrorPageInternal(error_html, GURL(kUnreachableWebDataURL),
- unreachable_url, replace, frame_load_type,
- history_item, std::move(document_state));
+ LoadNavigationErrorPageInternal(error_html, unreachable_url, replace, entry,
+ std::move(navigation_params),
+ std::move(navigation_data), &failed_request);
}
void RenderFrameImpl::LoadNavigationErrorPageInternal(
const std::string& error_html,
- const GURL& error_page_url,
const GURL& error_url,
bool replace,
- blink::WebFrameLoadType frame_load_type,
- const blink::WebHistoryItem& history_item,
- std::unique_ptr<blink::WebDocumentLoader::ExtraData> navigation_data) {
- frame_->CommitDataNavigation(error_html, WebString::FromUTF8("text/html"),
- WebString::FromUTF8("UTF-8"), error_page_url,
- error_url, replace, frame_load_type,
- history_item, false, std::move(navigation_data),
- blink::WebNavigationTimings());
+ HistoryEntry* history_entry,
+ std::unique_ptr<blink::WebNavigationParams> navigation_params,
+ std::unique_ptr<blink::WebDocumentLoader::ExtraData> navigation_data,
+ const WebURLRequest* failed_request) {
+ blink::WebFrameLoadType frame_load_type =
+ history_entry ? blink::WebFrameLoadType::kBackForward
+ : blink::WebFrameLoadType::kStandard;
+ const blink::WebHistoryItem& history_item =
+ history_entry ? history_entry->root() : blink::WebHistoryItem();
+
+ // Failed navigations will always provide a |failed_request|. Error induced
+ // by the client/renderer side after a commit won't have a |failed_request|.
+ bool is_client_redirect = !failed_request;
+
+ WebURLRequest new_request;
+ if (failed_request)
+ new_request = *failed_request;
+ new_request.SetURL(GURL(kUnreachableWebDataURL));
+
+ // Locally generated error pages should not be cached (in particular they
+ // should not inherit the cache mode from |failed_request|).
+ new_request.SetCacheMode(blink::mojom::FetchCacheMode::kNoStore);
+
+ frame_->CommitDataNavigationWithRequest(
+ new_request, error_html, "text/html", "UTF-8", error_url, replace,
+ frame_load_type, history_item, is_client_redirect,
+ std::move(navigation_params), std::move(navigation_data));
}
void RenderFrameImpl::DidMeaningfulLayout(
@@ -2835,11 +2885,10 @@ void RenderFrameImpl::LoadErrorPage(int reason) {
this, frame_->GetDocumentLoader()->GetRequest(), error, &error_html,
nullptr);
- frame_->CommitDataNavigation(
- error_html, WebString::FromUTF8("text/html"),
- WebString::FromUTF8("UTF-8"), GURL(kUnreachableWebDataURL), error.url(),
- true, blink::WebFrameLoadType::kStandard, blink::WebHistoryItem(), true,
- nullptr /* navigation_data */, blink::WebNavigationTimings());
+ LoadNavigationErrorPageInternal(
+ error_html, error.url(), true /* replace */, nullptr /* history_entry */,
+ nullptr /* navigation_params */, nullptr /* navigation_data */,
+ nullptr /* failed_request */);
}
void RenderFrameImpl::ExecuteJavaScript(const base::string16& javascript) {
@@ -2866,17 +2915,19 @@ RenderFrameImpl::GetRemoteAssociatedInterfaces() {
if (!remote_associated_interfaces_) {
ChildThreadImpl* thread = ChildThreadImpl::current();
if (thread) {
- mojom::AssociatedInterfaceProviderAssociatedPtr remote_interfaces;
+ blink::mojom::AssociatedInterfaceProviderAssociatedPtr remote_interfaces;
thread->GetRemoteRouteProvider()->GetRoute(
routing_id_, mojo::MakeRequest(&remote_interfaces));
- remote_associated_interfaces_.reset(new AssociatedInterfaceProviderImpl(
- std::move(remote_interfaces),
- GetTaskRunner(blink::TaskType::kInternalIPC)));
+ remote_associated_interfaces_ =
+ std::make_unique<blink::AssociatedInterfaceProvider>(
+ std::move(remote_interfaces),
+ GetTaskRunner(blink::TaskType::kInternalIPC));
} else {
// In some tests the thread may be null,
// so set up a self-contained interface provider instead.
- remote_associated_interfaces_.reset(new AssociatedInterfaceProviderImpl(
- GetTaskRunner(blink::TaskType::kInternalIPC)));
+ remote_associated_interfaces_ =
+ std::make_unique<blink::AssociatedInterfaceProvider>(
+ GetTaskRunner(blink::TaskType::kInternalIPC));
}
}
return remote_associated_interfaces_.get();
@@ -3040,6 +3091,18 @@ void RenderFrameImpl::GetCanonicalUrlForSharing(
: base::make_optional(GURL(canonical_url)));
}
+void RenderFrameImpl::BlockRequests() {
+ frame_request_blocker_->Block();
+}
+
+void RenderFrameImpl::ResumeBlockedRequests() {
+ frame_request_blocker_->Resume();
+}
+
+void RenderFrameImpl::CancelBlockedRequests() {
+ frame_request_blocker_->Cancel();
+}
+
void RenderFrameImpl::AllowBindings(int32_t enabled_bindings_flags) {
if (IsMainFrame() && (enabled_bindings_flags & BINDINGS_POLICY_WEB_UI) &&
!(enabled_bindings_ & BINDINGS_POLICY_WEB_UI)) {
@@ -3082,8 +3145,14 @@ void RenderFrameImpl::CommitNavigation(
return;
}
- controller_service_worker_info_ = std::move(controller_service_worker_info);
+ if (prefetch_shared_loader_factory_)
+ prefetch_shared_loader_factory_->Detach();
prefetch_loader_factory_ = std::move(prefetch_loader_factory);
+ if (prefetch_loader_factory_) {
+ prefetch_shared_loader_factory_ =
+ base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
+ prefetch_loader_factory_.get());
+ }
// If the request was initiated in the context of a user gesture then make
// sure that the navigation also executes in the context of a user gesture.
@@ -3113,8 +3182,16 @@ void RenderFrameImpl::CommitNavigation(
new PendingNavigationParams(common_params, request_params,
base::TimeTicks::Now(), std::move(callback)));
PrepareFrameForCommit(common_params.url, request_params);
- std::unique_ptr<DocumentState> document_state(
- BuildDocumentStateFromPending(pending_navigation_params_.get()));
+
+ // We only save metrics of the main frame's main resource to the
+ // document state. In view source mode, we effectively let the user
+ // see the source of the server's error page instead of using custom
+ // one derived from the metrics saved to document state.
+ const network::ResourceResponseHead* response_head = nullptr;
+ if (!frame_->Parent() && !frame_->IsViewSourceModeEnabled())
+ response_head = &head;
+ std::unique_ptr<DocumentState> document_state(BuildDocumentStateFromPending(
+ pending_navigation_params_.get(), response_head));
blink::WebFrameLoadType load_type = NavigationTypeToLoadType(
common_params.navigation_type, common_params.should_replace_current_entry,
@@ -3158,9 +3235,12 @@ void RenderFrameImpl::CommitNavigation(
head);
frame_->CommitNavigation(
request, load_type, item_for_history_navigation, is_client_redirect,
- devtools_navigation_token, std::move(document_state),
- BuildNavigationTimings(common_params.navigation_start,
- request_params.navigation_timing));
+ devtools_navigation_token,
+ BuildNavigationParams(
+ common_params, request_params,
+ BuildServiceWorkerNetworkProviderForNavigation(
+ &request_params, std::move(controller_service_worker_info))),
+ std::move(document_state));
// The commit can result in this frame being removed. Use a
// WeakPtr as an easy way to detect whether this has occured. If so, this
// method should return immediately and not touch any part of the object,
@@ -3194,8 +3274,10 @@ void RenderFrameImpl::CommitNavigation(
// NavigationResponseOverrideParameters. The architecture of committing the
// navigation in the renderer process should be simplified and avoid going
// through the ResourceFetcher for the main resource.
- if (continue_navigation)
+ if (continue_navigation) {
+ base::AutoReset<bool> replaying(&replaying_main_response_, true);
std::move(continue_navigation).Run();
+ }
}
void RenderFrameImpl::CommitFailedNavigation(
@@ -3208,8 +3290,6 @@ void RenderFrameImpl::CommitFailedNavigation(
CommitFailedNavigationCallback callback) {
DCHECK(
!FrameMsg_Navigate_Type::IsSameDocument(common_params.navigation_type));
- bool is_reload =
- FrameMsg_Navigate_Type::IsReload(common_params.navigation_type);
RenderFrameImpl::PrepareRenderViewForNavigation(common_params.url,
request_params);
@@ -3285,7 +3365,10 @@ void RenderFrameImpl::CommitFailedNavigation(
// specifically.
// TODO(clamy): see if initial commits in subframes should be handled
// separately.
- bool replace = is_reload || common_params.url == GetLoadingUrl() ||
+ bool is_reload_or_history =
+ FrameMsg_Navigate_Type::IsReload(common_params.navigation_type) ||
+ FrameMsg_Navigate_Type::IsHistory(common_params.navigation_type);
+ bool replace = is_reload_or_history || common_params.url == GetLoadingUrl() ||
common_params.should_replace_current_entry;
std::unique_ptr<HistoryEntry> history_entry;
if (request_params.page_state.IsValid())
@@ -3316,14 +3399,19 @@ void RenderFrameImpl::CommitFailedNavigation(
return;
}
- // If we didn't call didFailProvisionalLoad or there wasn't a
+ // If we didn't call DidFailProvisionalLoad or there wasn't a
// GetProvisionalDocumentLoader(), LoadNavigationErrorPage wasn't called, so
// do it now.
if (request_params.nav_entry_id != 0 || !had_provisional_document_loader) {
- std::unique_ptr<DocumentState> document_state(
- BuildDocumentStateFromPending(pending_navigation_params_.get()));
+ std::unique_ptr<blink::WebNavigationParams> navigation_params =
+ BuildNavigationParams(common_params, request_params,
+ BuildServiceWorkerNetworkProviderForNavigation(
+ &request_params, nullptr));
+ std::unique_ptr<DocumentState> document_state(BuildDocumentStateFromPending(
+ pending_navigation_params_.get(), nullptr));
LoadNavigationErrorPage(failed_request, error, replace, history_entry.get(),
- error_page_content, std::move(document_state));
+ error_page_content, std::move(navigation_params),
+ std::move(document_state));
if (!weak_this)
return;
}
@@ -3450,6 +3538,30 @@ void RenderFrameImpl::SetHostZoomLevel(const GURL& url, double zoom_level) {
// blink::WebLocalFrameClient implementation
// ----------------------------------------
+bool RenderFrameImpl::IsPluginHandledExternally(
+ const blink::WebElement& plugin_element,
+ const blink::WebURL& url,
+ const blink::WebString& suggested_mime_type) {
+#if BUILDFLAG(ENABLE_PLUGINS)
+ if (!BrowserPluginManager::Get()) {
+ // BrowserPluginManager needs a RenderThreadImpl, but some renderer tests
+ // use a MockRenderThread instead.
+ return false;
+ }
+ // TODO(ekaramad): The instance ID is mostly used for GuestView attaching and
+ // lookup. See if this can be removed (https://crbug.com/659750).
+ // The instance ID will not be consumed if the contents cannot be rendered
+ // externally.
+ int32_t tentative_element_instance_id =
+ BrowserPluginManager::Get()->GetNextInstanceID();
+ return GetContentClient()->renderer()->IsPluginHandledByMimeHandlerView(
+ this, plugin_element, GURL(url), suggested_mime_type.Utf8(),
+ tentative_element_instance_id);
+#else
+ return false;
+#endif
+}
+
blink::WebPlugin* RenderFrameImpl::CreatePlugin(
const blink::WebPluginParams& params) {
blink::WebPlugin* plugin = nullptr;
@@ -3561,8 +3673,13 @@ RenderFrameImpl::CreateWorkerFetchContext() {
container_host_ptr_info = provider_context->CloneContainerHostPtrInfo();
}
+ mojom::RendererPreferenceWatcherPtr watcher;
+ mojom::RendererPreferenceWatcherRequest watcher_request =
+ mojo::MakeRequest(&watcher);
+ render_view()->RegisterRendererPreferenceWatcherForWorker(std::move(watcher));
+
auto worker_fetch_context = std::make_unique<WebWorkerFetchContextImpl>(
- render_view_->renderer_preferences(),
+ render_view_->renderer_preferences(), std::move(watcher_request),
std::move(service_worker_client_request),
std::move(service_worker_worker_client_registry_ptr_info),
std::move(container_host_ptr_info), GetLoaderFactoryBundle()->Clone(),
@@ -3576,6 +3693,7 @@ RenderFrameImpl::CreateWorkerFetchContext() {
ChildThreadImpl::current()->GetConnector()->Clone());
worker_fetch_context->set_ancestor_frame_id(routing_id_);
+ worker_fetch_context->set_frame_request_blocker(frame_request_blocker_);
worker_fetch_context->set_site_for_cookies(
frame_->GetDocument().SiteForCookies());
worker_fetch_context->set_is_secure_context(
@@ -4029,55 +4147,17 @@ void RenderFrameImpl::WillSubmitForm(const blink::WebFormElement& form) {
void RenderFrameImpl::DidCreateDocumentLoader(
blink::WebDocumentLoader* document_loader) {
- // Ensure that the pending_navigation_params are destroyed when doing an
- // early return.
- std::unique_ptr<PendingNavigationParams> pending_navigation_params(
- std::move(pending_navigation_params_));
- bool has_pending_params = pending_navigation_params.get();
-
+ pending_navigation_params_.reset();
DocumentState* document_state =
DocumentState::FromDocumentLoader(document_loader);
if (!document_state) {
// This is either a placeholder document loader or an initial empty
// document.
document_loader->SetExtraData(BuildDocumentState());
+ document_loader->SetServiceWorkerNetworkProvider(
+ BuildServiceWorkerNetworkProviderForNavigation(
+ nullptr /* request_params */, nullptr /* controller_info */));
}
-
- // Create the serviceworker's per-document network observing object.
- // Same document navigation do not go through here so it should never exist.
- DCHECK(!document_loader->GetServiceWorkerNetworkProvider());
- scoped_refptr<network::SharedURLLoaderFactory> fallback_factory =
- network::SharedURLLoaderFactory::Create(
- GetLoaderFactoryBundle()->CloneWithoutDefaultFactory());
- document_loader->SetServiceWorkerNetworkProvider(
- ServiceWorkerNetworkProvider::CreateForNavigation(
- routing_id_,
- has_pending_params ? &(pending_navigation_params->request_params)
- : nullptr,
- frame_, std::move(controller_service_worker_info_),
- std::move(fallback_factory)));
-
- if (!has_pending_params)
- return;
-
- const CommonNavigationParams& common_params =
- pending_navigation_params->common_params;
- const RequestNavigationParams& request_params =
- pending_navigation_params->request_params;
-
- // Update the source location before processing the navigation commit.
- if (pending_navigation_params->common_params.source_location.has_value()) {
- blink::WebSourceLocation source_location;
- source_location.url =
- WebString::FromLatin1(common_params.source_location->url);
- source_location.line_number = common_params.source_location->line_number;
- source_location.column_number =
- common_params.source_location->column_number;
- document_loader->SetSourceLocation(source_location);
- }
-
- if (request_params.was_activated)
- document_loader->SetUserActivated();
}
void RenderFrameImpl::DidStartProvisionalLoad(
@@ -4110,6 +4190,7 @@ void RenderFrameImpl::DidStartProvisionalLoad(
pending_navigation_info_->devtools_initiator_info;
info.blob_url_token =
pending_navigation_info_->blob_url_token.PassInterface().PassHandle();
+ info.input_start = pending_navigation_info_->input_start;
pending_navigation_info_.reset(nullptr);
BeginNavigation(info);
@@ -4214,12 +4295,15 @@ void RenderFrameImpl::DidCommitProvisionalLoad(
// main frame documents. Subframes inherit from the main frame and should not
// change at commit time.
if (is_main_frame_) {
- previews_state_ = PREVIEWS_OFF;
+ previews_state_ =
+ frame_->GetDocumentLoader()->GetRequest().GetPreviewsState();
if (extra_data) {
- previews_state_ = extra_data->previews_state();
effective_connection_type_ =
EffectiveConnectionTypeToWebEffectiveConnectionType(
extra_data->effective_connection_type());
+ } else {
+ effective_connection_type_ =
+ blink::WebEffectiveConnectionType::kTypeUnknown;
}
}
@@ -4468,9 +4552,15 @@ void RenderFrameImpl::RunScriptsAtDocumentReady(bool document_is_empty) {
if (GetContentClient()->renderer()->HasErrorPage(http_status_code)) {
// This call may run scripts, e.g. via the beforeunload event.
std::unique_ptr<DocumentState> document_state(BuildDocumentState());
+ std::unique_ptr<blink::WebNavigationParams> navigation_params =
+ std::make_unique<blink::WebNavigationParams>();
+ navigation_params->service_worker_network_provider =
+ BuildServiceWorkerNetworkProviderForNavigation(
+ nullptr /* request_params */, nullptr /* controller_info */);
LoadNavigationErrorPageForHttpStatusError(
frame_->GetDocumentLoader()->GetRequest(), frame_->GetDocument().Url(),
- http_status_code, true, nullptr, std::move(document_state));
+ http_status_code, true /* replace */, nullptr /* entry */,
+ std::move(navigation_params), std::move(document_state));
}
// Do not use |this| or |frame_| here without checking |weak_self|.
}
@@ -4708,8 +4798,19 @@ bool RenderFrameImpl::RunFileChooser(
ipc_params.capture = params.use_media_capture;
#endif
ipc_params.requestor = params.requestor;
+ return RunFileChooser(ipc_params, chooser_completion);
+}
- return ScheduleFileChooser(ipc_params, chooser_completion);
+bool RenderFrameImpl::RunFileChooser(
+ const FileChooserParams& params,
+ blink::WebFileChooserCompletion* chooser_completion) {
+ // Do not open the file dialog in a hidden RenderFrame.
+ if (IsHidden())
+ return false;
+ DCHECK(!file_chooser_completion_);
+ file_chooser_completion_ = chooser_completion;
+ Send(new FrameHostMsg_RunFileChooser(routing_id_, params));
+ return true;
}
void RenderFrameImpl::ShowContextMenu(const blink::WebContextMenuData& data) {
@@ -4773,6 +4874,14 @@ void RenderFrameImpl::FrameRectsChanged(const blink::WebRect& frame_rect) {
}
void RenderFrameImpl::WillSendRequest(blink::WebURLRequest& request) {
+ if (request.GetFrameType() !=
+ network::mojom::RequestContextFrameType::kNone &&
+ pending_navigation_params_) {
+ // Skip the processing for the main resource, it has been done before
+ // sending the request to the browser.
+ return;
+ }
+
if (render_view_->renderer_preferences_.enable_do_not_track)
request.SetHTTPHeaderField(blink::WebString::FromUTF8(kDoNotTrackHeader),
"1");
@@ -4872,21 +4981,7 @@ void RenderFrameImpl::WillSendRequest(blink::WebURLRequest& request) {
is_for_no_state_prefetch && resource_type != RESOURCE_TYPE_MAIN_FRAME);
extra_data->set_initiated_in_secure_context(frame_document.IsSecureContext());
extra_data->set_attach_same_site_cookies(attach_same_site_cookies);
-
- // Renderer process transfers apply only to navigational requests.
- bool is_navigational_request =
- request.GetFrameType() != network::mojom::RequestContextFrameType::kNone;
- if (is_navigational_request) {
- // For navigation requests, we should copy the flag which indicates if this
- // was a navigation initiated by the renderer to the new RequestExtraData
- // instance.
- RequestExtraData* current_request_data =
- static_cast<RequestExtraData*>(request.GetExtraData());
- if (current_request_data) {
- extra_data->set_navigation_initiated_by_renderer(
- current_request_data->navigation_initiated_by_renderer());
- }
- }
+ extra_data->set_frame_request_blocker(frame_request_blocker_);
// The RenderThreadImpl or its URLLoaderThrottleProvider member may not be
// valid in some tests.
@@ -4930,6 +5025,12 @@ void RenderFrameImpl::WillSendRequest(blink::WebURLRequest& request) {
void RenderFrameImpl::DidReceiveResponse(
const blink::WebURLResponse& response) {
+ // For main resource, this is done in CommitNavigation instead.
+ // TODO(dgozman): get rid of this method once we always go through
+ // CommitNavigation, even for urls like about:blank.
+ if (replaying_main_response_)
+ return;
+
// Only do this for responses that correspond to a provisional data source
// of the top-most frame. If we have a provisional data source, then we
// can't have any sub-resources yet, so we know that this response must
@@ -5163,24 +5264,6 @@ void RenderFrameImpl::DidChangeScrollOffset() {
observer.DidChangeScrollOffset();
}
-void RenderFrameImpl::ReportFindInPageMatchCount(int request_id,
- int count,
- bool final_update) {
- // -1 here means don't update the active match ordinal.
- int active_match_ordinal = count ? -1 : 0;
-
- SendFindReply(request_id, count, active_match_ordinal, gfx::Rect(),
- final_update);
-}
-
-void RenderFrameImpl::ReportFindInPageSelection(
- int request_id,
- int active_match_ordinal,
- const blink::WebRect& selection_rect) {
- SendFindReply(request_id, -1 /* match_count */, active_match_ordinal,
- selection_rect, false /* final_status_update */);
-}
-
blink::WebPushClient* RenderFrameImpl::PushClient() {
if (!push_messaging_client_)
push_messaging_client_ = new PushMessagingClient(this);
@@ -5580,6 +5663,10 @@ RenderFrameImpl::MakeDidCommitProvisionalLoadParams(
}
}
+ WebURLResponseExtraDataImpl* extra_data = GetExtraDataFromResponse(response);
+ if (extra_data)
+ params->request_id = extra_data->request_id();
+
return params;
}
@@ -5943,37 +6030,14 @@ void RenderFrameImpl::OnReportContentSecurityPolicyViolation(
WebNavigationPolicy RenderFrameImpl::DecidePolicyForNavigation(
const NavigationPolicyInfo& info) {
- // A content initiated navigation may have originated from a link-click,
- // script, drag-n-drop operation, etc.
- // info.extraData is only non-null if this is a redirect. Use the extraData
- // initiation information for redirects, and check pending_navigation_params_
- // otherwise.
- bool is_content_initiated =
- info.extra_data ? static_cast<DocumentState*>(info.extra_data)
- ->navigation_state()
- ->IsContentInitiated()
- : !IsBrowserInitiated(pending_navigation_params_.get());
- // TODO(dgozman): clean this up after some Canary coverage.
- CHECK(!pending_navigation_params_);
- if (info.extra_data) {
- CHECK(static_cast<DocumentState*>(info.extra_data)
- ->navigation_state()
- ->IsContentInitiated());
- }
-
- // Webkit is asking whether to navigate to a new URL.
+ // This method is only called for renderer initiated navigations, which
+ // may have originated from a link-click, script, drag-n-drop operation, etc.
+
+ // Blink is asking whether to navigate to a new URL.
// This is fine normally, except if we're showing UI from one security
// context and they're trying to navigate to a different context.
const GURL& url = info.url_request.Url();
- // The redirect list is available for the first url. We maintain the old
- // behavior of not classifying the first URL in the chain as a redirect.
- bool is_redirect =
- info.extra_data ||
- (pending_navigation_params_ &&
- !pending_navigation_params_->request_params.redirects.empty() &&
- url != pending_navigation_params_->request_params.redirects[0]);
-
#ifdef OS_ANDROID
bool render_view_was_created_by_renderer =
render_view_->was_created_by_renderer_;
@@ -5981,19 +6045,18 @@ WebNavigationPolicy RenderFrameImpl::DecidePolicyForNavigation(
// crbug.com/325351 is resolved.
if (!IsURLHandledByNetworkStack(url) &&
GetContentClient()->renderer()->HandleNavigation(
- this, is_content_initiated, render_view_was_created_by_renderer,
- frame_, info.url_request, info.navigation_type, info.default_policy,
- is_redirect)) {
+ this, true /* is_content_initiated */,
+ render_view_was_created_by_renderer, frame_, info.url_request,
+ info.navigation_type, info.default_policy, false /* is_redirect */)) {
return blink::kWebNavigationPolicyIgnore;
}
#endif
// If the browser is interested, then give it a chance to look at the request.
- if (is_content_initiated && IsTopLevelNavigation(frame_) &&
+ if (IsTopLevelNavigation(frame_) &&
render_view_->renderer_preferences_
.browser_handles_all_top_level_requests) {
- OpenURL(info, /*send_referrer=*/true,
- /*is_history_navigation_in_new_child=*/false);
+ OpenURL(info, /*is_history_navigation_in_new_child=*/false);
return blink::kWebNavigationPolicyIgnore; // Suppress the load here.
}
@@ -6003,8 +6066,7 @@ WebNavigationPolicy RenderFrameImpl::DecidePolicyForNavigation(
// that have history items, or if it's staying at the initial about:blank URL,
// fall back to loading the default url. (We remove each name as we encounter
// it, because it will only be used once as the frame is created.)
- if (info.is_history_navigation_in_new_child_frame && is_content_initiated &&
- frame_->Parent()) {
+ if (info.is_history_navigation_in_new_child_frame && frame_->Parent()) {
// 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;
@@ -6023,8 +6085,7 @@ WebNavigationPolicy RenderFrameImpl::DecidePolicyForNavigation(
// case JavaScript on the page is trying to interrupt the history
// navigation.
if (!info.is_client_redirect) {
- OpenURL(info, /*send_referrer=*/true,
- /*is_history_navigation_in_new_child=*/true);
+ OpenURL(info, /*is_history_navigation_in_new_child=*/true);
// Suppress the load in Blink but mark the frame as loading.
return blink::kWebNavigationPolicyHandledByClientForInitialHistory;
} else {
@@ -6069,18 +6130,14 @@ WebNavigationPolicy RenderFrameImpl::DecidePolicyForNavigation(
frame_->Opener() == nullptr &&
// Must be a top-level frame.
frame_->Parent() == nullptr &&
- // Must not have issued the request from this page.
- is_content_initiated &&
// Must be targeted at the current tab.
info.default_policy == blink::kWebNavigationPolicyCurrentTab &&
// Must be a JavaScript navigation, which appears as "other".
info.navigation_type == blink::kWebNavigationTypeOther;
if (is_fork) {
- // Open the URL via the browser, not via WebKit. Make sure the referrer is
- // stripped.
- OpenURL(info, /*send_referrer=*/false,
- /*is_history_navigation_in_new_child=*/false);
+ // Open the URL via the browser, not via WebKit.
+ OpenURL(info, /*is_history_navigation_in_new_child=*/false);
return blink::kWebNavigationPolicyIgnore;
}
@@ -6088,10 +6145,7 @@ WebNavigationPolicy RenderFrameImpl::DecidePolicyForNavigation(
// an extension or app origin, leaving a WebUI page, etc). We only care about
// top-level navigations (not iframes). But we sometimes navigate to
// about:blank to clear a tab, and we want to still allow that.
- if (!frame_->Parent() && is_content_initiated &&
- !url.SchemeIs(url::kAboutScheme)) {
- bool send_referrer = false;
-
+ if (!frame_->Parent() && !url.SchemeIs(url::kAboutScheme)) {
// All navigations to or from WebUI URLs or within WebUI-enabled
// RenderProcesses must be handled by the browser process so that the
// correct bindings and data sources can be registered.
@@ -6120,23 +6174,17 @@ WebNavigationPolicy RenderFrameImpl::DecidePolicyForNavigation(
// Give the embedder a chance.
should_fork = GetContentClient()->renderer()->ShouldFork(
frame_, url, info.url_request.HttpMethod().Utf8(),
- is_initial_navigation, is_redirect, &send_referrer);
+ is_initial_navigation, false /* is_redirect */);
}
if (should_fork) {
- OpenURL(info, send_referrer,
- /*is_history_navigation_in_new_child=*/false);
+ OpenURL(info, /*is_history_navigation_in_new_child=*/false);
return blink::kWebNavigationPolicyIgnore; // Suppress the load here.
}
}
bool should_dispatch_before_unload =
info.default_policy == blink::kWebNavigationPolicyCurrentTab &&
- // There is no need to execute the BeforeUnload event during a redirect,
- // since it was already executed at the start of the navigation.
- !is_redirect &&
- // This should not be executed when commiting the navigation.
- info.url_request.CheckForBrowserSideNavigation() &&
// No need to dispatch beforeunload if the frame has not committed a
// navigation and contains an empty initial document.
(has_accessed_initial_document_ || !current_history_item_.IsNull());
@@ -6171,8 +6219,7 @@ WebNavigationPolicy RenderFrameImpl::DecidePolicyForNavigation(
if (info.default_policy == blink::kWebNavigationPolicyCurrentTab) {
// If the navigation is not synchronous, send it to the browser. This
// includes navigations with no request being sent to the network stack.
- if (!use_archive && info.url_request.CheckForBrowserSideNavigation() &&
- IsURLHandledByNetworkStack(url)) {
+ if (!use_archive && IsURLHandledByNetworkStack(url)) {
pending_navigation_info_.reset(new PendingNavigationInfo(info));
return blink::kWebNavigationPolicyHandledByClient;
} else {
@@ -6187,8 +6234,7 @@ WebNavigationPolicy RenderFrameImpl::DecidePolicyForNavigation(
blink::WebLocalFrameClient::CrossOriginRedirects::kFollow,
blob_url_token.PassHandle());
} else {
- OpenURL(info, /*send_referrer=*/true,
- /*is_history_navigation_in_new_child=*/false);
+ OpenURL(info, /*is_history_navigation_in_new_child=*/false);
}
return blink::kWebNavigationPolicyIgnore;
}
@@ -6314,30 +6360,6 @@ void RenderFrameImpl::OnWriteMHTMLToDiskComplete(
main_thread_use_time));
}
-void RenderFrameImpl::OnFind(int request_id,
- const base::string16& search_text,
- const WebFindOptions& options) {
- DCHECK(!search_text.empty());
-
- blink::WebPlugin* plugin = GetWebPluginForFind();
- // Check if the plugin still exists in the document.
- if (plugin) {
- if (options.find_next) {
- // Just navigate back/forward.
- plugin->SelectFindResult(options.forward, request_id);
- render_view_->webview()->SetFocusedFrame(frame_);
- } else if (!plugin->StartFind(WebString::FromUTF16(search_text),
- options.match_case, request_id)) {
- // Send "no results".
- SendFindReply(request_id, 0 /* match_count */, 0 /* ordinal */,
- gfx::Rect(), true /* final_status_update */);
- }
- return;
- }
-
- frame_->RequestFind(request_id, WebString::FromUTF16(search_text), options);
-}
-
#define STATIC_ASSERT_ENUM(a, b) \
static_assert(static_cast<int>(a) == static_cast<int>(b), \
"mismatching enums: " #a)
@@ -6357,7 +6379,7 @@ void RenderFrameImpl::OnFileChooserResponse(
const std::vector<content::FileChooserFileInfo>& files) {
// This could happen if we navigated to a different page before the user
// closed the chooser.
- if (file_chooser_completions_.empty())
+ if (!file_chooser_completion_)
return;
// Convert Chrome's SelectedFileInfo list to WebKit's.
@@ -6394,17 +6416,9 @@ void RenderFrameImpl::OnFileChooserResponse(
selected_files.Swap(truncated_list);
}
- if (file_chooser_completions_.front()->completion) {
- file_chooser_completions_.front()->completion->DidChooseFile(
- selected_files);
- }
- file_chooser_completions_.pop_front();
-
- // If there are more pending file chooser requests, schedule one now.
- if (!file_chooser_completions_.empty()) {
- Send(new FrameHostMsg_RunFileChooser(
- routing_id_, file_chooser_completions_.front()->params));
- }
+ blink::WebFileChooserCompletion* completion = file_chooser_completion_;
+ file_chooser_completion_ = nullptr;
+ completion->DidChooseFile(selected_files);
}
void RenderFrameImpl::OnClearFocusedElement() {
@@ -6495,7 +6509,6 @@ void RenderFrameImpl::OnSelectPopupMenuItems(
#endif
void RenderFrameImpl::OpenURL(const NavigationPolicyInfo& info,
- bool send_referrer,
bool is_history_navigation_in_new_child) {
WebNavigationPolicy policy = info.default_policy;
FrameHostMsg_OpenURL_Params params;
@@ -6504,9 +6517,8 @@ void RenderFrameImpl::OpenURL(const NavigationPolicyInfo& info,
params.resource_request_body =
GetRequestBodyForWebURLRequest(info.url_request);
params.extra_headers = GetWebURLRequestHeadersAsString(info.url_request);
- params.referrer = send_referrer ? RenderViewImpl::GetReferrerFromRequest(
- frame_, info.url_request)
- : content::Referrer();
+ params.referrer =
+ RenderViewImpl::GetReferrerFromRequest(frame_, info.url_request);
params.disposition = RenderViewImpl::NavigationPolicyToDisposition(policy);
params.triggering_event_info = info.triggering_event_info;
params.blob_url_token =
@@ -6564,23 +6576,10 @@ WebURLRequest RenderFrameImpl::CreateURLRequestForCommit(
? network::mojom::RequestContextFrameType::kTopLevel
: network::mojom::RequestContextFrameType::kNested);
- if (common_params.post_data) {
- request.SetHTTPBody(GetWebHTTPBodyForRequestBody(*common_params.post_data));
- if (!request_params.post_content_type.empty()) {
- request.AddHTTPHeaderField(
- WebString::FromASCII(net::HttpRequestHeaders::kContentType),
- WebString::FromASCII(request_params.post_content_type));
- }
- }
-
#if defined(OS_ANDROID)
request.SetHasUserGesture(common_params.has_user_gesture);
#endif
- // Make sure that Blink's loader will not try to use browser side navigation
- // for this request (since it already went to the browser).
- request.SetCheckForBrowserSideNavigation(false);
-
request.SetNavigationStartTime(common_params.navigation_start);
return request;
@@ -6882,14 +6881,14 @@ void RenderFrameImpl::BeginNavigation(const NavigationPolicyInfo& info) {
BindNavigationClient(mojo::MakeRequest(&navigation_client_info));
navigation_state->set_navigation_client(std::move(navigation_client_impl_));
}
- GetFrameHost()->BeginNavigation(MakeCommonNavigationParams(info, load_flags),
- std::move(begin_navigation_params),
- std::move(blob_url_token),
- std::move(navigation_client_info));
+ GetFrameHost()->BeginNavigation(
+ MakeCommonNavigationParams(info, load_flags, info.input_start),
+ std::move(begin_navigation_params), std::move(blob_url_token),
+ std::move(navigation_client_info));
}
void RenderFrameImpl::LoadDataURL(
- const CommonNavigationParams& params,
+ const CommonNavigationParams& common_params,
const RequestNavigationParams& request_params,
WebLocalFrame* frame,
blink::WebFrameLoadType load_type,
@@ -6897,7 +6896,7 @@ void RenderFrameImpl::LoadDataURL(
bool is_client_redirect,
std::unique_ptr<blink::WebDocumentLoader::ExtraData> navigation_data) {
// A loadData request with a specified base URL.
- GURL data_url = params.url;
+ GURL data_url = common_params.url;
#if defined(OS_ANDROID)
if (!request_params.data_url_as_string.empty()) {
#if DCHECK_IS_ON()
@@ -6909,14 +6908,15 @@ void RenderFrameImpl::LoadDataURL(
#endif
data_url = GURL(request_params.data_url_as_string);
if (!data_url.is_valid() || !data_url.SchemeIs(url::kDataScheme)) {
- data_url = params.url;
+ data_url = common_params.url;
}
}
#endif
std::string mime_type, charset, data;
if (net::DataURL::Parse(data_url, &mime_type, &charset, &data)) {
- const GURL base_url = params.base_url_for_data_url.is_empty() ?
- params.url : params.base_url_for_data_url;
+ const GURL base_url = common_params.base_url_for_data_url.is_empty()
+ ? common_params.url
+ : common_params.base_url_for_data_url;
bool replace = load_type == WebFrameLoadType::kReloadBypassingCache ||
load_type == WebFrameLoadType::kReload;
@@ -6924,14 +6924,16 @@ void RenderFrameImpl::LoadDataURL(
WebData(data.c_str(), data.length()), WebString::FromUTF8(mime_type),
WebString::FromUTF8(charset), base_url,
// Needed so that history-url-only changes don't become reloads.
- params.history_url_for_data_url, replace, load_type,
+ common_params.history_url_for_data_url, replace, load_type,
item_for_history_navigation, is_client_redirect,
- std::move(navigation_data),
- BuildNavigationTimings(params.navigation_start,
- request_params.navigation_timing));
+ BuildNavigationParams(
+ common_params, request_params,
+ BuildServiceWorkerNetworkProviderForNavigation(
+ &request_params, nullptr /* controller_service_worker_info */)),
+ std::move(navigation_data));
} else {
CHECK(false) << "Invalid URL passed: "
- << params.url.possibly_invalid_spec();
+ << common_params.url.possibly_invalid_spec();
}
}
@@ -7125,7 +7127,8 @@ void RenderFrameImpl::CheckIfAudioSinkExistsAndIsAuthorized(
media::OutputDeviceStatusCB callback =
media::ConvertToOutputDeviceStatusCB(web_callbacks);
std::move(callback).Run(
- AudioDeviceFactory::GetOutputDeviceInfo(GetRoutingID(), 0, sink_id.Utf8())
+ AudioDeviceFactory::GetOutputDeviceInfo(
+ GetRoutingID(), media::AudioSinkParameters(0, sink_id.Utf8()))
.device_status());
}
@@ -7204,28 +7207,6 @@ RenderFrameImpl::GetURLLoaderFactory() {
return GetLoaderFactoryBundle();
}
-blink::WebPlugin* RenderFrameImpl::GetWebPluginForFind() {
- return frame_->GetWebPluginForFind();
-}
-
-void RenderFrameImpl::SendFindReply(int request_id,
- int match_count,
- int ordinal,
- const WebRect& selection_rect,
- bool final_status_update) {
- DCHECK_GE(ordinal, -1);
- WebRect converted_rect = selection_rect;
-
- GetRenderWidget()->ConvertViewportToWindow(&converted_rect);
-
- Send(new FrameHostMsg_Find_Reply(routing_id_,
- request_id,
- match_count,
- converted_rect,
- ordinal,
- final_status_update));
-}
-
#if BUILDFLAG(ENABLE_PLUGINS)
void RenderFrameImpl::PepperInstanceCreated(
PepperPluginInstanceImpl* instance) {
@@ -7355,7 +7336,8 @@ RenderFrameImpl::PendingNavigationInfo::PendingNavigationInfo(
form(info.form),
source_location(info.source_location),
devtools_initiator_info(info.devtools_initiator_info),
- blob_url_token(CloneBlobURLToken(info.blob_url_token.get())) {}
+ blob_url_token(CloneBlobURLToken(info.blob_url_token.get())),
+ input_start(info.input_start) {}
RenderFrameImpl::PendingNavigationInfo::~PendingNavigationInfo() = default;
@@ -7412,4 +7394,16 @@ bool RenderFrameImpl::ShouldThrottleDownload() {
return false;
}
+std::unique_ptr<blink::WebServiceWorkerNetworkProvider>
+RenderFrameImpl::BuildServiceWorkerNetworkProviderForNavigation(
+ const RequestNavigationParams* request_params,
+ mojom::ControllerServiceWorkerInfoPtr controller_service_worker_info) {
+ scoped_refptr<network::SharedURLLoaderFactory> fallback_factory =
+ network::SharedURLLoaderFactory::Create(
+ GetLoaderFactoryBundle()->CloneWithoutDefaultFactory());
+ return ServiceWorkerNetworkProvider::CreateForNavigation(
+ routing_id_, request_params, frame_,
+ std::move(controller_service_worker_info), std::move(fallback_factory));
+}
+
} // namespace content
diff --git a/chromium/content/renderer/render_frame_impl.h b/chromium/content/renderer/render_frame_impl.h
index cb5ffc56b00..4f8775b0d90 100644
--- a/chromium/content/renderer/render_frame_impl.h
+++ b/chromium/content/renderer/render_frame_impl.h
@@ -29,7 +29,6 @@
#include "base/single_thread_task_runner.h"
#include "base/unguessable_token.h"
#include "build/build_config.h"
-#include "content/common/associated_interface_registry_impl.h"
#include "content/common/buildflags.h"
#include "content/common/download/mhtml_save_status.h"
#include "content/common/frame.mojom.h"
@@ -71,6 +70,8 @@
#include "services/service_manager/public/cpp/interface_provider.h"
#include "services/service_manager/public/mojom/connector.mojom.h"
#include "services/service_manager/public/mojom/interface_provider.mojom.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
#include "third_party/blink/public/common/feature_policy/feature_policy.h"
#include "third_party/blink/public/mojom/manifest/manifest_manager.mojom.h"
#include "third_party/blink/public/mojom/page/page_visibility_state.mojom.h"
@@ -113,15 +114,18 @@ struct FrameMsg_TextTrackSettings_Params;
namespace blink {
class WebComputedAXTree;
class WebContentDecryptionModule;
+class WebElement;
class WebLayerTreeView;
class WebLocalFrame;
class WebPushClient;
class WebRelatedAppsFetcher;
class WebSecurityOrigin;
+class WebString;
+class WebURL;
struct FramePolicy;
struct WebContextMenuData;
struct WebCursorInfo;
-struct WebFindOptions;
+struct WebNavigationParams;
struct WebMediaPlayerAction;
struct WebImeTextSpan;
struct WebScrollIntoViewParams;
@@ -137,6 +141,7 @@ class MediaPermission;
}
namespace network {
+class WeakWrapperSharedURLLoaderFactory;
struct ResourceResponseHead;
}
@@ -150,10 +155,10 @@ class Origin;
namespace content {
-class AssociatedInterfaceProviderImpl;
class BlinkInterfaceRegistryImpl;
class CompositorDependencies;
class ExternalPopupMenu;
+class FrameRequestBlocker;
class HistoryEntry;
class ManifestManager;
class MediaPermissionDispatcher;
@@ -248,8 +253,7 @@ class CONTENT_EXPORT RenderFrameImpl
// Just like RenderFrame::FromWebFrame but returns the implementation.
static RenderFrameImpl* FromWebFrame(blink::WebFrame* web_frame);
- // Used by content_layouttest_support to hook into the creation of
- // RenderFrameImpls.
+ // Constructor parameters are bundled into a struct.
struct CONTENT_EXPORT CreateParams {
CreateParams(
RenderViewImpl* render_view,
@@ -509,6 +513,9 @@ class CONTENT_EXPORT RenderFrameImpl
service_manager::mojom::InterfaceProviderRequest request) override;
void GetCanonicalUrlForSharing(
GetCanonicalUrlForSharingCallback callback) override;
+ void BlockRequests() override;
+ void ResumeBlockedRequests() override;
+ void CancelBlockedRequests() override;
#if defined(OS_ANDROID)
void ExtractSmartClipData(
const gfx::Rect& rect,
@@ -709,12 +716,6 @@ class CONTENT_EXPORT RenderFrameImpl
void WillReleaseScriptContext(v8::Local<v8::Context> context,
int world_id) override;
void DidChangeScrollOffset() override;
- void ReportFindInPageMatchCount(int request_id,
- int count,
- bool final_update) override;
- void ReportFindInPageSelection(int request_id,
- int active_match_ordinal,
- const blink::WebRect& sel) override;
blink::WebPushClient* PushClient() override;
blink::WebRelatedAppsFetcher* GetRelatedAppsFetcher() override;
void WillStartUsingPeerConnectionHandler(
@@ -806,14 +807,12 @@ class CONTENT_EXPORT RenderFrameImpl
// process; for layout tests, this allows the test to mock out services at
// the Mojo IPC layer.
void MaybeEnableMojoBindings();
- // Adds the given file chooser request to the file_chooser_completion_ queue
- // (see that var for more) and requests the chooser be displayed if there are
- // no other waiting items in the queue.
- //
- // Returns true if the chooser was successfully scheduled. False means we
- // didn't schedule anything.
- bool ScheduleFileChooser(const FileChooserParams& params,
- blink::WebFileChooserCompletion* completion);
+
+ // Another RunFileChooser() for content::FileChooserParams.
+ // Returns true if the chooser was successfully requested. False means we
+ // didn't request anything.
+ bool RunFileChooser(const FileChooserParams& params,
+ blink::WebFileChooserCompletion* completion);
// Internal version of DidFailProvisionalLoad() that allows specifying
// |error_page_content|.
@@ -1041,7 +1040,7 @@ class CONTENT_EXPORT RenderFrameImpl
void OnTextTrackSettingsChanged(
const FrameMsg_TextTrackSettings_Params& params);
void OnCheckCompleted();
- void OnPostMessageEvent(const FrameMsg_PostMessage_Params& params);
+ void OnPostMessageEvent(FrameMsg_PostMessage_Params params);
void OnReportContentSecurityPolicyViolation(
const content::CSPViolationParams& violation_params);
void OnGetSavableResourceLinks();
@@ -1049,9 +1048,6 @@ class CONTENT_EXPORT RenderFrameImpl
const std::map<GURL, base::FilePath>& url_to_local_path,
const std::map<int, base::FilePath>& frame_routing_id_to_local_path);
void OnSerializeAsMHTML(const FrameMsg_SerializeAsMHTML_Params& params);
- void OnFind(int request_id,
- const base::string16& search_text,
- const blink::WebFindOptions& options);
void OnEnableViewSourceMode();
void OnSuppressFurtherDialogs();
void OnFileChooserResponse(
@@ -1064,6 +1060,8 @@ class CONTENT_EXPORT RenderFrameImpl
void OnMediaPlayerActionAt(const gfx::PointF&,
const blink::WebMediaPlayerAction&);
+ void PostMessageEvent(FrameMsg_PostMessage_Params params);
+
#if BUILDFLAG(USE_EXTERNAL_POPUP_MENU)
#if defined(OS_MACOSX)
void OnSelectPopupMenuItem(int selected_index);
@@ -1086,7 +1084,6 @@ class CONTENT_EXPORT RenderFrameImpl
// look for a matching FrameNavigationEntry in the last committed entry to use
// instead of |url|.
void OpenURL(const NavigationPolicyInfo& info,
- bool send_referrer,
bool is_history_navigation_in_new_child);
// Creates a WebURLRequest to use fo the commit of a navigation.
@@ -1138,6 +1135,7 @@ class CONTENT_EXPORT RenderFrameImpl
bool replace,
HistoryEntry* entry,
const base::Optional<std::string>& error_page_content,
+ std::unique_ptr<blink::WebNavigationParams> navigation_params,
std::unique_ptr<blink::WebDocumentLoader::ExtraData> navigation_data);
void LoadNavigationErrorPageForHttpStatusError(
const blink::WebURLRequest& failed_request,
@@ -1145,15 +1143,16 @@ class CONTENT_EXPORT RenderFrameImpl
int http_status,
bool replace,
HistoryEntry* entry,
+ std::unique_ptr<blink::WebNavigationParams> navigation_params,
std::unique_ptr<blink::WebDocumentLoader::ExtraData> navigation_data);
void LoadNavigationErrorPageInternal(
const std::string& error_html,
- const GURL& error_page_url,
const GURL& error_url,
bool replace,
- blink::WebFrameLoadType frame_load_type,
- const blink::WebHistoryItem& history_item,
- std::unique_ptr<blink::WebDocumentLoader::ExtraData> navigation_data);
+ HistoryEntry* history_entry,
+ std::unique_ptr<blink::WebNavigationParams> navigation_params,
+ std::unique_ptr<blink::WebDocumentLoader::ExtraData> navigation_data,
+ const blink::WebURLRequest* failed_request);
void HandleJavascriptExecutionResult(const base::string16& javascript,
int id,
@@ -1175,7 +1174,7 @@ class CONTENT_EXPORT RenderFrameImpl
// Loads a data url.
void LoadDataURL(
- const CommonNavigationParams& params,
+ const CommonNavigationParams& common_params,
const RequestNavigationParams& request_params,
blink::WebLocalFrame* frame,
blink::WebFrameLoadType load_type,
@@ -1211,18 +1210,6 @@ class CONTENT_EXPORT RenderFrameImpl
void OnHostZoomClientRequest(mojom::HostZoomAssociatedRequest request);
- // Called to get the WebPlugin to handle find requests in the document.
- // Returns nullptr if there is no such WebPlugin.
- blink::WebPlugin* GetWebPluginForFind();
-
- // Sends a reply to the current find operation handling if it was a
- // synchronous find request.
- void SendFindReply(int request_id,
- int match_count,
- int ordinal,
- const blink::WebRect& selection_rect,
- bool final_status_update);
-
void InitializeBlameContext(RenderFrameImpl* parent_frame);
// service_manager::mojom::InterfaceProvider:
@@ -1287,6 +1274,10 @@ class CONTENT_EXPORT RenderFrameImpl
std::unique_ptr<blink::WebSocketHandshakeThrottle>
CreateWebSocketHandshakeThrottle() override;
+ bool IsPluginHandledExternally(
+ const blink::WebElement& plugin_element,
+ const blink::WebURL& url,
+ const blink::WebString& suggested_mime_type) override;
// Updates the state of this frame when asked to commit a navigation.
void PrepareFrameForCommit(const GURL& url,
@@ -1325,6 +1316,13 @@ class CONTENT_EXPORT RenderFrameImpl
// Whether url download should be throttled.
bool ShouldThrottleDownload();
+ // Creates a service worker network provider using browser provided data,
+ // to be supplied to the loader.
+ std::unique_ptr<blink::WebServiceWorkerNetworkProvider>
+ BuildServiceWorkerNetworkProviderForNavigation(
+ const RequestNavigationParams* request_params,
+ mojom::ControllerServiceWorkerInfoPtr controller_service_worker_info);
+
// 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
@@ -1425,7 +1423,7 @@ class CONTENT_EXPORT RenderFrameImpl
RendererWebCookieJarImpl cookie_jar_;
// All the registered observers.
- base::ObserverList<RenderFrameObserver> observers_;
+ base::ObserverList<RenderFrameObserver>::Unchecked observers_;
// External context menu requests we're waiting for. "Internal"
// (WebKit-originated) context menu events will have an ID of 0 and will not
@@ -1513,13 +1511,8 @@ class CONTENT_EXPORT RenderFrameImpl
// stack that interferes with swapping out.
bool suppress_further_dialogs_;
- // The current and pending file chooser completion objects. If the queue is
- // nonempty, the first item represents the currently running file chooser
- // callback, and the remaining elements are the other file chooser completion
- // still waiting to be run (in order).
- struct PendingFileChooser;
- base::circular_deque<std::unique_ptr<PendingFileChooser>>
- file_chooser_completions_;
+ // The current file chooser completion object.
+ blink::WebFileChooserCompletion* file_chooser_completion_ = nullptr;
#if BUILDFLAG(USE_EXTERNAL_POPUP_MENU)
// The external popup for the currently showing select popup.
@@ -1571,8 +1564,8 @@ class CONTENT_EXPORT RenderFrameImpl
// Creates various media clients.
MediaFactory media_factory_;
- AssociatedInterfaceRegistryImpl associated_interfaces_;
- std::unique_ptr<AssociatedInterfaceProviderImpl>
+ blink::AssociatedInterfaceRegistry associated_interfaces_;
+ std::unique_ptr<blink::AssociatedInterfaceProvider>
remote_associated_interfaces_;
// TODO(dcheng): Remove these members.
@@ -1601,6 +1594,7 @@ class CONTENT_EXPORT RenderFrameImpl
blink::WebSourceLocation source_location;
blink::WebString devtools_initiator_info;
blink::mojom::BlobURLTokenPtr blob_url_token;
+ base::TimeTicks input_start;
explicit PendingNavigationInfo(const NavigationPolicyInfo& info);
~PendingNavigationInfo();
@@ -1617,15 +1611,11 @@ class CONTENT_EXPORT RenderFrameImpl
mojo::BindingSet<service_manager::mojom::InterfaceProvider>
interface_provider_bindings_;
- // Non-null if this frame is to be controlled by a service worker.
- // Sent from the browser process on navigation commit. Valid until the
- // document loader for this frame is actually created (where this is
- // consumed to initialize a subresource loader).
- mojom::ControllerServiceWorkerInfoPtr controller_service_worker_info_;
-
// Set on CommitNavigation when Network Service is enabled, and used
// by FrameURLLoaderFactory for prefetch requests.
network::mojom::URLLoaderFactoryPtr prefetch_loader_factory_;
+ scoped_refptr<network::WeakWrapperSharedURLLoaderFactory>
+ prefetch_shared_loader_factory_;
// URLLoaderFactory instances used for subresource loading.
// Depending on how the frame was created, |loader_factories_| could be:
@@ -1633,6 +1623,8 @@ class CONTENT_EXPORT RenderFrameImpl
// * |TrackedChildURLLoaderFactoryBundle| for frames opened by other frames.
scoped_refptr<ChildURLLoaderFactoryBundle> loader_factories_;
+ scoped_refptr<FrameRequestBlocker> frame_request_blocker_;
+
// AndroidOverlay routing token from the browser, if we have one yet.
base::Optional<base::UnguessableToken> overlay_routing_token_;
@@ -1680,6 +1672,12 @@ class CONTENT_EXPORT RenderFrameImpl
int num_burst_download_requests_ = 0;
base::TimeTicks burst_download_start_time_;
+ // Set to true while we are replaying main resource response,
+ // which was captured in the browser, during navigation commit.
+ // TODO(dgozman): should be temporary until we stop using
+ // WebURLRequest for this.
+ bool replaying_main_response_ = false;
+
base::WeakPtrFactory<RenderFrameImpl> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(RenderFrameImpl);
diff --git a/chromium/content/renderer/render_frame_impl_browsertest.cc b/chromium/content/renderer/render_frame_impl_browsertest.cc
index 884e79b63e8..7debc6529b8 100644
--- a/chromium/content/renderer/render_frame_impl_browsertest.cc
+++ b/chromium/content/renderer/render_frame_impl_browsertest.cc
@@ -256,7 +256,9 @@ TEST_F(RenderFrameImplTest, FrameWasShownAfterWidgetClose) {
ViewMsg_WasShown was_shown_message(0, true, base::TimeTicks());
// Test passes if this does not crash.
- static_cast<RenderViewImpl*>(view_)->OnMessageReceived(was_shown_message);
+ RenderWidget* render_widget =
+ static_cast<RenderViewImpl*>(view_)->GetWidget();
+ render_widget->OnMessageReceived(was_shown_message);
}
// Test that LoFi state only updates for new main frame documents. Subframes
@@ -301,7 +303,7 @@ TEST_F(RenderFrameImplTest, LoFiNotUpdatedOnSubframeCommits) {
GetMainRenderFrame()->DidCommitProvisionalLoad(
item, blink::kWebStandardCommit,
blink::WebGlobalObjectReusePolicy::kCreateNew);
- EXPECT_EQ(PREVIEWS_OFF, GetMainRenderFrame()->GetPreviewsState());
+ EXPECT_EQ(PREVIEWS_UNSPECIFIED, GetMainRenderFrame()->GetPreviewsState());
// The subframe would be deleted here after a cross-document navigation. It
// happens to be left around in this test because this does not simulate the
// frame detach.
@@ -480,8 +482,7 @@ TEST_F(RenderFrameImplTest, ZoomLimit) {
TEST_F(RenderFrameImplTest, NoCrashWhenDeletingFrameDuringFind) {
blink::WebFindOptions options;
options.force = true;
- FrameMsg_Find find_message(0, 1, base::ASCIIToUTF16("foo"), options);
- frame()->OnMessageReceived(find_message);
+ frame()->GetWebFrame()->Find(1, "foo", options, false);
FrameMsg_Delete delete_message(0);
frame()->OnMessageReceived(delete_message);
diff --git a/chromium/content/renderer/render_frame_proxy.cc b/chromium/content/renderer/render_frame_proxy.cc
index 8a50e185e1f..954ea7fbf07 100644
--- a/chromium/content/renderer/render_frame_proxy.cc
+++ b/chromium/content/renderer/render_frame_proxy.cc
@@ -55,8 +55,8 @@
#if BUILDFLAG(ENABLE_PRINTING)
// nogncheck because dependency on //printing is conditional upon
// enable_basic_printing flags.
+#include "printing/metafile_skia.h" // nogncheck
#include "printing/metafile_skia_wrapper.h" // nogncheck
-#include "printing/pdf_metafile_skia.h" // nogncheck
#endif
namespace content {
@@ -92,17 +92,21 @@ RenderFrameProxy* RenderFrameProxy::CreateProxyToReplaceFrame(
blink::WebRemoteFrame* web_frame =
blink::WebRemoteFrame::Create(scope, proxy.get());
+ bool parent_is_local =
+ !frame_to_replace->GetWebFrame()->Parent() ||
+ frame_to_replace->GetWebFrame()->Parent()->IsWebLocalFrame();
+
// If frame_to_replace has a RenderFrameProxy parent, then its
// RenderWidget will be destroyed along with it, so the new
// RenderFrameProxy uses its parent's RenderWidget.
RenderWidget* widget =
- (!frame_to_replace->GetWebFrame()->Parent() ||
- frame_to_replace->GetWebFrame()->Parent()->IsWebLocalFrame())
+ parent_is_local
? frame_to_replace->GetRenderWidget()
: RenderFrameProxy::FromWebFrame(
frame_to_replace->GetWebFrame()->Parent()->ToWebRemoteFrame())
->render_widget();
- proxy->Init(web_frame, frame_to_replace->render_view(), widget);
+ proxy->Init(web_frame, frame_to_replace->render_view(), widget,
+ parent_is_local);
return proxy.release();
}
@@ -158,7 +162,7 @@ RenderFrameProxy* RenderFrameProxy::CreateFrameProxy(
render_widget = parent->render_widget();
}
- proxy->Init(web_frame, render_view, render_widget);
+ proxy->Init(web_frame, render_view, render_widget, false);
// Initialize proxy's WebRemoteFrame with the security origin and other
// replicated information.
@@ -220,7 +224,8 @@ RenderFrameProxy::~RenderFrameProxy() {
void RenderFrameProxy::Init(blink::WebRemoteFrame* web_frame,
RenderViewImpl* render_view,
- RenderWidget* render_widget) {
+ RenderWidget* render_widget,
+ bool parent_is_local) {
CHECK(web_frame);
CHECK(render_view);
CHECK(render_widget);
@@ -237,13 +242,14 @@ void RenderFrameProxy::Init(blink::WebRemoteFrame* web_frame,
enable_surface_synchronization_ = features::IsSurfaceSynchronizationEnabled();
- compositing_helper_ = std::make_unique<ChildFrameCompositingHelper>(this);
+ if (parent_is_local)
+ compositing_helper_ = std::make_unique<ChildFrameCompositingHelper>(this);
pending_visual_properties_.screen_info =
render_widget_->GetOriginalScreenInfo();
#if defined(USE_AURA)
- if (!features::IsAshInBrowserProcess()) {
+ if (features::IsUsingWindowService()) {
RendererWindowTreeClient* renderer_window_tree_client =
RendererWindowTreeClient::Get(render_widget_->routing_id());
// It's possible a MusEmbeddedFrame has already been scheduled for creation
@@ -264,13 +270,13 @@ void RenderFrameProxy::ResendVisualProperties() {
}
void RenderFrameProxy::WillBeginCompositorFrame() {
- if (compositing_helper_->primary_surface_id().is_valid()) {
+ if (compositing_helper_ &&
+ compositing_helper_->primary_surface_id().is_valid()) {
FrameHostMsg_HittestData_Params params;
params.surface_id = compositing_helper_->primary_surface_id();
params.ignored_for_hittest = web_frame_->IsIgnoredForHitTest();
render_widget_->QueueMessage(
- new FrameHostMsg_HittestData(render_widget_->routing_id(), params),
- MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE);
+ new FrameHostMsg_HittestData(render_widget_->routing_id(), params));
}
}
@@ -485,7 +491,7 @@ void RenderFrameProxy::OnViewChanged(
const FrameMsg_ViewChanged_Params& params) {
crashed_ = false;
// In mash the FrameSinkId comes from RendererWindowTreeClient.
- if (features::IsAshInBrowserProcess())
+ if (!features::IsUsingWindowService())
frame_sink_id_ = *params.frame_sink_id;
// Resend the FrameRects and allocate a new viz::LocalSurfaceId when the view
@@ -687,7 +693,8 @@ void RenderFrameProxy::SynchronizeVisualProperties() {
// the intersection rects.
gfx::Rect new_compositor_visible_rect = web_frame_->GetCompositingRect();
if (new_compositor_visible_rect != last_compositor_visible_rect_)
- UpdateRemoteViewportIntersection(last_intersection_rect_);
+ UpdateRemoteViewportIntersection(last_intersection_rect_,
+ last_occluded_or_obscured_);
}
void RenderFrameProxy::OnSetHasReceivedUserGestureBeforeNavigation(bool value) {
@@ -775,6 +782,8 @@ void RenderFrameProxy::Navigate(const blink::WebURLRequest& request,
params.uses_post = request.HttpMethod().Utf8() == "POST";
params.resource_request_body = GetRequestBodyForWebURLRequest(request);
params.extra_headers = GetWebURLRequestHeadersAsString(request);
+ // TODO(domfarolino): Retrieve the referrer in the form of a referrer member
+ // instead of the header field. See https://crbug.com/850813.
params.referrer = Referrer(blink::WebStringToGURL(request.HttpHeaderField(
blink::WebString::FromUTF8("Referer"))),
request.GetReferrerPolicy());
@@ -805,12 +814,14 @@ void RenderFrameProxy::FrameRectsChanged(
}
void RenderFrameProxy::UpdateRemoteViewportIntersection(
- const blink::WebRect& viewport_intersection) {
+ const blink::WebRect& viewport_intersection,
+ bool occluded_or_obscured) {
last_intersection_rect_ = viewport_intersection;
last_compositor_visible_rect_ = web_frame_->GetCompositingRect();
+ last_occluded_or_obscured_ = occluded_or_obscured;
Send(new FrameHostMsg_UpdateViewportIntersection(
routing_id_, gfx::Rect(viewport_intersection),
- last_compositor_visible_rect_));
+ last_compositor_visible_rect_, last_occluded_or_obscured_));
}
void RenderFrameProxy::VisibilityChanged(bool visible) {
@@ -872,7 +883,7 @@ void RenderFrameProxy::OnMusEmbeddedFrameSurfaceChanged(
void RenderFrameProxy::OnMusEmbeddedFrameSinkIdAllocated(
const viz::FrameSinkId& frame_sink_id) {
// RendererWindowTreeClient should only call this when mus is hosting viz.
- DCHECK(!features::IsAshInBrowserProcess());
+ DCHECK(features::IsUsingWindowService());
frame_sink_id_ = frame_sink_id;
// Resend the FrameRects and allocate a new viz::LocalSurfaceId when the view
// changes.
@@ -898,7 +909,7 @@ SkBitmap* RenderFrameProxy::GetSadPageBitmap() {
uint32_t RenderFrameProxy::Print(const blink::WebRect& rect,
cc::PaintCanvas* canvas) {
#if BUILDFLAG(ENABLE_PRINTING)
- printing::PdfMetafileSkia* metafile =
+ printing::MetafileSkia* metafile =
printing::MetafileSkiaWrapper::GetMetafileFromCanvas(canvas);
DCHECK(metafile);
diff --git a/chromium/content/renderer/render_frame_proxy.h b/chromium/content/renderer/render_frame_proxy.h
index abe2aaa15ce..4715761b72d 100644
--- a/chromium/content/renderer/render_frame_proxy.h
+++ b/chromium/content/renderer/render_frame_proxy.h
@@ -196,7 +196,8 @@ class CONTENT_EXPORT RenderFrameProxy : public IPC::Listener,
void FrameRectsChanged(const blink::WebRect& local_frame_rect,
const blink::WebRect& screen_space_rect) override;
void UpdateRemoteViewportIntersection(
- const blink::WebRect& viewport_intersection) override;
+ const blink::WebRect& viewport_intersection,
+ bool occluded_or_obscured) override;
void VisibilityChanged(bool visible) override;
void SetIsInert(bool) override;
void SetInheritedEffectiveTouchAction(cc::TouchAction) override;
@@ -217,7 +218,8 @@ class CONTENT_EXPORT RenderFrameProxy : public IPC::Listener,
void Init(blink::WebRemoteFrame* frame,
RenderViewImpl* render_view,
- RenderWidget* render_widget);
+ RenderWidget* render_widget,
+ bool parent_is_local);
void ResendVisualProperties();
@@ -287,6 +289,8 @@ class CONTENT_EXPORT RenderFrameProxy : public IPC::Listener,
// Stores the WebRemoteFrame we are associated with.
blink::WebRemoteFrame* web_frame_;
std::string unique_name_;
+
+ // Can be nullptr when this RenderFrameProxy's parent is not a RenderFrame.
std::unique_ptr<ChildFrameCompositingHelper> compositing_helper_;
RenderViewImpl* render_view_;
@@ -316,6 +320,7 @@ class CONTENT_EXPORT RenderFrameProxy : public IPC::Listener,
gfx::Rect last_intersection_rect_;
gfx::Rect last_compositor_visible_rect_;
+ bool last_occluded_or_obscured_ = false;
#if defined(USE_AURA)
std::unique_ptr<MusEmbeddedFrame> mus_embedded_frame_;
diff --git a/chromium/content/renderer/render_process.h b/chromium/content/renderer/render_process.h
index bbbad22c956..740819536fd 100644
--- a/chromium/content/renderer/render_process.h
+++ b/chromium/content/renderer/render_process.h
@@ -10,7 +10,7 @@
#include <vector>
#include "base/macros.h"
-#include "base/task_scheduler/task_scheduler.h"
+#include "base/task/task_scheduler/task_scheduler.h"
#include "content/child/child_process.h"
namespace content {
diff --git a/chromium/content/renderer/render_process_impl.cc b/chromium/content/renderer/render_process_impl.cc
index 80559a12e02..49973c56fcd 100644
--- a/chromium/content/renderer/render_process_impl.cc
+++ b/chromium/content/renderer/render_process_impl.cc
@@ -26,7 +26,7 @@
#include "base/feature_list.h"
#include "base/memory/ptr_util.h"
#include "base/sys_info.h"
-#include "base/task_scheduler/initialization_util.h"
+#include "base/task/task_scheduler/initialization_util.h"
#include "base/time/time.h"
#include "content/common/task_scheduler.h"
#include "content/public/common/bindings_policy.h"
@@ -191,6 +191,12 @@ RenderProcessImpl::RenderProcessImpl(
const base::CommandLine& command_line =
*base::CommandLine::ForCurrentProcess();
+ if (command_line.HasSwitch(switches::kNoV8UntrustedCodeMitigations)) {
+ const char* disable_mitigations = "--no-untrusted-code-mitigations";
+ v8::V8::SetFlagsFromString(disable_mitigations,
+ strlen(disable_mitigations));
+ }
+
if (command_line.HasSwitch(switches::kJavaScriptFlags)) {
std::string flags(
command_line.GetSwitchValueASCII(switches::kJavaScriptFlags));
diff --git a/chromium/content/renderer/render_process_impl.h b/chromium/content/renderer/render_process_impl.h
index 65f6e373b5c..0776bb239e2 100644
--- a/chromium/content/renderer/render_process_impl.h
+++ b/chromium/content/renderer/render_process_impl.h
@@ -9,7 +9,7 @@
#include <vector>
#include "base/macros.h"
-#include "base/task_scheduler/task_scheduler.h"
+#include "base/task/task_scheduler/task_scheduler.h"
#include "content/renderer/render_process.h"
namespace content {
diff --git a/chromium/content/renderer/render_thread_impl.cc b/chromium/content/renderer/render_thread_impl.cc
index c078565cef7..b36daaee097 100644
--- a/chromium/content/renderer/render_thread_impl.cc
+++ b/chromium/content/renderer/render_thread_impl.cc
@@ -19,7 +19,6 @@
#include "base/memory/discardable_memory_allocator.h"
#include "base/memory/memory_coordinator_client_registry.h"
#include "base/memory/shared_memory.h"
-#include "base/message_loop/message_loop.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
@@ -32,6 +31,7 @@
#include "base/strings/string_split.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task/post_task.h"
#include "base/threading/simple_thread.h"
#include "base/threading/thread_local.h"
#include "base/threading/thread_restrictions.h"
@@ -145,9 +145,9 @@
#include "services/metrics/public/cpp/mojo_ukm_recorder.h"
#include "services/service_manager/public/cpp/connector.h"
#include "services/service_manager/public/cpp/interface_provider.h"
-#include "services/ui/public/cpp/gpu/context_provider_command_buffer.h"
-#include "services/ui/public/cpp/gpu/gpu.h"
-#include "services/ui/public/interfaces/constants.mojom.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/child/webthread_base.h"
#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
@@ -330,7 +330,7 @@ void CreateFrameFactory(mojom::FrameFactoryRequest request,
std::move(request));
}
-scoped_refptr<ui::ContextProviderCommandBuffer> CreateOffscreenContext(
+scoped_refptr<ws::ContextProviderCommandBuffer> CreateOffscreenContext(
scoped_refptr<gpu::GpuChannelHost> gpu_channel_host,
gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
const gpu::SharedMemoryLimits& limits,
@@ -340,7 +340,7 @@ scoped_refptr<ui::ContextProviderCommandBuffer> CreateOffscreenContext(
bool support_oop_rasterization,
bool support_grcontext,
bool automatic_flushes,
- ui::command_buffer_metrics::ContextType type,
+ ws::command_buffer_metrics::ContextType type,
int32_t stream_id,
gpu::SchedulingPriority stream_priority) {
DCHECK(gpu_channel_host);
@@ -365,11 +365,11 @@ scoped_refptr<ui::ContextProviderCommandBuffer> CreateOffscreenContext(
attributes.enable_oop_rasterization = support_oop_rasterization &&
support_raster_interface &&
!support_gles2_interface;
- return base::MakeRefCounted<ui::ContextProviderCommandBuffer>(
+ return base::MakeRefCounted<ws::ContextProviderCommandBuffer>(
std::move(gpu_channel_host), gpu_memory_buffer_manager, stream_id,
stream_priority, gpu::kNullSurfaceHandle,
GURL("chrome://gpu/RenderThreadImpl::CreateOffscreenContext/" +
- ui::command_buffer_metrics::ContextTypeToString(type)),
+ ws::command_buffer_metrics::ContextTypeToString(type)),
automatic_flushes, support_locking, support_grcontext, limits, attributes,
type);
}
@@ -637,28 +637,6 @@ bool RenderThreadImpl::HistogramCustomizer::IsAlexaTop10NonGoogleSite(
}
// static
-RenderThreadImpl* RenderThreadImpl::Create(
- const InProcessChildThreadParams& params,
- base::MessageLoop* unowned_message_loop) {
- TRACE_EVENT0("startup", "RenderThreadImpl::Create");
- std::unique_ptr<blink::scheduler::WebThreadScheduler> main_thread_scheduler =
- blink::scheduler::WebThreadScheduler::CreateMainThreadScheduler();
- scoped_refptr<base::SingleThreadTaskRunner> test_task_counter;
- return new RenderThreadImpl(params, std::move(main_thread_scheduler),
- test_task_counter, unowned_message_loop);
-}
-
-// static
-RenderThreadImpl* RenderThreadImpl::Create(
- std::unique_ptr<base::MessageLoop> main_message_loop,
- std::unique_ptr<blink::scheduler::WebThreadScheduler>
- main_thread_scheduler) {
- TRACE_EVENT0("startup", "RenderThreadImpl::Create");
- return new RenderThreadImpl(std::move(main_message_loop),
- std::move(main_thread_scheduler));
-}
-
-// static
RenderThreadImpl* RenderThreadImpl::current() {
return lazy_tls.Pointer()->Get();
}
@@ -702,62 +680,49 @@ RenderThreadImpl::DeprecatedGetMainTaskRunner() {
// the browser
RenderThreadImpl::RenderThreadImpl(
const InProcessChildThreadParams& params,
- std::unique_ptr<blink::scheduler::WebThreadScheduler> scheduler,
- const scoped_refptr<base::SingleThreadTaskRunner>& resource_task_queue,
- base::MessageLoop* unowned_message_loop)
- : ChildThreadImpl(
- Options::Builder()
- .InBrowserProcess(params)
- .AutoStartServiceManagerConnection(false)
- .ConnectToBrowser(true)
- .IPCTaskRunner(scheduler ? scheduler->IPCTaskRunner() : nullptr)
- .Build()),
+ std::unique_ptr<blink::scheduler::WebThreadScheduler> scheduler)
+ : ChildThreadImpl(Options::Builder()
+ .InBrowserProcess(params)
+ .AutoStartServiceManagerConnection(false)
+ .ConnectToBrowser(true)
+ .IPCTaskRunner(scheduler->IPCTaskRunner())
+ .Build()),
main_thread_scheduler_(std::move(scheduler)),
- main_message_loop_(unowned_message_loop),
categorized_worker_pool_(new CategorizedWorkerPool()),
renderer_binding_(this),
client_id_(1),
compositing_mode_watcher_binding_(this),
weak_factory_(this) {
- Init(resource_task_queue);
+ TRACE_EVENT0("startup", "RenderThreadImpl::Create");
+ Init();
}
-// When we run plugins in process, we actually run them on the render thread,
-// which means that we need to make the render thread pump UI events.
+// Multi-process mode.
RenderThreadImpl::RenderThreadImpl(
- std::unique_ptr<base::MessageLoop> owned_message_loop,
std::unique_ptr<blink::scheduler::WebThreadScheduler> scheduler)
- : ChildThreadImpl(
- Options::Builder()
- .AutoStartServiceManagerConnection(false)
- .ConnectToBrowser(true)
- .IPCTaskRunner(scheduler ? scheduler->IPCTaskRunner() : nullptr)
- .Build()),
+ : ChildThreadImpl(Options::Builder()
+ .AutoStartServiceManagerConnection(false)
+ .ConnectToBrowser(true)
+ .IPCTaskRunner(scheduler->IPCTaskRunner())
+ .Build()),
main_thread_scheduler_(std::move(scheduler)),
- owned_message_loop_(std::move(owned_message_loop)),
- main_message_loop_(owned_message_loop_.get()),
categorized_worker_pool_(new CategorizedWorkerPool()),
is_scroll_animator_enabled_(false),
renderer_binding_(this),
compositing_mode_watcher_binding_(this),
weak_factory_(this) {
- scoped_refptr<base::SingleThreadTaskRunner> test_task_counter;
+ TRACE_EVENT0("startup", "RenderThreadImpl::Create");
DCHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kRendererClientId));
base::StringToInt(base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kRendererClientId),
&client_id_);
- Init(test_task_counter);
+ Init();
}
-void RenderThreadImpl::Init(
- const scoped_refptr<base::SingleThreadTaskRunner>& resource_task_queue) {
+void RenderThreadImpl::Init() {
TRACE_EVENT0("startup", "RenderThreadImpl::Init");
- // Whether owned or unowned, |main_message_loop_| needs to be initialized in
- // all constructors.
- DCHECK(main_message_loop_);
-
GetContentClient()->renderer()->PostIOThreadCreated(GetIOTaskRunner().get());
base::trace_event::TraceLog::GetInstance()->SetThreadSortIndex(
@@ -770,7 +735,7 @@ void RenderThreadImpl::Init(
#endif
lazy_tls.Pointer()->Set(this);
- g_main_task_runner.Get() = main_message_loop_->task_runner();
+ g_main_task_runner.Get() = base::ThreadTaskRunnerHandle::Get();
// Register this object as the main thread.
ChildProcess::current()->set_main_thread(this);
@@ -779,10 +744,10 @@ void RenderThreadImpl::Init(
base::BindRepeating(&CreateSingleSampleMetricsProvider,
main_thread_runner(), GetConnector()));
- gpu_ = ui::Gpu::Create(GetConnector(),
- features::IsAshInBrowserProcess()
- ? mojom::kBrowserServiceName
- : ui::mojom::kServiceName,
+ gpu_ = ws::Gpu::Create(GetConnector(),
+ features::IsUsingWindowService()
+ ? ws::mojom::kServiceName
+ : mojom::kBrowserServiceName,
GetIOTaskRunner());
resource_dispatcher_.reset(new ResourceDispatcher());
@@ -791,7 +756,7 @@ void RenderThreadImpl::Init(
URLLoaderThrottleProviderType::kFrame);
auto registry = std::make_unique<service_manager::BinderRegistry>();
- InitializeWebKit(resource_task_queue, registry.get());
+ InitializeWebKit(registry.get());
// In single process the single process is all there is.
webkit_shared_timer_suspended_ = false;
@@ -808,7 +773,6 @@ void RenderThreadImpl::Init(
GetWebMainThreadScheduler()->IPCTaskRunner());
dom_storage_dispatcher_.reset(new DomStorageDispatcher());
main_thread_indexed_db_dispatcher_.reset(new IndexedDBDispatcher());
- file_system_dispatcher_.reset(new FileSystemDispatcher());
vc_manager_.reset(new VideoCaptureImplManager());
@@ -818,8 +782,7 @@ void RenderThreadImpl::Init(
peer_connection_tracker_.reset(new PeerConnectionTracker());
AddObserver(peer_connection_tracker_.get());
- p2p_socket_dispatcher_ = new P2PSocketDispatcher(GetIOTaskRunner().get());
- AddFilter(p2p_socket_dispatcher_.get());
+ p2p_socket_dispatcher_ = new P2PSocketDispatcher();
peer_connection_factory_.reset(
new PeerConnectionDependencyFactory(p2p_socket_dispatcher_.get()));
@@ -837,7 +800,7 @@ void RenderThreadImpl::Init(
AddFilter(midi_message_filter_.get());
#if defined(USE_AURA)
- if (!features::IsAshInBrowserProcess())
+ if (features::IsUsingWindowService())
CreateRenderWidgetWindowTreeClientFactory(GetServiceManagerConnection());
#endif
@@ -992,10 +955,10 @@ void RenderThreadImpl::Init(
categorized_worker_pool_->Start(num_raster_threads);
discardable_memory::mojom::DiscardableSharedMemoryManagerPtr manager_ptr;
- if (!features::IsAshInBrowserProcess()) {
+ if (features::IsUsingWindowService()) {
#if defined(USE_AURA)
GetServiceManagerConnection()->GetConnector()->BindInterface(
- ui::mojom::kServiceName, &manager_ptr);
+ ws::mojom::kServiceName, &manager_ptr);
#else
NOTREACHED();
#endif
@@ -1051,7 +1014,6 @@ RenderThreadImpl::~RenderThreadImpl() {
void RenderThreadImpl::Shutdown() {
ChildThreadImpl::Shutdown();
- file_system_dispatcher_.reset();
WebFileSystemImpl::DeleteThreadSpecificInstance();
// In a multi-process mode, we immediately exit the renderer.
// Historically we had a graceful shutdown sequence here but it was
@@ -1229,8 +1191,22 @@ void RenderThreadImpl::InitializeCompositorThread() {
#endif
}
+scoped_refptr<base::SingleThreadTaskRunner>
+RenderThreadImpl::CreateVideoFrameCompositorTaskRunner() {
+ if (!video_frame_compositor_task_runner_) {
+ // All of Chromium's GPU code must know which thread it's running on, and
+ // be the same thread on which the rendering context was initialized. This
+ // is why this must be a SingleThreadTaskRunner instead of a
+ // SequencedTaskRunner.
+ video_frame_compositor_task_runner_ =
+ base::CreateSingleThreadTaskRunnerWithTraits(
+ {base::MayBlock(), base::TaskPriority::USER_VISIBLE});
+ }
+
+ return video_frame_compositor_task_runner_;
+}
+
void RenderThreadImpl::InitializeWebKit(
- const scoped_refptr<base::SingleThreadTaskRunner>& resource_task_queue,
service_manager::BinderRegistry* registry) {
DCHECK(!blink_platform_impl_);
@@ -1248,7 +1224,8 @@ void RenderThreadImpl::InitializeWebKit(
GetContentClient()
->renderer()
->SetRuntimeFeaturesDefaultsBeforeBlinkInitialization();
- blink::Initialize(blink_platform_impl_.get(), registry);
+ blink::Initialize(blink_platform_impl_.get(), registry,
+ blink_platform_impl_->CurrentThread());
v8::Isolate* isolate = blink::MainThreadIsolate();
isolate->SetCreateHistogramFunction(CreateHistogram);
@@ -1376,9 +1353,6 @@ void RenderThreadImpl::IdleHandler() {
} else {
idle_timer_.Stop();
}
-
- for (auto& observer : observers_)
- observer.IdleNotification();
}
int64_t RenderThreadImpl::GetIdleNotificationDelayInMs() const {
@@ -1432,12 +1406,12 @@ media::GpuVideoAcceleratorFactories* RenderThreadImpl::GetGpuFactories() {
bool support_oop_rasterization = false;
bool support_grcontext = false;
bool automatic_flushes = false;
- scoped_refptr<ui::ContextProviderCommandBuffer> media_context_provider =
+ scoped_refptr<ws::ContextProviderCommandBuffer> media_context_provider =
CreateOffscreenContext(
gpu_channel_host, GetGpuMemoryBufferManager(), limits,
support_locking, support_gles2_interface, support_raster_interface,
support_oop_rasterization, support_grcontext, automatic_flushes,
- ui::command_buffer_metrics::ContextType::MEDIA, kGpuStreamIdMedia,
+ ws::command_buffer_metrics::ContextType::MEDIA, kGpuStreamIdMedia,
kGpuStreamPriorityMedia);
const bool enable_video_accelerator =
@@ -1476,7 +1450,41 @@ media::GpuVideoAcceleratorFactories* RenderThreadImpl::GetGpuFactories() {
return gpu_factories_.back().get();
}
-scoped_refptr<ui::ContextProviderCommandBuffer>
+scoped_refptr<viz::ContextProvider>
+RenderThreadImpl::GetVideoFrameCompositorContextProvider(
+ scoped_refptr<viz::ContextProvider> unwanted_context_provider) {
+ if (video_frame_compositor_context_provider_ &&
+ video_frame_compositor_context_provider_ != unwanted_context_provider) {
+ return video_frame_compositor_context_provider_;
+ }
+
+ video_frame_compositor_context_provider_ = nullptr;
+
+ scoped_refptr<gpu::GpuChannelHost> gpu_channel_host =
+ EstablishGpuChannelSync();
+ if (!gpu_channel_host)
+ return nullptr;
+
+ // This context is only used to create textures and mailbox them, so
+ // use lower limits than the default.
+ gpu::SharedMemoryLimits limits = gpu::SharedMemoryLimits::ForMailboxContext();
+
+ bool support_locking = false;
+ bool support_gles2_interface = true;
+ bool support_raster_interface = false;
+ bool support_oop_rasterization = false;
+ bool support_grcontext = false;
+ bool automatic_flushes = false;
+ video_frame_compositor_context_provider_ = CreateOffscreenContext(
+ gpu_channel_host, GetGpuMemoryBufferManager(), limits, support_locking,
+ support_gles2_interface, support_raster_interface,
+ support_oop_rasterization, support_grcontext, automatic_flushes,
+ ws::command_buffer_metrics::ContextType::RENDER_COMPOSITOR,
+ kGpuStreamIdMedia, kGpuStreamPriorityMedia);
+ return video_frame_compositor_context_provider_;
+}
+
+scoped_refptr<ws::ContextProviderCommandBuffer>
RenderThreadImpl::SharedMainThreadContextProvider() {
DCHECK(IsMainThread());
if (shared_main_thread_contexts_ &&
@@ -1504,7 +1512,7 @@ RenderThreadImpl::SharedMainThreadContextProvider() {
gpu::SharedMemoryLimits(), support_locking, support_gles2_interface,
support_raster_interface, support_oop_rasterization, support_grcontext,
automatic_flushes,
- ui::command_buffer_metrics::ContextType::RENDERER_MAIN_THREAD,
+ ws::command_buffer_metrics::ContextType::RENDERER_MAIN_THREAD,
kGpuStreamIdDefault, kGpuStreamPriorityDefault);
auto result = shared_main_thread_contexts_->BindToCurrentThread();
if (result != gpu::ContextResult::kSuccess)
@@ -1519,7 +1527,7 @@ scoped_refptr<StreamTextureFactory> RenderThreadImpl::GetStreamTexureFactory() {
if (!stream_texture_factory_.get() ||
stream_texture_factory_->ContextGL()->GetGraphicsResetStatusKHR() !=
GL_NO_ERROR) {
- scoped_refptr<ui::ContextProviderCommandBuffer> shared_context_provider =
+ scoped_refptr<ws::ContextProviderCommandBuffer> shared_context_provider =
SharedMainThreadContextProvider();
if (!shared_context_provider) {
stream_texture_factory_ = nullptr;
@@ -1565,18 +1573,10 @@ blink::WebString RenderThreadImpl::GetUserAgent() const {
return user_agent_;
}
-bool RenderThreadImpl::OnMessageReceived(const IPC::Message& msg) {
- if (file_system_dispatcher_->OnMessageReceived(msg))
- return true;
- return ChildThreadImpl::OnMessageReceived(msg);
-}
-
void RenderThreadImpl::OnAssociatedInterfaceRequest(
const std::string& name,
mojo::ScopedInterfaceEndpointHandle handle) {
- if (associated_interfaces_.CanBindRequest(name))
- associated_interfaces_.BindRequest(name, std::move(handle));
- else
+ if (!associated_interfaces_.TryBindInterface(name, &handle))
ChildThreadImpl::OnAssociatedInterfaceRequest(name, std::move(handle));
}
@@ -1694,15 +1694,13 @@ void RenderThreadImpl::OnChannelError() {
}
void RenderThreadImpl::OnProcessFinalRelease() {
- if (on_channel_error_called())
- return;
- // The child process shutdown sequence is a request response based mechanism,
- // where we send out an initial feeler request to the child process host
- // instance in the browser to verify if it's ok to shutdown the child process.
- // The browser then sends back a response if it's ok to shutdown. This avoids
- // race conditions if the process refcount is 0 but there's an IPC message
- // inflight that would addref it.
- GetRendererHost()->ShutdownRequest();
+ // Do not shutdown the process. The browser process is the only one
+ // responsible for renderer shutdown.
+ //
+ // Renderer process used to request self shutdown. It has been removed. It
+ // caused race conditions, where the browser process was reusing renderer
+ // processes that were shutting down.
+ // See https://crbug.com/535246 or https://crbug.com/873541/#c8.
}
bool RenderThreadImpl::OnControlMessageReceived(const IPC::Message& msg) {
@@ -1723,12 +1721,6 @@ void RenderThreadImpl::SetSchedulerKeepActive(bool keep_active) {
}
void RenderThreadImpl::SetProcessBackgrounded(bool backgrounded) {
- // Set timer slack to maximum on main thread when in background.
- base::TimerSlack timer_slack = base::TIMER_SLACK_NONE;
- if (backgrounded)
- timer_slack = base::TIMER_SLACK_MAXIMUM;
- main_message_loop_->SetTimerSlack(timer_slack);
-
main_thread_scheduler_->SetRendererBackgrounded(backgrounded);
if (backgrounded) {
needs_to_record_first_active_paint_ = false;
@@ -2003,7 +1995,7 @@ void RenderThreadImpl::RequestNewLayerTreeFrameSink(
params.synthetic_begin_frame_source = CreateSyntheticBeginFrameSource();
#if defined(USE_AURA)
- if (!features::IsAshInBrowserProcess()) {
+ if (features::IsUsingWindowService()) {
if (!RendererWindowTreeClient::Get(routing_id)) {
std::move(callback).Run(nullptr);
return;
@@ -2086,13 +2078,13 @@ void RenderThreadImpl::RequestNewLayerTreeFrameSink(
constexpr bool support_locking = false;
constexpr bool support_grcontext = true;
- scoped_refptr<ui::ContextProviderCommandBuffer> context_provider(
- new ui::ContextProviderCommandBuffer(
+ scoped_refptr<ws::ContextProviderCommandBuffer> context_provider(
+ new ws::ContextProviderCommandBuffer(
gpu_channel_host, GetGpuMemoryBufferManager(), kGpuStreamIdDefault,
kGpuStreamPriorityDefault, gpu::kNullSurfaceHandle, url,
automatic_flushes, support_locking, support_grcontext, limits,
attributes,
- ui::command_buffer_metrics::ContextType::RENDER_COMPOSITOR));
+ ws::command_buffer_metrics::ContextType::RENDER_COMPOSITOR));
if (layout_test_deps_) {
if (!layout_test_deps_->UseDisplayCompositorPixelDump()) {
@@ -2237,6 +2229,8 @@ void RenderThreadImpl::OnNetworkConnectionChanged(
double max_bandwidth_mbps) {
bool online = type != net::NetworkChangeNotifier::CONNECTION_NONE;
WebNetworkStateNotifier::SetOnLine(online);
+ if (url_loader_throttle_provider_)
+ url_loader_throttle_provider_->SetOnline(online);
for (auto& observer : observers_)
observer.NetworkStateChanged(online);
WebNetworkStateNotifier::SetWebConnection(
@@ -2278,7 +2272,7 @@ void RenderThreadImpl::UpdateScrollbarTheme(
blink::WebScrollbarTheme::UpdateScrollbarsWithNSDefaults(
params->initial_button_delay, params->autoscroll_button_delay,
params->preferred_scroller_style, params->redraw,
- params->button_placement, params->jump_on_track_click);
+ params->jump_on_track_click);
is_elastic_overscroll_enabled_ = params->scroll_view_rubber_banding;
#else
@@ -2406,7 +2400,7 @@ RenderThreadImpl::SharedCompositorWorkerContextProvider() {
std::move(gpu_channel_host), GetGpuMemoryBufferManager(),
shared_memory_limits, support_locking, support_gles2_interface,
support_raster_interface, support_oop_rasterization, support_grcontext,
- automatic_flushes, ui::command_buffer_metrics::ContextType::RENDER_WORKER,
+ automatic_flushes, ws::command_buffer_metrics::ContextType::RENDER_WORKER,
kGpuStreamIdWorker, kGpuStreamPriorityWorker);
auto result = shared_worker_context_provider_->BindToCurrentThread();
if (result != gpu::ContextResult::kSuccess)
@@ -2414,10 +2408,6 @@ RenderThreadImpl::SharedCompositorWorkerContextProvider() {
return shared_worker_context_provider_;
}
-void RenderThreadImpl::SampleGamepads(device::Gamepads* data) {
- blink_platform_impl_->SampleGamepads(*data);
-}
-
bool RenderThreadImpl::RendererIsHidden() const {
return widget_count_ > 0 && hidden_widget_count_ == widget_count_;
}
diff --git a/chromium/content/renderer/render_thread_impl.h b/chromium/content/renderer/render_thread_impl.h
index 78326bc4c21..61d79566e6b 100644
--- a/chromium/content/renderer/render_thread_impl.h
+++ b/chromium/content/renderer/render_thread_impl.h
@@ -30,7 +30,6 @@
#include "build/build_config.h"
#include "content/child/child_thread_impl.h"
#include "content/child/memory/child_memory_coordinator_impl.h"
-#include "content/common/associated_interface_registry_impl.h"
#include "content/common/content_export.h"
#include "content/common/frame.mojom.h"
#include "content/common/frame_replication_state.h"
@@ -58,8 +57,9 @@
#include "services/service_manager/public/cpp/bind_source_info.h"
#include "services/service_manager/public/cpp/binder_registry.h"
#include "services/viz/public/interfaces/compositing/compositing_mode_watcher.mojom.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
#include "third_party/blink/public/mojom/dom_storage/storage_partition_service.mojom.h"
-#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
+#include "third_party/blink/public/platform/scheduler/web_rail_mode_observer.h"
#include "third_party/blink/public/platform/web_connection_type.h"
#include "third_party/blink/public/web/web_memory_statistics.h"
#include "ui/gfx/native_widget_types.h"
@@ -89,10 +89,6 @@ class SyntheticBeginFrameSource;
class TaskGraphRunner;
}
-namespace device {
-class Gamepads;
-}
-
namespace discardable_memory {
class ClientDiscardableSharedMemoryManager;
}
@@ -109,11 +105,6 @@ namespace media {
class GpuVideoAcceleratorFactories;
}
-namespace ui {
-class ContextProviderCommandBuffer;
-class Gpu;
-}
-
namespace v8 {
class Extension;
}
@@ -124,6 +115,11 @@ class RasterContextProvider;
class SyntheticBeginFrameSource;
}
+namespace ws {
+class ContextProviderCommandBuffer;
+class Gpu;
+} // namespace ws
+
namespace content {
class AppCacheDispatcher;
@@ -132,7 +128,6 @@ class AudioRendererMixerManager;
class BrowserPluginManager;
class CategorizedWorkerPool;
class DomStorageDispatcher;
-class FileSystemDispatcher;
class FrameSwapMessageQueue;
class GpuVideoAcceleratorFactoriesImpl;
class IndexedDBDispatcher;
@@ -168,18 +163,12 @@ class StreamTextureFactory;
class CONTENT_EXPORT RenderThreadImpl
: public RenderThread,
public ChildThreadImpl,
- public blink::scheduler::WebThreadScheduler::RAILModeObserver,
+ public blink::scheduler::WebRAILModeObserver,
public base::MemoryCoordinatorClient,
public mojom::Renderer,
public viz::mojom::CompositingModeWatcher,
public CompositorDependencies {
public:
- static RenderThreadImpl* Create(const InProcessChildThreadParams& params,
- base::MessageLoop* unowned_message_loop);
- static RenderThreadImpl* Create(
- std::unique_ptr<base::MessageLoop> main_message_loop,
- std::unique_ptr<blink::scheduler::WebThreadScheduler>
- main_thread_scheduler);
static RenderThreadImpl* current();
static mojom::RenderMessageFilter* current_render_message_filter();
static RendererBlinkPlatformImpl* current_blink_platform_impl();
@@ -193,6 +182,11 @@ class CONTENT_EXPORT RenderThreadImpl
static scoped_refptr<base::SingleThreadTaskRunner>
DeprecatedGetMainTaskRunner();
+ explicit RenderThreadImpl(
+ std::unique_ptr<blink::scheduler::WebThreadScheduler> scheduler);
+ RenderThreadImpl(
+ const InProcessChildThreadParams& params,
+ std::unique_ptr<blink::scheduler::WebThreadScheduler> scheduler);
~RenderThreadImpl() override;
void Shutdown() override;
bool ShouldBeDestroyed() override;
@@ -232,7 +226,6 @@ class CONTENT_EXPORT RenderThreadImpl
blink::WebString GetUserAgent() const override;
// IPC::Listener implementation via ChildThreadImpl:
- bool OnMessageReceived(const IPC::Message& msg) override;
void OnAssociatedInterfaceRequest(
const std::string& name,
mojo::ScopedInterfaceEndpointHandle handle) override;
@@ -263,7 +256,7 @@ class CONTENT_EXPORT RenderThreadImpl
bool IsThreadedAnimationEnabled();
- // blink::scheduler::WebThreadScheduler::RAILModeObserver implementation.
+ // blink::scheduler::WebRAILModeObserver implementation.
void OnRAILModeChanged(v8::RAILMode rail_mode) override;
// viz::mojom::CompositingModeWatcher implementation.
@@ -339,10 +332,6 @@ class CONTENT_EXPORT RenderThreadImpl
return dom_storage_dispatcher_.get();
}
- FileSystemDispatcher* file_system_dispatcher() const {
- return file_system_dispatcher_.get();
- }
-
MidiMessageFilter* midi_message_filter() {
return midi_message_filter_.get();
}
@@ -403,6 +392,13 @@ class CONTENT_EXPORT RenderThreadImpl
// A TaskRunner instance that runs tasks on the raster worker pool.
base::TaskRunner* GetWorkerTaskRunner();
+ // Creates a ContextProvider if yet created, and returns it to be used for
+ // video frame compositing. The ContextProvider given as an argument is
+ // one that has been lost, and is a hint to the RenderThreadImpl to clear
+ // it's |video_frame_compositor_context_provider_| if it matches.
+ scoped_refptr<viz::ContextProvider> GetVideoFrameCompositorContextProvider(
+ scoped_refptr<viz::ContextProvider>);
+
// Returns a worker context provider that will be bound on the compositor
// thread.
scoped_refptr<viz::RasterContextProvider>
@@ -415,7 +411,7 @@ class CONTENT_EXPORT RenderThreadImpl
media::GpuVideoAcceleratorFactories* GetGpuFactories();
- scoped_refptr<ui::ContextProviderCommandBuffer>
+ scoped_refptr<ws::ContextProviderCommandBuffer>
SharedMainThreadContextProvider();
// AudioRendererMixerManager instance which manages renderer side mixer
@@ -482,9 +478,6 @@ class CONTENT_EXPORT RenderThreadImpl
return &histogram_customizer_;
}
- // Retrieve current gamepad data.
- void SampleGamepads(device::Gamepads* data);
-
// Called by a RenderWidget when it is created or destroyed. This
// allows the process to know when there are no visible widgets.
void WidgetCreated();
@@ -522,15 +515,8 @@ class CONTENT_EXPORT RenderThreadImpl
// Sets the current pipeline rendering color space.
void SetRenderingColorSpace(const gfx::ColorSpace& color_space);
- protected:
- RenderThreadImpl(
- const InProcessChildThreadParams& params,
- std::unique_ptr<blink::scheduler::WebThreadScheduler> scheduler,
- const scoped_refptr<base::SingleThreadTaskRunner>& resource_task_queue,
- base::MessageLoop* unowned_message_loop);
- RenderThreadImpl(
- std::unique_ptr<base::MessageLoop> main_message_loop,
- std::unique_ptr<blink::scheduler::WebThreadScheduler> scheduler);
+ scoped_refptr<base::SingleThreadTaskRunner>
+ CreateVideoFrameCompositorTaskRunner();
private:
void OnProcessFinalRelease() override;
@@ -550,14 +536,9 @@ class CONTENT_EXPORT RenderThreadImpl
void RecordPurgeMemory(RendererMemoryMetrics before);
- void Init(
- const scoped_refptr<base::SingleThreadTaskRunner>& resource_task_queue);
-
+ void Init();
void InitializeCompositorThread();
-
- void InitializeWebKit(
- const scoped_refptr<base::SingleThreadTaskRunner>& resource_task_queue,
- service_manager::BinderRegistry* registry);
+ void InitializeWebKit(service_manager::BinderRegistry* registry);
void OnTransferBitmap(const SkBitmap& bitmap, int resource_id);
void OnGetAccessibilityTree();
@@ -630,7 +611,6 @@ class CONTENT_EXPORT RenderThreadImpl
std::unique_ptr<blink::scheduler::WebThreadScheduler> main_thread_scheduler_;
std::unique_ptr<RendererBlinkPlatformImpl> blink_platform_impl_;
std::unique_ptr<ResourceDispatcher> resource_dispatcher_;
- std::unique_ptr<FileSystemDispatcher> file_system_dispatcher_;
std::unique_ptr<URLLoaderThrottleProvider> url_loader_throttle_provider_;
// Used on the renderer and IPC threads.
@@ -690,15 +670,6 @@ class CONTENT_EXPORT RenderThreadImpl
// software-based.
bool is_gpu_compositing_disabled_ = false;
- // The message loop of the renderer main thread.
- // This message loop should be destructed before the RenderThreadImpl
- // shuts down Blink.
- // Some test users (e.g. InProcessRenderThread) own the MessageLoop used by
- // their RenderThreadImpls. |main_message_loop_| is always non-nulll,
- // |owned_message_loop_| is non-null if handed in at creation.
- const std::unique_ptr<base::MessageLoop> owned_message_loop_;
- base::MessageLoop* const main_message_loop_;
-
// May be null if overridden by ContentRendererClient.
std::unique_ptr<blink::scheduler::WebThreadBase> compositor_thread_;
@@ -715,6 +686,10 @@ class CONTENT_EXPORT RenderThreadImpl
// regardless of whether |compositor_thread_| is overriden.
scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_;
+ // Task to run the VideoFrameCompositor on.
+ scoped_refptr<base::SingleThreadTaskRunner>
+ video_frame_compositor_task_runner_;
+
// Pool of workers used for raster operations (e.g., tile rasterization).
scoped_refptr<CategorizedWorkerPool> categorized_worker_pool_;
@@ -722,9 +697,11 @@ class CONTENT_EXPORT RenderThreadImpl
scoped_refptr<StreamTextureFactory> stream_texture_factory_;
#endif
- scoped_refptr<ui::ContextProviderCommandBuffer> shared_main_thread_contexts_;
+ scoped_refptr<ws::ContextProviderCommandBuffer> shared_main_thread_contexts_;
+
+ base::ObserverList<RenderThreadObserver>::Unchecked observers_;
- base::ObserverList<RenderThreadObserver> observers_;
+ scoped_refptr<viz::ContextProvider> video_frame_compositor_context_provider_;
scoped_refptr<viz::RasterContextProvider> shared_worker_context_provider_;
@@ -738,7 +715,7 @@ class CONTENT_EXPORT RenderThreadImpl
// memory saving mode.
std::unique_ptr<LowMemoryModeController> low_memory_mode_controller_;
- std::unique_ptr<ui::Gpu> gpu_;
+ std::unique_ptr<ws::Gpu> gpu_;
scoped_refptr<base::SingleThreadTaskRunner>
main_thread_compositor_task_runner_;
@@ -789,7 +766,7 @@ class CONTENT_EXPORT RenderThreadImpl
blink::mojom::StoragePartitionServicePtr storage_partition_service_;
mojom::RendererHostAssociatedPtr renderer_host_;
- AssociatedInterfaceRegistryImpl associated_interfaces_;
+ blink::AssociatedInterfaceRegistry associated_interfaces_;
mojo::AssociatedBinding<mojom::Renderer> renderer_binding_;
diff --git a/chromium/content/renderer/render_thread_impl_browsertest.cc b/chromium/content/renderer/render_thread_impl_browsertest.cc
index 3e65072fe27..93a88a7ea72 100644
--- a/chromium/content/renderer/render_thread_impl_browsertest.cc
+++ b/chromium/content/renderer/render_thread_impl_browsertest.cc
@@ -21,7 +21,7 @@
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
-#include "base/task_scheduler/task_scheduler.h"
+#include "base/task/task_scheduler/task_scheduler.h"
#include "base/test/scoped_feature_list.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -122,31 +122,6 @@ class TestTaskCounter : public base::SingleThreadTaskRunner {
int count_;
};
-#if defined(COMPILER_MSVC)
-// See explanation for other RenderViewHostImpl which is the same issue.
-#pragma warning(push)
-#pragma warning(disable: 4250)
-#endif
-
-class RenderThreadImplForTest : public RenderThreadImpl {
- public:
- RenderThreadImplForTest(
- const InProcessChildThreadParams& params,
- std::unique_ptr<blink::scheduler::WebThreadScheduler> scheduler,
- scoped_refptr<base::SingleThreadTaskRunner>& test_task_counter,
- base::MessageLoop* unowned_message_loop)
- : RenderThreadImpl(params,
- std::move(scheduler),
- test_task_counter,
- unowned_message_loop) {}
-
- ~RenderThreadImplForTest() override {}
-};
-
-#if defined(COMPILER_MSVC)
-#pragma warning(pop)
-#endif
-
class QuitOnTestMsgFilter : public IPC::MessageFilter {
public:
explicit QuitOnTestMsgFilter(base::OnceClosure quit_closure)
@@ -201,12 +176,12 @@ class RenderThreadImplBrowserTest : public testing::Test {
content_renderer_client_.reset(new ContentRendererClient());
SetRendererClientForTesting(content_renderer_client_.get());
- main_message_loop_.reset(new base::MessageLoop(base::MessageLoop::TYPE_IO));
+ main_message_loop_.reset(new base::MessageLoop(base::MessageLoop::TYPE_UI));
test_task_scheduler_.reset(new TestTaskScheduler);
browser_threads_.reset(
- new TestBrowserThreadBundle(TestBrowserThreadBundle::IO_MAINLOOP));
+ new TestBrowserThreadBundle(TestBrowserThreadBundle::REAL_IO_THREAD));
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner =
- blink::scheduler::GetSingleThreadTaskRunnerForTesting();
+ BrowserThread::GetTaskRunnerForThread(BrowserThread::IO);
InitializeMojo();
mojo_ipc_support_.reset(new mojo::core::ScopedIPCSupport(
@@ -256,11 +231,10 @@ class RenderThreadImplBrowserTest : public testing::Test {
base::FieldTrialList::CreateTrialsFromCommandLine(
*cmd, switches::kFieldTrialHandle, -1);
- thread_ = new RenderThreadImplForTest(
+ thread_ = new RenderThreadImpl(
InProcessChildThreadParams(io_task_runner, &invitation,
child_connection_->service_token()),
- std::move(main_thread_scheduler), test_task_counter,
- main_message_loop_.get());
+ std::move(main_thread_scheduler));
cmd->InitFromArgv(old_argv);
run_loop_ = std::make_unique<base::RunLoop>();
@@ -297,7 +271,11 @@ class RenderThreadImplBrowserTest : public testing::Test {
std::unique_ptr<MockRenderProcess> mock_process_;
scoped_refptr<QuitOnTestMsgFilter> test_msg_filter_;
- RenderThreadImplForTest* thread_; // Owned by mock_process_.
+
+ // RenderThreadImpl doesn't currently support a proper shutdown sequence
+ // and it's okay when we're running in multi-process mode because renderers
+ // get killed by the OS. Memory leaks aren't nice but it's test-only.
+ RenderThreadImpl* thread_;
base::FieldTrialList field_trial_list_;
diff --git a/chromium/content/renderer/render_view_browsertest.cc b/chromium/content/renderer/render_view_browsertest.cc
index caa6b4a4d37..d22f9ea8f65 100644
--- a/chromium/content/renderer/render_view_browsertest.cc
+++ b/chromium/content/renderer/render_view_browsertest.cc
@@ -91,6 +91,7 @@
#include "ui/accessibility/ax_modes.h"
#include "ui/events/base_event_utils.h"
#include "ui/events/event.h"
+#include "ui/events/keycodes/dom/dom_code.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/codec/jpeg_codec.h"
#include "ui/gfx/range/range.h"
@@ -249,6 +250,24 @@ class RenderViewImplTest : public RenderViewTest {
return static_cast<TestRenderFrame*>(view()->GetMainRenderFrame());
}
+ void ReceiveDisableDeviceEmulation(RenderViewImpl* view) {
+ // Emulates receiving an IPC message.
+ view->GetWidget()->OnDisableDeviceEmulation();
+ }
+
+ void ReceiveEnableDeviceEmulation(
+ RenderViewImpl* view,
+ const blink::WebDeviceEmulationParams& params) {
+ // Emulates receiving an IPC message.
+ view->GetWidget()->OnEnableDeviceEmulation(params);
+ }
+
+ void ReceiveSetTextDirection(RenderViewImpl* view,
+ blink::WebTextDirection direction) {
+ // Emulates receiving an IPC message.
+ view->OnSetTextDirection(direction);
+ }
+
void GoToOffsetWithParams(int offset,
const PageState& state,
const CommonNavigationParams common_params,
@@ -370,7 +389,7 @@ class RenderViewImplTest : public RenderViewTest {
ui::KeyEvent char_event(keydown_event.GetCharacter(),
static_cast<ui::KeyboardCode>(key_code),
- flags);
+ ui::DomCode::NONE, flags);
NativeWebKeyboardEvent char_web_event(char_event);
SendNativeKeyEvent(char_web_event);
@@ -396,7 +415,7 @@ class RenderViewImplTest : public RenderViewTest {
}
const gfx::Size& GetPreferredSize() {
- view()->CheckPreferredSize();
+ view()->UpdatePreferredSize();
return view()->preferred_size_;
}
@@ -487,7 +506,7 @@ class RenderViewImplScaleFactorTest : public RenderViewImplTest {
params.view_size.width = width;
params.view_size.height = height;
params.device_scale_factor = dpr;
- view()->OnEnableDeviceEmulation(params);
+ ReceiveEnableDeviceEmulation(view(), params);
EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(get_width, &emulated_width));
EXPECT_EQ(width, emulated_width);
EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(get_height,
@@ -524,80 +543,6 @@ class RenderViewImplDisableZoomForDSFTest
}
};
-#if defined(OS_ANDROID)
-class TapCallbackFilter : public IPC::Listener {
- public:
- explicit TapCallbackFilter(
- base::RepeatingCallback<void(const gfx::Rect&, const gfx::Size&)>
- callback)
- : callback_(callback) {}
-
- bool OnMessageReceived(const IPC::Message& msg) override {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(TapCallbackFilter, msg)
- IPC_MESSAGE_HANDLER(ViewHostMsg_ShowDisambiguationPopup,
- OnShowDisambiguationPopup)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
- }
-
- void OnShowDisambiguationPopup(const gfx::Rect& rect_pixels,
- const gfx::Size& size,
- base::SharedMemoryHandle handle) {
- callback_.Run(rect_pixels, size);
- }
-
- private:
- base::RepeatingCallback<void(const gfx::Rect&, const gfx::Size&)> callback_;
-};
-
-static blink::WebCoalescedInputEvent FatTap(int x,
- int y,
- int width,
- int height) {
- blink::WebGestureEvent event(
- blink::WebInputEvent::kGestureTap, blink::WebInputEvent::kNoModifiers,
- blink::WebInputEvent::GetStaticTimeStampForTests(),
- blink::kWebGestureDeviceTouchscreen);
- event.SetPositionInWidget(gfx::PointF(x, y));
- event.data.tap.width = width;
- event.data.tap.height = height;
- return blink::WebCoalescedInputEvent(event);
-}
-
-TEST_F(RenderViewImplScaleFactorTest, TapDisambiguatorSize) {
- // TODO(oshima): This test tried in the past to enable UseZoomForDSF but
- // didn't actually do so for the compositor, and fails with it enabled.
- const float device_scale = 2.625f;
- SetDeviceScaleFactor(device_scale);
- EXPECT_EQ(device_scale, view()->GetDeviceScaleFactor());
-
- LoadHTML(
- "<style type=\"text/css\">"
- " a {"
- " display: block;"
- " width: 40px;"
- " height: 40px;"
- " background-color:#ccccff;"
- " }"
- "</style>"
- "<body style=\"margin: 0px\">"
- "<a href=\"#\">link </a>"
- "<a href=\"#\">link </a>"
- "</body>");
- std::unique_ptr<TapCallbackFilter> callback_filter(
- new TapCallbackFilter(base::BindRepeating(
- [](const gfx::Rect& rect_pixels, const gfx::Size& canvas_size) {
- EXPECT_EQ(rect_pixels, gfx::Rect(28, 68, 24, 24));
- EXPECT_EQ(canvas_size, gfx::Size(48, 48));
- })));
- render_thread_->sink().AddFilter(callback_filter.get());
- view()->webview()->HandleInputEvent(FatTap(40, 80, 200, 200));
- render_thread_->sink().RemoveFilter(callback_filter.get());
-}
-#endif
-
// Ensure that the main RenderFrame is deleted and cleared from the RenderView
// after closing it.
TEST_F(RenderViewImplTest, RenderFrameClearedAfterClose) {
@@ -732,12 +677,6 @@ TEST_F(RenderViewImplTest, DecideNavigationPolicy) {
// stop and be sent to the browser.
EXPECT_EQ(blink::kWebNavigationPolicyHandledByClient, policy);
- // If this a navigation that is ready to commit, it should be handled
- // locally.
- request.SetCheckForBrowserSideNavigation(false);
- policy = frame()->DecidePolicyForNavigation(policy_info);
- EXPECT_EQ(blink::kWebNavigationPolicyCurrentTab, policy);
-
// Verify that form posts to WebUI URLs will be sent to the browser process.
blink::WebURLRequest form_request(GURL("chrome://foo"));
blink::WebLocalFrameClient::NavigationPolicyInfo form_policy_info(
@@ -893,10 +832,10 @@ TEST_F(RenderViewImplScaleFactorTest, DeviceEmulationWithOOPIF) {
view()->GetWidget()->GetOriginalScreenInfo().device_scale_factor);
EXPECT_EQ(device_scale, child_proxy->screen_info().device_scale_factor);
- view()->OnDisableDeviceEmulation();
+ ReceiveDisableDeviceEmulation(view());
blink::WebDeviceEmulationParams params;
- view()->OnEnableDeviceEmulation(params);
+ ReceiveEnableDeviceEmulation(view(), params);
// Don't disable here to test that emulation is being shutdown properly.
}
@@ -1458,7 +1397,7 @@ TEST_F(RenderViewImplTest, OnSetTextDirection) {
for (size_t i = 0; i < arraysize(kTextDirection); ++i) {
// Set the text direction of the <textarea> element.
ExecuteJavaScriptForTests("document.getElementById('test').focus();");
- view()->OnSetTextDirection(kTextDirection[i].direction);
+ ReceiveSetTextDirection(view(), kTextDirection[i].direction);
// Write the values of its DOM 'dir' attribute and its CSS 'direction'
// property to the <div> element.
@@ -1844,7 +1783,15 @@ TEST_F(RenderViewImplTest, OnDeleteSurroundingText) {
EXPECT_EQ(0, info.selection_end);
}
-TEST_F(RenderViewImplTest, OnDeleteSurroundingTextInCodePoints) {
+#if defined(OS_ANDROID)
+// Failing on Android M: http://crbug.com/873580
+#define MAYBE_OnDeleteSurroundingTextInCodePoints \
+ DISABLED_OnDeleteSurroundingTextInCodePoints
+#else
+#define MAYBE_OnDeleteSurroundingTextInCodePoints \
+ OnDeleteSurroundingTextInCodePoints
+#endif
+TEST_F(RenderViewImplTest, MAYBE_OnDeleteSurroundingTextInCodePoints) {
// Load an HTML page consisting of an input field.
LoadHTML(
// "ab" + trophy + space + "cdef" + trophy + space + "gh".
@@ -1911,7 +1858,7 @@ TEST_F(RenderViewImplTest, BasicRenderFrame) {
TEST_F(RenderViewImplTest, MessageOrderInDidChangeSelection) {
LoadHTML("<textarea id=\"test\"></textarea>");
- view()->SetHandlingInputEventForTesting(true);
+ view()->GetWidget()->SetHandlingInputEvent(true);
ExecuteJavaScriptForTests("document.getElementById('test').focus();");
bool is_input_type_called = false;
@@ -2551,20 +2498,38 @@ TEST_F(RenderViewImplBlinkSettingsTest, Default) {
TEST_F(RenderViewImplBlinkSettingsTest, CommandLine) {
base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
- switches::kBlinkSettings,
- "multiTargetTapNotificationEnabled=true,viewportEnabled=true");
+ switches::kBlinkSettings, "viewportEnabled=true");
DoSetUp();
- EXPECT_TRUE(settings()->MultiTargetTapNotificationEnabled());
EXPECT_TRUE(settings()->ViewportEnabled());
}
-TEST_F(RenderViewImplBlinkSettingsTest, Negative) {
- base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
- switches::kBlinkSettings,
- "multiTargetTapNotificationEnabled=false,viewportEnabled=true");
+// Ensure that setting default page scale limits immediately recomputes the
+// minimum scale factor to the final value. With
+// shrinks_viewport_contents_to_fit, Blink clamps the minimum cased on the
+// content width. In this case, that'll always be 1.
+TEST_F(RenderViewImplBlinkSettingsTest, DefaultPageScaleSettings) {
DoSetUp();
- EXPECT_FALSE(settings()->MultiTargetTapNotificationEnabled());
- EXPECT_TRUE(settings()->ViewportEnabled());
+ LoadHTML(
+ "<style>"
+ " body,html {"
+ " margin: 0;"
+ " width:100%;"
+ " height:100%;"
+ "}"
+ "</style>");
+
+ EXPECT_EQ(1.f, view()->webview()->PageScaleFactor());
+ EXPECT_EQ(1.f, view()->webview()->MinimumPageScaleFactor());
+
+ WebPreferences prefs;
+ prefs.shrinks_viewport_contents_to_fit = true;
+ prefs.default_minimum_page_scale_factor = 0.1f;
+ prefs.default_maximum_page_scale_factor = 5.5f;
+ view()->SetWebkitPreferences(prefs);
+
+ EXPECT_EQ(1.f, view()->webview()->PageScaleFactor());
+ EXPECT_EQ(1.f, view()->webview()->MinimumPageScaleFactor());
+ EXPECT_EQ(5.5f, view()->webview()->MaximumPageScaleFactor());
}
TEST_F(RenderViewImplDisableZoomForDSFTest,
@@ -2599,10 +2564,10 @@ TEST_F(RenderViewImplScaleFactorTest, ScreenMetricsEmulationWithOriginalDSF1) {
TestEmulatedSizeDprDsf(1005, 1102, 3.f, 1.f);
}
- view()->OnDisableDeviceEmulation();
+ ReceiveDisableDeviceEmulation(view());
blink::WebDeviceEmulationParams params;
- view()->OnEnableDeviceEmulation(params);
+ ReceiveEnableDeviceEmulation(view(), params);
// Don't disable here to test that emulation is being shutdown properly.
}
@@ -2628,10 +2593,10 @@ TEST_F(RenderViewImplScaleFactorTest, ScreenMetricsEmulationWithOriginalDSF2) {
TestEmulatedSizeDprDsf(1005, 1102, 3.f, compositor_dsf);
}
- view()->OnDisableDeviceEmulation();
+ ReceiveDisableDeviceEmulation(view());
blink::WebDeviceEmulationParams params;
- view()->OnEnableDeviceEmulation(params);
+ ReceiveEnableDeviceEmulation(view(), params);
// Don't disable here to test that emulation is being shutdown properly.
}
@@ -2714,7 +2679,8 @@ const char kAutoResizeTestPage[] =
} // namespace
TEST_F(RenderViewImplEnableZoomForDSFTest, AutoResizeWithZoomForDSF) {
- view()->EnableAutoResizeForTesting(gfx::Size(5, 5), gfx::Size(1000, 1000));
+ view()->GetWidget()->EnableAutoResizeForTesting(gfx::Size(5, 5),
+ gfx::Size(1000, 1000));
LoadHTML(kAutoResizeTestPage);
gfx::Size size_at_1x = view()->GetWidget()->size();
ASSERT_FALSE(size_at_1x.IsEmpty());
@@ -2726,7 +2692,8 @@ TEST_F(RenderViewImplEnableZoomForDSFTest, AutoResizeWithZoomForDSF) {
}
TEST_F(RenderViewImplScaleFactorTest, AutoResizeWithoutZoomForDSF) {
- view()->EnableAutoResizeForTesting(gfx::Size(5, 5), gfx::Size(1000, 1000));
+ view()->GetWidget()->EnableAutoResizeForTesting(gfx::Size(5, 5),
+ gfx::Size(1000, 1000));
LoadHTML(kAutoResizeTestPage);
gfx::Size size_at_1x = view()->GetWidget()->size();
ASSERT_FALSE(size_at_1x.IsEmpty());
diff --git a/chromium/content/renderer/render_view_impl.cc b/chromium/content/renderer/render_view_impl.cc
index 03d9cda9f95..215c4a750f0 100644
--- a/chromium/content/renderer/render_view_impl.cc
+++ b/chromium/content/renderer/render_view_impl.cc
@@ -75,7 +75,6 @@
#include "content/renderer/drop_data_builder.h"
#include "content/renderer/gpu/layer_tree_view.h"
#include "content/renderer/history_serialization.h"
-#include "content/renderer/idle_user_detector.h"
#include "content/renderer/ime_event_guard.h"
#include "content/renderer/internal_document_state_data.h"
#include "content/renderer/loader/request_extra_data.h"
@@ -140,6 +139,7 @@
#include "third_party/blink/public/web/web_dom_event.h"
#include "third_party/blink/public/web/web_dom_message_event.h"
#include "third_party/blink/public/web/web_element.h"
+#include "third_party/blink/public/web/web_file_chooser_completion.h"
#include "third_party/blink/public/web/web_file_chooser_params.h"
#include "third_party/blink/public/web/web_form_control_element.h"
#include "third_party/blink/public/web/web_form_element.h"
@@ -184,7 +184,6 @@
#include "base/android/build_info.h"
#include "base/memory/shared_memory.h"
#include "content/child/child_thread_impl.h"
-#include "content/renderer/android/disambiguation_popup_helper.h"
#include "ui/gfx/geometry/rect_f.h"
#elif defined(OS_MACOSX)
@@ -423,43 +422,21 @@ content::mojom::WindowContainerType WindowFeaturesToContainerType(
} // namespace
-RenderViewImpl::RenderViewImpl(
- CompositorDependencies* compositor_deps,
- const mojom::CreateViewParams& params,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+RenderViewImpl::RenderViewImpl(CompositorDependencies* compositor_deps,
+ const mojom::CreateViewParams& params)
: RenderWidget(params.main_frame_widget_routing_id,
compositor_deps,
blink::kWebPopupTypeNone,
params.visual_properties.screen_info,
+ params.visual_properties.display_mode,
params.swapped_out,
params.hidden,
- params.never_visible,
- task_runner),
+ params.never_visible),
routing_id_(params.view_id),
+ renderer_wide_named_frame_lookup_(
+ params.renderer_wide_named_frame_lookup),
webkit_preferences_(params.web_preferences),
- send_content_state_immediately_(false),
- send_preferred_size_changes_(false),
- navigation_gesture_(NavigationGestureUnknown),
- history_list_offset_(-1),
- history_list_length_(0),
- frames_in_progress_(0),
- target_url_status_(TARGET_NONE),
-#if defined(OS_ANDROID)
- top_controls_constraints_(BROWSER_CONTROLS_STATE_BOTH),
-#endif
- browser_controls_shrink_blink_size_(false),
- top_controls_height_(0.f),
- bottom_controls_height_(0.f),
- webview_(nullptr),
- page_zoom_level_(0),
- main_render_frame_(nullptr),
- frame_widget_(nullptr),
-#if defined(OS_ANDROID)
- was_created_by_renderer_(false),
-#endif
- enumeration_completion_id_(0),
session_storage_namespace_id_(params.session_storage_namespace_id),
- renderer_wide_named_frame_lookup_(false),
weak_ptr_factory_(this) {
GetWidget()->set_owner_delegate(this);
RenderThread::Get()->AddRoute(routing_id_, this);
@@ -469,14 +446,12 @@ void RenderViewImpl::Initialize(
mojom::CreateViewParamsPtr params,
RenderWidget::ShowCallback show_callback,
scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
- bool was_created_by_renderer = !show_callback.is_null();
+ bool has_show_callback = !!show_callback;
#if defined(OS_ANDROID)
// TODO(sgurun): crbug.com/325351 Needed only for android webview's deprecated
// HandleNavigation codepath.
- was_created_by_renderer_ = was_created_by_renderer;
+ was_created_by_renderer_ = has_show_callback;
#endif
- renderer_wide_named_frame_lookup_ = params->renderer_wide_named_frame_lookup;
- display_mode_ = params->visual_properties.display_mode;
WebFrame* opener_frame =
RenderFrameImpl::ResolveOpener(params->opener_frame_route_id);
@@ -499,7 +474,7 @@ void RenderViewImpl::Initialize(
if (command_line.HasSwitch(switches::kStatsCollectionController))
stats_collection_observer_.reset(new StatsCollectionObserver(this));
- webview()->SetDisplayMode(display_mode_);
+ webview()->SetDisplayMode(GetWidget()->display_mode());
webview()->GetSettings()->SetThreadedScrollingEnabled(
!command_line.HasSwitch(switches::kDisableThreadedScrolling));
webview()->SetShowFPSCounter(
@@ -530,14 +505,14 @@ void RenderViewImpl::Initialize(
webview()->GetSettings()->SetPassiveEventListenerDefault(passiveDefault);
}
- std::string fmp_network_quiet_timeout =
- command_line.GetSwitchValueASCII(switches::kFMPNetworkQuietTimeout);
- if (!fmp_network_quiet_timeout.empty()) {
- double fmp_network_quiet_timeout_seconds = 0.0;
- if (base::StringToDouble(fmp_network_quiet_timeout,
- &fmp_network_quiet_timeout_seconds)) {
- webview()->GetSettings()->SetFMPNetworkQuietTimeout(
- fmp_network_quiet_timeout_seconds);
+ std::string network_quiet_timeout =
+ command_line.GetSwitchValueASCII(switches::kNetworkQuietTimeout);
+ if (!network_quiet_timeout.empty()) {
+ double network_quiet_timeout_seconds = 0.0;
+ if (base::StringToDouble(network_quiet_timeout,
+ &network_quiet_timeout_seconds)) {
+ webview()->GetSettings()->SetNetworkQuietTimeout(
+ network_quiet_timeout_seconds);
}
}
@@ -551,9 +526,9 @@ void RenderViewImpl::Initialize(
this, params->main_frame_routing_id,
std::move(main_frame_interface_provider),
params->main_frame_widget_routing_id, params->hidden,
- GetWebScreenInfo(), compositor_deps_, opener_frame,
- params->devtools_main_frame_token, params->replicated_frame_state,
- params->has_committed_real_load);
+ GetWidget()->GetWebScreenInfo(), GetWidget()->compositor_deps(),
+ opener_frame, params->devtools_main_frame_token,
+ params->replicated_frame_state, params->has_committed_real_load);
}
// TODO(dcheng): Shouldn't these be mutually exclusive at this point? See
@@ -572,10 +547,11 @@ void RenderViewImpl::Initialize(
// If this RenderView's creation was initiated by an opener page in this
// process, (e.g. window.open()), we won't be visible until we ask the opener,
- // via show_callback, to make us visible. Otherwise, we went through a
- // browser-initiated creation, and show() won't be called.
- if (!was_created_by_renderer)
- did_show_ = true;
+ // via |show_callback|, to make us visible. Otherwise, we went through a
+ // browser-initiated creation, and Show() won't be called. In this case, no
+ // |show_callback| is given to inform that Show() won't be called.
+ if (!has_show_callback)
+ RenderWidget::set_did_show();
// TODO(davidben): Move this state from Blink into content.
if (params->window_was_created_with_opener)
@@ -583,16 +559,13 @@ void RenderViewImpl::Initialize(
UpdateWebViewWithDeviceScaleFactor();
OnSetRendererPrefs(params->renderer_preferences);
-
OnSynchronizeVisualProperties(params->visual_properties);
-
- idle_user_detector_.reset(new IdleUserDetector());
+ RenderWidget::SetUpIdleUserDetector();
GetContentClient()->renderer()->RenderViewCreated(this);
page_zoom_level_ = 0;
nav_state_sync_timer_.SetTaskRunner(task_runner);
- check_preferred_size_timer_.SetTaskRunner(std::move(task_runner));
}
RenderViewImpl::~RenderViewImpl() {
@@ -616,7 +589,6 @@ RenderViewImpl::~RenderViewImpl() {
DCHECK_NE(this, it->second) << "Failed to call Close?";
#endif
- idle_user_detector_.reset();
for (auto& observer : observers_)
observer.RenderViewGone();
for (auto& observer : observers_)
@@ -817,7 +789,12 @@ void RenderView::ApplyWebPreferences(const WebPreferences& prefs,
settings->SetTextTrackMarginPercentage(prefs.text_track_margin_percentage);
- // Needs to happen before setIgnoreVIewportTagScaleLimits below.
+ // Needs to happen before SetDefaultPageScaleLimits below since that'll
+ // recalculate the final page scale limits and that depends on this setting.
+ settings->SetShrinksViewportContentToFit(
+ prefs.shrinks_viewport_contents_to_fit);
+
+ // Needs to happen before SetIgnoreViewportTagScaleLimits below.
web_view->SetDefaultPageScaleLimits(prefs.default_minimum_page_scale_factor,
prefs.default_maximum_page_scale_factor);
@@ -912,8 +889,6 @@ void RenderView::ApplyWebPreferences(const WebPreferences& prefs,
settings->SetViewportEnabled(prefs.viewport_enabled);
settings->SetViewportMetaEnabled(prefs.viewport_meta_enabled);
- settings->SetShrinksViewportContentToFit(
- prefs.shrinks_viewport_contents_to_fit);
settings->SetViewportStyle(
static_cast<blink::WebViewportStyle>(prefs.viewport_style));
@@ -944,7 +919,8 @@ void RenderView::ApplyWebPreferences(const WebPreferences& prefs,
settings->SetPictureInPictureEnabled(
prefs.picture_in_picture_enabled &&
- MediaFactory::VideoSurfaceLayerEnabled());
+ MediaFactory::GetVideoSurfaceLayerMode() !=
+ media::WebMediaPlayerParams::SurfaceLayerMode::kNever);
settings->SetDataSaverHoldbackWebApi(
prefs.data_saver_holdback_web_api_enabled);
@@ -957,30 +933,64 @@ void RenderView::ApplyWebPreferences(const WebPreferences& prefs,
case net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN:
settings->SetLazyFrameLoadingDistanceThresholdPxUnknown(
ect_distance_pair.second);
- break;
+ continue;
case net::EFFECTIVE_CONNECTION_TYPE_OFFLINE:
settings->SetLazyFrameLoadingDistanceThresholdPxOffline(
ect_distance_pair.second);
- break;
+ continue;
case net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G:
settings->SetLazyFrameLoadingDistanceThresholdPxSlow2G(
ect_distance_pair.second);
- break;
+ continue;
case net::EFFECTIVE_CONNECTION_TYPE_2G:
settings->SetLazyFrameLoadingDistanceThresholdPx2G(
ect_distance_pair.second);
- break;
+ continue;
case net::EFFECTIVE_CONNECTION_TYPE_3G:
settings->SetLazyFrameLoadingDistanceThresholdPx3G(
ect_distance_pair.second);
- break;
+ continue;
case net::EFFECTIVE_CONNECTION_TYPE_4G:
settings->SetLazyFrameLoadingDistanceThresholdPx4G(
ect_distance_pair.second);
- break;
- default:
- NOTREACHED();
+ continue;
+ case net::EFFECTIVE_CONNECTION_TYPE_LAST:
+ continue;
}
+ NOTREACHED();
+ }
+
+ for (const auto& ect_distance_pair :
+ prefs.lazy_image_loading_distance_thresholds_px) {
+ switch (ect_distance_pair.first) {
+ case net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN:
+ settings->SetLazyImageLoadingDistanceThresholdPxUnknown(
+ ect_distance_pair.second);
+ continue;
+ case net::EFFECTIVE_CONNECTION_TYPE_OFFLINE:
+ settings->SetLazyImageLoadingDistanceThresholdPxOffline(
+ ect_distance_pair.second);
+ continue;
+ case net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G:
+ settings->SetLazyImageLoadingDistanceThresholdPxSlow2G(
+ ect_distance_pair.second);
+ continue;
+ case net::EFFECTIVE_CONNECTION_TYPE_2G:
+ settings->SetLazyImageLoadingDistanceThresholdPx2G(
+ ect_distance_pair.second);
+ continue;
+ case net::EFFECTIVE_CONNECTION_TYPE_3G:
+ settings->SetLazyImageLoadingDistanceThresholdPx3G(
+ ect_distance_pair.second);
+ continue;
+ case net::EFFECTIVE_CONNECTION_TYPE_4G:
+ settings->SetLazyImageLoadingDistanceThresholdPx4G(
+ ect_distance_pair.second);
+ continue;
+ case net::EFFECTIVE_CONNECTION_TYPE_LAST:
+ continue;
+ }
+ NOTREACHED();
}
#if defined(OS_MACOSX)
@@ -991,6 +1001,13 @@ void RenderView::ApplyWebPreferences(const WebPreferences& prefs,
#if defined(OS_WIN)
WebRuntimeFeatures::EnableMiddleClickAutoscroll(true);
#endif
+
+ // Only enable href translate if we have the experimental web platform
+ // flag on and the translation service is available.
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableExperimentalWebPlatformFeatures)) {
+ WebRuntimeFeatures::EnableHrefTranslate(prefs.translate_service_available);
+ }
}
/*static*/
@@ -1005,7 +1022,7 @@ RenderViewImpl* RenderViewImpl::Create(
if (g_create_render_view_impl)
render_view = g_create_render_view_impl(compositor_deps, *params);
else
- render_view = new RenderViewImpl(compositor_deps, *params, task_runner);
+ render_view = new RenderViewImpl(compositor_deps, *params);
render_view->Initialize(std::move(params), std::move(show_callback),
std::move(task_runner));
@@ -1037,21 +1054,25 @@ const blink::WebView* RenderViewImpl::webview() const {
return webview_;
}
-// RenderWidgetInputHandlerDelegate -----------------------------------------
+// RenderWidgetOwnerDelegate -----------------------------------------
-bool RenderViewImpl::RenderWidgetWillHandleMouseEvent(
+blink::WebWidget* RenderViewImpl::GetWebWidgetForWidget() const {
+ return frame_widget_;
+}
+
+bool RenderViewImpl::RenderWidgetWillHandleMouseEventForWidget(
const blink::WebMouseEvent& event) {
// If the mouse is locked, only the current owner of the mouse lock can
// process mouse events.
- return mouse_lock_dispatcher_->WillHandleMouseEvent(event);
+ return GetWidget()->mouse_lock_dispatcher()->WillHandleMouseEvent(event);
}
-void RenderViewImpl::SetActive(bool active) {
+void RenderViewImpl::SetActiveForWidget(bool active) {
if (webview())
webview()->SetIsActive(active);
}
-void RenderViewImpl::SetBackgroundOpaque(bool opaque) {
+void RenderViewImpl::SetBackgroundOpaqueForWidget(bool opaque) {
if (!frame_widget_)
return;
@@ -1064,69 +1085,137 @@ void RenderViewImpl::SetBackgroundOpaque(bool opaque) {
}
}
-// IPC::Listener implementation ----------------------------------------------
+bool RenderViewImpl::SupportsMultipleWindowsForWidget() {
+ return webkit_preferences_.supports_multiple_windows;
+}
-bool RenderViewImpl::OnMessageReceived(const IPC::Message& message) {
- WebFrame* main_frame = webview() ? webview()->MainFrame() : nullptr;
- if (main_frame) {
- GURL active_url;
- if (main_frame->IsWebLocalFrame())
- active_url = main_frame->ToWebLocalFrame()->GetDocument().Url();
- GetContentClient()->SetActiveURL(
- active_url, main_frame->Top()->GetSecurityOrigin().ToString().Utf8());
+void RenderViewImpl::DidHandleGestureEventForWidget(
+ const WebGestureEvent& event) {
+ for (auto& observer : observers_)
+ observer.DidHandleGestureEvent(event);
+}
+
+void RenderViewImpl::OverrideCloseForWidget() {
+ DCHECK(frame_widget_);
+ frame_widget_->Close();
+ frame_widget_ = nullptr;
+}
+
+void RenderViewImpl::DidCloseWidget() {
+ // The webview_ is already destroyed by the time we get here, remove any
+ // references to it.
+ g_view_map.Get().erase(webview_);
+ webview_ = nullptr;
+ g_routing_id_view_map.Get().erase(GetRoutingID());
+ // TODO(ajwong): Does this message actually get sent?
+ RenderThread::Get()->Send(new ViewHostMsg_Close_ACK(GetRoutingID()));
+}
+
+void RenderViewImpl::ApplyNewSizeForWidget(const gfx::Size& old_size,
+ const gfx::Size& new_size) {
+ if (webview()) {
+ // Only hide popups when the size changes. There are situations (e.g. hiding
+ // the ChromeOS virtual keyboard) where we send a resize message with no
+ // change in size, but we don't want to close popups.
+ // See https://crbug.com/761908.
+ if (new_size != old_size)
+ webview()->HidePopups();
+
+ if (send_preferred_size_changes_ &&
+ webview()->MainFrame()->IsWebLocalFrame()) {
+ webview()->MainFrame()->ToWebLocalFrame()->SetCanHaveScrollbars(
+ ShouldDisplayScrollbars(new_size.width(), new_size.height()));
+ }
}
+}
- for (auto& observer : observers_) {
- if (observer.OnMessageReceived(message))
- return true;
+void RenderViewImpl::ApplyNewDisplayModeForWidget(
+ const blink::WebDisplayMode& new_display_mode) {
+ if (webview())
+ webview()->SetDisplayMode(new_display_mode);
+}
+
+void RenderViewImpl::ApplyAutoResizeLimitsForWidget(const gfx::Size& min_size,
+ const gfx::Size& max_size) {
+ webview()->EnableAutoResizeMode(min_size, max_size);
+}
+
+void RenderViewImpl::DisableAutoResizeForWidget() {
+ webview()->DisableAutoResizeMode();
+}
+
+void RenderViewImpl::ScrollFocusedNodeIntoViewForWidget() {
+ if (WebLocalFrame* focused_frame = GetWebView()->FocusedFrame()) {
+ auto* frame_widget = focused_frame->LocalRoot()->FrameWidget();
+ frame_widget->ScrollFocusedEditableElementIntoView();
}
+}
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(RenderViewImpl, message)
- IPC_MESSAGE_HANDLER(ViewMsg_SetPageScale, OnSetPageScale)
- IPC_MESSAGE_HANDLER(ViewMsg_SetInitialFocus, OnSetInitialFocus)
- IPC_MESSAGE_HANDLER(ViewMsg_UpdateTargetURL_ACK, OnUpdateTargetURLAck)
- IPC_MESSAGE_HANDLER(ViewMsg_UpdateWebPreferences, OnUpdateWebPreferences)
- IPC_MESSAGE_HANDLER(ViewMsg_EnumerateDirectoryResponse,
- OnEnumerateDirectoryResponse)
- IPC_MESSAGE_HANDLER(ViewMsg_ClosePage, OnClosePage)
- IPC_MESSAGE_HANDLER(ViewMsg_MoveOrResizeStarted, OnMoveOrResizeStarted)
- IPC_MESSAGE_HANDLER(ViewMsg_EnablePreferredSizeChangedMode,
- OnEnablePreferredSizeChangedMode)
- IPC_MESSAGE_HANDLER(ViewMsg_DisableScrollbarsForSmallWindows,
- OnDisableScrollbarsForSmallWindows)
- IPC_MESSAGE_HANDLER(ViewMsg_SetRendererPrefs, OnSetRendererPrefs)
- IPC_MESSAGE_HANDLER(ViewMsg_PluginActionAt, OnPluginActionAt)
- IPC_MESSAGE_HANDLER(ViewMsg_ResolveTapDisambiguation,
- OnResolveTapDisambiguation)
- IPC_MESSAGE_HANDLER(ViewMsg_SelectWordAroundCaret, OnSelectWordAroundCaret)
+void RenderViewImpl::DidReceiveSetFocusEventForWidget() {
+ // This message must always be received when the main frame is a
+ // WebLocalFrame.
+ // TODO(ajwong): Can this be removed and just check |owner_delegate_| in
+ // RenderWidget instead?
+ CHECK(webview()->MainFrame()->IsWebLocalFrame());
+}
- // Page messages.
- IPC_MESSAGE_HANDLER(PageMsg_UpdateWindowScreenRect,
- OnUpdateWindowScreenRect)
- IPC_MESSAGE_HANDLER(PageMsg_WasHidden, OnPageWasHidden)
- IPC_MESSAGE_HANDLER(PageMsg_WasShown, OnPageWasShown)
- IPC_MESSAGE_HANDLER(PageMsg_SetHistoryOffsetAndLength,
- OnSetHistoryOffsetAndLength)
- IPC_MESSAGE_HANDLER(PageMsg_AudioStateChanged, OnAudioStateChanged)
- IPC_MESSAGE_HANDLER(PageMsg_PausePageScheduledTasks,
- OnPausePageScheduledTasks)
- IPC_MESSAGE_HANDLER(PageMsg_UpdateScreenInfo, OnUpdateScreenInfo)
- IPC_MESSAGE_HANDLER(PageMsg_SetPageFrozen, SetPageFrozen)
+void RenderViewImpl::DidChangeFocusForWidget() {
+ // Notify all BrowserPlugins of the RenderView's focus state.
+ if (BrowserPluginManager::Get())
+ BrowserPluginManager::Get()->UpdateFocusState();
+}
-#if defined(OS_MACOSX)
- IPC_MESSAGE_HANDLER(ViewMsg_Close, OnClose)
-#endif
- // Adding a new message? Add platform independent ones first, then put the
- // platform specific ones at the end.
+GURL RenderViewImpl::GetURLForGraphicsContext3DForWidget() {
+ DCHECK(webview());
+ WebFrame* main_frame = webview()->MainFrame();
+ if (main_frame && main_frame->IsWebLocalFrame())
+ return GURL(main_frame->ToWebLocalFrame()->GetDocument().Url());
+ else
+ return GURL("chrome://gpu/RenderViewImpl::CreateGraphicsContext3D");
+}
- // Have the super handle all other messages.
- IPC_MESSAGE_UNHANDLED(handled = RenderWidget::OnMessageReceived(message))
- IPC_END_MESSAGE_MAP()
+void RenderViewImpl::DidCommitCompositorFrameForWidget() {
+ for (auto& observer : observers_)
+ observer.DidCommitCompositorFrame();
+ UpdatePreferredSize();
+}
- return handled;
+void RenderViewImpl::DidCompletePageScaleAnimationForWidget() {
+ if (auto* focused_frame = GetWebView()->FocusedFrame()) {
+ if (focused_frame->AutofillClient())
+ focused_frame->AutofillClient()->DidCompleteFocusChangeInFrame();
+ }
+}
+
+void RenderViewImpl::ResizeWebWidgetForWidget(
+ const gfx::Size& size,
+ float top_controls_height,
+ float bottom_controls_height,
+ bool browser_controls_shrink_blink_size) {
+ webview()->ResizeWithBrowserControls(size, top_controls_height,
+ bottom_controls_height,
+ browser_controls_shrink_blink_size);
+}
+
+void RenderViewImpl::RequestScheduleAnimationForWidget() {
+ // Schedule the animation on the WidgetClient() which may not be the
+ // RenderWidget directly in layout tests.
+ WidgetClient()->ScheduleAnimation();
+}
+
+void RenderViewImpl::SetScreenMetricsEmulationParametersForWidget(
+ bool enabled,
+ const blink::WebDeviceEmulationParams& params) {
+ if (webview() && GetWidget()->layer_tree_view()) {
+ if (enabled)
+ webview()->EnableDeviceEmulation(params);
+ else
+ webview()->DisableDeviceEmulation();
+ }
}
+// IPC message handlers -----------------------------------------
+
void RenderViewImpl::OnSelectWordAroundCaret() {
// TODO(ajwong): Move this into RenderWidget. http://crbug.com/545684
// Set default values for the ACK
@@ -1137,7 +1226,7 @@ void RenderViewImpl::OnSelectWordAroundCaret() {
if (webview()) {
WebLocalFrame* focused_frame = GetWebView()->FocusedFrame();
if (focused_frame) {
- input_handler_->set_handling_input_event(true);
+ GetWidget()->SetHandlingInputEvent(true);
blink::WebRange initial_range = focused_frame->SelectionRange();
if (!initial_range.IsNull())
did_select = focused_frame->SelectWordAroundCaret();
@@ -1147,7 +1236,7 @@ void RenderViewImpl::OnSelectWordAroundCaret() {
adjusted_range.StartOffset() - initial_range.StartOffset();
end_adjust = adjusted_range.EndOffset() - initial_range.EndOffset();
}
- input_handler_->set_handling_input_event(false);
+ GetWidget()->SetHandlingInputEvent(false);
}
}
Send(new ViewHostMsg_SelectWordAroundCaretAck(
@@ -1180,7 +1269,8 @@ void RenderViewImpl::OnSetInitialFocus(bool reverse) {
}
void RenderViewImpl::OnUpdateWindowScreenRect(gfx::Rect window_screen_rect) {
- RenderWidget::OnUpdateWindowScreenRect(window_screen_rect);
+ // Defers to the RenderWidget message handler.
+ GetWidget()->SetWindowScreenRect(window_screen_rect);
}
void RenderViewImpl::OnAudioStateChanged(bool is_audio_playing) {
@@ -1224,6 +1314,67 @@ void RenderViewImpl::ApplyWebPreferencesInternal(const WebPreferences& prefs,
ApplyWebPreferences(prefs, web_view);
}
+// IPC::Listener -------------------------------------------------------------
+
+bool RenderViewImpl::OnMessageReceived(const IPC::Message& message) {
+ WebFrame* main_frame = webview() ? webview()->MainFrame() : nullptr;
+ if (main_frame) {
+ GURL active_url;
+ if (main_frame->IsWebLocalFrame())
+ active_url = main_frame->ToWebLocalFrame()->GetDocument().Url();
+ GetContentClient()->SetActiveURL(
+ active_url, main_frame->Top()->GetSecurityOrigin().ToString().Utf8());
+ }
+
+ for (auto& observer : observers_) {
+ if (observer.OnMessageReceived(message))
+ return true;
+ }
+
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(RenderViewImpl, message)
+ IPC_MESSAGE_HANDLER(ViewMsg_SetPageScale, OnSetPageScale)
+ IPC_MESSAGE_HANDLER(ViewMsg_SetInitialFocus, OnSetInitialFocus)
+ IPC_MESSAGE_HANDLER(ViewMsg_UpdateTargetURL_ACK, OnUpdateTargetURLAck)
+ IPC_MESSAGE_HANDLER(ViewMsg_UpdateWebPreferences, OnUpdateWebPreferences)
+ IPC_MESSAGE_HANDLER(ViewMsg_EnumerateDirectoryResponse,
+ OnEnumerateDirectoryResponse)
+ IPC_MESSAGE_HANDLER(ViewMsg_ClosePage, OnClosePage)
+ IPC_MESSAGE_HANDLER(ViewMsg_MoveOrResizeStarted, OnMoveOrResizeStarted)
+ IPC_MESSAGE_HANDLER(ViewMsg_EnablePreferredSizeChangedMode,
+ OnEnablePreferredSizeChangedMode)
+ IPC_MESSAGE_HANDLER(ViewMsg_DisableScrollbarsForSmallWindows,
+ OnDisableScrollbarsForSmallWindows)
+ IPC_MESSAGE_HANDLER(ViewMsg_SetRendererPrefs, OnSetRendererPrefs)
+ IPC_MESSAGE_HANDLER(ViewMsg_PluginActionAt, OnPluginActionAt)
+ IPC_MESSAGE_HANDLER(ViewMsg_SelectWordAroundCaret, OnSelectWordAroundCaret)
+
+ // Page messages.
+ IPC_MESSAGE_HANDLER(PageMsg_UpdateWindowScreenRect,
+ OnUpdateWindowScreenRect)
+ IPC_MESSAGE_HANDLER(PageMsg_WasHidden, OnPageWasHidden)
+ IPC_MESSAGE_HANDLER(PageMsg_WasShown, OnPageWasShown)
+ IPC_MESSAGE_HANDLER(PageMsg_SetHistoryOffsetAndLength,
+ OnSetHistoryOffsetAndLength)
+ IPC_MESSAGE_HANDLER(PageMsg_AudioStateChanged, OnAudioStateChanged)
+ IPC_MESSAGE_HANDLER(PageMsg_PausePageScheduledTasks,
+ OnPausePageScheduledTasks)
+ IPC_MESSAGE_HANDLER(PageMsg_UpdateScreenInfo, OnUpdateScreenInfo)
+ IPC_MESSAGE_HANDLER(PageMsg_SetPageFrozen, SetPageFrozen)
+
+#if defined(OS_MACOSX)
+ IPC_MESSAGE_HANDLER(ViewMsg_Close, OnClose)
+#endif
+ // Adding a new message? Add platform independent ones first, then put the
+ // platform specific ones at the end.
+
+ // Have the super handle all other messages.
+ IPC_MESSAGE_UNHANDLED(handled = RenderWidget::OnMessageReceived(message))
+ IPC_END_MESSAGE_MAP()
+
+ return handled;
+}
+
// blink::WebViewClient ------------------------------------------------------
// TODO(csharrison): Migrate this method to WebLocalFrameClient /
@@ -1312,7 +1463,7 @@ WebView* RenderViewImpl::CreateView(WebLocalFrame* creator,
bool never_visible = false;
VisualProperties visual_properties = VisualProperties();
- visual_properties.screen_info = screen_info_;
+ visual_properties.screen_info = GetWidget()->screen_info();
// The initial hidden state for the RenderViewImpl here has to match what the
// browser will eventually decide for the given disposition. Since we have to
@@ -1352,7 +1503,8 @@ WebView* RenderViewImpl::CreateView(WebLocalFrame* creator,
base::Unretained(creator_frame), opened_by_user_gesture);
RenderViewImpl* view = RenderViewImpl::Create(
- compositor_deps_, std::move(view_params), std::move(show_callback),
+ GetWidget()->compositor_deps(), std::move(view_params),
+ std::move(show_callback),
creator->GetTaskRunner(blink::TaskType::kInternalDefault));
return view->webview();
@@ -1360,16 +1512,13 @@ WebView* RenderViewImpl::CreateView(WebLocalFrame* creator,
WebWidget* RenderViewImpl::CreatePopup(blink::WebLocalFrame* creator,
blink::WebPopupType popup_type) {
- RenderWidget* widget = RenderWidget::CreateForPopup(
- this, compositor_deps_, popup_type, screen_info_,
- creator->GetTaskRunner(blink::TaskType::kInternalDefault));
- if (!widget)
+ RenderWidget* popup_widget =
+ RenderWidget::CreateForPopup(this, GetWidget()->compositor_deps(),
+ popup_type, GetWidget()->screen_info());
+ if (!popup_widget)
return nullptr;
- if (screen_metrics_emulator_) {
- widget->SetPopupOriginAdjustmentsForEmulation(
- screen_metrics_emulator_.get());
- }
- return widget->GetWebWidget();
+ popup_widget->ApplyEmulatedScreenMetricsForPopupWidget(GetWidget());
+ return popup_widget->GetWebWidget();
}
base::StringPiece RenderViewImpl::GetSessionStorageNamespaceId() {
@@ -1389,7 +1538,7 @@ void RenderViewImpl::PrintPage(WebLocalFrame* frame) {
frame->Top()->IsWebRemoteFrame());
RenderFrameImpl::FromWebFrame(frame)->ScriptedPrint(
- input_handler().handling_input_event());
+ GetWidget()->input_handler().handling_input_event());
}
bool RenderViewImpl::EnumerateChosenDirectory(
@@ -1555,21 +1704,12 @@ void RenderViewImpl::FocusedNodeChanged(const WebNode& fromNode,
main_render_frame_->FocusedNodeChangedForAccessibility(toNode);
}
-void RenderViewImpl::DidUpdateLayout() {
+void RenderViewImpl::DidUpdateMainFrameLayout() {
for (auto& observer : observers_)
- observer.DidUpdateLayout();
-
- // We don't always want to set up a timer, only if we've been put in that
- // mode by getting a |ViewMsg_EnablePreferredSizeChangedMode|
- // message.
- if (!send_preferred_size_changes_ || !webview())
- return;
+ observer.DidUpdateMainFrameLayout();
- if (check_preferred_size_timer_.IsRunning())
- return;
- check_preferred_size_timer_.Start(FROM_HERE,
- TimeDelta::FromMilliseconds(0), this,
- &RenderViewImpl::CheckPreferredSize);
+ // The main frame may have changed size.
+ needs_preferred_size_update_ = true;
}
void RenderViewImpl::NavigateBackForwardSoon(int offset) {
@@ -1587,6 +1727,11 @@ void RenderViewImpl::DidCommitProvisionalHistoryLoad() {
history_navigation_virtual_time_pauser_.UnpauseVirtualTime();
}
+void RenderViewImpl::RegisterRendererPreferenceWatcherForWorker(
+ mojom::RendererPreferenceWatcherPtr watcher) {
+ renderer_preference_watchers_.AddPtr(std::move(watcher));
+}
+
int RenderViewImpl::HistoryBackListCount() {
return history_list_offset_ < 0 ? 0 : history_list_offset_;
}
@@ -1597,40 +1742,6 @@ int RenderViewImpl::HistoryForwardListCount() {
// blink::WebWidgetClient ----------------------------------------------------
-void RenderViewImpl::DidFocus(blink::WebLocalFrame* calling_frame) {
- // TODO(jcivelli): when https://bugs.webkit.org/show_bug.cgi?id=33389 is fixed
- // we won't have to test for user gesture anymore and we can
- // move that code back to render_widget.cc
- if (WebUserGestureIndicator::IsProcessingUserGesture(calling_frame) &&
- !RenderThreadImpl::current()->layout_test_mode()) {
- Send(new ViewHostMsg_Focus(GetRoutingID()));
-
- // Tattle on the frame that called |window.focus()|.
- RenderFrameImpl* calling_render_frame =
- RenderFrameImpl::FromWebFrame(calling_frame);
- if (calling_render_frame)
- calling_render_frame->FrameDidCallFocus();
- }
-}
-
-// We are supposed to get a single call to show() for a newly created RenderView
-// that was created via RenderViewImpl::createView. We wait until this point to
-// run |show_callback|, which is bound to our opener's ShowCreatedViewWidget()
-// method.
-//
-// This method provides us with the information about how to display the newly
-// created RenderView (i.e., as a blocked popup or as a new tab).
-void RenderViewImpl::Show(WebNavigationPolicy policy) {
- if (did_show_ && !webkit_preferences_.supports_multiple_windows) {
- // When supports_multiple_windows is disabled, popups are reusing
- // the same view. In some scenarios, this makes WebKit to call show() twice.
- return;
- }
-
- RenderWidget::Show(policy);
-}
-
-
bool RenderViewImpl::CanHandleGestureEvent() {
return true;
}
@@ -1639,16 +1750,6 @@ bool RenderViewImpl::CanUpdateLayout() {
return true;
}
-void RenderViewImpl::DidHandleGestureEvent(const WebGestureEvent& event,
- bool event_cancelled) {
- RenderWidget::DidHandleGestureEvent(event, event_cancelled);
-
- if (!event_cancelled) {
- for (auto& observer : observers_)
- observer.DidHandleGestureEvent(event);
- }
-}
-
blink::WebWidgetClient* RenderViewImpl::WidgetClient() {
return this;
}
@@ -1680,12 +1781,17 @@ gfx::RectF RenderViewImpl::ElementBoundsInWindow(
return gfx::RectF(bounding_box_in_window);
}
-void RenderViewImpl::CheckPreferredSize() {
+void RenderViewImpl::UpdatePreferredSize() {
// We don't always want to send the change messages over IPC, only if we've
// been put in that mode by getting a |ViewMsg_EnablePreferredSizeChangedMode|
// message.
if (!send_preferred_size_changes_ || !webview())
return;
+
+ if (!needs_preferred_size_update_)
+ return;
+ needs_preferred_size_update_ = false;
+
blink::WebSize tmp_size = webview()->ContentsPreferredMinimumSize();
blink::WebRect tmp_rect(0, 0, tmp_size.width, tmp_size.height);
WidgetClient()->ConvertViewportToWindow(&tmp_rect);
@@ -1705,6 +1811,10 @@ blink::WebString RenderViewImpl::AcceptLanguages() {
// RenderView implementation ---------------------------------------------------
bool RenderViewImpl::Send(IPC::Message* message) {
+ // This method is an override of IPC::Sender, but RenderWidget also has an
+ // override of IPC::Sender, so this method also overrides RenderWidget. Thus
+ // we must call to the base class, not via an upcast or virtual dispatch would
+ // go back here.
return RenderWidget::Send(message);
}
@@ -1793,9 +1903,19 @@ void RenderViewImpl::OnEnablePreferredSizeChangedMode() {
return;
send_preferred_size_changes_ = true;
- // Start off with an initial preferred size notification (in case
- // |didUpdateLayout| was already called).
- DidUpdateLayout();
+ if (!webview())
+ return;
+
+ needs_preferred_size_update_ = true;
+
+ // We need to ensure |UpdatePreferredSize| gets called. If a layout is needed,
+ // force an update here which will call |DidUpdateMainFrameLayout|.
+ webview()->UpdateLifecycle(WebWidget::LifecycleUpdate::kLayout);
+
+ // If a layout was not needed, |DidUpdateMainFrameLayout| will not be called.
+ // We explicitly update the preferred size here to ensure the preferred size
+ // notification is sent.
+ UpdatePreferredSize();
}
void RenderViewImpl::OnDisableScrollbarsForSmallWindows(
@@ -1809,6 +1929,11 @@ void RenderViewImpl::OnSetRendererPrefs(
renderer_preferences_ = renderer_prefs;
+ renderer_preference_watchers_.ForAllPtrs(
+ [&renderer_prefs](mojom::RendererPreferenceWatcher* watcher) {
+ watcher->NotifyUpdate(renderer_prefs);
+ });
+
UpdateFontRenderingFromRendererPrefs();
UpdateThemePrefs();
blink::SetCaretBlinkInterval(renderer_prefs.caret_blink_interval);
@@ -1857,8 +1982,11 @@ void RenderViewImpl::OnClosePage() {
#if defined(OS_MACOSX)
void RenderViewImpl::OnClose() {
- if (closing_)
+ if (GetWidget()->closing())
RenderThread::Get()->Send(new ViewHostMsg_Close_ACK(GetRoutingID()));
+ // This method is protected for OS_MACOSX only, because the message gets sent
+ // to the RenderViewImpl instead of to the RenderWidget.
+ // TODO(danakj): Move this message to RenderWidget?
RenderWidget::OnClose();
}
#endif
@@ -1868,113 +1996,6 @@ void RenderViewImpl::OnMoveOrResizeStarted() {
webview()->HidePopups();
}
-void RenderViewImpl::ResizeWebWidget() {
- webview()->ResizeWithBrowserControls(
- GetSizeForWebWidget(), top_controls_height_, bottom_controls_height_,
- browser_controls_shrink_blink_size_);
-}
-
-void RenderViewImpl::RequestScheduleAnimation() {
- // RenderWidget is a WebWidgetClient but layout tests want to override the
- // client for WebViews, and can't do it by subclassing RenderWidget since they
- // have a RenderViewImpl in this case, which is-a RenderWidget.
- WidgetClient()->ScheduleAnimation();
-}
-
-void RenderViewImpl::OnSynchronizeVisualProperties(
- const VisualProperties& params) {
- TRACE_EVENT0("renderer", "RenderViewImpl::OnSynchronizeVisualProperties");
-
- if (webview()) {
- // Only hide popups when the size changes. There are situations (e.g. hiding
- // the ChromeOS virtual keyboard) where we send a resize message with no
- // change in size, but we don't want to close popups.
- // See https://crbug.com/761908.
- if (params.new_size != GetSize())
- webview()->HidePopups();
-
- if (send_preferred_size_changes_ &&
- webview()->MainFrame()->IsWebLocalFrame()) {
- webview()->MainFrame()->ToWebLocalFrame()->SetCanHaveScrollbars(
- ShouldDisplayScrollbars(params.new_size.width(),
- params.new_size.height()));
- }
- if (display_mode_ != params.display_mode) {
- display_mode_ = params.display_mode;
- webview()->SetDisplayMode(display_mode_);
- }
- }
-
- bool auto_resize_mode_changed =
- auto_resize_mode_ != params.auto_resize_enabled;
- auto_resize_mode_ = params.auto_resize_enabled;
- min_size_for_auto_resize_ = params.min_size_for_auto_resize;
- max_size_for_auto_resize_ = params.max_size_for_auto_resize;
- if (auto_resize_mode_) {
- if (IsUseZoomForDSFEnabled()) {
- webview()->EnableAutoResizeMode(
- gfx::ScaleToCeiledSize(params.min_size_for_auto_resize,
- params.screen_info.device_scale_factor),
- gfx::ScaleToCeiledSize(params.max_size_for_auto_resize,
- params.screen_info.device_scale_factor));
- } else {
- webview()->EnableAutoResizeMode(params.min_size_for_auto_resize,
- params.max_size_for_auto_resize);
- }
- } else if (auto_resize_mode_changed) {
- webview()->DisableAutoResizeMode();
- if (params.new_size.IsEmpty())
- return;
- }
-
- browser_controls_shrink_blink_size_ =
- params.browser_controls_shrink_blink_size;
- top_controls_height_ = params.top_controls_height;
- bottom_controls_height_ = params.bottom_controls_height;
-
- if (device_scale_factor_for_testing_) {
- VisualProperties p(params);
- p.screen_info.device_scale_factor = *device_scale_factor_for_testing_;
- p.compositor_viewport_pixel_size =
- gfx::ScaleToCeiledSize(p.new_size, p.screen_info.device_scale_factor);
- RenderWidget::OnSynchronizeVisualProperties(p);
- } else {
- RenderWidget::OnSynchronizeVisualProperties(params);
- }
-
- if (!params.scroll_focused_node_into_view)
- return;
-
- if (WebLocalFrame* focused_frame = GetWebView()->FocusedFrame()) {
- focused_frame->LocalRoot()
- ->FrameWidget()
- ->ScrollFocusedEditableElementIntoView();
- }
-}
-
-blink::WebWidget* RenderViewImpl::GetWebWidget() const {
- if (frame_widget_)
- return frame_widget_;
-
- return RenderWidget::GetWebWidget();
-}
-
-void RenderViewImpl::CloseForFrame() {
- DCHECK(frame_widget_);
- frame_widget_->Close();
- frame_widget_ = nullptr;
-}
-
-void RenderViewImpl::Close() {
- // We need to grab a pointer to the doomed WebView before we destroy it.
- WebView* doomed = webview_;
- RenderWidget::Close();
- webview_ = nullptr;
- g_view_map.Get().erase(doomed);
- g_routing_id_view_map.Get().erase(GetRoutingID());
- RenderThread::Get()->Send(new ViewHostMsg_Close_ACK(GetRoutingID()));
-}
-
void RenderViewImpl::OnPageWasHidden() {
#if defined(OS_ANDROID)
SuspendVideoCaptureDevices(true);
@@ -2009,8 +2030,9 @@ void RenderViewImpl::OnUpdateScreenInfo(const ScreenInfo& screen_info) {
// This IPC only updates the screen info on RenderViews that have a remote
// main frame. For local main frames, the ScreenInfo is updated in
// ViewMsg_Resize.
+ // TODO(danakj): Move this message to RenderWidget?
if (!main_render_frame_)
- screen_info_ = screen_info;
+ GetWidget()->set_screen_info(screen_info);
}
void RenderViewImpl::SetPageFrozen(bool frozen) {
@@ -2018,46 +2040,10 @@ void RenderViewImpl::SetPageFrozen(bool frozen) {
webview()->SetPageFrozen(frozen);
}
-GURL RenderViewImpl::GetURLForGraphicsContext3D() {
- DCHECK(webview());
- WebFrame* main_frame = webview()->MainFrame();
- if (main_frame && main_frame->IsWebLocalFrame())
- return GURL(main_frame->ToWebLocalFrame()->GetDocument().Url());
- else
- return GURL("chrome://gpu/RenderViewImpl::CreateGraphicsContext3D");
-}
-
-void RenderViewImpl::OnSetFocus(bool enable) {
- // This message must always be received when the main frame is a
- // WebLocalFrame.
- CHECK(webview()->MainFrame()->IsWebLocalFrame());
- SetFocus(enable);
-}
-
void RenderViewImpl::SetFocus(bool enable) {
- RenderWidget::OnSetFocus(enable);
-
- // Notify all BrowserPlugins of the RenderView's focus state.
- if (BrowserPluginManager::Get())
- BrowserPluginManager::Get()->UpdateFocusState();
-}
-
-void RenderViewImpl::DidCompletePageScaleAnimation() {
- if (auto* focused_frame = GetWebView()->FocusedFrame()) {
- if (focused_frame->AutofillClient())
- focused_frame->AutofillClient()->DidCompleteFocusChangeInFrame();
- }
-}
-
-void RenderViewImpl::SetScreenMetricsEmulationParameters(
- bool enabled,
- const blink::WebDeviceEmulationParams& params) {
- if (webview() && layer_tree_view()) {
- if (enabled)
- webview()->EnableDeviceEmulation(params);
- else
- webview()->DisableDeviceEmulation();
- }
+ // This is not an IPC message, don't go through the IPC handler. This is used
+ // in cases where the IPC message should not happen.
+ GetWidget()->SetFocus(enable);
}
void RenderViewImpl::ZoomLimitsChanged(double minimum_level,
@@ -2103,13 +2089,29 @@ void RenderViewImpl::PageImportanceSignalsChanged() {
}
void RenderViewImpl::DidAutoResize(const blink::WebSize& newSize) {
- RenderWidget::DidAutoResize(newSize);
+ GetWidget()->DidAutoResize(newSize);
}
blink::WebRect RenderViewImpl::RootWindowRect() {
return WidgetClient()->WindowRect();
}
+void RenderViewImpl::DidFocus(blink::WebLocalFrame* calling_frame) {
+ // TODO(jcivelli): when https://bugs.webkit.org/show_bug.cgi?id=33389 is fixed
+ // we won't have to test for user gesture anymore and we can
+ // move that code back to render_widget.cc
+ if (WebUserGestureIndicator::IsProcessingUserGesture(calling_frame) &&
+ !RenderThreadImpl::current()->layout_test_mode()) {
+ Send(new ViewHostMsg_Focus(GetRoutingID()));
+
+ // Tattle on the frame that called |window.focus()|.
+ RenderFrameImpl* calling_render_frame =
+ RenderFrameImpl::FromWebFrame(calling_frame);
+ if (calling_render_frame)
+ calling_render_frame->FrameDidCallFocus();
+ }
+}
+
#if defined(OS_ANDROID)
bool RenderViewImpl::OpenDateTimeChooser(
const blink::WebDateTimeChooserParams& params,
@@ -2127,96 +2129,6 @@ void RenderViewImpl::DismissDateTimeDialog() {
date_time_picker_client_.reset();
}
-bool RenderViewImpl::DidTapMultipleTargets(
- const WebSize& inner_viewport_offset,
- const WebRect& touch_rect,
- const WebVector<WebRect>& target_rects) {
- // Never show a disambiguation popup when accessibility is enabled,
- // as this interferes with "touch exploration".
- ui::AXMode accessibility_mode = GetMainRenderFrame()->accessibility_mode();
- if (accessibility_mode == ui::kAXModeComplete)
- return false;
-
- // The touch_rect, target_rects and zoom_rect are in the outer viewport
- // reference frame.
- float to_pix =
- IsUseZoomForDSFEnabled() ? 1 : GetWebScreenInfo().device_scale_factor;
- gfx::Rect zoom_rect;
- float new_total_scale =
- DisambiguationPopupHelper::ComputeZoomAreaAndScaleFactor(
- touch_rect, target_rects, GetSize(),
- gfx::Rect(webview()->MainFrame()->VisibleContentRect()).size(),
- to_pix * webview()->PageScaleFactor(), &zoom_rect);
- if (!new_total_scale || zoom_rect.IsEmpty())
- return false;
-
- bool handled = false;
- switch (renderer_preferences_.tap_multiple_targets_strategy) {
- case TAP_MULTIPLE_TARGETS_STRATEGY_ZOOM:
- handled = webview()->ZoomToMultipleTargetsRect(zoom_rect);
- break;
- case TAP_MULTIPLE_TARGETS_STRATEGY_POPUP: {
- gfx::Size canvas_size =
- gfx::ScaleToCeiledSize(zoom_rect.size(), new_total_scale);
-
- SkImageInfo info =
- SkImageInfo::MakeN32Premul(canvas_size.width(), canvas_size.height());
- size_t shm_size = info.computeMinByteSize();
-
- if (shm_size == 0) {
- DLOG(ERROR) << "Invalid size for SharedMemory";
- return false;
- }
-
- auto shm = ChildThreadImpl::AllocateSharedMemory(shm_size);
- if (!shm || !shm->Map(shm_size)) {
- DLOG(ERROR) << "SharedMemory allocate/map failed";
- return false;
- }
-
- {
- SkBitmap bitmap;
- bitmap.installPixels(info, shm->memory(), info.minRowBytes());
- cc::SkiaPaintCanvas canvas(bitmap);
-
- // TODO(trchen): Cleanup the device scale factor mess.
- // device scale will be applied in WebKit
- // --> zoom_rect doesn't include device scale,
- // but WebKit will still draw on zoom_rect *
- // GetWebScreenInfo().device_scale_factor
- canvas.scale(new_total_scale / to_pix, new_total_scale / to_pix);
- canvas.translate(-zoom_rect.x() * to_pix, -zoom_rect.y() * to_pix);
-
- DCHECK(webview_->IsAcceleratedCompositingActive());
- webview_->UpdateAllLifecyclePhases();
- webview_->PaintContentIgnoringCompositing(&canvas, zoom_rect);
- }
-
- gfx::Rect zoom_rect_in_screen =
- zoom_rect - gfx::Vector2d(inner_viewport_offset.width,
- inner_viewport_offset.height);
-
- gfx::Rect physical_window_zoom_rect = gfx::ToEnclosingRect(
- gfx::ScaleRect(gfx::RectF(zoom_rect_in_screen),
- to_pix * webview()->PageScaleFactor()));
-
- // A SharedMemoryHandle is sent to the browser process, which is
- // responsible for freeing the shared memory when no longer needed.
- Send(new ViewHostMsg_ShowDisambiguationPopup(
- GetWidget()->routing_id(), physical_window_zoom_rect, canvas_size,
- shm->TakeHandle()));
-
- handled = true;
- break;
- }
- case TAP_MULTIPLE_TARGETS_STRATEGY_NONE:
- // No-op.
- break;
- }
-
- return handled;
-}
-
void RenderViewImpl::SuspendVideoCaptureDevices(bool suspend) {
if (!main_render_frame_)
return;
@@ -2244,129 +2156,18 @@ void RenderViewImpl::SetFocusAndActivateForTesting(bool enable) {
if (webview()->MainFrame()->IsWebRemoteFrame())
return;
+ if (enable == has_focus())
+ return;
+
if (enable) {
- if (has_focus())
- return;
- SetActive(true);
+ SetActiveForWidget(true);
+ // Fake an IPC message so go through the IPC handler.
OnSetFocus(true);
} else {
- if (!has_focus())
- return;
+ // Fake an IPC message so go through the IPC handler.
OnSetFocus(false);
- SetActive(false);
- }
-}
-
-void RenderViewImpl::SetDeviceScaleFactorForTesting(float factor) {
- device_scale_factor_for_testing_ = factor;
-
- VisualProperties visual_properties;
- visual_properties.screen_info = screen_info_;
- visual_properties.screen_info.device_scale_factor = factor;
- visual_properties.new_size = size();
- visual_properties.visible_viewport_size = visible_viewport_size_;
- visual_properties.compositor_viewport_pixel_size =
- gfx::ScaleToCeiledSize(size(), factor);
- visual_properties.browser_controls_shrink_blink_size = false;
- visual_properties.top_controls_height = 0.f;
- visual_properties.is_fullscreen_granted = is_fullscreen_granted();
- visual_properties.display_mode = display_mode_;
- visual_properties.local_surface_id = local_surface_id_from_parent_;
- // We are changing the device scale factor from the renderer, so allocate a
- // new viz::LocalSurfaceId to avoid surface invariants violations in tests.
- if (layer_tree_view())
- layer_tree_view()->RequestNewLocalSurfaceId();
-
- OnSynchronizeVisualProperties(visual_properties);
-}
-
-void RenderViewImpl::SetDeviceColorSpaceForTesting(
- const gfx::ColorSpace& color_space) {
- VisualProperties visual_properties;
- visual_properties.screen_info = screen_info_;
- visual_properties.screen_info.color_space = color_space;
- visual_properties.new_size = size();
- visual_properties.visible_viewport_size = visible_viewport_size_;
- visual_properties.compositor_viewport_pixel_size =
- compositor_viewport_pixel_size_;
- visual_properties.browser_controls_shrink_blink_size = false;
- visual_properties.top_controls_height = 0.f;
- visual_properties.is_fullscreen_granted = is_fullscreen_granted();
- visual_properties.display_mode = display_mode_;
- visual_properties.local_surface_id = local_surface_id_from_parent_;
- // We are changing the device color space from the renderer, so allocate a
- // new viz::LocalSurfaceId to avoid surface invariants violations in tests.
- if (layer_tree_view())
- layer_tree_view()->RequestNewLocalSurfaceId();
- OnSynchronizeVisualProperties(visual_properties);
-}
-
-void RenderViewImpl::ForceResizeForTesting(const gfx::Size& new_size) {
- gfx::Rect new_window_rect(RootWindowRect().x, RootWindowRect().y,
- new_size.width(), new_size.height());
- SetWindowRectSynchronously(new_window_rect);
-}
-
-void RenderViewImpl::UseSynchronousResizeModeForTesting(bool enable) {
- resizing_mode_selector_->set_is_synchronous_mode(enable);
-}
-
-void RenderViewImpl::EnableAutoResizeForTesting(const gfx::Size& min_size,
- const gfx::Size& max_size) {
- VisualProperties visual_properties;
- visual_properties.auto_resize_enabled = true;
- visual_properties.min_size_for_auto_resize = min_size;
- visual_properties.max_size_for_auto_resize = max_size;
- visual_properties.local_surface_id = base::Optional<viz::LocalSurfaceId>(
- viz::LocalSurfaceId(1, 1, base::UnguessableToken::Create()));
- OnSynchronizeVisualProperties(visual_properties);
-}
-
-void RenderViewImpl::DisableAutoResizeForTesting(const gfx::Size& new_size) {
- if (!auto_resize_mode_)
- return;
-
- VisualProperties visual_properties;
- visual_properties.auto_resize_enabled = false;
- visual_properties.screen_info = screen_info_;
- visual_properties.new_size = new_size;
- visual_properties.compositor_viewport_pixel_size =
- compositor_viewport_pixel_size_;
- visual_properties.browser_controls_shrink_blink_size =
- browser_controls_shrink_blink_size_;
- visual_properties.top_controls_height = top_controls_height_;
- visual_properties.visible_viewport_size = visible_viewport_size_;
- visual_properties.is_fullscreen_granted = is_fullscreen_granted();
- visual_properties.display_mode = display_mode_;
- OnSynchronizeVisualProperties(visual_properties);
-}
-
-void RenderViewImpl::OnResolveTapDisambiguation(
- base::TimeTicks timestamp,
- const gfx::Point& tap_viewport_offset,
- bool is_long_press) {
- webview()->ResolveTapDisambiguation(timestamp, tap_viewport_offset,
- is_long_press);
-}
-
-void RenderViewImpl::DidCommitCompositorFrame() {
- RenderWidget::DidCommitCompositorFrame();
- for (auto& observer : observers_)
- observer.DidCommitCompositorFrame();
-}
-
-void RenderViewImpl::HandleInputEvent(
- const blink::WebCoalescedInputEvent& input_event,
- const ui::LatencyInfo& latency_info,
- HandledEventCallback callback) {
- if (is_swapped_out_) {
- std::move(callback).Run(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, latency_info,
- nullptr, base::nullopt);
- return;
+ SetActiveForWidget(false);
}
- idle_user_detector_->ActivityDetected();
- RenderWidget::HandleInputEvent(input_event, latency_info,
- std::move(callback));
}
} // namespace content
diff --git a/chromium/content/renderer/render_view_impl.h b/chromium/content/renderer/render_view_impl.h
index bcd629c4386..fc982820b97 100644
--- a/chromium/content/renderer/render_view_impl.h
+++ b/chromium/content/renderer/render_view_impl.h
@@ -33,6 +33,7 @@
#include "content/public/common/drop_data.h"
#include "content/public/common/page_zoom.h"
#include "content/public/common/referrer.h"
+#include "content/public/common/renderer_preference_watcher.mojom.h"
#include "content/public/common/renderer_preferences.h"
#include "content/public/common/web_preferences.h"
#include "content/public/renderer/render_view.h"
@@ -41,6 +42,7 @@
#include "content/renderer/render_widget_owner_delegate.h"
#include "content/renderer/stats_collection_observer.h"
#include "ipc/ipc_platform_file.h"
+#include "mojo/public/cpp/bindings/interface_ptr_set.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"
@@ -72,19 +74,12 @@ struct WebPluginAction;
struct WebWindowFeatures;
} // namespace blink
-namespace gfx {
-class ColorSpace;
-}
-
namespace content {
-
-class IdleUserDetector;
class RendererDateTimePicker;
class RenderViewImplTest;
class RenderViewObserver;
class RenderViewTest;
struct FileChooserParams;
-struct VisualProperties;
namespace mojom {
class CreateViewParams;
@@ -213,26 +208,13 @@ class CONTENT_EXPORT RenderViewImpl : private RenderWidget,
// synchronously from the renderer.
void SetFocusAndActivateForTesting(bool enable);
- // Change the device scale factor and force the compositor to resize.
- void SetDeviceScaleFactorForTesting(float factor);
-
- // Change the device ICC color profile while running a layout test.
- void SetDeviceColorSpaceForTesting(const gfx::ColorSpace& color_space);
-
- // Used to force the size of a window when running layout tests.
- void ForceResizeForTesting(const gfx::Size& new_size);
-
- void UseSynchronousResizeModeForTesting(bool enable);
-
void DidCommitProvisionalHistoryLoad();
- // Control autoresize mode.
- void EnableAutoResizeForTesting(const gfx::Size& min_size,
- const gfx::Size& max_size);
- void DisableAutoResizeForTesting(const gfx::Size& new_size);
-
- // IPC::Listener implementation ----------------------------------------------
+ // Registers a watcher to observe changes in the RendererPreferences.
+ void RegisterRendererPreferenceWatcherForWorker(
+ mojom::RendererPreferenceWatcherPtr watcher);
+ // IPC::Listener implementation (via RenderWidget inheritance).
bool OnMessageReceived(const IPC::Message& msg) override;
// blink::WebViewClient implementation --------------------------------------
@@ -263,15 +245,7 @@ class CONTENT_EXPORT RenderViewImpl : private RenderWidget,
void FocusedNodeChanged(const blink::WebNode& fromNode,
const blink::WebNode& toNode) override;
bool CanUpdateLayout() override;
- void DidUpdateLayout() override;
-#if defined(OS_ANDROID)
- // |touch_rect| is in physical pixels if --use-zoom-for-dsf is enabled.
- // Otherwise, it is in DIPs.
- bool DidTapMultipleTargets(
- const blink::WebSize& inner_viewport_offset,
- const blink::WebRect& touch_rect,
- const blink::WebVector<blink::WebRect>& target_rects) override;
-#endif
+ void DidUpdateMainFrameLayout() override;
blink::WebString AcceptLanguages() override;
void NavigateBackForwardSoon(int offset) override;
int HistoryBackListCount() override;
@@ -285,7 +259,7 @@ class CONTENT_EXPORT RenderViewImpl : private RenderWidget,
blink::WebRect RootWindowRect() override;
void DidFocus(blink::WebLocalFrame* calling_frame) override;
bool CanHandleGestureEvent() override;
- WebWidgetClient* WidgetClient() override;
+ blink::WebWidgetClient* WidgetClient() override;
#if defined(OS_ANDROID)
// Only used on Android since all other platforms implement
@@ -329,38 +303,18 @@ class CONTENT_EXPORT RenderViewImpl : private RenderWidget,
return weak_ptr_factory_.GetWeakPtr();
}
- void HandleInputEvent(const blink::WebCoalescedInputEvent& input_event,
- const ui::LatencyInfo& latency_info,
- HandledEventCallback callback) override;
-
bool renderer_wide_named_frame_lookup() {
return renderer_wide_named_frame_lookup_;
}
void UpdateZoomLevel(double zoom_level);
protected:
- // RenderWidget overrides:
- blink::WebWidget* GetWebWidget() const override;
- void CloseForFrame() override;
- void Close() override;
- void OnSynchronizeVisualProperties(const VisualProperties& params) override;
- void OnSetFocus(bool enable) override;
- GURL GetURLForGraphicsContext3D() override;
- void DidCommitCompositorFrame() override;
- void DidCompletePageScaleAnimation() override;
- void ResizeWebWidget() override;
- void RequestScheduleAnimation() override;
-
RenderViewImpl(CompositorDependencies* compositor_deps,
- const mojom::CreateViewParams& params,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+ const mojom::CreateViewParams& params);
void Initialize(mojom::CreateViewParamsPtr params,
RenderWidget::ShowCallback show_callback,
scoped_refptr<base::SingleThreadTaskRunner> task_runner);
- void SetScreenMetricsEmulationParameters(
- bool enabled,
- const blink::WebDeviceEmulationParams& params) override;
// Do not delete directly. This class is reference counted.
~RenderViewImpl() override;
@@ -391,7 +345,6 @@ class CONTENT_EXPORT RenderViewImpl : private RenderWidget,
FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, OnHandleKeyboardEvent);
FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, OnImeTypeChanged);
FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, OnNavStateChanged);
- FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, OnSetTextDirection);
FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, OnUpdateWebPreferences);
FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest,
SetEditableSelectionAndComposition);
@@ -403,12 +356,6 @@ class CONTENT_EXPORT RenderViewImpl : private RenderWidget,
GetCompositionCharacterBoundsTest);
FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, OnNavigationHttpPost);
FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, UpdateDSFAfterSwapIn);
- FRIEND_TEST_ALL_PREFIXES(RenderViewImplScaleFactorTest,
- ScreenMetricsEmulationWithOriginalDSF1);
- FRIEND_TEST_ALL_PREFIXES(RenderViewImplScaleFactorTest,
- ScreenMetricsEmulationWithOriginalDSF2);
- FRIEND_TEST_ALL_PREFIXES(RenderViewImplScaleFactorTest,
- DeviceEmulationWithOOPIF);
FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest,
DecideNavigationPolicyHandlesAllTopLevel);
#if defined(OS_MACOSX)
@@ -441,10 +388,38 @@ class CONTENT_EXPORT RenderViewImpl : private RenderWidget,
// RenderWidgetOwnerDelegate implementation ----------------------------------
- bool RenderWidgetWillHandleMouseEvent(
+ blink::WebWidget* GetWebWidgetForWidget() const override;
+ bool RenderWidgetWillHandleMouseEventForWidget(
const blink::WebMouseEvent& event) override;
- void SetActive(bool active) override;
- void SetBackgroundOpaque(bool opaque) override;
+ void SetActiveForWidget(bool active) override;
+ void SetBackgroundOpaqueForWidget(bool opaque) override;
+ bool SupportsMultipleWindowsForWidget() override;
+ void DidHandleGestureEventForWidget(
+ const blink::WebGestureEvent& event) override;
+ void OverrideCloseForWidget() override;
+ void DidCloseWidget() override;
+ void ApplyNewSizeForWidget(const gfx::Size& old_size,
+ const gfx::Size& new_size) override;
+ void ApplyNewDisplayModeForWidget(
+ const blink::WebDisplayMode& new_display_mode) override;
+ void ApplyAutoResizeLimitsForWidget(const gfx::Size& min_size,
+ const gfx::Size& max_size) override;
+ void DisableAutoResizeForWidget() override;
+ void ScrollFocusedNodeIntoViewForWidget() override;
+ void DidReceiveSetFocusEventForWidget() override;
+ void DidChangeFocusForWidget() override;
+ GURL GetURLForGraphicsContext3DForWidget() override;
+ void DidCommitCompositorFrameForWidget() override;
+ void DidCompletePageScaleAnimationForWidget() override;
+ void ResizeWebWidgetForWidget(
+ const gfx::Size& size,
+ float top_controls_height,
+ float bottom_controls_height,
+ bool browser_controls_shrink_blink_size) override;
+ void RequestScheduleAnimationForWidget() override;
+ void SetScreenMetricsEmulationParametersForWidget(
+ bool enabled,
+ const blink::WebDeviceEmulationParams& params) override;
// Old WebLocalFrameClient implementations
// ----------------------------------------
@@ -465,12 +440,6 @@ class CONTENT_EXPORT RenderViewImpl : private RenderWidget,
void ApplyWebPreferencesInternal(const WebPreferences& prefs,
blink::WebView* web_view);
- // blink::WebWidgetClient overrides from RenderWidget ------------------------
-
- void Show(blink::WebNavigationPolicy policy) override;
- void DidHandleGestureEvent(const blink::WebGestureEvent& event,
- bool event_cancelled) override;
-
// IPC message handlers ------------------------------------------------------
//
// The documentation for these functions should be in
@@ -492,9 +461,6 @@ class CONTENT_EXPORT RenderViewImpl : private RenderWidget,
void OnPluginActionAt(const gfx::Point& location,
const blink::WebPluginAction& action);
void OnMoveOrResizeStarted();
- void OnResolveTapDisambiguation(base::TimeTicks timestamp,
- const gfx::Point& tap_viewport_offset,
- bool is_long_press);
void OnExitFullscreen();
void OnSetHistoryOffsetAndLength(int history_offset, int history_length);
void OnSetInitialFocus(bool reverse);
@@ -519,8 +485,9 @@ class CONTENT_EXPORT RenderViewImpl : private RenderWidget,
// and put it in the same position in the .cc file.
// Misc private functions ----------------------------------------------------
- // Check whether the preferred size has changed.
- void CheckPreferredSize();
+ // Check whether the preferred size has changed. This should only be called
+ // with up-to-date layout.
+ void UpdatePreferredSize();
#if defined(OS_ANDROID)
// Make the video capture devices (e.g. webcam) stop/resume delivering video
@@ -548,7 +515,9 @@ class CONTENT_EXPORT RenderViewImpl : private RenderWidget,
// to access RenderViewImpl state. The set of state variables are page-level
// specific, so they don't belong in RenderFrameImpl and should remain in
// this object.
- base::ObserverList<RenderViewObserver>& observers() { return observers_; }
+ base::ObserverList<RenderViewObserver>::Unchecked& observers() {
+ return observers_;
+ }
NavigationGesture navigation_gesture() {
return navigation_gesture_;
@@ -573,18 +542,31 @@ class CONTENT_EXPORT RenderViewImpl : private RenderWidget,
// RenderViewHost in the parent browser process.
const int32_t routing_id_;
+ // Whether lookup of frames in the created RenderView (e.g. lookup via
+ // window.open or via <a target=...>) should be renderer-wide (i.e. going
+ // beyond the usual opener-relationship-based BrowsingInstance boundaries).
+ const bool renderer_wide_named_frame_lookup_ = false;
+
// Settings ------------------------------------------------------------------
WebPreferences webkit_preferences_;
RendererPreferences renderer_preferences_;
+ // These are observing changes in |renderer_preferences_|. This is used for
+ // keeping WorkerFetchContext in sync.
+ mojo::InterfacePtrSet<mojom::RendererPreferenceWatcher>
+ renderer_preference_watchers_;
// 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.
- bool send_content_state_immediately_;
+ bool send_content_state_immediately_ = false;
// If true, we send IPC messages when |preferred_size_| changes.
- bool send_preferred_size_changes_;
+ bool send_preferred_size_changes_ = false;
+
+ // Whether the preferred size may have changed and |UpdatePreferredSize| needs
+ // to be called.
+ bool needs_preferred_size_update_ = true;
// If non-empty, and |send_preferred_size_changes_| is true, disable drawing
// scroll bars on windows smaller than this size. Used for windows that the
@@ -601,7 +583,7 @@ class CONTENT_EXPORT RenderViewImpl : private RenderWidget,
// The gesture that initiated the current navigation.
// TODO(nasko): Move to RenderFrame, as this is per-frame state.
- NavigationGesture navigation_gesture_;
+ NavigationGesture navigation_gesture_ = NavigationGestureUnknown;
// Timer used to delay the updating of nav state (see
// StartNavStateSyncTimerIfNecessary).
@@ -614,19 +596,20 @@ class CONTENT_EXPORT RenderViewImpl : private RenderWidget,
// History list --------------------------------------------------------------
// The offset of the current item in the history list.
- int history_list_offset_;
+ int history_list_offset_ = -1;
// The RenderView's current impression of the history length. This includes
// any items that have committed in this process, but because of cross-process
// navigations, the history may have some entries that were committed in other
// processes. We won't know about them until the next navigation in this
// process.
- int history_list_length_;
+ int history_list_length_ = 0;
// Counter to track how many frames have sent start notifications but not stop
- // notifications. TODO(avi): Remove this once DidStartLoading/DidStopLoading
- // are gone.
- int frames_in_progress_;
+ // notifications.
+ // TODO(avi): Remove this once FrameDidStartLoading/FrameDidStopLoading are
+ // gone.
+ int frames_in_progress_ = 0;
// UI state ------------------------------------------------------------------
@@ -642,7 +625,7 @@ class CONTENT_EXPORT RenderViewImpl : private RenderWidget,
TARGET_NONE,
TARGET_INFLIGHT, // We have a request in-flight, waiting for an ACK
TARGET_PENDING // INFLIGHT + we have a URL waiting to be sent
- } target_url_status_;
+ } target_url_status_ = TARGET_NONE;
// The URL we show the user in the status bar. We use this to determine if we
// want to send a new one (we do not need to send duplicates). It will be
@@ -662,42 +645,28 @@ class CONTENT_EXPORT RenderViewImpl : private RenderWidget,
#if defined(OS_ANDROID)
// Cache the old browser controls state constraints. Used when updating
// current value only without altering the constraints.
- BrowserControlsState top_controls_constraints_;
+ BrowserControlsState top_controls_constraints_ = BROWSER_CONTROLS_STATE_BOTH;
#endif
- // Whether or not Blink's viewport size should be shrunk by the height of the
- // URL-bar.
- bool browser_controls_shrink_blink_size_;
-
- // The height of the browser top controls.
- float top_controls_height_;
-
- // The height of the browser bottom controls.
- float bottom_controls_height_;
-
// View ----------------------------------------------------------------------
- blink::WebView* webview_;
+ blink::WebView* webview_ = nullptr;
// Cache the preferred size of the page in order to prevent sending the IPC
// when layout() recomputes but doesn't actually change sizes.
gfx::Size preferred_size_;
- // Used to delay determining the preferred size (to avoid intermediate
- // states for the sizes).
- base::OneShotTimer check_preferred_size_timer_;
-
// Used to indicate the zoom level to be used during subframe loads, since
// they should match page zoom level.
- double page_zoom_level_;
+ double page_zoom_level_ = 0;
// Helper objects ------------------------------------------------------------
- RenderFrameImpl* main_render_frame_;
+ RenderFrameImpl* main_render_frame_ = nullptr;
// Note: RenderViewImpl is pulling double duty: it's the RenderWidget for the
// "view", but it's also the RenderWidget for the main frame.
- blink::WebFrameWidget* frame_widget_;
+ blink::WebFrameWidget* frame_widget_ = nullptr;
#if defined(OS_ANDROID)
// Android Specific ---------------------------------------------------------
@@ -706,16 +675,14 @@ class CONTENT_EXPORT RenderViewImpl : private RenderWidget,
std::unique_ptr<RendererDateTimePicker> date_time_picker_client_;
// Whether this was a renderer-created or browser-created RenderView.
- bool was_created_by_renderer_;
+ bool was_created_by_renderer_ = false;
#endif
// Misc ----------------------------------------------------------------------
// The current directory enumeration callback
std::map<int, blink::WebFileChooserCompletion*> enumeration_completions_;
- int enumeration_completion_id_;
-
- base::Optional<float> device_scale_factor_for_testing_;
+ int enumeration_completion_id_ = 0;
// The SessionStorage namespace that we're assigned to has an ID, and that ID
// is passed to us upon creation. WebKit asks for this ID upon first use and
@@ -724,21 +691,14 @@ class CONTENT_EXPORT RenderViewImpl : private RenderWidget,
// All the registered observers. We expect this list to be small, so vector
// is fine.
- base::ObserverList<RenderViewObserver> observers_;
+ base::ObserverList<RenderViewObserver>::Unchecked observers_;
// NOTE: stats_collection_observer_ should be the last members because their
// constructors call the AddObservers method of RenderViewImpl.
std::unique_ptr<StatsCollectionObserver> stats_collection_observer_;
- std::unique_ptr<IdleUserDetector> idle_user_detector_;
-
blink::WebScopedVirtualTimePauser history_navigation_virtual_time_pauser_;
- // Whether lookup of frames in the created RenderView (e.g. lookup via
- // window.open or via <a target=...>) should be renderer-wide (i.e. going
- // beyond the usual opener-relationship-based BrowsingInstance boundaries).
- bool renderer_wide_named_frame_lookup_;
-
// ---------------------------------------------------------------------------
// ADDING NEW DATA? Please see if it fits appropriately in one of the above
// sections rather than throwing it randomly at the end. If you're adding a
diff --git a/chromium/content/renderer/render_widget.cc b/chromium/content/renderer/render_widget.cc
index 560c7caaa74..6d0580d5b0b 100644
--- a/chromium/content/renderer/render_widget.cc
+++ b/chromium/content/renderer/render_widget.cc
@@ -61,6 +61,7 @@
#include "content/renderer/gpu/frame_swap_message_queue.h"
#include "content/renderer/gpu/layer_tree_view.h"
#include "content/renderer/gpu/queue_message_swap_promise.h"
+#include "content/renderer/idle_user_detector.h"
#include "content/renderer/ime_event_guard.h"
#include "content/renderer/input/main_thread_event_queue.h"
#include "content/renderer/input/widget_input_handler_manager.h"
@@ -82,6 +83,7 @@
#include "ppapi/buildflags/buildflags.h"
#include "skia/ext/platform_canvas.h"
#include "third_party/blink/public/platform/file_path_conversion.h"
+#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/scheduler/web_render_widget_scheduling_state.h"
#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
#include "third_party/blink/public/platform/web_cursor_info.h"
@@ -93,6 +95,7 @@
#include "third_party/blink/public/platform/web_runtime_features.h"
#include "third_party/blink/public/platform/web_size.h"
#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/public/platform/web_thread.h"
#include "third_party/blink/public/web/web_autofill_client.h"
#include "third_party/blink/public/web/web_device_emulation_params.h"
#include "third_party/blink/public/web/web_frame_widget.h"
@@ -390,10 +393,10 @@ RenderWidget::RenderWidget(
CompositorDependencies* compositor_deps,
blink::WebPopupType popup_type,
const ScreenInfo& screen_info,
+ blink::WebDisplayMode display_mode,
bool swapped_out,
bool hidden,
bool never_visible,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner,
mojom::WidgetRequest widget_request)
: routing_id_(widget_routing_id),
compositor_deps_(compositor_deps),
@@ -404,7 +407,7 @@ RenderWidget::RenderWidget(
is_hidden_(hidden),
compositor_never_visible_(never_visible),
is_fullscreen_granted_(false),
- display_mode_(blink::kWebDisplayModeUndefined),
+ display_mode_(display_mode),
ime_event_guard_(nullptr),
closing_(false),
host_closing_(false),
@@ -432,7 +435,6 @@ RenderWidget::RenderWidget(
was_shown_time_(base::TimeTicks::Now()),
current_content_source_id_(0),
widget_binding_(this, std::move(widget_request)),
- task_runner_(task_runner),
weak_ptr_factory_(this) {
DCHECK_NE(routing_id_, MSG_ROUTING_NONE);
// TODO(nasko, alexmos): ref count the process based on the lifetime of
@@ -450,7 +452,7 @@ RenderWidget::RenderWidget(
}
#if defined(USE_AURA)
RendererWindowTreeClient::CreateIfNecessary(routing_id_);
- if (!features::IsAshInBrowserProcess())
+ if (features::IsUsingWindowService())
RendererWindowTreeClient::Get(routing_id_)->SetVisible(!is_hidden_);
#endif
@@ -501,8 +503,7 @@ RenderWidget* RenderWidget::CreateForPopup(
RenderViewImpl* opener,
CompositorDependencies* compositor_deps,
blink::WebPopupType popup_type,
- const ScreenInfo& screen_info,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
+ const ScreenInfo& screen_info) {
mojom::WidgetPtr widget_channel;
mojom::WidgetRequest widget_channel_request =
mojo::MakeRequest(&widget_channel);
@@ -515,9 +516,10 @@ RenderWidget* RenderWidget::CreateForPopup(
return nullptr;
}
- scoped_refptr<RenderWidget> widget(new RenderWidget(
- routing_id, compositor_deps, popup_type, screen_info, false, false, false,
- task_runner, std::move(widget_channel_request)));
+ scoped_refptr<RenderWidget> widget(
+ new RenderWidget(routing_id, compositor_deps, popup_type, screen_info,
+ blink::kWebDisplayModeUndefined, false, false, false,
+ std::move(widget_channel_request)));
ShowCallback opener_callback = base::BindOnce(
&RenderViewImpl::ShowCreatedPopupWidget, opener->GetWeakPtr());
widget->Init(std::move(opener_callback),
@@ -550,16 +552,16 @@ RenderWidget* RenderWidget::CreateForFrame(
view->GetWidget()->UpdateWebViewWithDeviceScaleFactor();
return view->GetWidget();
}
- scoped_refptr<base::SingleThreadTaskRunner> task_runner =
- frame->GetTaskRunner(blink::TaskType::kInternalDefault);
scoped_refptr<RenderWidget> widget(
g_create_render_widget
? g_create_render_widget(widget_routing_id, compositor_deps,
- blink::kWebPopupTypeNone, screen_info, false,
+ blink::kWebPopupTypeNone, screen_info,
+ blink::kWebDisplayModeUndefined, false,
hidden, false)
: new RenderWidget(widget_routing_id, compositor_deps,
- blink::kWebPopupTypeNone, screen_info, false,
- hidden, false, task_runner));
+ blink::kWebPopupTypeNone, screen_info,
+ blink::kWebDisplayModeUndefined, false, hidden,
+ false));
widget->for_oopif_ = true;
// Init increments the reference count on |widget|, keeping it alive after
// this function returns.
@@ -593,6 +595,10 @@ blink::WebWidget* RenderWidget::CreateWebWidget(RenderWidget* render_widget) {
}
void RenderWidget::CloseForFrame() {
+ if (owner_delegate_) {
+ owner_delegate_->OverrideCloseForWidget();
+ return;
+ }
OnClose();
}
@@ -639,8 +645,16 @@ void RenderWidget::Init(ShowCallback show_callback, WebWidget* web_widget) {
}
}
-void RenderWidget::SetPopupOriginAdjustmentsForEmulation(
- RenderWidgetScreenMetricsEmulator* emulator) {
+void RenderWidget::SetUpIdleUserDetector() {
+ idle_user_detector_ = std::make_unique<IdleUserDetector>();
+}
+
+void RenderWidget::ApplyEmulatedScreenMetricsForPopupWidget(
+ RenderWidget* origin_widget) {
+ RenderWidgetScreenMetricsEmulator* emulator =
+ origin_widget->screen_metrics_emulator_.get();
+ if (!emulator)
+ return;
popup_origin_scale_for_emulation_ = emulator->scale();
popup_view_origin_for_emulation_ = emulator->applied_widget_rect().origin();
popup_screen_origin_for_emulation_ =
@@ -749,29 +763,6 @@ bool RenderWidget::ShouldHandleImeEvents() const {
(has_focus_ || for_oopif_);
}
-void RenderWidget::SetWindowRectSynchronously(
- const gfx::Rect& new_window_rect) {
- VisualProperties visual_properties;
- visual_properties.screen_info = screen_info_;
- visual_properties.new_size = new_window_rect.size();
- visual_properties.compositor_viewport_pixel_size = gfx::ScaleToCeiledSize(
- new_window_rect.size(), GetWebScreenInfo().device_scale_factor);
- visual_properties.visible_viewport_size = new_window_rect.size();
- visual_properties.is_fullscreen_granted = is_fullscreen_granted_;
- visual_properties.display_mode = display_mode_;
- visual_properties.local_surface_id = local_surface_id_from_parent_;
- // We are resizing the window from the renderer, so allocate a new
- // viz::LocalSurfaceId to avoid surface invariants violations in tests.
- if (layer_tree_view_)
- layer_tree_view_->RequestNewLocalSurfaceId();
- SynchronizeVisualProperties(visual_properties);
-
- view_screen_rect_ = new_window_rect;
- window_screen_rect_ = new_window_rect;
- if (!did_show_)
- initial_rect_ = new_window_rect;
-}
-
void RenderWidget::OnClose() {
DCHECK(content::RenderThread::Get());
if (closing_)
@@ -800,32 +791,80 @@ void RenderWidget::OnClose() {
// If there is a Send call on the stack, then it could be dangerous to close
// now. Post a task that only gets invoked when there are no nested message
// loops.
- task_runner_->PostNonNestableTask(FROM_HERE,
- base::BindOnce(&RenderWidget::Close, this));
+ GetCleanupTaskRunner()->PostNonNestableTask(
+ FROM_HERE, base::BindOnce(&RenderWidget::Close, this));
// Balances the AddRef taken when we called AddRoute.
Release();
}
void RenderWidget::OnSynchronizeVisualProperties(
- const VisualProperties& params) {
- gfx::Size old_visible_viewport_size = visible_viewport_size_;
+ const VisualProperties& original_params) {
+ TRACE_EVENT0("renderer", "RenderWidget::OnSynchronizeVisualProperties");
- if (resizing_mode_selector_->ShouldAbortOnResize(this, params)) {
- return;
- }
+ VisualProperties params = original_params;
+ if (owner_delegate_) {
+ owner_delegate_->ApplyNewSizeForWidget(size_, params.new_size);
- if (screen_metrics_emulator_) {
- screen_metrics_emulator_->OnSynchronizeVisualProperties(params);
- return;
- }
+ if (display_mode_ != params.display_mode) {
+ display_mode_ = params.display_mode;
+ owner_delegate_->ApplyNewDisplayModeForWidget(params.display_mode);
+ }
- SynchronizeVisualProperties(params);
+ bool auto_resize_mode_changed =
+ auto_resize_mode_ != params.auto_resize_enabled;
+ auto_resize_mode_ = params.auto_resize_enabled;
+ min_size_for_auto_resize_ = params.min_size_for_auto_resize;
+ max_size_for_auto_resize_ = params.max_size_for_auto_resize;
+
+ if (auto_resize_mode_) {
+ gfx::Size min_auto_size = min_size_for_auto_resize_;
+ gfx::Size max_auto_size = max_size_for_auto_resize_;
+ if (compositor_deps_->IsUseZoomForDSFEnabled()) {
+ min_auto_size = gfx::ScaleToCeiledSize(
+ min_auto_size, params.screen_info.device_scale_factor);
+ max_auto_size = gfx::ScaleToCeiledSize(
+ max_auto_size, params.screen_info.device_scale_factor);
+ }
+ owner_delegate_->ApplyAutoResizeLimitsForWidget(min_auto_size,
+ max_auto_size);
+ } else if (auto_resize_mode_changed) {
+ owner_delegate_->DisableAutoResizeForWidget();
+ if (params.new_size.IsEmpty())
+ return;
+ }
- if (old_visible_viewport_size != visible_viewport_size_) {
- for (auto& render_frame : render_frames_)
- render_frame.DidChangeVisibleViewport();
+ browser_controls_shrink_blink_size_ =
+ params.browser_controls_shrink_blink_size;
+ top_controls_height_ = params.top_controls_height;
+ bottom_controls_height_ = params.bottom_controls_height;
+
+ // TODO(fsamuel): Modifies the |params| that are used for
+ // SynchronizeVisualProperties(), but does not used this modified
+ // device_scale_factor for the auto-resize values, which is probably a bug.
+ if (device_scale_factor_for_testing_) {
+ params.screen_info.device_scale_factor =
+ *device_scale_factor_for_testing_;
+ params.compositor_viewport_pixel_size = gfx::ScaleToCeiledSize(
+ params.new_size, params.screen_info.device_scale_factor);
+ }
}
+
+ if (!resizing_mode_selector_->ShouldAbortOnResize(this, params)) {
+ if (screen_metrics_emulator_) {
+ screen_metrics_emulator_->OnSynchronizeVisualProperties(params);
+ } else {
+ gfx::Size old_visible_viewport_size = visible_viewport_size_;
+ SynchronizeVisualProperties(params);
+ if (old_visible_viewport_size != visible_viewport_size_) {
+ for (auto& render_frame : render_frames_)
+ render_frame.DidChangeVisibleViewport();
+ }
+ }
+ }
+
+ if (owner_delegate_ && params.scroll_focused_node_into_view)
+ owner_delegate_->ScrollFocusedNodeIntoViewForWidget();
}
void RenderWidget::OnEnableDeviceEmulation(
@@ -903,18 +942,22 @@ void RenderWidget::DidPresentForceDrawFrame(
Send(new ViewHostMsg_ForceRedrawComplete(routing_id(), snapshot_id));
}
-GURL RenderWidget::GetURLForGraphicsContext3D() {
- return GURL();
-}
-
-viz::FrameSinkId RenderWidget::GetFrameSinkIdAtPoint(const gfx::Point& point) {
- return input_handler_->GetFrameSinkIdAtPoint(point);
+viz::FrameSinkId RenderWidget::GetFrameSinkIdAtPoint(const gfx::Point& point,
+ gfx::PointF* local_point) {
+ return input_handler_->GetFrameSinkIdAtPoint(point, local_point);
}
void RenderWidget::HandleInputEvent(
const blink::WebCoalescedInputEvent& input_event,
const ui::LatencyInfo& latency_info,
HandledEventCallback callback) {
+ if (owner_delegate_ && is_swapped_out_) {
+ std::move(callback).Run(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, latency_info,
+ nullptr, base::nullopt);
+ return;
+ }
+ if (idle_user_detector_)
+ idle_user_detector_->ActivityDetected();
input_handler_->HandleInputEvent(input_event, latency_info,
std::move(callback));
}
@@ -940,15 +983,21 @@ void RenderWidget::OnSetEditCommandsForNextKeyEvent(
void RenderWidget::OnSetActive(bool active) {
if (owner_delegate_)
- owner_delegate_->SetActive(active);
+ owner_delegate_->SetActiveForWidget(active);
}
void RenderWidget::OnSetBackgroundOpaque(bool opaque) {
if (owner_delegate_)
- owner_delegate_->SetBackgroundOpaque(opaque);
+ owner_delegate_->SetBackgroundOpaqueForWidget(opaque);
}
void RenderWidget::OnSetFocus(bool enable) {
+ if (owner_delegate_)
+ owner_delegate_->DidReceiveSetFocusEventForWidget();
+ SetFocus(enable);
+}
+
+void RenderWidget::SetFocus(bool enable) {
has_focus_ = enable;
if (GetWebWidget())
@@ -956,6 +1005,9 @@ void RenderWidget::OnSetFocus(bool enable) {
for (auto& observer : render_frames_)
observer.RenderWidgetSetFocus(enable);
+
+ if (owner_delegate_)
+ owner_delegate_->DidChangeFocusForWidget();
}
void RenderWidget::SetNeedsMainFrame() {
@@ -1036,9 +1088,14 @@ void RenderWidget::DidCommitAndDrawCompositorFrame() {
}
void RenderWidget::DidCommitCompositorFrame() {
+ if (owner_delegate_)
+ owner_delegate_->DidCommitCompositorFrameForWidget();
}
-void RenderWidget::DidCompletePageScaleAnimation() {}
+void RenderWidget::DidCompletePageScaleAnimation() {
+ if (owner_delegate_)
+ owner_delegate_->DidCompletePageScaleAnimationForWidget();
+}
void RenderWidget::DidReceiveCompositorFrameAck() {
}
@@ -1063,6 +1120,10 @@ bool RenderWidget::IsClosing() const {
}
void RenderWidget::RequestScheduleAnimation() {
+ if (owner_delegate_) {
+ owner_delegate_->RequestScheduleAnimationForWidget();
+ return;
+ }
ScheduleAnimation();
}
@@ -1296,7 +1357,7 @@ bool RenderWidget::WillHandleMouseEvent(const blink::WebMouseEvent& event) {
gfx::Point(event.PositionInScreen().x, event.PositionInScreen().y);
if (owner_delegate_)
- return owner_delegate_->RenderWidgetWillHandleMouseEvent(event);
+ return owner_delegate_->RenderWidgetWillHandleMouseEventForWidget(event);
return false;
}
@@ -1310,7 +1371,14 @@ void RenderWidget::Redraw() {
}
void RenderWidget::ResizeWebWidget() {
- GetWebWidget()->Resize(GetSizeForWebWidget());
+ gfx::Size size = GetSizeForWebWidget();
+ if (owner_delegate_) {
+ owner_delegate_->ResizeWebWidgetForWidget(
+ size, top_controls_height_, bottom_controls_height_,
+ browser_controls_shrink_blink_size_);
+ return;
+ }
+ GetWebWidget()->Resize(size);
}
gfx::Size RenderWidget::GetSizeForWebWidget() const {
@@ -1405,8 +1473,10 @@ void RenderWidget::SynchronizeVisualProperties(const VisualProperties& params) {
void RenderWidget::SetScreenMetricsEmulationParameters(
bool enabled,
const blink::WebDeviceEmulationParams& params) {
- // This is only supported in RenderView.
- NOTREACHED();
+ // This is only supported in RenderView, which has an |owner_delegate_|.
+ DCHECK(owner_delegate_);
+ owner_delegate_->SetScreenMetricsEmulationParametersForWidget(enabled,
+ params);
}
void RenderWidget::SetScreenRects(const gfx::Rect& view_screen_rect,
@@ -1481,8 +1551,7 @@ void RenderWidget::WillCloseLayerTreeView() {
void RenderWidget::DidMeaningfulLayout(blink::WebMeaningfulLayout layout_type) {
if (layout_type == blink::WebMeaningfulLayout::kVisuallyNonEmpty) {
- QueueMessage(new ViewHostMsg_DidFirstVisuallyNonEmptyPaint(routing_id_),
- MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE);
+ QueueMessage(new ViewHostMsg_DidFirstVisuallyNonEmptyPaint(routing_id_));
}
for (auto& observer : render_frames_)
@@ -1492,14 +1561,12 @@ void RenderWidget::DidMeaningfulLayout(blink::WebMeaningfulLayout layout_type) {
// static
std::unique_ptr<cc::SwapPromise> RenderWidget::QueueMessageImpl(
IPC::Message* msg,
- MessageDeliveryPolicy policy,
FrameSwapMessageQueue* frame_swap_message_queue,
scoped_refptr<IPC::SyncMessageFilter> sync_message_filter,
int source_frame_number) {
bool first_message_for_frame = false;
- frame_swap_message_queue->QueueMessageForFrame(policy, source_frame_number,
- base::WrapUnique(msg),
- &first_message_for_frame);
+ frame_swap_message_queue->QueueMessageForFrame(
+ source_frame_number, base::WrapUnique(msg), &first_message_for_frame);
if (first_message_for_frame) {
std::unique_ptr<cc::SwapPromise> promise(new QueueMessageSwapPromise(
sync_message_filter, frame_swap_message_queue, source_frame_number));
@@ -1508,8 +1575,11 @@ std::unique_ptr<cc::SwapPromise> RenderWidget::QueueMessageImpl(
return nullptr;
}
-void RenderWidget::QueueMessage(IPC::Message* msg,
- MessageDeliveryPolicy policy) {
+void RenderWidget::SetHandlingInputEvent(bool handling_input_event) {
+ input_handler_->set_handling_input_event(handling_input_event);
+}
+
+void RenderWidget::QueueMessage(IPC::Message* msg) {
// RenderThreadImpl::current() is NULL in some tests.
if (!layer_tree_view_ || !RenderThreadImpl::current()) {
Send(msg);
@@ -1517,7 +1587,7 @@ void RenderWidget::QueueMessage(IPC::Message* msg,
}
std::unique_ptr<cc::SwapPromise> swap_promise =
- QueueMessageImpl(msg, policy, frame_swap_message_queue_.get(),
+ QueueMessageImpl(msg, frame_swap_message_queue_.get(),
RenderThreadImpl::current()->sync_message_filter(),
layer_tree_view_->GetSourceFrameNumber());
@@ -1556,13 +1626,22 @@ void RenderWidget::AutoscrollEnd() {
// created RenderWidget (i.e., as a blocked popup or as a new tab).
//
void RenderWidget::Show(WebNavigationPolicy policy) {
- DCHECK(!did_show_) << "received extraneous Show call";
+ if (did_show_) {
+ if (owner_delegate_) {
+ // When SupportsMultipleWindows is disabled, popups are reusing
+ // the same view. In some scenarios, this makes blink to call Show()
+ // twice. But otherwise, if it is enabled, we should not visit Show() more
+ // than once.
+ DCHECK(!owner_delegate_->SupportsMultipleWindowsForWidget());
+ } else {
+ DCHECK(!did_show_) << "received extraneous Show call";
+ }
+ return;
+ }
+
DCHECK(routing_id_ != MSG_ROUTING_NONE);
DCHECK(show_callback_);
- if (did_show_)
- return;
-
did_show_ = true;
// The opener is responsible for actually showing this widget.
@@ -1602,14 +1681,16 @@ void RenderWidget::CloseWidgetSoon() {
// could be closed before the JS finishes executing. So instead, post a
// message back to the message loop, which won't run until the JS is
// complete, and then the Close message can be sent.
- task_runner_->PostTask(FROM_HERE,
- base::BindOnce(&RenderWidget::DoDeferredClose, this));
+ GetCleanupTaskRunner()->PostTask(
+ FROM_HERE, base::BindOnce(&RenderWidget::DoDeferredClose, this));
}
void RenderWidget::Close() {
screen_metrics_emulator_.reset();
CloseWebWidget();
layer_tree_view_.reset();
+ if (owner_delegate_)
+ owner_delegate_->DidCloseWidget();
}
void RenderWidget::CloseWebWidget() {
@@ -1879,6 +1960,29 @@ void RenderWidget::UpdateSurfaceAndScreenInfo(
UpdateWebViewWithDeviceScaleFactor();
}
+void RenderWidget::SetWindowRectSynchronously(
+ const gfx::Rect& new_window_rect) {
+ VisualProperties visual_properties;
+ visual_properties.screen_info = screen_info_;
+ visual_properties.new_size = new_window_rect.size();
+ visual_properties.compositor_viewport_pixel_size = gfx::ScaleToCeiledSize(
+ new_window_rect.size(), GetWebScreenInfo().device_scale_factor);
+ visual_properties.visible_viewport_size = new_window_rect.size();
+ visual_properties.is_fullscreen_granted = is_fullscreen_granted_;
+ visual_properties.display_mode = display_mode_;
+ visual_properties.local_surface_id = local_surface_id_from_parent_;
+ // We are resizing the window from the renderer, so allocate a new
+ // viz::LocalSurfaceId to avoid surface invariants violations in tests.
+ if (layer_tree_view_)
+ layer_tree_view_->RequestNewLocalSurfaceId();
+ SynchronizeVisualProperties(visual_properties);
+
+ view_screen_rect_ = new_window_rect;
+ window_screen_rect_ = new_window_rect;
+ if (!did_show_)
+ initial_rect_ = new_window_rect;
+}
+
void RenderWidget::UpdateCaptureSequenceNumber(
uint32_t capture_sequence_number) {
if (capture_sequence_number == last_capture_sequence_number_)
@@ -1908,21 +2012,15 @@ void RenderWidget::OnUpdateScreenRects(const gfx::Rect& view_screen_rect,
Send(new ViewHostMsg_UpdateScreenRects_ACK(routing_id()));
}
-void RenderWidget::OnUpdateWindowScreenRect(
- const gfx::Rect& window_screen_rect) {
- if (screen_metrics_emulator_)
- screen_metrics_emulator_->OnUpdateWindowScreenRect(window_screen_rect);
- else
- window_screen_rect_ = window_screen_rect;
-}
-
void RenderWidget::OnSetViewportIntersection(
const gfx::Rect& viewport_intersection,
- const gfx::Rect& compositor_visible_rect) {
+ const gfx::Rect& compositor_visible_rect,
+ bool occluded_or_obscured) {
if (auto* frame_widget = GetFrameWidget()) {
DCHECK_EQ(popup_type_, WebPopupType::kWebPopupTypeNone);
compositor_visible_rect_ = compositor_visible_rect;
- frame_widget->SetRemoteViewportIntersection(viewport_intersection);
+ frame_widget->SetRemoteViewportIntersection(viewport_intersection,
+ occluded_or_obscured);
layer_tree_view_->SetViewportVisibleRect(ViewportVisibleRect());
}
}
@@ -1989,7 +2087,6 @@ void RenderWidget::OnDragTargetDragLeave(const gfx::PointF& client_point,
return;
frame_widget
-
->DragTargetDragLeave(ConvertWindowPointToViewport(client_point),
screen_point);
}
@@ -2133,6 +2230,12 @@ void RenderWidget::OnOrientationChange() {
}
}
+GURL RenderWidget::GetURLForGraphicsContext3D() {
+ if (owner_delegate_)
+ return owner_delegate_->GetURLForGraphicsContext3DForWidget();
+ return GURL();
+}
+
void RenderWidget::SetHidden(bool hidden) {
if (is_hidden_ == hidden)
return;
@@ -2142,7 +2245,7 @@ void RenderWidget::SetHidden(bool hidden) {
is_hidden_ = hidden;
#if defined(USE_AURA)
- if (!features::IsAshInBrowserProcess())
+ if (features::IsUsingWindowService())
RendererWindowTreeClient::Get(routing_id_)->SetVisible(!hidden);
#endif
@@ -2177,10 +2280,8 @@ void RenderWidget::OnImeEventGuardStart(ImeEventGuard* guard) {
}
void RenderWidget::OnImeEventGuardFinish(ImeEventGuard* guard) {
- if (ime_event_guard_ != guard) {
- DCHECK(!ime_event_guard_->reply_to_request());
+ if (ime_event_guard_ != guard)
return;
- }
ime_event_guard_ = nullptr;
// While handling an ime event, text input state and selection bounds updates
@@ -2385,9 +2486,12 @@ blink::WebScreenInfo RenderWidget::GetScreenInfo() {
void RenderWidget::DidHandleGestureEvent(const WebGestureEvent& event,
bool event_cancelled) {
-#if defined(OS_ANDROID) || defined(USE_AURA)
- if (event_cancelled)
+ if (event_cancelled) {
+ // The |owner_delegate_| doesn't need to hear about cancelled events.
return;
+ }
+
+#if defined(OS_ANDROID) || defined(USE_AURA)
if (event.GetType() == WebInputEvent::kGestureTap) {
ShowVirtualKeyboard();
} else if (event.GetType() == WebInputEvent::kGestureLongPress) {
@@ -2401,19 +2505,22 @@ void RenderWidget::DidHandleGestureEvent(const WebGestureEvent& event,
// TODO(ananta): Piggyback off existing IPCs to communicate this information,
// crbug/420130.
#if defined(OS_WIN)
- if (event.GetType() != blink::WebGestureEvent::kGestureTap)
- return;
-
- // TODO(estade): hit test the event against focused node to make sure
- // the tap actually hit the focused node.
- blink::WebInputMethodController* controller = GetInputMethodController();
- blink::WebTextInputType text_input_type =
- controller ? controller->TextInputType() : blink::kWebTextInputTypeNone;
+ if (event.GetType() == blink::WebGestureEvent::kGestureTap) {
+ // TODO(estade): hit test the event against focused node to make sure
+ // the tap actually hit the focused node.
+ blink::WebInputMethodController* controller = GetInputMethodController();
+ blink::WebTextInputType text_input_type =
+ controller ? controller->TextInputType() : blink::kWebTextInputTypeNone;
- Send(new ViewHostMsg_FocusedNodeTouched(
- routing_id_, text_input_type != blink::kWebTextInputTypeNone));
+ Send(new ViewHostMsg_FocusedNodeTouched(
+ routing_id_, text_input_type != blink::kWebTextInputTypeNone));
+ }
#endif
#endif
+
+ // The |owner_delegate_| gets to respond to handling gestures last.
+ if (owner_delegate_)
+ owner_delegate_->DidHandleGestureEventForWidget(event);
}
void RenderWidget::DidOverscroll(
@@ -2863,8 +2970,9 @@ void RenderWidget::StartCompositor() {
layer_tree_view_->SetVisible(true);
}
-void RenderWidget::SetHandlingInputEventForTesting(bool handling_input_event) {
- input_handler_->set_handling_input_event(handling_input_event);
+void RenderWidget::HasPointerRawMoveEventHandlers(bool has_handlers) {
+ if (input_event_queue_)
+ input_event_queue_->HasPointerRawMoveEventHandlers(has_handlers);
}
void RenderWidget::HasTouchEventHandlers(bool has_handlers) {
@@ -2920,8 +3028,8 @@ void RenderWidget::UnregisterBrowserPlugin(BrowserPlugin* browser_plugin) {
}
void RenderWidget::OnWaitNextFrameForTests(int routing_id) {
- QueueMessage(new ViewHostMsg_WaitForNextFrameForTests_ACK(routing_id),
- MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE);
+ // Sends an ACK to the browser process during the next compositor frame.
+ QueueMessage(new ViewHostMsg_WaitForNextFrameForTests_ACK(routing_id));
}
const ScreenInfo& RenderWidget::GetWebScreenInfo() const {
@@ -2985,6 +3093,12 @@ void RenderWidget::DidNavigate() {
}
blink::WebWidget* RenderWidget::GetWebWidget() const {
+ if (owner_delegate_) {
+ blink::WebWidget* delegate_widget =
+ owner_delegate_->GetWebWidgetForWidget();
+ if (delegate_widget)
+ return delegate_widget;
+ }
return webwidget_internal_;
}
@@ -3017,11 +3131,101 @@ void RenderWidget::SetMouseCapture(bool capture) {
}
}
+void RenderWidget::SetWindowScreenRect(const gfx::Rect& window_screen_rect) {
+ if (screen_metrics_emulator_)
+ screen_metrics_emulator_->OnUpdateWindowScreenRect(window_screen_rect);
+ else
+ window_screen_rect_ = window_screen_rect;
+}
+
bool RenderWidget::IsSurfaceSynchronizationEnabled() const {
return layer_tree_view_ &&
layer_tree_view_->IsSurfaceSynchronizationEnabled();
}
+void RenderWidget::UseSynchronousResizeModeForTesting(bool enable) {
+ resizing_mode_selector_->set_is_synchronous_mode(enable);
+}
+
+void RenderWidget::SetDeviceScaleFactorForTesting(float factor) {
+ device_scale_factor_for_testing_ = factor;
+
+ VisualProperties visual_properties;
+ visual_properties.screen_info = screen_info_;
+ visual_properties.screen_info.device_scale_factor = factor;
+ visual_properties.new_size = size();
+ visual_properties.visible_viewport_size = visible_viewport_size_;
+ visual_properties.compositor_viewport_pixel_size =
+ gfx::ScaleToCeiledSize(size(), factor);
+ visual_properties.browser_controls_shrink_blink_size = false;
+ visual_properties.top_controls_height = 0.f;
+ visual_properties.is_fullscreen_granted = is_fullscreen_granted_;
+ visual_properties.display_mode = display_mode_;
+ visual_properties.local_surface_id = local_surface_id_from_parent_;
+ // We are changing the device scale factor from the renderer, so allocate a
+ // new viz::LocalSurfaceId to avoid surface invariants violations in tests.
+ if (layer_tree_view_)
+ layer_tree_view_->RequestNewLocalSurfaceId();
+
+ OnSynchronizeVisualProperties(visual_properties);
+}
+
+void RenderWidget::SetDeviceColorSpaceForTesting(
+ const gfx::ColorSpace& color_space) {
+ VisualProperties visual_properties;
+ visual_properties.screen_info = screen_info_;
+ visual_properties.screen_info.color_space = color_space;
+ visual_properties.new_size = size();
+ visual_properties.visible_viewport_size = visible_viewport_size_;
+ visual_properties.compositor_viewport_pixel_size =
+ compositor_viewport_pixel_size_;
+ visual_properties.browser_controls_shrink_blink_size = false;
+ visual_properties.top_controls_height = 0.f;
+ visual_properties.is_fullscreen_granted = is_fullscreen_granted_;
+ visual_properties.display_mode = display_mode_;
+ visual_properties.local_surface_id = local_surface_id_from_parent_;
+ // We are changing the device color space from the renderer, so allocate a
+ // new viz::LocalSurfaceId to avoid surface invariants violations in tests.
+ if (layer_tree_view_)
+ layer_tree_view_->RequestNewLocalSurfaceId();
+ OnSynchronizeVisualProperties(visual_properties);
+}
+
+void RenderWidget::SetWindowRectSynchronouslyForTesting(
+ const gfx::Rect& new_window_rect) {
+ SetWindowRectSynchronously(new_window_rect);
+}
+
+void RenderWidget::EnableAutoResizeForTesting(const gfx::Size& min_size,
+ const gfx::Size& max_size) {
+ VisualProperties visual_properties;
+ visual_properties.auto_resize_enabled = true;
+ visual_properties.min_size_for_auto_resize = min_size;
+ visual_properties.max_size_for_auto_resize = max_size;
+ visual_properties.local_surface_id = base::Optional<viz::LocalSurfaceId>(
+ viz::LocalSurfaceId(1, 1, base::UnguessableToken::Create()));
+ OnSynchronizeVisualProperties(visual_properties);
+}
+
+void RenderWidget::DisableAutoResizeForTesting(const gfx::Size& new_size) {
+ if (!auto_resize_mode_)
+ return;
+
+ VisualProperties visual_properties;
+ visual_properties.auto_resize_enabled = false;
+ visual_properties.screen_info = screen_info_;
+ visual_properties.new_size = new_size;
+ visual_properties.compositor_viewport_pixel_size =
+ compositor_viewport_pixel_size_;
+ visual_properties.browser_controls_shrink_blink_size =
+ browser_controls_shrink_blink_size_;
+ visual_properties.top_controls_height = top_controls_height_;
+ visual_properties.visible_viewport_size = visible_viewport_size_;
+ visual_properties.is_fullscreen_granted = is_fullscreen_granted_;
+ visual_properties.display_mode = display_mode_;
+ OnSynchronizeVisualProperties(visual_properties);
+}
+
void RenderWidget::UpdateURLForCompositorUkm() {
DCHECK(layer_tree_view_);
blink::WebFrameWidget* frame_widget = GetFrameWidget();
@@ -3075,6 +3279,14 @@ gfx::Rect RenderWidget::ViewportVisibleRect() {
: gfx::Rect(compositor_viewport_pixel_size_);
}
+// static
+scoped_refptr<base::SingleThreadTaskRunner>
+RenderWidget::GetCleanupTaskRunner() {
+ return RenderThreadImpl::current_blink_platform_impl()
+ ->main_thread_scheduler()
+ ->CleanupTaskRunner();
+}
+
base::WeakPtr<RenderWidget> RenderWidget::AsWeakPtr() {
return weak_ptr_factory_.GetWeakPtr();
}
diff --git a/chromium/content/renderer/render_widget.h b/chromium/content/renderer/render_widget.h
index ab52a4efb1c..15031b62b93 100644
--- a/chromium/content/renderer/render_widget.h
+++ b/chromium/content/renderer/render_widget.h
@@ -42,7 +42,6 @@
#include "content/renderer/input/main_thread_event_queue.h"
#include "content/renderer/input/render_widget_input_handler.h"
#include "content/renderer/input/render_widget_input_handler_delegate.h"
-#include "content/renderer/message_delivery_policy.h"
#include "content/renderer/mouse_lock_dispatcher.h"
#include "content/renderer/render_widget_mouse_lock_dispatcher.h"
#include "ipc/ipc_listener.h"
@@ -94,6 +93,7 @@ class SwapPromise;
}
namespace gfx {
+class ColorSpace;
class Range;
}
@@ -106,6 +106,7 @@ class BrowserPlugin;
class CompositorDependencies;
class ExternalPopupMenu;
class FrameSwapMessageQueue;
+class IdleUserDetector;
class ImeEventGuard;
class LayerTreeView;
class MainThreadEventQueue;
@@ -145,14 +146,18 @@ class CONTENT_EXPORT RenderWidget
blink::WebNavigationPolicy policy,
const gfx::Rect& initial_rect)>;
+ // Time-To-First-Active-Paint(TTFAP) type
+ enum {
+ TTFAP_AFTER_PURGED,
+ TTFAP_5MIN_AFTER_BACKGROUNDED,
+ };
+
// Creates a new RenderWidget for a popup. |opener| is the RenderView that
// this widget lives inside.
- static RenderWidget* CreateForPopup(
- RenderViewImpl* opener,
- CompositorDependencies* compositor_deps,
- blink::WebPopupType popup_type,
- const ScreenInfo& screen_info,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+ static RenderWidget* CreateForPopup(RenderViewImpl* opener,
+ CompositorDependencies* compositor_deps,
+ blink::WebPopupType popup_type,
+ const ScreenInfo& screen_info);
// Creates a new RenderWidget that will be attached to a RenderFrame.
static RenderWidget* CreateForFrame(int widget_routing_id,
@@ -163,32 +168,38 @@ class CONTENT_EXPORT RenderWidget
// Used by content_layouttest_support to hook into the creation of
// RenderWidgets.
- using CreateRenderWidgetFunction = RenderWidget* (*)(int32_t,
- CompositorDependencies*,
- blink::WebPopupType,
- const ScreenInfo&,
- bool,
- bool,
- bool);
+ using CreateRenderWidgetFunction =
+ RenderWidget* (*)(int32_t,
+ CompositorDependencies*,
+ blink::WebPopupType,
+ const ScreenInfo&,
+ blink::WebDisplayMode display_mode,
+ bool,
+ bool,
+ bool);
using RenderWidgetInitializedCallback = void (*)(RenderWidget*);
static void InstallCreateHook(
CreateRenderWidgetFunction create_render_widget,
RenderWidgetInitializedCallback render_widget_initialized_callback);
+ void set_owner_delegate(RenderWidgetOwnerDelegate* owner_delegate) {
+ DCHECK(!owner_delegate_);
+ owner_delegate_ = owner_delegate;
+ }
+ RenderWidgetOwnerDelegate* owner_delegate() const { return owner_delegate_; }
+
// Returns the RenderWidget for the given routing ID.
static RenderWidget* FromRoutingID(int32_t routing_id);
// Closes a RenderWidget that was created by |CreateForFrame|.
- // TODO(avi): De-virtualize this once RenderViewImpl has-a RenderWidget.
- // https://crbug.com/545684
- virtual void CloseForFrame();
+ void CloseForFrame();
int32_t routing_id() const { return routing_id_; }
CompositorDependencies* compositor_deps() const { return compositor_deps_; }
// This can return nullptr while the RenderWidget is closing.
- virtual blink::WebWidget* GetWebWidget() const;
+ blink::WebWidget* GetWebWidget() const;
// Returns the current instance of WebInputMethodController which is to be
// used for IME related tasks. This instance corresponds to the one from
@@ -214,19 +225,14 @@ class CONTENT_EXPORT RenderWidget
return visible_viewport_size_;
}
- void set_owner_delegate(RenderWidgetOwnerDelegate* owner_delegate) {
- DCHECK(!owner_delegate_);
- owner_delegate_ = owner_delegate;
- }
-
- RenderWidgetOwnerDelegate* owner_delegate() const { return owner_delegate_; }
+ ScreenInfo screen_info() const { return screen_info_; }
+ void set_screen_info(const ScreenInfo& info) { screen_info_ = info; }
// Sets whether this RenderWidget has been swapped out to be displayed by
// a RenderWidget in a different process. If so, no new IPC messages will be
// sent (only ACKs) and the process is free to exit when there are no other
// active RenderWidgets.
void SetSwappedOut(bool is_swapped_out);
-
bool is_swapped_out() const { return is_swapped_out_; }
// Manage edit commands to be used for the next keyboard event.
@@ -339,10 +345,15 @@ class CONTENT_EXPORT RenderWidget
blink::WebDragOperationsMask mask,
const SkBitmap& drag_image,
const blink::WebPoint& image_offset) override;
+ void SetTouchAction(cc::TouchAction touch_action) override;
+ void RequestUnbufferedInputEvents() override;
+ void HasPointerRawMoveEventHandlers(bool has_handlers) override;
+ void HasTouchEventHandlers(bool has_handlers) override;
+ void SetNeedsLowLatencyInput(bool) override;
// Override point to obtain that the current input method state and caret
// position.
- virtual ui::TextInputType GetTextInputType();
+ ui::TextInputType GetTextInputType();
// Internal helper that generates the LayerTreeSettings to be given to the
// compositor in StartCompositor().
@@ -365,35 +376,28 @@ class CONTENT_EXPORT RenderWidget
void WillCloseLayerTreeView();
LayerTreeView* layer_tree_view() const { return layer_tree_view_.get(); }
-
WidgetInputHandlerManager* widget_input_handler_manager() {
return widget_input_handler_manager_.get();
}
-
const RenderWidgetInputHandler& input_handler() const {
return *input_handler_;
}
- void SetHandlingInputEventForTesting(bool handling_input_event);
+ void SetHandlingInputEvent(bool handling_input_event);
- // Deliveres |message| together with compositor state change updates. The
- // exact behavior depends on |policy|.
+ // Delivers |message| together with compositor state change updates.
// This mechanism is not a drop-in replacement for IPC: messages sent this way
// will not be automatically available to BrowserMessageFilter, for example.
- // FIFO ordering is preserved between messages enqueued with the same
- // |policy|, the ordering between messages enqueued for different policies is
- // undefined.
+ // FIFO ordering is preserved between messages enqueued.
//
// |msg| message to send, ownership of |msg| is transferred.
- // |policy| see the comment on MessageDeliveryPolicy.
- void QueueMessage(IPC::Message* msg, MessageDeliveryPolicy policy);
+ void QueueMessage(IPC::Message* msg);
// Handle start and finish of IME event guard.
void OnImeEventGuardStart(ImeEventGuard* guard);
void OnImeEventGuardFinish(ImeEventGuard* guard);
- void SetPopupOriginAdjustmentsForEmulation(
- RenderWidgetScreenMetricsEmulator* emulator);
+ void ApplyEmulatedScreenMetricsForPopupWidget(RenderWidget* origin_widget);
gfx::Rect AdjustValidationMessageAnchor(const gfx::Rect& anchor);
@@ -401,7 +405,7 @@ class CONTENT_EXPORT RenderWidget
// the new value will be sent to the browser process.
void UpdateSelectionBounds();
- virtual void GetSelectionBounds(gfx::Rect* start, gfx::Rect* end);
+ void GetSelectionBounds(gfx::Rect* start, gfx::Rect* end);
void OnShowHostContextMenu(ContextMenuParams* params);
@@ -413,6 +417,12 @@ class CONTENT_EXPORT RenderWidget
// the browser even if the composition info is not changed.
void UpdateCompositionInfo(bool immediate_request);
+ // Override point to obtain that the current composition character bounds.
+ // In the case of surrogate pairs, the character is treated as two characters:
+ // the bounds for first character is actual one, and the bounds for second
+ // character is zero width rectangle.
+ void GetCompositionCharacterBounds(std::vector<gfx::Rect>* character_bounds);
+
// Called when the Widget has changed size as a result of an auto-resize.
void DidAutoResize(const gfx::Size& new_size);
@@ -436,7 +446,6 @@ class CONTENT_EXPORT RenderWidget
// Helper to convert |point| using ConvertWindowToViewport().
gfx::PointF ConvertWindowPointToViewport(const gfx::PointF& point);
gfx::Point ConvertWindowPointToViewport(const gfx::Point& point);
-
uint32_t GetContentSourceId();
void DidNavigate();
@@ -459,7 +468,8 @@ class CONTENT_EXPORT RenderWidget
// Requests a BeginMainFrame callback from the compositor.
void SetNeedsMainFrame() override;
- viz::FrameSinkId GetFrameSinkIdAtPoint(const gfx::Point& point);
+ viz::FrameSinkId GetFrameSinkIdAtPoint(const gfx::Point& point,
+ gfx::PointF* local_point);
void HandleInputEvent(const blink::WebCoalescedInputEvent& input_event,
const ui::LatencyInfo& latency_info,
@@ -471,7 +481,7 @@ class CONTENT_EXPORT RenderWidget
scoped_refptr<MainThreadEventQueue> GetInputEventQueue();
void OnSetActive(bool active);
- virtual void OnSetFocus(bool enable);
+ void OnSetFocus(bool enable);
void OnSetBackgroundOpaque(bool opaque);
void OnMouseCaptureLost();
void OnCursorVisibilityChange(bool is_visible);
@@ -488,6 +498,10 @@ class CONTENT_EXPORT RenderWidget
int relative_cursor_pos);
void OnImeFinishComposingText(bool keep_selection);
+ // This does the actual focus change, but is called in more situations than
+ // just as an IPC message.
+ void SetFocus(bool enable);
+
// Called by the browser process to update text input state.
void OnRequestTextInputStateUpdate();
@@ -504,39 +518,32 @@ class CONTENT_EXPORT RenderWidget
void SetMouseCapture(bool capture);
- // Time-To-First-Active-Paint(TTFAP) type
- enum {
- TTFAP_AFTER_PURGED,
- TTFAP_5MIN_AFTER_BACKGROUNDED,
- };
+ void SetWindowScreenRect(const gfx::Rect& window_screen_rect);
bool IsSurfaceSynchronizationEnabled() const;
+ void UseSynchronousResizeModeForTesting(bool enable);
+ void SetDeviceScaleFactorForTesting(float factor);
+ void SetDeviceColorSpaceForTesting(const gfx::ColorSpace& color_space);
+ void SetWindowRectSynchronouslyForTesting(const gfx::Rect& new_window_rect);
+ void EnableAutoResizeForTesting(const gfx::Size& min_size,
+ const gfx::Size& max_size);
+ void DisableAutoResizeForTesting(const gfx::Size& new_size);
+
base::WeakPtr<RenderWidget> AsWeakPtr();
protected:
- // Friend RefCounted so that the dtor can be non-public. Using this class
- // without ref-counting is an error.
- friend class base::RefCounted<RenderWidget>;
-
- // For unit tests.
- friend class RenderWidgetTest;
-
- enum ResizeAck {
- SEND_RESIZE_ACK,
- NO_RESIZE_ACK,
- };
-
RenderWidget(int32_t widget_routing_id,
CompositorDependencies* compositor_deps,
blink::WebPopupType popup_type,
const ScreenInfo& screen_info,
+ blink::WebDisplayMode display_mode,
bool swapped_out,
bool hidden,
bool never_visible,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner,
mojom::WidgetRequest widget_request = nullptr);
+ // Avoid making RenderWidget other than as a refptr.
~RenderWidget() override;
static blink::WebFrameWidget* CreateWebFrameWidget(
@@ -547,69 +554,108 @@ class CONTENT_EXPORT RenderWidget
static blink::WebWidget* CreateWebWidget(RenderWidget* render_widget);
// Called by Create() functions and subclasses to finish initialization.
- // |show_callback| will be invoked once WebWidgetClient::show() occurs, and
- // should be null if show() won't be triggered for this widget.
+ // |show_callback| will be invoked once WebWidgetClient::Show() occurs, and
+ // should be null if Show() won't be triggered for this widget.
void Init(ShowCallback show_callback, blink::WebWidget* web_widget);
+ // Initialization methods used by the RenderViewImpl subclass.
+ //
+ // Idle user detector is optionally set up and destroyed during
+ // initialization/teardown.
+ void SetUpIdleUserDetector();
+ // Update the web view's device scale factor.
+ void UpdateWebViewWithDeviceScaleFactor();
+ // Informs that Show() will not happen.
+ void set_did_show() { did_show_ = true; }
+
+ // Close the underlying WebWidget and stop the compositor.
+ virtual void Close();
+
+ // Notify subclasses that we initiated the paint operation.
+ virtual void DidInitiatePaint() {}
+
+ // Gets the current URL or a placeholder constant for creating 3d contexts and
+ // attributing them back to a URL.
+ virtual GURL GetURLForGraphicsContext3D();
+
+ // RenderWidget IPC message handler that can be overridden by subclasses.
+ virtual void OnSynchronizeVisualProperties(const VisualProperties& params);
+
+#if defined(OS_MACOSX)
+ // On MacOSX this message arrives on RenderViewImpl instead of here, and it
+ // needs to be able to call back to the normal message handler here.
+ void OnClose();
+#endif
+
+ private:
+ // Friend RefCounted so that the dtor can be non-public. Using this class
+ // without ref-counting is an error.
+ friend class base::RefCounted<RenderWidget>;
+
+ // TODO(nasko): Temporarily friend RenderFrameImpl for WasSwappedOut(),
+ // while we move frame specific code away from RenderViewImpl/RenderWidget.
+ friend class RenderFrameImpl;
+
+ // For unit tests.
+ friend class InteractiveRenderWidget;
+ friend class PopupRenderWidget;
+ friend class QueueMessageSwapPromiseTest;
+ friend class RenderWidgetTest;
+ friend class RenderViewImplTest;
+ FRIEND_TEST_ALL_PREFIXES(RenderWidgetPopupUnittest, EmulatingPopupRect);
+
+ static scoped_refptr<base::SingleThreadTaskRunner> GetCleanupTaskRunner();
+
void DoDeferredClose();
void NotifyOnClose();
gfx::Size GetSizeForWebWidget() const;
- virtual void ResizeWebWidget();
-
- // Close the underlying WebWidget and stop the compositor.
- virtual void Close();
+ void ResizeWebWidget();
// Just Close the WebWidget, in cases where the Close() will be deferred.
// It is safe to call this multiple times, which happens in the case of
// frame widgets beings closed, since subsequent calls are ignored.
void CloseWebWidget();
- // Update the web view's device scale factor.
- void UpdateWebViewWithDeviceScaleFactor();
-
- // Used to force the size of a window when running layout tests.
- void SetWindowRectSynchronously(const gfx::Rect& new_window_rect);
#if BUILDFLAG(USE_EXTERNAL_POPUP_MENU)
void SetExternalPopupOriginAdjustmentsForEmulation(
ExternalPopupMenu* popup,
RenderWidgetScreenMetricsEmulator* emulator);
#endif
- // RenderWidget IPC message handlers
+ // RenderWidget IPC message handlers.
void OnHandleInputEvent(
const blink::WebInputEvent* event,
const std::vector<const blink::WebInputEvent*>& coalesced_events,
const ui::LatencyInfo& latency_info,
InputEventDispatchType dispatch_type);
+#if !defined(OS_MACOSX)
void OnClose();
+#endif
void OnCreatingNewAck();
- virtual void OnSynchronizeVisualProperties(const VisualProperties& params);
void OnEnableDeviceEmulation(const blink::WebDeviceEmulationParams& params);
void OnDisableDeviceEmulation();
- virtual void OnWasHidden();
- virtual void OnWasShown(bool needs_repainting,
- base::TimeTicks show_request_timestamp);
+ void OnWasHidden();
+ void OnWasShown(bool needs_repainting,
+ base::TimeTicks show_request_timestamp);
void OnCreateVideoAck(int32_t video_id);
void OnUpdateVideoAck(int32_t video_id);
void OnRequestSetBoundsAck();
void OnForceRedraw(int snapshot_id);
- // Request from browser to show context menu.
- virtual void OnShowContextMenu(ui::MenuSourceType source_type,
- const gfx::Point& location);
+ void OnShowContextMenu(ui::MenuSourceType source_type,
+ const gfx::Point& location);
void OnSetTextDirection(blink::WebTextDirection direction);
void OnGetFPS();
void OnUpdateScreenRects(const gfx::Rect& view_screen_rect,
const gfx::Rect& window_screen_rect);
- void OnUpdateWindowScreenRect(const gfx::Rect& window_screen_rect);
void OnSetViewportIntersection(const gfx::Rect& viewport_intersection,
- const gfx::Rect& compositor_visible_rect);
+ const gfx::Rect& compositor_visible_rect,
+ bool occluded_or_obscured);
void OnSetIsInert(bool);
void OnSetInheritedEffectiveTouchAction(cc::TouchAction touch_action);
void OnUpdateRenderThrottlingStatus(bool is_throttled,
bool subtree_throttled);
- // Real data that is dragged is not included at DragEnter time.
void OnDragTargetDragEnter(
const std::vector<DropData::Metadata>& drop_meta_data,
const gfx::PointF& client_pt,
@@ -630,15 +676,8 @@ class CONTENT_EXPORT RenderWidget
const gfx::PointF& screen_point,
blink::WebDragOperation drag_operation);
void OnDragSourceSystemDragEnded();
-
void OnOrientationChange();
-
- // Override points to notify derived classes that a paint has happened.
- // DidInitiatePaint happens when that has completed, and subsequent rendering
- // won't affect the painted content.
- virtual void DidInitiatePaint() {}
-
- virtual GURL GetURLForGraphicsContext3D();
+ void OnWaitNextFrameForTests(int routing_id);
// Sets the "hidden" state of this widget. All accesses to is_hidden_ should
// use this method so that we can properly inform the RenderThread of our
@@ -656,21 +695,13 @@ class CONTENT_EXPORT RenderWidget
// testing.
static std::unique_ptr<cc::SwapPromise> QueueMessageImpl(
IPC::Message* msg,
- MessageDeliveryPolicy policy,
FrameSwapMessageQueue* frame_swap_message_queue,
scoped_refptr<IPC::SyncMessageFilter> sync_message_filter,
int source_frame_number);
- // Override point to obtain that the current composition character bounds.
- // In the case of surrogate pairs, the character is treated as two characters:
- // the bounds for first character is actual one, and the bounds for second
- // character is zero width rectangle.
- virtual void GetCompositionCharacterBounds(
- std::vector<gfx::Rect>* character_bounds);
-
// Returns the range of the text that is being composed or the selection if
// the composition does not exist.
- virtual void GetCompositionRange(gfx::Range* range);
+ void GetCompositionRange(gfx::Range* range);
// Returns true if the composition range or composition character bounds
// should be sent to the browser process.
@@ -680,7 +711,7 @@ class CONTENT_EXPORT RenderWidget
// Override point to obtain that the current input method state about
// composition text.
- virtual bool CanComposeInline();
+ bool CanComposeInline();
// Set the pending window rect.
// Because the real render_widget is hosted in another process, there is
@@ -690,21 +721,80 @@ class CONTENT_EXPORT RenderWidget
// GetWindowRect() we'll use this pending window rect as the size.
void SetPendingWindowRect(const blink::WebRect& r);
- // Check whether the WebWidget has any touch event handlers registered.
- void HasTouchEventHandlers(bool has_handlers) override;
+ // 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
+ // a local root associated with it. RenderWidgetFullscreenPepper and a swapped
+ // out RenderWidgets are amongst the cases where this method returns nullptr.
+ blink::WebFrameWidget* GetFrameWidget() const;
- // Called to update whether low latency input mode is enabled or not.
- void SetNeedsLowLatencyInput(bool) override;
+ // Applies/Removes the DevTools device emulation transformation to/from a
+ // window rect.
+ void ScreenRectToEmulatedIfNeeded(blink::WebRect* window_rect) const;
+ void EmulatedToScreenRectIfNeeded(blink::WebRect* window_rect) const;
- // Requests unbuffered (ie. low latency) input until a pointerup
- // event occurs.
- void RequestUnbufferedInputEvents() override;
+ bool CreateWidget(int32_t opener_id,
+ blink::WebPopupType popup_type,
+ int32_t* routing_id);
- // Tell the browser about the actions permitted for a new touch point.
- void SetTouchAction(cc::TouchAction touch_action) override;
+ void UpdateSurfaceAndScreenInfo(
+ const viz::LocalSurfaceId& new_local_surface_id,
+ const gfx::Size& new_compositor_viewport_pixel_size,
+ const ScreenInfo& new_screen_info);
- // Sends an ACK to the browser process during the next compositor frame.
- void OnWaitNextFrameForTests(int routing_id);
+ // Used to force the size of a window when running layout tests.
+ void SetWindowRectSynchronously(const gfx::Rect& new_window_rect);
+
+ void UpdateCaptureSequenceNumber(uint32_t capture_sequence_number);
+
+ // A variant of Send but is fatal if it fails. The browser may
+ // be waiting for this IPC Message and if the send fails the browser will
+ // be left in a state waiting for something that never comes. And if it
+ // never comes then it may later determine this is a hung renderer; so
+ // instead fail right away.
+ void SendOrCrash(IPC::Message* msg);
+
+ // Determines whether or not RenderWidget should process IME events from the
+ // browser. It always returns true unless there is no WebFrameWidget to
+ // handle the event, or there is no page focus.
+ bool ShouldHandleImeEvents() const;
+
+ void UpdateTextInputStateInternal(bool show_virtual_keyboard,
+ bool reply_to_request);
+
+ gfx::ColorSpace GetRasterColorSpace() const;
+
+ void SendInputEventAck(blink::WebInputEvent::Type type,
+ uint32_t touch_event_id,
+ InputEventAckState ack_state,
+ const ui::LatencyInfo& latency_info,
+ std::unique_ptr<ui::DidOverscrollParams>,
+ base::Optional<cc::TouchAction>);
+
+ void UpdateZoom(double zoom_level);
+
+#if BUILDFLAG(ENABLE_PLUGINS)
+ // Returns the focused pepper plugin, if any, inside the WebWidget. That is
+ // the pepper plugin which is focused inside a frame which belongs to the
+ // local root associated with this RenderWidget.
+ PepperPluginInstanceImpl* GetFocusedPepperPluginInsideWidget();
+#endif
+ void RecordTimeToFirstActivePaint();
+
+ // Updates the URL used by the compositor for keying UKM metrics.
+ // Note that this uses the main frame's URL and only if its available in the
+ // current process. In the case where it is not available, no metrics will be
+ // recorded.
+ void UpdateURLForCompositorUkm();
+
+ // This method returns the WebLocalFrame which is currently focused and
+ // belongs to the frame tree associated with this RenderWidget.
+ blink::WebLocalFrame* GetFocusedWebLocalFrameInWidget() const;
// Routing ID that allows us to communicate to the parent browser process
// RenderWidgetHost.
@@ -732,6 +822,8 @@ class CONTENT_EXPORT RenderWidget
// messages.
WebCursor current_cursor_;
+ base::Optional<float> device_scale_factor_for_testing_;
+
// The size of the RenderWidget in DIPs. This may differ from
// |compositor_viewport_pixel_size_| in the following (and possibly other)
// cases: * On Android, for top and bottom controls * On OOPIF, due to
@@ -852,14 +944,14 @@ class CONTENT_EXPORT RenderWidget
// Lists of RenderFrameProxy objects that need to be notified of
// compositing-related events (e.g. DidCommitCompositorFrame).
- base::ObserverList<RenderFrameProxy> render_frame_proxies_;
+ base::ObserverList<RenderFrameProxy>::Unchecked render_frame_proxies_;
// A list of RenderFrames associated with this RenderWidget. Notifications
// are sent to each frame in the list for events such as changing
// visibility state for example.
- base::ObserverList<RenderFrameImpl> render_frames_;
+ base::ObserverList<RenderFrameImpl>::Unchecked render_frames_;
- base::ObserverList<BrowserPlugin> browser_plugins_;
+ base::ObserverList<BrowserPlugin>::Unchecked browser_plugins_;
bool has_host_context_menu_location_;
gfx::Point host_context_menu_location_;
@@ -875,79 +967,6 @@ class CONTENT_EXPORT RenderWidget
viz::LocalSurfaceId local_surface_id_from_parent_;
- private:
- // 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
- // a local root associated with it. RenderWidgetFullscreenPepper and a swapped
- // out RenderWidgets are amongst the cases where this method returns nullptr.
- blink::WebFrameWidget* GetFrameWidget() const;
-
- // Applies/Removes the DevTools device emulation transformation to/from a
- // window rect.
- void ScreenRectToEmulatedIfNeeded(blink::WebRect* window_rect) const;
- void EmulatedToScreenRectIfNeeded(blink::WebRect* window_rect) const;
-
- bool CreateWidget(int32_t opener_id,
- blink::WebPopupType popup_type,
- int32_t* routing_id);
-
- void UpdateSurfaceAndScreenInfo(
- const viz::LocalSurfaceId& new_local_surface_id,
- const gfx::Size& new_compositor_viewport_pixel_size,
- const ScreenInfo& new_screen_info);
-
- void UpdateCaptureSequenceNumber(uint32_t capture_sequence_number);
-
- // A variant of Send but is fatal if it fails. The browser may
- // be waiting for this IPC Message and if the send fails the browser will
- // be left in a state waiting for something that never comes. And if it
- // never comes then it may later determine this is a hung renderer; so
- // instead fail right away.
- void SendOrCrash(IPC::Message* msg);
-
- // Determines whether or not RenderWidget should process IME events from the
- // browser. It always returns true unless there is no WebFrameWidget to
- // handle the event, or there is no page focus.
- bool ShouldHandleImeEvents() const;
-
- void UpdateTextInputStateInternal(bool show_virtual_keyboard,
- bool reply_to_request);
-
- gfx::ColorSpace GetRasterColorSpace() const;
-
- void SendInputEventAck(blink::WebInputEvent::Type type,
- uint32_t touch_event_id,
- InputEventAckState ack_state,
- const ui::LatencyInfo& latency_info,
- std::unique_ptr<ui::DidOverscrollParams>,
- base::Optional<cc::TouchAction>);
-
- void UpdateZoom(double zoom_level);
-
-#if BUILDFLAG(ENABLE_PLUGINS)
- // Returns the focused pepper plugin, if any, inside the WebWidget. That is
- // the pepper plugin which is focused inside a frame which belongs to the
- // local root associated with this RenderWidget.
- PepperPluginInstanceImpl* GetFocusedPepperPluginInsideWidget();
-#endif
- void RecordTimeToFirstActivePaint();
-
- // Updates the URL used by the compositor for keying UKM metrics.
- // Note that this uses the main frame's URL and only if its available in the
- // current process. In the case where it is not available, no metrics will be
- // recorded.
- void UpdateURLForCompositorUkm();
-
- // This method returns the WebLocalFrame which is currently focused and
- // belongs to the frame tree associated with this RenderWidget.
- blink::WebLocalFrame* GetFocusedWebLocalFrameInWidget() const;
-
// Indicates whether this widget has focus.
bool has_focus_;
@@ -976,6 +995,14 @@ class CONTENT_EXPORT RenderWidget
bool first_update_visual_state_after_hidden_;
base::TimeTicks was_shown_time_;
+ // Whether or not Blink's viewport size should be shrunk by the height of the
+ // URL-bar.
+ bool browser_controls_shrink_blink_size_ = false;
+ // The height of the browser top controls.
+ float top_controls_height_ = 0.f;
+ // The height of the browser bottom controls.
+ float bottom_controls_height_ = 0.f;
+
// This is initialized to zero and is incremented on each non-same-page
// navigation commit by RenderFrameImpl. At that time it is sent to the
// compositor so that it can tag compositor frames, and RenderFrameImpl is
@@ -992,8 +1019,9 @@ class CONTENT_EXPORT RenderWidget
scoped_refptr<MainThreadEventQueue> input_event_queue_;
mojo::Binding<mojom::Widget> widget_binding_;
-
- scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+ // IdleUserDetector is setup optionally on RenderWidget by its creator, so may
+ // be null.
+ std::unique_ptr<IdleUserDetector> idle_user_detector_;
gfx::Rect compositor_visible_rect_;
diff --git a/chromium/content/renderer/render_widget_browsertest.cc b/chromium/content/renderer/render_widget_browsertest.cc
index f1732625658..8082956a61c 100644
--- a/chromium/content/renderer/render_widget_browsertest.cc
+++ b/chromium/content/renderer/render_widget_browsertest.cc
@@ -70,7 +70,8 @@ TEST_F(RenderWidgetTest, OnSynchronizeVisualProperties) {
render_thread_->sink().ClearMessages();
viz::ParentLocalSurfaceIdAllocator local_surface_id_allocator;
gfx::Size size(100, 100);
- visual_properties.local_surface_id = local_surface_id_allocator.GenerateId();
+ visual_properties.local_surface_id =
+ local_surface_id_allocator.GetCurrentLocalSurfaceId();
visual_properties.new_size = size;
visual_properties.compositor_viewport_pixel_size = size;
OnSynchronizeVisualProperties(visual_properties);
@@ -98,23 +99,18 @@ TEST_F(RenderWidgetTest, OnSynchronizeVisualProperties) {
}
class RenderWidgetInitialSizeTest : public RenderWidgetTest {
- public:
- RenderWidgetInitialSizeTest() : RenderWidgetTest(), initial_size_(200, 100) {
- local_surface_id_ = local_surface_id_allocator_.GenerateId();
- }
-
protected:
std::unique_ptr<VisualProperties> InitialVisualProperties() override {
std::unique_ptr<VisualProperties> initial_visual_properties(
new VisualProperties());
initial_visual_properties->new_size = initial_size_;
initial_visual_properties->compositor_viewport_pixel_size = initial_size_;
- initial_visual_properties->local_surface_id = local_surface_id_;
+ initial_visual_properties->local_surface_id =
+ local_surface_id_allocator_.GetCurrentLocalSurfaceId();
return initial_visual_properties;
}
- gfx::Size initial_size_;
- viz::LocalSurfaceId local_surface_id_;
+ gfx::Size initial_size_ = gfx::Size(200, 100);
viz::ParentLocalSurfaceIdAllocator local_surface_id_allocator_;
};
@@ -125,20 +121,23 @@ TEST_F(RenderWidgetTest, HitTestAPI) {
"<iframe style='width: 200px; height: 100px;'"
"srcdoc='<body style=\"margin: 0px; height: 100px; width: 200px;\">"
"</body>'></iframe><div></body>");
+ gfx::PointF point;
viz::FrameSinkId main_frame_sink_id =
- widget()->GetFrameSinkIdAtPoint(gfx::Point(10, 10));
+ widget()->GetFrameSinkIdAtPoint(gfx::Point(10, 10), &point);
EXPECT_EQ(static_cast<uint32_t>(widget()->routing_id()),
main_frame_sink_id.sink_id());
EXPECT_EQ(static_cast<uint32_t>(RenderThreadImpl::Get()->GetClientId()),
main_frame_sink_id.client_id());
+ EXPECT_EQ(gfx::PointF(10, 10), point);
// Targeting a child frame should also return the FrameSinkId for the main
// widget.
viz::FrameSinkId frame_sink_id =
- widget()->GetFrameSinkIdAtPoint(gfx::Point(150, 150));
+ widget()->GetFrameSinkIdAtPoint(gfx::Point(150, 150), &point);
EXPECT_EQ(static_cast<uint32_t>(widget()->routing_id()),
frame_sink_id.sink_id());
EXPECT_EQ(main_frame_sink_id.client_id(), frame_sink_id.client_id());
+ EXPECT_EQ(gfx::PointF(150, 150), point);
}
TEST_F(RenderWidgetTest, GetCompositionRangeValidComposition) {
diff --git a/chromium/content/renderer/render_widget_fullscreen_pepper.cc b/chromium/content/renderer/render_widget_fullscreen_pepper.cc
index 28bf42737ca..28ce36b09a4 100644
--- a/chromium/content/renderer/render_widget_fullscreen_pepper.cc
+++ b/chromium/content/renderer/render_widget_fullscreen_pepper.cc
@@ -281,10 +281,10 @@ RenderWidgetFullscreenPepper::RenderWidgetFullscreenPepper(
compositor_deps,
blink::kWebPopupTypeNone,
screen_info,
+ blink::kWebDisplayModeUndefined,
false,
false,
false,
- base::ThreadTaskRunnerHandle::Get(),
std::move(widget_request)),
active_url_(active_url),
plugin_(plugin),
@@ -295,7 +295,7 @@ RenderWidgetFullscreenPepper::~RenderWidgetFullscreenPepper() {
}
void RenderWidgetFullscreenPepper::Invalidate() {
- InvalidateRect(gfx::Rect(size_.width(), size_.height()));
+ InvalidateRect(gfx::Rect(size()));
}
void RenderWidgetFullscreenPepper::InvalidateRect(const blink::WebRect& rect) {
@@ -321,7 +321,7 @@ void RenderWidgetFullscreenPepper::Destroy() {
// away.
SetLayer(nullptr);
- Send(new ViewHostMsg_Close(routing_id_));
+ Send(new ViewHostMsg_Close(routing_id()));
Release();
}
diff --git a/chromium/content/renderer/render_widget_owner_delegate.h b/chromium/content/renderer/render_widget_owner_delegate.h
index 8438e9ac6a2..2365a3944fe 100644
--- a/chromium/content/renderer/render_widget_owner_delegate.h
+++ b/chromium/content/renderer/render_widget_owner_delegate.h
@@ -21,15 +21,98 @@ namespace content {
// are disentangled; see https://crbug.com/583347 and https://crbug.com/478281.
class CONTENT_EXPORT RenderWidgetOwnerDelegate {
public:
- // As in RenderWidgetInputHandlerDelegate.
- virtual bool RenderWidgetWillHandleMouseEvent(
+ // Returns the WebWidget if the delegate has one. Otherwise it returns null,
+ // and RenderWidget will fall back to its own WebWidget.
+ virtual blink::WebWidget* GetWebWidgetForWidget() const = 0;
+
+ // As in RenderWidgetInputHandlerDelegate. Return true if the event was
+ // handled.
+ virtual bool RenderWidgetWillHandleMouseEventForWidget(
const blink::WebMouseEvent& event) = 0;
// See comment in RenderWidgetHost::SetActive().
- virtual void SetActive(bool active) = 0;
+ virtual void SetActiveForWidget(bool active) = 0;
// See comment in RenderWidgetHostImpl::SetBackgroundOpaque().
- virtual void SetBackgroundOpaque(bool opaque) = 0;
+ virtual void SetBackgroundOpaqueForWidget(bool opaque) = 0;
+
+ // Returns whether multiple windows are allowed for the widget. If true, then
+ // Show() may be called more than once.
+ virtual bool SupportsMultipleWindowsForWidget() = 0;
+
+ // Called after RenderWidget services WebWidgetClient::DidHandleGestureEvent()
+ // if the event was not cancelled.
+ virtual void DidHandleGestureEventForWidget(
+ const blink::WebGestureEvent& event) = 0;
+
+ // ==================================
+ // These methods called during closing of a RenderWidget.
+ //
+ // Called when RenderWidget is closed that was "created for a frame".
+ virtual void OverrideCloseForWidget() = 0;
+ // Called after closing the RenderWidget and destroying the WebView.
+ virtual void DidCloseWidget() = 0;
+ // ==================================
+
+ // ==================================
+ // These methods called during handling of a SynchronizeVisualProperties
+ // message to handle updating state on the delegate.
+ //
+ // Called during handling a SynchronizeVisualProperties message, with the new
+ // size that will be applied to the RenderWidget. The size in the RenderWidget
+ // has not yet changed when this method is called, as it is changed later.
+ virtual void ApplyNewSizeForWidget(const gfx::Size& old_size,
+ const gfx::Size& new_size) = 0;
+ // Called during handling a SynchronizeVisualProperties message, with the new
+ // display mode that will be applied to the RenderWidget. The display mode in
+ // the RenderWidget is already changed when this method is called.
+ virtual void ApplyNewDisplayModeForWidget(
+ const blink::WebDisplayMode& new_display_mode) = 0;
+ // Called during handling a SynchronizeVisualProperties message, if auto
+ // resize is enabled, with the new auto size limits.
+ virtual void ApplyAutoResizeLimitsForWidget(const gfx::Size& min_size,
+ const gfx::Size& max_size) = 0;
+ // Called during handling a SynchronizeVisualProperties message, if auto
+ // resize was enabled but is being disabled.
+ virtual void DisableAutoResizeForWidget() = 0;
+ // Called during handling a SynchronizeVisualProperties message, if the
+ // message informed that the focused node should be scrolled into view.
+ virtual void ScrollFocusedNodeIntoViewForWidget() = 0;
+ // ==================================
+
+ // Called when RenderWidget receives a SetFocus event.
+ virtual void DidReceiveSetFocusEventForWidget() = 0;
+
+ // Called after RenderWidget changes focus.
+ virtual void DidChangeFocusForWidget() = 0;
+
+ // Called to get the current URL if it exists or a hardcoded fallback.
+ virtual GURL GetURLForGraphicsContext3DForWidget() = 0;
+
+ // Called when the RenderWidget handles
+ // LayerTreeViewDelegate::DidCommitCompositorFrame().
+ virtual void DidCommitCompositorFrameForWidget() = 0;
+
+ // Called when the RenderWidget handles
+ // LayerTreeViewDelegate::DidCompletePageScaleAnimation().
+ virtual void DidCompletePageScaleAnimationForWidget() = 0;
+
+ // Called to resize the WebWidget, so the delegate may change how resize
+ // happens.
+ virtual void ResizeWebWidgetForWidget(
+ const gfx::Size& size,
+ float top_controls_height,
+ float bottom_controls_height,
+ bool browser_controls_shrink_blink_size) = 0;
+
+ // Called to schedule an animation on the WebWidgetClient.
+ virtual void RequestScheduleAnimationForWidget() = 0;
+
+ // Called when RenderWidget services RenderWidgetScreenMetricsEmulatorDelegate
+ // SetScreenMetricsEmulationParameters().
+ virtual void SetScreenMetricsEmulationParametersForWidget(
+ bool enabled,
+ const blink::WebDeviceEmulationParams& params) = 0;
protected:
virtual ~RenderWidgetOwnerDelegate() {}
diff --git a/chromium/content/renderer/render_widget_unittest.cc b/chromium/content/renderer/render_widget_unittest.cc
index 91392d4c552..98c17ad635c 100644
--- a/chromium/content/renderer/render_widget_unittest.cc
+++ b/chromium/content/renderer/render_widget_unittest.cc
@@ -26,6 +26,7 @@
#include "content/renderer/devtools/render_widget_screen_metrics_emulator.h"
#include "content/renderer/gpu/layer_tree_view.h"
#include "content/renderer/input/widget_input_handler_manager.h"
+#include "content/renderer/render_widget_owner_delegate.h"
#include "content/test/fake_compositor_dependencies.h"
#include "content/test/mock_render_process.h"
#include "ipc/ipc_test_sink.h"
@@ -145,10 +146,10 @@ class InteractiveRenderWidget : public RenderWidget {
compositor_deps,
blink::kWebPopupTypeNone,
ScreenInfo(),
+ blink::kWebDisplayModeUndefined,
false,
false,
- false,
- blink::scheduler::GetSingleThreadTaskRunnerForTesting()),
+ false),
always_overscroll_(false) {
Init(RenderWidget::ShowCallback(), mock_webwidget());
@@ -390,10 +391,10 @@ class PopupRenderWidget : public RenderWidget {
compositor_deps,
blink::kWebPopupTypePage,
ScreenInfo(),
+ blink::kWebDisplayModeUndefined,
false,
false,
- false,
- blink::scheduler::GetSingleThreadTaskRunnerForTesting()) {
+ false) {
Init(RenderWidget::ShowCallback(), mock_webwidget());
did_show_ = true;
}
@@ -406,8 +407,15 @@ class PopupRenderWidget : public RenderWidget {
bool,
const blink::WebDeviceEmulationParams&) override {}
+ // Shuts down the metrics emulator, the compositor, and destroys the internal
+ // WebWidget. Should be called before destroying the object.
+ void Shutdown() {
+ RenderWidget::Close();
+ shutdown_ = true;
+ }
+
protected:
- ~PopupRenderWidget() override { webwidget_internal_ = nullptr; }
+ ~PopupRenderWidget() override { DCHECK(shutdown_); }
bool Send(IPC::Message* msg) override {
sink_.OnMessageReceived(*msg);
@@ -416,6 +424,7 @@ class PopupRenderWidget : public RenderWidget {
}
private:
+ bool shutdown_ = false;
IPC::TestSink sink_;
MockWebWidget mock_webwidget_;
static int routing_id_;
@@ -435,7 +444,7 @@ class RenderWidgetPopupUnittest : public testing::Test {
widget_->Release();
DCHECK(widget_->HasOneRef());
}
- ~RenderWidgetPopupUnittest() override {}
+ ~RenderWidgetPopupUnittest() override { widget_->Shutdown(); }
PopupRenderWidget* widget() const { return widget_.get(); }
FakeCompositorDependencies compositor_deps_;
@@ -451,6 +460,44 @@ class RenderWidgetPopupUnittest : public testing::Test {
DISALLOW_COPY_AND_ASSIGN(RenderWidgetPopupUnittest);
};
+class StubRenderWidgetOwnerDelegate : public RenderWidgetOwnerDelegate {
+ public:
+ blink::WebWidget* GetWebWidgetForWidget() const override { return nullptr; }
+ bool RenderWidgetWillHandleMouseEventForWidget(
+ const blink::WebMouseEvent& event) override {
+ return false;
+ }
+ void SetActiveForWidget(bool active) override {}
+ void SetBackgroundOpaqueForWidget(bool opaque) override {}
+ bool SupportsMultipleWindowsForWidget() override { return true; }
+ void DidHandleGestureEventForWidget(
+ const blink::WebGestureEvent& event) override {}
+ void OverrideCloseForWidget() override {}
+ void DidCloseWidget() override {}
+ void ApplyNewSizeForWidget(const gfx::Size& old_size,
+ const gfx::Size& new_size) override {}
+ void ApplyNewDisplayModeForWidget(
+ const blink::WebDisplayMode& new_display_mode) override {}
+ void ApplyAutoResizeLimitsForWidget(const gfx::Size& min_size,
+ const gfx::Size& max_size) override {}
+ void DisableAutoResizeForWidget() override {}
+ void ScrollFocusedNodeIntoViewForWidget() override {}
+ void DidReceiveSetFocusEventForWidget() override {}
+ void DidChangeFocusForWidget() override {}
+ GURL GetURLForGraphicsContext3DForWidget() override { return {}; }
+ void DidCommitCompositorFrameForWidget() override {}
+ void DidCompletePageScaleAnimationForWidget() override {}
+ void ResizeWebWidgetForWidget(
+ const gfx::Size& size,
+ float top_controls_height,
+ float bottom_controls_height,
+ bool browser_controls_shrink_blink_size) override {}
+ void RequestScheduleAnimationForWidget() override {}
+ void SetScreenMetricsEmulationParametersForWidget(
+ bool enabled,
+ const blink::WebDeviceEmulationParams& params) override {}
+};
+
TEST_F(RenderWidgetPopupUnittest, EmulatingPopupRect) {
blink::WebRect popup_screen_rect(200, 250, 100, 400);
widget()->SetWindowRect(popup_screen_rect);
@@ -478,12 +525,16 @@ TEST_F(RenderWidgetPopupUnittest, EmulatingPopupRect) {
scoped_refptr<PopupRenderWidget> parent_widget(
new PopupRenderWidget(&compositor_deps_));
parent_widget->Release(); // Balance Init().
- RenderWidgetScreenMetricsEmulator emulator(
- parent_widget.get(), emulation_params, visual_properties,
- parent_window_rect, parent_window_rect);
- emulator.Apply();
- widget()->SetPopupOriginAdjustmentsForEmulation(&emulator);
+ // Emulation only happens for RenderWidgets with an owner delegate.
+ StubRenderWidgetOwnerDelegate delegate;
+ parent_widget->set_owner_delegate(&delegate);
+
+ // Setup emulation on the |parent_widget|.
+ parent_widget->OnSynchronizeVisualProperties(visual_properties);
+ parent_widget->OnEnableDeviceEmulation(emulation_params);
+ // Then use it for the popup widget under test.
+ widget()->ApplyEmulatedScreenMetricsForPopupWidget(parent_widget.get());
// Position of the popup as seen by the emulated widget.
gfx::Point emulated_position(
@@ -507,6 +558,8 @@ TEST_F(RenderWidgetPopupUnittest, EmulatingPopupRect) {
EXPECT_EQ(popup_emulated_rect.y, widget()->WindowRect().y);
EXPECT_EQ(popup_emulated_rect.x, widget()->ViewRect().x);
EXPECT_EQ(popup_emulated_rect.y, widget()->ViewRect().y);
+
+ parent_widget->Shutdown();
}
// Verify desktop memory limit calculations.
diff --git a/chromium/content/renderer/renderer_blink_platform_impl.cc b/chromium/content/renderer/renderer_blink_platform_impl.cc
index a9b86c68fe5..4a594bd98bc 100644
--- a/chromium/content/renderer/renderer_blink_platform_impl.cc
+++ b/chromium/content/renderer/renderer_blink_platform_impl.cc
@@ -24,7 +24,7 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "build/build_config.h"
@@ -52,6 +52,7 @@
#include "content/renderer/image_capture/image_capture_frame_grabber.h"
#include "content/renderer/indexed_db/webidbfactory_impl.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"
@@ -64,6 +65,7 @@
#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"
@@ -72,10 +74,9 @@
#include "content/renderer/worker_thread_registry.h"
#include "device/gamepad/public/cpp/gamepads.h"
#include "gpu/command_buffer/client/gles2_interface.h"
+#include "gpu/config/gpu_driver_bug_workaround_type.h"
#include "gpu/config/gpu_info.h"
#include "gpu/ipc/client/gpu_channel_host.h"
-#include "ipc/ipc_sync_channel.h"
-#include "ipc/ipc_sync_message_filter.h"
#include "media/audio/audio_output_device.h"
#include "media/blink/webcontentdecryptionmodule_impl.h"
#include "media/filters/stream_parser_factory.h"
@@ -88,9 +89,10 @@
#include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
#include "services/service_manager/public/cpp/connector.h"
#include "services/service_manager/public/cpp/interface_provider.h"
-#include "services/ui/public/cpp/gpu/context_provider_command_buffer.h"
+#include "services/ws/public/cpp/gpu/context_provider_command_buffer.h"
#include "storage/common/database/database_identifier.h"
#include "third_party/blink/public/common/origin_trials/trial_token_validator.h"
+#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h"
#include "third_party/blink/public/platform/blame_context.h"
#include "third_party/blink/public/platform/file_path_conversion.h"
#include "third_party/blink/public/platform/modules/webmidi/web_midi_accessor.h"
@@ -110,7 +112,6 @@
#include "third_party/blink/public/platform/web_url_loader_factory.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/public/platform/web_vector.h"
-#include "third_party/blink/public/platform/websocket_handshake_throttle.h"
#include "third_party/blink/public/web/web_local_frame.h"
#include "third_party/sqlite/sqlite3.h"
#include "url/gurl.h"
@@ -176,7 +177,7 @@ media::AudioParameters GetAudioHardwareParams() {
return media::AudioParameters::UnavailableDeviceParams();
return AudioDeviceFactory::GetOutputDeviceInfo(render_frame->GetRoutingID(),
- 0, std::string())
+ media::AudioSinkParameters())
.output_params();
}
@@ -192,6 +193,8 @@ gpu::ContextType ToGpuContextType(blink::Platform::ContextType type) {
return gpu::CONTEXT_TYPE_OPENGLES2;
case blink::Platform::kGLES3ContextType:
return gpu::CONTEXT_TYPE_OPENGLES3;
+ case blink::Platform::kWebGPUContextType:
+ return gpu::CONTEXT_TYPE_WEBGPU;
}
NOTREACHED();
return gpu::CONTEXT_TYPE_OPENGLES2;
@@ -255,16 +258,13 @@ RendererBlinkPlatformImpl::RendererBlinkPlatformImpl(
// RenderThread may not exist in some tests.
if (RenderThreadImpl::current()) {
+ io_runner_ = RenderThreadImpl::current()->GetIOTaskRunner();
connector_ = RenderThreadImpl::current()
->GetServiceManagerConnection()
->GetConnector()
->Clone();
- sync_message_filter_ = RenderThreadImpl::current()->sync_message_filter();
thread_safe_sender_ = RenderThreadImpl::current()->thread_safe_sender();
blob_registry_.reset(new WebBlobRegistryImpl(thread_safe_sender_.get()));
- web_idb_factory_.reset(new WebIDBFactoryImpl(
- sync_message_filter_,
- RenderThreadImpl::current()->GetIOTaskRunner().get()));
#if defined(OS_LINUX)
font_loader_ = sk_make_sp<font_service::FontLoader>(connector_.get());
SkFontConfigInterface::SetGlobal(font_loader_);
@@ -325,6 +325,11 @@ RendererBlinkPlatformImpl::CreateDefaultURLLoaderFactory() {
CreateDefaultURLLoaderFactoryBundle());
}
+std::unique_ptr<blink::CodeCacheLoader>
+RendererBlinkPlatformImpl::CreateCodeCacheLoader() {
+ return std::make_unique<CodeCacheLoaderImpl>();
+}
+
std::unique_ptr<blink::WebURLLoaderFactory>
RendererBlinkPlatformImpl::WrapURLLoaderFactory(
mojo::ScopedMessagePipeHandle url_loader_factory_handle) {
@@ -463,6 +468,19 @@ void RendererBlinkPlatformImpl::CacheMetadata(const blink::WebURL& url,
->DidGenerateCacheableMetadata(url, response_time, copy);
}
+void RendererBlinkPlatformImpl::FetchCachedCode(
+ const GURL& url,
+ base::OnceCallback<void(base::Time, const std::vector<uint8_t>&)>
+ callback) {
+ RenderThreadImpl::current()->render_message_filter()->FetchCachedCode(
+ url, std::move(callback));
+}
+
+void RendererBlinkPlatformImpl::ClearCodeCacheEntry(const GURL& url) {
+ RenderThreadImpl::current()->render_message_filter()->ClearCodeCacheEntry(
+ url);
+}
+
void RendererBlinkPlatformImpl::CacheMetadataInCacheStorage(
const blink::WebURL& url,
base::Time response_time,
@@ -561,14 +579,19 @@ void RendererBlinkPlatformImpl::CloneSessionStorageNamespace(
//------------------------------------------------------------------------------
-WebIDBFactory* RendererBlinkPlatformImpl::IdbFactory() {
- return web_idb_factory_.get();
+std::unique_ptr<blink::WebIDBFactory>
+RendererBlinkPlatformImpl::CreateIdbFactory() {
+ blink::mojom::IDBFactoryPtrInfo web_idb_factory_host_info;
+ GetInterfaceProvider()->GetInterface(
+ mojo::MakeRequest(&web_idb_factory_host_info));
+ return std::make_unique<WebIDBFactoryImpl>(
+ std::move(web_idb_factory_host_info));
}
//------------------------------------------------------------------------------
WebFileSystem* RendererBlinkPlatformImpl::FileSystem() {
- return WebFileSystemImpl::ThreadSpecificInstance(default_task_runner_);
+ return WebFileSystemImpl::ThreadSpecificInstance(default_task_runner_.get());
}
WebString RendererBlinkPlatformImpl::FileSystemCreateOriginIdentifier(
@@ -777,11 +800,6 @@ WebBlobRegistry* RendererBlinkPlatformImpl::GetBlobRegistry() {
//------------------------------------------------------------------------------
-void RendererBlinkPlatformImpl::SampleGamepads(device::Gamepads& gamepads) {
-}
-
-//------------------------------------------------------------------------------
-
std::unique_ptr<WebMediaRecorderHandler>
RendererBlinkPlatformImpl::CreateMediaRecorderHandler(
scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
@@ -833,6 +851,38 @@ bool RendererBlinkPlatformImpl::SetSandboxEnabledForTesting(bool enable) {
//------------------------------------------------------------------------------
+scoped_refptr<base::SingleThreadTaskRunner>
+RendererBlinkPlatformImpl::GetWebRtcWorkerThread() {
+ RenderThreadImpl* render_thread = RenderThreadImpl::current();
+ DCHECK(render_thread);
+ PeerConnectionDependencyFactory* rtc_dependency_factory =
+ render_thread->GetPeerConnectionDependencyFactory();
+ rtc_dependency_factory->EnsureInitialized();
+ return rtc_dependency_factory->GetWebRtcWorkerThread();
+}
+
+rtc::Thread* RendererBlinkPlatformImpl::GetWebRtcWorkerThreadRtcThread() {
+ RenderThreadImpl* render_thread = RenderThreadImpl::current();
+ DCHECK(render_thread);
+ PeerConnectionDependencyFactory* rtc_dependency_factory =
+ render_thread->GetPeerConnectionDependencyFactory();
+ rtc_dependency_factory->EnsureInitialized();
+ return rtc_dependency_factory->GetWebRtcWorkerThreadRtcThread();
+}
+
+std::unique_ptr<cricket::PortAllocator>
+RendererBlinkPlatformImpl::CreateWebRtcPortAllocator(
+ blink::WebLocalFrame* frame) {
+ RenderThreadImpl* render_thread = RenderThreadImpl::current();
+ DCHECK(render_thread);
+ PeerConnectionDependencyFactory* rtc_dependency_factory =
+ render_thread->GetPeerConnectionDependencyFactory();
+ rtc_dependency_factory->EnsureInitialized();
+ return rtc_dependency_factory->CreatePortAllocator(frame);
+}
+
+//------------------------------------------------------------------------------
+
std::unique_ptr<WebCanvasCaptureHandler>
RendererBlinkPlatformImpl::CreateCanvasCaptureHandler(
const WebSize& size,
@@ -927,13 +977,6 @@ void RendererBlinkPlatformImpl::UpdateWebRTCAPICount(
//------------------------------------------------------------------------------
-std::unique_ptr<blink::WebSocketHandshakeThrottle>
-RendererBlinkPlatformImpl::CreateWebSocketHandshakeThrottle() {
- return GetContentClient()->renderer()->CreateWebSocketHandshakeThrottle();
-}
-
-//------------------------------------------------------------------------------
-
std::unique_ptr<blink::WebSpeechSynthesizer>
RendererBlinkPlatformImpl::CreateSpeechSynthesizer(
blink::WebSpeechSynthesizerClient* client) {
@@ -1008,15 +1051,22 @@ RendererBlinkPlatformImpl::CreateOffscreenGraphicsContext3DProvider(
constexpr bool automatic_flushes = true;
constexpr bool support_locking = false;
- scoped_refptr<ui::ContextProviderCommandBuffer> provider(
- new ui::ContextProviderCommandBuffer(
+ uint32_t stream_id = kGpuStreamIdDefault;
+ gpu::SchedulingPriority priority = kGpuStreamPriorityDefault;
+ if (gpu_channel_host->gpu_feature_info().IsWorkaroundEnabled(
+ gpu::USE_HIGH_PRIORITY_FOR_WEBGL)) {
+ stream_id = kGpuStreamIdHighPriorityWebGL;
+ priority = kGpuStreamPriorityHighPriorityWebGL;
+ }
+
+ scoped_refptr<ws::ContextProviderCommandBuffer> provider(
+ new ws::ContextProviderCommandBuffer(
std::move(gpu_channel_host),
- RenderThreadImpl::current()->GetGpuMemoryBufferManager(),
- kGpuStreamIdDefault, kGpuStreamPriorityDefault,
- gpu::kNullSurfaceHandle, GURL(top_document_web_url),
+ RenderThreadImpl::current()->GetGpuMemoryBufferManager(), stream_id,
+ priority, gpu::kNullSurfaceHandle, GURL(top_document_web_url),
automatic_flushes, support_locking, web_attributes.support_grcontext,
gpu::SharedMemoryLimits(), attributes,
- ui::command_buffer_metrics::ContextType::WEBGL));
+ ws::command_buffer_metrics::ContextType::WEBGL));
return std::make_unique<WebGraphicsContext3DProviderImpl>(
std::move(provider));
}
@@ -1027,7 +1077,7 @@ std::unique_ptr<blink::WebGraphicsContext3DProvider>
RendererBlinkPlatformImpl::CreateSharedOffscreenGraphicsContext3DProvider() {
auto* thread = RenderThreadImpl::current();
- scoped_refptr<ui::ContextProviderCommandBuffer> provider =
+ scoped_refptr<ws::ContextProviderCommandBuffer> provider =
thread->SharedMainThreadContextProvider();
if (!provider)
return nullptr;
@@ -1047,6 +1097,45 @@ RendererBlinkPlatformImpl::CreateSharedOffscreenGraphicsContext3DProvider() {
//------------------------------------------------------------------------------
+std::unique_ptr<blink::WebGraphicsContext3DProvider>
+RendererBlinkPlatformImpl::CreateWebGPUGraphicsContext3DProvider(
+ const blink::WebURL& top_document_web_url,
+ blink::Platform::GraphicsInfo* gl_info) {
+ scoped_refptr<gpu::GpuChannelHost> gpu_channel_host(
+ RenderThreadImpl::current()->EstablishGpuChannelSync());
+ if (!gpu_channel_host) {
+ std::string error_message(
+ "OffscreenContext Creation failed, GpuChannelHost creation failed");
+ gl_info->error_message = WebString::FromUTF8(error_message);
+ return nullptr;
+ }
+ Collect3DContextInformation(gl_info, gpu_channel_host->gpu_info());
+
+ gpu::ContextCreationAttribs attributes;
+ // TODO(kainino): It's not clear yet how GPU preferences work for WebGPU.
+ attributes.gpu_preference = gl::PreferDiscreteGpu;
+ attributes.enable_gles2_interface = false;
+ attributes.context_type = gpu::CONTEXT_TYPE_WEBGPU;
+
+ constexpr bool automatic_flushes = true;
+ constexpr bool support_locking = false;
+ constexpr bool support_grcontext = false;
+
+ scoped_refptr<ws::ContextProviderCommandBuffer> provider(
+ new ws::ContextProviderCommandBuffer(
+ std::move(gpu_channel_host),
+ RenderThreadImpl::current()->GetGpuMemoryBufferManager(),
+ kGpuStreamIdDefault, kGpuStreamPriorityDefault,
+ gpu::kNullSurfaceHandle, GURL(top_document_web_url),
+ automatic_flushes, support_locking, support_grcontext,
+ gpu::SharedMemoryLimits(), attributes,
+ ws::command_buffer_metrics::ContextType::WEBGPU));
+ return std::make_unique<WebGraphicsContext3DProviderImpl>(
+ std::move(provider));
+}
+
+//------------------------------------------------------------------------------
+
gpu::GpuMemoryBufferManager*
RendererBlinkPlatformImpl::GetGpuMemoryBufferManager() {
RenderThreadImpl* thread = RenderThreadImpl::current();
@@ -1080,16 +1169,6 @@ blink::InterfaceProvider* RendererBlinkPlatformImpl::GetInterfaceProvider() {
return blink_interface_provider_.get();
}
-void RendererBlinkPlatformImpl::StartListening(
- blink::WebPlatformEventType type,
- blink::WebPlatformEventListener* listener) {
-
-}
-
-void RendererBlinkPlatformImpl::StopListening(
- blink::WebPlatformEventType type) {
-}
-
//------------------------------------------------------------------------------
blink::WebPushProvider* RendererBlinkPlatformImpl::PushProvider() {
diff --git a/chromium/content/renderer/renderer_blink_platform_impl.h b/chromium/content/renderer/renderer_blink_platform_impl.h
index bebcd933b8c..b3bde113adb 100644
--- a/chromium/content/renderer/renderer_blink_platform_impl.h
+++ b/chromium/content/renderer/renderer_blink_platform_impl.h
@@ -34,10 +34,6 @@
#include "third_party/skia/include/core/SkRefCnt.h" // nogncheck
#endif
-namespace IPC {
-class SyncMessageFilter;
-}
-
namespace blink {
namespace scheduler {
class WebThreadScheduler;
@@ -68,6 +64,10 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
blink::scheduler::WebThreadScheduler* main_thread_scheduler);
~RendererBlinkPlatformImpl() override;
+ blink::scheduler::WebThreadScheduler* main_thread_scheduler() {
+ return main_thread_scheduler_;
+ }
+
// Shutdown must be called just prior to shutting down blink.
void Shutdown();
@@ -87,6 +87,11 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
base::Time,
const char*,
size_t) override;
+ void FetchCachedCode(
+ const GURL&,
+ base::OnceCallback<void(base::Time, const std::vector<uint8_t>&)>)
+ override;
+ void ClearCodeCacheEntry(const GURL&) override;
void CacheMetadataInCacheStorage(
const blink::WebURL&,
base::Time,
@@ -120,7 +125,7 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
viz::FrameSinkId GenerateFrameSinkId() override;
bool IsLockedToSite() const override;
- blink::WebIDBFactory* IdbFactory() override;
+ std::unique_ptr<blink::WebIDBFactory> CreateIdbFactory() override;
blink::WebFileSystem* FileSystem() override;
blink::WebString FileSystemCreateOriginIdentifier(
const blink::WebSecurityOrigin& origin) override;
@@ -147,7 +152,6 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
blink::WebMIDIAccessorClient* client) override;
blink::WebBlobRegistry* GetBlobRegistry() override;
- void SampleGamepads(device::Gamepads&) override;
std::unique_ptr<blink::WebRTCPeerConnectionHandler>
CreateRTCPeerConnectionHandler(
blink::WebRTCPeerConnectionHandlerClient* client,
@@ -158,6 +162,10 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
scoped_refptr<base::SingleThreadTaskRunner> task_runner) override;
std::unique_ptr<blink::WebMediaStreamCenter> CreateMediaStreamCenter()
override;
+ scoped_refptr<base::SingleThreadTaskRunner> GetWebRtcWorkerThread() override;
+ rtc::Thread* GetWebRtcWorkerThreadRtcThread() override;
+ std::unique_ptr<cricket::PortAllocator> CreateWebRtcPortAllocator(
+ blink::WebLocalFrame* frame) override;
std::unique_ptr<blink::WebCanvasCaptureHandler> CreateCanvasCaptureHandler(
const blink::WebSize& size,
double frame_rate,
@@ -176,8 +184,6 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
std::unique_ptr<webrtc::RtpCapabilities> GetRtpReceiverCapabilities(
const blink::WebString& kind) override;
void UpdateWebRTCAPICount(blink::WebRTCAPIName api_name) override;
- std::unique_ptr<blink::WebSocketHandshakeThrottle>
- CreateWebSocketHandshakeThrottle() override;
std::unique_ptr<blink::WebGraphicsContext3DProvider>
CreateOffscreenGraphicsContext3DProvider(
const blink::Platform::ContextAttributes& attributes,
@@ -185,13 +191,14 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
blink::Platform::GraphicsInfo* gl_info) override;
std::unique_ptr<blink::WebGraphicsContext3DProvider>
CreateSharedOffscreenGraphicsContext3DProvider() override;
+ std::unique_ptr<blink::WebGraphicsContext3DProvider>
+ CreateWebGPUGraphicsContext3DProvider(
+ const blink::WebURL& top_document_web_url,
+ blink::Platform::GraphicsInfo* gl_info) override;
gpu::GpuMemoryBufferManager* GetGpuMemoryBufferManager() override;
blink::WebString ConvertIDNToUnicode(const blink::WebString& host) override;
service_manager::Connector* GetConnector() override;
blink::InterfaceProvider* GetInterfaceProvider() override;
- void StartListening(blink::WebPlatformEventType,
- blink::WebPlatformEventListener*) override;
- void StopListening(blink::WebPlatformEventType) override;
blink::WebThread* CurrentThread() override;
blink::BlameContext* GetTopLevelBlameContext() override;
void RecordRappor(const char* metric,
@@ -217,6 +224,7 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
std::unique_ptr<blink::WebURLLoaderFactory> CreateDefaultURLLoaderFactory()
override;
+ std::unique_ptr<blink::CodeCacheLoader> CreateCodeCacheLoader() override;
std::unique_ptr<blink::WebURLLoaderFactory> WrapURLLoaderFactory(
mojo::ScopedMessagePipeHandle url_loader_factory_handle) override;
std::unique_ptr<blink::WebURLLoaderFactory> WrapSharedURLLoaderFactory(
@@ -250,10 +258,6 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
private:
bool CheckPreparsedJsCachingEnabled() const;
- // TODO(crbug.com/850997): Remove when Device*EventPump classes are
- // moved to blink
- void StopDeviceSensorEventPump(blink::WebPlatformEventType type);
-
// Ensure that the WebDatabaseHost has been initialized.
void InitializeWebDatabaseHostIfNeeded();
@@ -264,6 +268,7 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
std::unique_ptr<blink::WebThread> main_thread_;
std::unique_ptr<service_manager::Connector> connector_;
+ scoped_refptr<base::SingleThreadTaskRunner> io_runner_;
#if !defined(OS_ANDROID) && !defined(OS_WIN) && !defined(OS_FUCHSIA)
class SandboxSupport;
@@ -279,12 +284,9 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
// If true, the renderer process is locked to a site.
bool is_locked_to_site_;
- std::unique_ptr<blink::WebIDBFactory> web_idb_factory_;
-
std::unique_ptr<blink::WebBlobRegistry> blob_registry_;
scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_;
- scoped_refptr<IPC::SyncMessageFilter> sync_message_filter_;
scoped_refptr<ThreadSafeSender> thread_safe_sender_;
std::unique_ptr<WebDatabaseObserverImpl> web_database_observer_impl_;
diff --git a/chromium/content/renderer/renderer_main.cc b/chromium/content/renderer/renderer_main.cc
index 0b722923ba6..9e76e271b65 100644
--- a/chromium/content/renderer/renderer_main.cc
+++ b/chromium/content/renderer/renderer_main.cc
@@ -84,10 +84,9 @@ int RendererMain(const MainFunctionParams& parameters) {
const base::CommandLine& command_line = parameters.command_line;
- base::SamplingHeapProfiler::InitTLSSlot();
+ base::SamplingHeapProfiler::Init();
if (command_line.HasSwitch(switches::kSamplingHeapProfiler)) {
- base::SamplingHeapProfiler* profiler =
- base::SamplingHeapProfiler::GetInstance();
+ base::SamplingHeapProfiler* profiler = base::SamplingHeapProfiler::Get();
unsigned sampling_interval = 0;
bool parsed = base::StringToUint(
command_line.GetSwitchValueASCII(switches::kSamplingHeapProfiler),
@@ -182,9 +181,10 @@ int RendererMain(const MainFunctionParams& parameters) {
}
#endif
- auto render_process = RenderProcessImpl::Create();
- RenderThreadImpl::Create(std::move(main_message_loop),
- std::move(main_thread_scheduler));
+ std::unique_ptr<RenderProcess> render_process = RenderProcessImpl::Create();
+ // It's not a memory leak since RenderThread has the same lifetime
+ // as a renderer process.
+ new RenderThreadImpl(std::move(main_thread_scheduler));
if (need_sandbox)
run_loop = platform.EnableSandbox();
diff --git a/chromium/content/renderer/renderer_main_platform_delegate_mac.mm b/chromium/content/renderer/renderer_main_platform_delegate_mac.mm
index 1e2cc38d386..e2122fb5fe9 100644
--- a/chromium/content/renderer/renderer_main_platform_delegate_mac.mm
+++ b/chromium/content/renderer/renderer_main_platform_delegate_mac.mm
@@ -20,15 +20,12 @@
#include "content/public/common/content_switches.h"
#include "content/public/common/sandbox_init.h"
#include "sandbox/mac/seatbelt.h"
+#include "sandbox/mac/system_services.h"
#include "services/service_manager/sandbox/mac/sandbox_mac.h"
extern "C" {
void CGSSetDenyWindowServerConnections(bool);
void CGSShutdownServerConnections();
-OSStatus SetApplicationIsDaemon(Boolean isDaemon);
-void _LSSetApplicationLaunchServicesServerConnectionStatus(
- uint64_t flags,
- bool (^connection_allowed)(CFDictionaryRef));
};
namespace content {
@@ -44,16 +41,8 @@ void DisconnectWindowServer() {
// messages to be printed to the system logger on certain OS versions.
CGSSetDenyWindowServerConnections(true);
CGSShutdownServerConnections();
- // Allow the process to continue without a LaunchServices ASN. The
- // INIT_Process function in HIServices will abort if it cannot connect to
- // launchservicesd to get an ASN. By setting this flag, HIServices skips
- // that.
- SetApplicationIsDaemon(true);
- // Tell LaunchServices no connections are ever allowed.
- _LSSetApplicationLaunchServicesServerConnectionStatus(
- 0, ^bool(CFDictionaryRef options) {
- return false;
- });
+
+ sandbox::DisableLaunchServices();
}
// You are about to read a pretty disgusting hack. In a static initializer,
diff --git a/chromium/content/renderer/service_worker/controller_service_worker_connector.h b/chromium/content/renderer/service_worker/controller_service_worker_connector.h
index e24bbdac674..066a87c7fce 100644
--- a/chromium/content/renderer/service_worker/controller_service_worker_connector.h
+++ b/chromium/content/renderer/service_worker/controller_service_worker_connector.h
@@ -109,7 +109,7 @@ class CONTENT_EXPORT ControllerServiceWorkerConnector
// in the renderer process)
mojom::ControllerServiceWorkerPtr controller_service_worker_;
- base::ObserverList<Observer> observer_list_;
+ base::ObserverList<Observer>::Unchecked observer_list_;
// The web-exposed client id, used for FetchEvent#clientId (i.e.,
// ServiceWorkerProviderHost::client_uuid and not
diff --git a/chromium/content/renderer/service_worker/controller_service_worker_impl.cc b/chromium/content/renderer/service_worker/controller_service_worker_impl.cc
index a90ae551b9b..66db6a3c332 100644
--- a/chromium/content/renderer/service_worker/controller_service_worker_impl.cc
+++ b/chromium/content/renderer/service_worker/controller_service_worker_impl.cc
@@ -26,7 +26,7 @@ void ControllerServiceWorkerImpl::Clone(
void ControllerServiceWorkerImpl::DispatchFetchEvent(
blink::mojom::DispatchFetchEventParamsPtr params,
- mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
+ blink::mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
DispatchFetchEventCallback callback) {
DCHECK(context_client_);
context_client_->DispatchOrQueueFetchEvent(
diff --git a/chromium/content/renderer/service_worker/controller_service_worker_impl.h b/chromium/content/renderer/service_worker/controller_service_worker_impl.h
index 308fa39d3cb..ebda20badec 100644
--- a/chromium/content/renderer/service_worker/controller_service_worker_impl.h
+++ b/chromium/content/renderer/service_worker/controller_service_worker_impl.h
@@ -40,7 +40,7 @@ class ControllerServiceWorkerImpl : public mojom::ControllerServiceWorker {
// mojom::ControllerServiceWorker:
void DispatchFetchEvent(
blink::mojom::DispatchFetchEventParamsPtr params,
- mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
+ blink::mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
DispatchFetchEventCallback callback) override;
void Clone(mojom::ControllerServiceWorkerRequest request) override;
diff --git a/chromium/content/renderer/service_worker/embedded_worker_instance_client_impl.cc b/chromium/content/renderer/service_worker/embedded_worker_instance_client_impl.cc
index 6c0ee47de40..d54d88dd273 100644
--- a/chromium/content/renderer/service_worker/embedded_worker_instance_client_impl.cc
+++ b/chromium/content/renderer/service_worker/embedded_worker_instance_client_impl.cc
@@ -16,6 +16,7 @@
#include "content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_installed_scripts_manager.h"
+#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
#include "third_party/blink/public/platform/web_content_settings_client.h"
#include "third_party/blink/public/platform/web_security_origin.h"
#include "third_party/blink/public/platform/web_url.h"
@@ -75,7 +76,8 @@ void EmbeddedWorkerInstanceClientImpl::StartWorker(
std::move(params->service_worker_request),
std::move(params->controller_request), std::move(params->instance_host),
std::move(params->provider_info), std::move(temporal_self_),
- std::move(start_timing),
+ std::move(start_timing), std::move(params->preference_watcher_request),
+ std::move(params->subresource_loader_factories),
RenderThreadImpl::current()
->GetWebMainThreadScheduler()
->DefaultTaskRunner());
diff --git a/chromium/content/renderer/service_worker/embedded_worker_instance_client_impl.h b/chromium/content/renderer/service_worker/embedded_worker_instance_client_impl.h
index d86d3387c6b..4544a991922 100644
--- a/chromium/content/renderer/service_worker/embedded_worker_instance_client_impl.h
+++ b/chromium/content/renderer/service_worker/embedded_worker_instance_client_impl.h
@@ -68,6 +68,10 @@ class EmbeddedWorkerInstanceClientImpl
// Called from ServiceWorkerContextClient.
void WorkerContextDestroyed();
+ // mojom::EmbeddedWorkerInstanceClient implementation (partially exposed to
+ // public)
+ void StopWorker() override;
+
private:
// A thin wrapper of WebEmbeddedWorker which also adds and releases process
// references automatically.
@@ -89,7 +93,6 @@ class EmbeddedWorkerInstanceClientImpl
// mojom::EmbeddedWorkerInstanceClient implementation
void StartWorker(mojom::EmbeddedWorkerStartParamsPtr params) override;
- void StopWorker() override;
void ResumeAfterDownload() override;
void AddMessageToConsole(blink::WebConsoleMessage::Level level,
const std::string& message) override;
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 fecbaf9bea3..51440106f6f 100644
--- a/chromium/content/renderer/service_worker/service_worker_context_client.cc
+++ b/chromium/content/renderer/service_worker/service_worker_context_client.cc
@@ -20,16 +20,15 @@
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "content/common/service_worker/service_worker.mojom.h"
-#include "content/common/service_worker/service_worker_messages.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/common/content_features.h"
-#include "content/public/common/push_event_payload.h"
#include "content/public/common/referrer.h"
#include "content/public/renderer/content_renderer_client.h"
#include "content/public/renderer/document_state.h"
#include "content/public/renderer/worker_thread.h"
#include "content/renderer/loader/child_url_loader_factory_bundle.h"
#include "content/renderer/loader/request_extra_data.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"
@@ -66,7 +65,8 @@
#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_settled_fetch.h"
+#include "third_party/blink/public/platform/modules/background_fetch/background_fetch.mojom.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"
@@ -93,6 +93,9 @@ namespace content {
namespace {
+constexpr char kServiceWorkerContextClientScope[] =
+ "ServiceWorkerContextClient";
+
// For now client must be a per-thread instance.
base::LazyInstance<base::ThreadLocalPointer<ServiceWorkerContextClient>>::
Leaky g_worker_client_tls = LAZY_INSTANCE_INITIALIZER;
@@ -168,6 +171,13 @@ class StreamHandleListener
blink::mojom::ServiceWorkerStreamCallbackPtr callback_ptr_;
};
+bool IsOutOfProcessNetworkService() {
+ return base::FeatureList::IsEnabled(network::features::kNetworkService) &&
+ !base::FeatureList::IsEnabled(features::kNetworkServiceInProcess) &&
+ !base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kSingleProcess);
+}
+
WebURLRequest::RequestContext GetBlinkRequestContext(
RequestContextType request_context_type) {
return static_cast<WebURLRequest::RequestContext>(request_context_type);
@@ -189,20 +199,67 @@ blink::WebServiceWorkerClientInfo ToWebServiceWorkerClientInfo(
return web_client_info;
}
+// Converts a content::BackgroundFetchRegistration object to
+// a blink::WebBackgroundFetchRegistration object.
+blink::WebBackgroundFetchRegistration ToWebBackgroundFetchRegistration(
+ const BackgroundFetchRegistration& registration) {
+ return blink::WebBackgroundFetchRegistration(
+ blink::WebString::FromUTF8(registration.developer_id),
+ blink::WebString::FromUTF8(registration.unique_id),
+ registration.upload_total, registration.uploaded,
+ registration.download_total, registration.downloaded, registration.state,
+ registration.failure_reason);
+}
+
+// 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;
+}
+
+// If |is_for_fetch_event| is true, some headers may be omitted according
+// to the embedder. It's always true now, but it might change with
+// more Onion Souping, and future callsites like Background Fetch probably don't
+// want to do the header filtering, since it's important for them to have the
+// exact request as sent to network.
void ToWebServiceWorkerRequest(const network::ResourceRequest& request,
const std::string request_body_blob_uuid,
uint64_t request_body_blob_size,
blink::mojom::BlobPtrInfo request_body_blob,
const std::string& client_id,
std::vector<blink::mojom::BlobPtrInfo> blob_ptrs,
- blink::WebServiceWorkerRequest* web_request) {
+ blink::WebServiceWorkerRequest* web_request,
+ bool is_for_fetch_event) {
DCHECK(web_request);
web_request->SetURL(blink::WebURL(request.url));
web_request->SetMethod(blink::WebString::FromUTF8(request.method));
if (!request.headers.IsEmpty()) {
for (net::HttpRequestHeaders::Iterator it(request.headers); it.GetNext();) {
- web_request->SetHeader(blink::WebString::FromUTF8(it.name()),
- blink::WebString::FromUTF8(it.value()));
+ if (!is_for_fetch_event ||
+ !GetContentClient()
+ ->renderer()
+ ->IsExcludedHeaderForServiceWorkerFetchEvent(it.name())) {
+ web_request->SetHeader(blink::WebString::FromUTF8(it.name()),
+ blink::WebString::FromUTF8(it.value()));
+ }
}
}
@@ -244,82 +301,13 @@ void ToWebServiceWorkerRequest(const network::ResourceRequest& request,
ui::PAGE_TRANSITION_RELOAD));
web_request->SetIntegrity(
blink::WebString::FromUTF8(request.fetch_integrity));
+ web_request->SetPriority(
+ ConvertNetPriorityToWebKitPriority(request.priority));
web_request->SetKeepalive(request.keepalive);
web_request->SetIsHistoryNavigation(request.transition_type &
ui::PAGE_TRANSITION_FORWARD_BACK);
}
-// Converts the |request| to its equivalent type in the Blink API.
-// TODO(peter): Remove this when the Mojo FetchAPIRequest type exists.
-void ToWebServiceWorkerRequest(const ServiceWorkerFetchRequest& request,
- 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) {
- web_request->SetHeader(blink::WebString::FromUTF8(pair.first),
- blink::WebString::FromUTF8(pair.second));
- }
- 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(
- GetBlinkRequestContext(request.request_context_type));
- web_request->SetFrameType(request.frame_type);
- web_request->SetClientId(blink::WebString::FromUTF8(request.client_id));
- web_request->SetIsReload(request.is_reload);
- web_request->SetIntegrity(blink::WebString::FromUTF8(request.integrity));
- web_request->SetKeepalive(request.keepalive);
- web_request->SetIsHistoryNavigation(request.is_history_navigation);
-}
-
-// Converts |response| to its equivalent type in the Blink API.
-// TODO(peter): Remove this when the Mojo FetchAPIResponse type exists.
-void ToWebServiceWorkerResponse(const ServiceWorkerResponse& response,
- blink::WebServiceWorkerResponse* web_response) {
- DCHECK(web_response);
-
- std::vector<blink::WebURL> url_list;
- for (const GURL& url : response.url_list)
- url_list.push_back(blink::WebURL(url));
-
- web_response->SetURLList(blink::WebVector<blink::WebURL>(url_list));
- web_response->SetStatus(static_cast<unsigned short>(response.status_code));
- web_response->SetStatusText(blink::WebString::FromUTF8(response.status_text));
- web_response->SetResponseType(response.response_type);
- for (const auto& pair : response.headers) {
- web_response->SetHeader(blink::WebString::FromUTF8(pair.first),
- blink::WebString::FromUTF8(pair.second));
- }
- if (!response.blob_uuid.empty()) {
- DCHECK(response.blob);
- mojo::ScopedMessagePipeHandle blob_pipe;
- if (response.blob)
- blob_pipe = response.blob->Clone().PassInterface().PassHandle();
- web_response->SetBlob(blink::WebString::FromASCII(response.blob_uuid),
- response.blob_size, std::move(blob_pipe));
- }
- web_response->SetError(response.error);
- web_response->SetResponseTime(response.response_time);
- if (response.is_in_cache_storage) {
- web_response->SetCacheStorageCacheName(
- blink::WebString::FromUTF8(response.cache_storage_cache_name));
- }
-
- std::vector<blink::WebString> cors_exposed_header_names;
- for (const auto& name : response.cors_exposed_header_names)
- cors_exposed_header_names.push_back(blink::WebString::FromUTF8(name));
-
- web_response->SetCorsExposedHeaderNames(
- blink::WebVector<blink::WebString>(cors_exposed_header_names));
-}
-
// 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.
@@ -491,7 +479,7 @@ struct ServiceWorkerContextClient::WorkerContextData {
background_fetch_click_event_callbacks;
std::map<int, DispatchBackgroundFetchFailEventCallback>
background_fetch_fail_event_callbacks;
- std::map<int, DispatchBackgroundFetchedEventCallback>
+ std::map<int, DispatchBackgroundFetchSuccessEventCallback>
background_fetched_event_callbacks;
std::map<int, DispatchSyncEventCallback> sync_event_callbacks;
std::map<int, payments::mojom::PaymentHandlerResponseCallbackPtr>
@@ -519,7 +507,7 @@ struct ServiceWorkerContextClient::WorkerContextData {
can_make_payment_result_callbacks;
std::map<int, payments::mojom::PaymentHandlerResponseCallbackPtr>
payment_response_callbacks;
- std::map<int, mojom::ServiceWorkerFetchResponseCallbackPtr>
+ std::map<int, blink::mojom::ServiceWorkerFetchResponseCallbackPtr>
fetch_response_callbacks;
// Inflight navigation preload requests.
@@ -563,7 +551,8 @@ class ServiceWorkerContextClient::NavigationPreloadRequest final
// TODO(horo): Set report_security_info to true when DevTools is attached.
const bool report_security_info = false;
WebURLLoaderImpl::PopulateURLResponse(url_, response_head, response_.get(),
- report_security_info);
+ report_security_info,
+ -1 /* request_id */);
MaybeReportResponseToClient();
}
@@ -580,7 +569,8 @@ class ServiceWorkerContextClient::NavigationPreloadRequest final
return;
response_ = std::make_unique<blink::WebURLResponse>();
WebURLLoaderImpl::PopulateURLResponse(url_, response_head, response_.get(),
- false /* report_security_info */);
+ false /* report_security_info */,
+ -1 /* request_id */);
client->OnNavigationPreloadResponse(fetch_event_id_, std::move(response_),
nullptr);
// This will delete |this|.
@@ -705,6 +695,8 @@ ServiceWorkerContextClient::ServiceWorkerContextClient(
mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
std::unique_ptr<EmbeddedWorkerInstanceClientImpl> embedded_worker_client,
mojom::EmbeddedWorkerStartTimingPtr start_timing,
+ mojom::RendererPreferenceWatcherRequest preference_watcher_request,
+ std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loaders,
scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner)
: embedded_worker_id_(embedded_worker_id),
service_worker_version_id_(service_worker_version_id),
@@ -712,6 +704,7 @@ ServiceWorkerContextClient::ServiceWorkerContextClient(
script_url_(script_url),
is_starting_installed_worker_(is_starting_installed_worker),
renderer_preferences_(std::move(renderer_preferences)),
+ preference_watcher_request_(std::move(preference_watcher_request)),
main_thread_task_runner_(std::move(main_thread_task_runner)),
proxy_(nullptr),
pending_service_worker_request_(std::move(service_worker_request)),
@@ -722,6 +715,29 @@ ServiceWorkerContextClient::ServiceWorkerContextClient(
mojom::ThreadSafeEmbeddedWorkerInstanceHostAssociatedPtr::Create(
std::move(instance_host), main_thread_task_runner_);
+ if (subresource_loaders) {
+ if (IsOutOfProcessNetworkService()) {
+ // If the network service crashes, this worker self-terminates, so it can
+ // be restarted later with a connection to the restarted network
+ // service.
+ // Note that the default factory is the network service factory. It's set
+ // on the start worker sequence.
+ network_service_connection_error_handler_holder_.Bind(
+ std::move(subresource_loaders->default_factory_info()));
+ network_service_connection_error_handler_holder_->Clone(
+ mojo::MakeRequest(&subresource_loaders->default_factory_info()));
+ network_service_connection_error_handler_holder_
+ .set_connection_error_handler(base::BindOnce(
+ &ServiceWorkerContextClient::StopWorker, base::Unretained(this)));
+ }
+
+ loader_factories_ = base::MakeRefCounted<HostChildURLLoaderFactoryBundle>(
+ main_thread_task_runner_);
+ loader_factories_->Update(std::make_unique<ChildURLLoaderFactoryBundleInfo>(
+ std::move(subresource_loaders)),
+ base::nullopt /* subresource_overrides */);
+ }
+
// Create a content::ServiceWorkerNetworkProvider for this data source so
// we can observe its requests.
pending_network_provider_ = ServiceWorkerNetworkProvider::CreateForController(
@@ -817,6 +833,19 @@ void ServiceWorkerContextClient::WorkerContextFailedToStart() {
embedded_worker_client_->WorkerContextDestroyed();
}
+void ServiceWorkerContextClient::FailedToLoadInstalledScript() {
+ DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
+ TRACE_EVENT_NESTABLE_ASYNC_END1("ServiceWorker", "LOAD_SCRIPT", this,
+ "Status", "FailedToLoadInstalledScript");
+ // Cleanly send an OnStopped() message instead of just breaking the
+ // Mojo connection on termination, for consistency with the other
+ // startup failure paths.
+ (*instance_host_)->OnStopped();
+
+ // The caller is responsible for terminating the thread which
+ // eventually destroys |this|.
+}
+
void ServiceWorkerContextClient::WorkerScriptLoaded() {
if (!is_starting_installed_worker_)
(*instance_host_)->OnScriptLoaded();
@@ -971,10 +1000,12 @@ void ServiceWorkerContextClient::DidHandleActivateEvent(
int request_id,
blink::mojom::ServiceWorkerEventStatus status,
double event_dispatch_time) {
- TRACE_EVENT2("ServiceWorker",
- "ServiceWorkerContextClient::DidHandleActivateEvent", "event_id",
- request_id, "status",
- ServiceWorkerUtils::MojoEnumToString(status));
+ 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,
base::Time::FromDoubleT(event_dispatch_time));
@@ -984,10 +1015,13 @@ void ServiceWorkerContextClient::DidHandleBackgroundFetchAbortEvent(
int request_id,
blink::mojom::ServiceWorkerEventStatus status,
double event_dispatch_time) {
- TRACE_EVENT2("ServiceWorker",
- "ServiceWorkerContextClient::DidHandleBackgroundFetchAbortEvent",
- "event_id", request_id, "status",
- ServiceWorkerUtils::MojoEnumToString(status));
+ 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,
base::Time::FromDoubleT(event_dispatch_time));
@@ -997,10 +1031,13 @@ void ServiceWorkerContextClient::DidHandleBackgroundFetchClickEvent(
int request_id,
blink::mojom::ServiceWorkerEventStatus status,
double event_dispatch_time) {
- TRACE_EVENT2("ServiceWorker",
- "ServiceWorkerContextClient::DidHandleBackgroundFetchClickEvent",
- "event_id", request_id, "status",
- ServiceWorkerUtils::MojoEnumToString(status));
+ 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,
base::Time::FromDoubleT(event_dispatch_time));
@@ -1010,23 +1047,29 @@ void ServiceWorkerContextClient::DidHandleBackgroundFetchFailEvent(
int request_id,
blink::mojom::ServiceWorkerEventStatus status,
double event_dispatch_time) {
- TRACE_EVENT2("ServiceWorker",
- "ServiceWorkerContextClient::DidHandleBackgroundFetchFailEvent",
- "event_id", request_id, "status",
- ServiceWorkerUtils::MojoEnumToString(status));
+ 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,
base::Time::FromDoubleT(event_dispatch_time));
}
-void ServiceWorkerContextClient::DidHandleBackgroundFetchedEvent(
+void ServiceWorkerContextClient::DidHandleBackgroundFetchSuccessEvent(
int request_id,
blink::mojom::ServiceWorkerEventStatus status,
double event_dispatch_time) {
- TRACE_EVENT2("ServiceWorker",
- "ServiceWorkerContextClient::DidHandleBackgroundFetchedEvent",
- "event_id", request_id, "status",
- ServiceWorkerUtils::MojoEnumToString(status));
+ 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,
base::Time::FromDoubleT(event_dispatch_time));
@@ -1036,10 +1079,12 @@ void ServiceWorkerContextClient::DidHandleCookieChangeEvent(
int request_id,
blink::mojom::ServiceWorkerEventStatus status,
double event_dispatch_time) {
- TRACE_EVENT2("ServiceWorker",
- "ServiceWorkerContextClient::DidHandleCookieChangeEvent",
- "event_id", request_id, "status",
- ServiceWorkerUtils::MojoEnumToString(status));
+ 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,
base::Time::FromDoubleT(event_dispatch_time));
@@ -1049,10 +1094,13 @@ void ServiceWorkerContextClient::DidHandleExtendableMessageEvent(
int request_id,
blink::mojom::ServiceWorkerEventStatus status,
double event_dispatch_time) {
- TRACE_EVENT2("ServiceWorker",
- "ServiceWorkerContextClient::DidHandleExtendableMessageEvent",
- "event_id", request_id, "status",
- ServiceWorkerUtils::MojoEnumToString(status));
+ 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,
base::Time::FromDoubleT(event_dispatch_time));
@@ -1062,10 +1110,12 @@ void ServiceWorkerContextClient::DidHandleInstallEvent(
int event_id,
blink::mojom::ServiceWorkerEventStatus status,
double event_dispatch_time) {
- TRACE_EVENT2("ServiceWorker",
- "ServiceWorkerContextClient::DidHandleInstallEvent", "event_id",
- event_id, "status",
- ServiceWorkerUtils::MojoEnumToString(status));
+ 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(),
@@ -1075,11 +1125,14 @@ void ServiceWorkerContextClient::DidHandleInstallEvent(
void ServiceWorkerContextClient::RespondToFetchEventWithNoResponse(
int fetch_event_id,
double event_dispatch_time) {
- TRACE_EVENT1("ServiceWorker",
- "ServiceWorkerContextClient::RespondToFetchEventWithNoResponse",
- "event_id", fetch_event_id);
+ 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 mojom::ServiceWorkerFetchResponseCallbackPtr& response_callback =
+ const blink::mojom::ServiceWorkerFetchResponseCallbackPtr& response_callback =
context_->fetch_response_callbacks[fetch_event_id];
DCHECK(response_callback.is_bound());
response_callback->OnFallback(base::Time::FromDoubleT(event_dispatch_time));
@@ -1090,29 +1143,19 @@ void ServiceWorkerContextClient::RespondToFetchEvent(
int fetch_event_id,
const blink::WebServiceWorkerResponse& web_response,
double event_dispatch_time) {
- TRACE_EVENT1("ServiceWorker",
- "ServiceWorkerContextClient::RespondToFetchEvent", "event_id",
- fetch_event_id);
+ 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));
- ServiceWorkerResponse response(
- GetServiceWorkerResponseFromWebResponse(web_response));
- const mojom::ServiceWorkerFetchResponseCallbackPtr& response_callback =
+ blink::mojom::FetchAPIResponsePtr response(
+ GetFetchAPIResponseFromWebResponse(web_response));
+ const blink::mojom::ServiceWorkerFetchResponseCallbackPtr& response_callback =
context_->fetch_response_callbacks[fetch_event_id];
- if (!response.blob_uuid.empty()) {
- // TODO(falken): Can we just keep |response.blob| and call OnResponse
- // directly?
- blink::mojom::BlobPtr blob_ptr;
- DCHECK(response.blob);
- blob_ptr = response.blob->TakeBlobPtr();
- response.blob = nullptr;
- response_callback->OnResponseBlob(
- response, std::move(blob_ptr),
- base::Time::FromDoubleT(event_dispatch_time));
- } else {
- response_callback->OnResponse(response,
- base::Time::FromDoubleT(event_dispatch_time));
- }
+ response_callback->OnResponse(std::move(response),
+ base::Time::FromDoubleT(event_dispatch_time));
context_->fetch_response_callbacks.erase(fetch_event_id);
}
@@ -1121,14 +1164,16 @@ void ServiceWorkerContextClient::RespondToFetchEventWithResponseStream(
const blink::WebServiceWorkerResponse& web_response,
blink::WebServiceWorkerStreamHandle* web_body_as_stream,
double event_dispatch_time) {
- TRACE_EVENT1(
+ TRACE_EVENT_WITH_FLOW0(
"ServiceWorker",
"ServiceWorkerContextClient::RespondToFetchEventWithResponseStream",
- "event_id", fetch_event_id);
+ 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));
- ServiceWorkerResponse response(
- GetServiceWorkerResponseFromWebResponse(web_response));
- const mojom::ServiceWorkerFetchResponseCallbackPtr& response_callback =
+ 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();
@@ -1141,7 +1186,7 @@ void ServiceWorkerContextClient::RespondToFetchEventWithResponseStream(
std::make_unique<StreamHandleListener>(std::move(callback_ptr)));
response_callback->OnResponseStream(
- response, std::move(body_as_stream),
+ std::move(response), std::move(body_as_stream),
base::Time::FromDoubleT(event_dispatch_time));
context_->fetch_response_callbacks.erase(fetch_event_id);
}
@@ -1152,10 +1197,12 @@ void ServiceWorkerContextClient::DidHandleFetchEvent(
double event_dispatch_time) {
// This TRACE_EVENT is used for perf benchmark to confirm if all of fetch
// events have completed. (crbug.com/736697)
- TRACE_EVENT2("ServiceWorker",
- "ServiceWorkerContextClient::DidHandleFetchEvent", "event_id",
- event_id, "status",
- ServiceWorkerUtils::MojoEnumToString(status));
+ 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,
base::Time::FromDoubleT(event_dispatch_time))) {
@@ -1167,10 +1214,13 @@ void ServiceWorkerContextClient::DidHandleNotificationClickEvent(
int request_id,
blink::mojom::ServiceWorkerEventStatus status,
double event_dispatch_time) {
- TRACE_EVENT2("ServiceWorker",
- "ServiceWorkerContextClient::DidHandleNotificationClickEvent",
- "event_id", request_id, "status",
- ServiceWorkerUtils::MojoEnumToString(status));
+ 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,
base::Time::FromDoubleT(event_dispatch_time));
@@ -1180,10 +1230,13 @@ void ServiceWorkerContextClient::DidHandleNotificationCloseEvent(
int request_id,
blink::mojom::ServiceWorkerEventStatus status,
double event_dispatch_time) {
- TRACE_EVENT2("ServiceWorker",
- "ServiceWorkerContextClient::DidHandleNotificationCloseEvent",
- "event_id", request_id, "status",
- ServiceWorkerUtils::MojoEnumToString(status));
+ 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,
base::Time::FromDoubleT(event_dispatch_time));
@@ -1193,10 +1246,12 @@ void ServiceWorkerContextClient::DidHandlePushEvent(
int request_id,
blink::mojom::ServiceWorkerEventStatus status,
double event_dispatch_time) {
- TRACE_EVENT2("ServiceWorker",
- "ServiceWorkerContextClient::DidHandlePushEvent", "event_id",
- request_id, "status",
- ServiceWorkerUtils::MojoEnumToString(status));
+ 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,
base::Time::FromDoubleT(event_dispatch_time));
@@ -1206,10 +1261,12 @@ void ServiceWorkerContextClient::DidHandleSyncEvent(
int request_id,
blink::mojom::ServiceWorkerEventStatus status,
double event_dispatch_time) {
- TRACE_EVENT2("ServiceWorker",
- "ServiceWorkerContextClient::DidHandleSyncEvent", "event_id",
- request_id, "status",
- ServiceWorkerUtils::MojoEnumToString(status));
+ 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,
base::Time::FromDoubleT(event_dispatch_time));
@@ -1219,9 +1276,11 @@ void ServiceWorkerContextClient::RespondToAbortPaymentEvent(
int event_id,
bool payment_aborted,
double dispatch_event_time) {
- TRACE_EVENT1("ServiceWorker",
- "ServiceWorkerContextClient::RespondToAbortPaymentEvent",
- "event_id", event_id);
+ 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];
@@ -1234,10 +1293,12 @@ void ServiceWorkerContextClient::DidHandleAbortPaymentEvent(
int event_id,
blink::mojom::ServiceWorkerEventStatus status,
double dispatch_event_time) {
- TRACE_EVENT2("ServiceWorker",
- "ServiceWorkerContextClient::DidHandleAbortPaymentEvent",
- "event_id", event_id, "status",
- ServiceWorkerUtils::MojoEnumToString(status));
+ 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,
base::Time::FromDoubleT(dispatch_event_time))) {
@@ -1249,9 +1310,12 @@ void ServiceWorkerContextClient::RespondToCanMakePaymentEvent(
int event_id,
bool can_make_payment,
double dispatch_event_time) {
- TRACE_EVENT1("ServiceWorker",
- "ServiceWorkerContextClient::RespondToCanMakePaymentEvent",
- "event_id", event_id);
+ 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 =
@@ -1265,10 +1329,13 @@ void ServiceWorkerContextClient::DidHandleCanMakePaymentEvent(
int event_id,
blink::mojom::ServiceWorkerEventStatus status,
double dispatch_event_time) {
- TRACE_EVENT2("ServiceWorker",
- "ServiceWorkerContextClient::DidHandleCanMakePaymentEvent",
- "event_id", event_id, "status",
- ServiceWorkerUtils::MojoEnumToString(status));
+ 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,
base::Time::FromDoubleT(dispatch_event_time))) {
@@ -1280,9 +1347,12 @@ void ServiceWorkerContextClient::RespondToPaymentRequestEvent(
int payment_request_id,
const blink::WebPaymentHandlerResponse& web_response,
double dispatch_event_time) {
- TRACE_EVENT1("ServiceWorker",
- "ServiceWorkerContextClient::RespondToPaymentRequestEvent",
- "event_id", payment_request_id);
+ 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 =
@@ -1300,10 +1370,13 @@ void ServiceWorkerContextClient::DidHandlePaymentRequestEvent(
int payment_request_id,
blink::mojom::ServiceWorkerEventStatus status,
double event_dispatch_time) {
- TRACE_EVENT2("ServiceWorker",
- "ServiceWorkerContextClient::DidHandlePaymentRequestEvent",
- "event_id", payment_request_id, "status",
- ServiceWorkerUtils::MojoEnumToString(status));
+ 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, base::Time::FromDoubleT(event_dispatch_time))) {
@@ -1322,11 +1395,16 @@ std::unique_ptr<blink::WebWorkerFetchContext>
ServiceWorkerContextClient::CreateServiceWorkerFetchContext(
blink::WebServiceWorkerNetworkProvider* provider) {
DCHECK(main_thread_task_runner_->RunsTasksInCurrentSequence());
+ DCHECK(preference_watcher_request_.is_pending());
- scoped_refptr<ChildURLLoaderFactoryBundle> url_loader_factory_bundle =
- RenderThreadImpl::current()
- ->blink_platform_impl()
- ->CreateDefaultURLLoaderFactoryBundle();
+ scoped_refptr<ChildURLLoaderFactoryBundle> url_loader_factory_bundle;
+ if (loader_factories_) {
+ url_loader_factory_bundle = loader_factories_;
+ } else {
+ url_loader_factory_bundle = RenderThreadImpl::current()
+ ->blink_platform_impl()
+ ->CreateDefaultURLLoaderFactoryBundle();
+ }
DCHECK(url_loader_factory_bundle);
std::unique_ptr<network::SharedURLLoaderFactoryInfo>
@@ -1348,7 +1426,8 @@ ServiceWorkerContextClient::CreateServiceWorkerFetchContext(
URLLoaderThrottleProviderType::kWorker),
GetContentClient()
->renderer()
- ->CreateWebSocketHandshakeThrottleProvider());
+ ->CreateWebSocketHandshakeThrottleProvider(),
+ std::move(preference_watcher_request_));
}
std::unique_ptr<blink::WebServiceWorkerProvider>
@@ -1401,7 +1480,7 @@ void ServiceWorkerContextClient::Claim(
void ServiceWorkerContextClient::DispatchOrQueueFetchEvent(
blink::mojom::DispatchFetchEventParamsPtr params,
- mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
+ blink::mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
DispatchFetchEventCallback callback) {
TRACE_EVENT2("ServiceWorker",
"ServiceWorkerContextClient::DispatchOrQueueFetchEvent", "url",
@@ -1425,8 +1504,11 @@ void ServiceWorkerContextClient::DispatchSyncEvent(
int request_id = context_->timeout_timer->StartEventWithCustomTimeout(
CreateAbortCallback(&context_->sync_event_callbacks), timeout);
context_->sync_event_callbacks.emplace(request_id, std::move(callback));
- TRACE_EVENT1("ServiceWorker", "ServiceWorkerContextClient::DispatchSyncEvent",
- "request_id", request_id);
+ 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.
@@ -1443,9 +1525,11 @@ void ServiceWorkerContextClient::DispatchAbortPaymentEvent(
std::move(callback));
context_->abort_payment_result_callbacks.emplace(
event_id, std::move(response_callback));
- TRACE_EVENT1("ServiceWorker",
- "ServiceWorkerContextClient::DispatchAbortPaymentEvent",
- "event_id", event_id);
+ 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);
}
@@ -1459,9 +1543,12 @@ void ServiceWorkerContextClient::DispatchCanMakePaymentEvent(
std::move(callback));
context_->can_make_payment_result_callbacks.emplace(
event_id, std::move(response_callback));
- TRACE_EVENT1("ServiceWorker",
- "ServiceWorkerContextClient::DispatchCanMakePaymentEvent",
- "event_id", event_id);
+ 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));
@@ -1478,9 +1565,12 @@ void ServiceWorkerContextClient::DispatchPaymentRequestEvent(
std::move(callback));
context_->payment_response_callbacks.emplace(event_id,
std::move(response_callback));
- TRACE_EVENT1("ServiceWorker",
- "ServiceWorkerContextClient::DispatchPaymentRequestEvent",
- "event_id", event_id);
+ 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));
@@ -1508,105 +1598,84 @@ void ServiceWorkerContextClient::DispatchActivateEvent(
int request_id = context_->timeout_timer->StartEvent(
CreateAbortCallback(&context_->activate_event_callbacks));
context_->activate_event_callbacks.emplace(request_id, std::move(callback));
- TRACE_EVENT1("ServiceWorker",
- "ServiceWorkerContextClient::DispatchActivateEvent",
- "request_id", request_id);
+ 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(
- const std::string& developer_id,
- const std::string& unique_id,
- const std::vector<BackgroundFetchSettledFetch>& fetches,
+ const BackgroundFetchRegistration& registration,
DispatchBackgroundFetchAbortEventCallback callback) {
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_EVENT1("ServiceWorker",
- "ServiceWorkerContextClient::DispatchBackgroundFetchAbortEvent",
- "request_id", request_id);
-
- blink::WebVector<blink::WebBackgroundFetchSettledFetch> web_fetches(
- fetches.size());
- for (size_t i = 0; i < fetches.size(); ++i) {
- ToWebServiceWorkerRequest(fetches[i].request, &web_fetches[i].request);
- ToWebServiceWorkerResponse(fetches[i].response, &web_fetches[i].response);
- }
+ 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, blink::WebString::FromUTF8(developer_id),
- blink::WebString::FromUTF8(unique_id), web_fetches);
+ request_id, ToWebBackgroundFetchRegistration(registration));
}
void ServiceWorkerContextClient::DispatchBackgroundFetchClickEvent(
- const std::string& developer_id,
- mojom::BackgroundFetchState state,
+ const BackgroundFetchRegistration& registration,
DispatchBackgroundFetchClickEventCallback callback) {
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_EVENT1("ServiceWorker",
- "ServiceWorkerContextClient::DispatchBackgroundFetchClickEvent",
- "request_id", request_id);
+ TRACE_EVENT_WITH_FLOW0(
+ "ServiceWorker",
+ "ServiceWorkerContextClient::DispatchBackgroundFetchClickEvent",
+ TRACE_ID_WITH_SCOPE(kServiceWorkerContextClientScope,
+ TRACE_ID_LOCAL(request_id)),
+ TRACE_EVENT_FLAG_FLOW_OUT);
- // TODO(peter): Use typemap when this is moved to blink-side.
- blink::WebServiceWorkerContextProxy::BackgroundFetchState web_state =
- mojo::ConvertTo<
- blink::WebServiceWorkerContextProxy::BackgroundFetchState>(state);
proxy_->DispatchBackgroundFetchClickEvent(
- request_id, blink::WebString::FromUTF8(developer_id), web_state);
+ request_id, ToWebBackgroundFetchRegistration(registration));
}
void ServiceWorkerContextClient::DispatchBackgroundFetchFailEvent(
- const std::string& developer_id,
- const std::string& unique_id,
- const std::vector<BackgroundFetchSettledFetch>& fetches,
+ const BackgroundFetchRegistration& registration,
DispatchBackgroundFetchFailEventCallback callback) {
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_EVENT1("ServiceWorker",
- "ServiceWorkerContextClient::DispatchBackgroundFetchFailEvent",
- "request_id", request_id);
-
- blink::WebVector<blink::WebBackgroundFetchSettledFetch> web_fetches(
- fetches.size());
- for (size_t i = 0; i < fetches.size(); ++i) {
- ToWebServiceWorkerRequest(fetches[i].request, &web_fetches[i].request);
- ToWebServiceWorkerResponse(fetches[i].response, &web_fetches[i].response);
- }
+ 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, blink::WebString::FromUTF8(developer_id),
- blink::WebString::FromUTF8(unique_id), web_fetches);
+ request_id, ToWebBackgroundFetchRegistration(registration));
}
-void ServiceWorkerContextClient::DispatchBackgroundFetchedEvent(
- const std::string& developer_id,
- const std::string& unique_id,
- const std::vector<BackgroundFetchSettledFetch>& fetches,
- DispatchBackgroundFetchedEventCallback callback) {
+void ServiceWorkerContextClient::DispatchBackgroundFetchSuccessEvent(
+ const BackgroundFetchRegistration& registration,
+ DispatchBackgroundFetchSuccessEventCallback callback) {
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_EVENT1("ServiceWorker",
- "ServiceWorkerContextClient::DispatchBackgroundFetchedEvent",
- "request_id", request_id);
-
- blink::WebVector<blink::WebBackgroundFetchSettledFetch> web_fetches(
- fetches.size());
- for (size_t i = 0; i < fetches.size(); ++i) {
- ToWebServiceWorkerRequest(fetches[i].request, &web_fetches[i].request);
- ToWebServiceWorkerResponse(fetches[i].response, &web_fetches[i].response);
- }
+ TRACE_EVENT_WITH_FLOW0(
+ "ServiceWorker",
+ "ServiceWorkerContextClient::DispatchBackgroundFetchSuccessEvent",
+ TRACE_ID_WITH_SCOPE(kServiceWorkerContextClientScope,
+ TRACE_ID_LOCAL(request_id)),
+ TRACE_EVENT_FLAG_FLOW_OUT);
- proxy_->DispatchBackgroundFetchedEvent(
- request_id, blink::WebString::FromUTF8(developer_id),
- blink::WebString::FromUTF8(unique_id), web_fetches);
+ proxy_->DispatchBackgroundFetchSuccessEvent(
+ request_id, ToWebBackgroundFetchRegistration(registration));
}
void ServiceWorkerContextClient::InitializeGlobalScope(
@@ -1633,9 +1702,11 @@ void ServiceWorkerContextClient::DispatchInstallEvent(
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_EVENT1("ServiceWorker",
- "ServiceWorkerContextClient::DispatchInstallEvent", "event_id",
- event_id);
+ 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);
}
@@ -1646,8 +1717,43 @@ void ServiceWorkerContextClient::DispatchExtendableMessageEvent(
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);
+ scoped_refptr<WebServiceWorkerImpl> worker = GetOrCreateServiceWorkerObject(
+ std::move(event->source_info_for_service_worker));
+ proxy_->DispatchExtendableMessageEvent(
+ request_id, std::move(event->message), event->source_origin,
+ WebServiceWorkerImpl::CreateHandle(worker));
+}
+
+void ServiceWorkerContextClient::
+ DispatchExtendableMessageEventWithCustomTimeout(
+ mojom::ExtendableMessageEventPtr event,
+ base::TimeDelta timeout,
+ DispatchExtendableMessageEventCallback callback) {
+ 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::DispatchExtendableMessageEvent",
+ "ServiceWorkerContextClient::"
+ "DispatchExtendableMessageEventWithCustomTimeout",
"request_id", request_id);
if (event->source_info_for_client) {
@@ -1671,7 +1777,7 @@ void ServiceWorkerContextClient::DispatchExtendableMessageEvent(
// S13nServiceWorker
void ServiceWorkerContextClient::DispatchFetchEvent(
blink::mojom::DispatchFetchEventParamsPtr params,
- mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
+ blink::mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
DispatchFetchEventCallback callback) {
int event_id = context_->timeout_timer->StartEvent(
CreateAbortCallback(&context_->fetch_event_callbacks));
@@ -1681,9 +1787,11 @@ void ServiceWorkerContextClient::DispatchFetchEvent(
// This TRACE_EVENT is used for perf benchmark to confirm if all of fetch
// events have completed. (crbug.com/736697)
- TRACE_EVENT2("ServiceWorker",
- "ServiceWorkerContextClient::DispatchFetchEvent", "event_id",
- event_id, "url", params->request.url.spec());
+ 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;
@@ -1698,7 +1806,7 @@ void ServiceWorkerContextClient::DispatchFetchEvent(
std::move(params->request), params->request_body_blob_uuid,
params->request_body_blob_size, std::move(params->request_body_blob),
params->client_id, std::move(params->request_body_blob_ptrs),
- &web_request);
+ &web_request, true /* is_for_fetch_event */);
proxy_->DispatchFetchEvent(event_id, web_request, navigation_preload_sent);
}
@@ -1712,9 +1820,12 @@ void ServiceWorkerContextClient::DispatchNotificationClickEvent(
CreateAbortCallback(&context_->notification_click_event_callbacks));
context_->notification_click_event_callbacks.emplace(request_id,
std::move(callback));
- TRACE_EVENT1("ServiceWorker",
- "ServiceWorkerContextClient::DispatchNotificationClickEvent",
- "request_id", request_id);
+ 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)
@@ -1733,28 +1844,34 @@ void ServiceWorkerContextClient::DispatchNotificationCloseEvent(
CreateAbortCallback(&context_->notification_close_event_callbacks));
context_->notification_close_event_callbacks.emplace(request_id,
std::move(callback));
- TRACE_EVENT1("ServiceWorker",
- "ServiceWorkerContextClient::DispatchNotificationCloseEvent",
- "request_id", request_id);
+ 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 PushEventPayload& payload,
+ const base::Optional<std::string>& payload,
DispatchPushEventCallback callback) {
int request_id = context_->timeout_timer->StartEventWithCustomTimeout(
CreateAbortCallback(&context_->push_event_callbacks),
base::TimeDelta::FromSeconds(mojom::kPushEventTimeoutSeconds));
context_->push_event_callbacks.emplace(request_id, std::move(callback));
- TRACE_EVENT1("ServiceWorker", "ServiceWorkerContextClient::DispatchPushEvent",
- "request_id", request_id);
+ 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.is_null)
- data = blink::WebString::FromUTF8(payload.data);
+ if (payload)
+ data = blink::WebString::FromUTF8(*payload);
proxy_->DispatchPushEvent(request_id, data);
}
@@ -1766,9 +1883,11 @@ void ServiceWorkerContextClient::DispatchCookieChangeEvent(
CreateAbortCallback(&context_->cookie_change_event_callbacks));
context_->cookie_change_event_callbacks.emplace(request_id,
std::move(callback));
- TRACE_EVENT1("ServiceWorker",
- "ServiceWorkerContextClient::DispatchCookieChangeEvent",
- "request_id", request_id);
+ 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());
@@ -1802,9 +1921,12 @@ void ServiceWorkerContextClient::OnNavigationPreloadResponse(
int fetch_event_id,
std::unique_ptr<blink::WebURLResponse> response,
std::unique_ptr<blink::WebDataConsumerHandle> data_consumer_handle) {
- TRACE_EVENT1("ServiceWorker",
- "ServiceWorkerContextClient::OnNavigationPreloadResponse",
- "event_id", fetch_event_id);
+ TRACE_EVENT_WITH_FLOW0(
+ "ServiceWorker",
+ "ServiceWorkerContextClient::OnNavigationPreloadResponse",
+ TRACE_ID_WITH_SCOPE(kServiceWorkerContextClientScope,
+ TRACE_ID_LOCAL(fetch_event_id)),
+ TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
proxy_->OnNavigationPreloadResponse(fetch_event_id, std::move(response),
std::move(data_consumer_handle));
}
@@ -1812,9 +1934,11 @@ void ServiceWorkerContextClient::OnNavigationPreloadResponse(
void ServiceWorkerContextClient::OnNavigationPreloadError(
int fetch_event_id,
std::unique_ptr<blink::WebServiceWorkerError> error) {
- TRACE_EVENT1("ServiceWorker",
- "ServiceWorkerContextClient::OnNavigationPreloadError",
- "event_id", fetch_event_id);
+ TRACE_EVENT_WITH_FLOW0("ServiceWorker",
+ "ServiceWorkerContextClient::OnNavigationPreloadError",
+ TRACE_ID_WITH_SCOPE(kServiceWorkerContextClientScope,
+ TRACE_ID_LOCAL(fetch_event_id)),
+ TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
proxy_->OnNavigationPreloadError(fetch_event_id, std::move(error));
context_->preload_requests.Remove(fetch_event_id);
}
@@ -1825,9 +1949,12 @@ void ServiceWorkerContextClient::OnNavigationPreloadComplete(
int64_t encoded_data_length,
int64_t encoded_body_length,
int64_t decoded_body_length) {
- TRACE_EVENT1("ServiceWorker",
- "ServiceWorkerContextClient::OnNavigationPreloadComplete",
- "event_id", fetch_event_id);
+ TRACE_EVENT_WITH_FLOW0(
+ "ServiceWorker",
+ "ServiceWorkerContextClient::OnNavigationPreloadComplete",
+ TRACE_ID_WITH_SCOPE(kServiceWorkerContextClientScope,
+ TRACE_ID_LOCAL(fetch_event_id)),
+ TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
proxy_->OnNavigationPreloadComplete(fetch_event_id, completion_time,
encoded_data_length, encoded_body_length,
decoded_body_length);
@@ -1849,13 +1976,37 @@ void ServiceWorkerContextClient::OnIdleTimeout() {
// ServiceWorkerContextClient::OnIdleTiemout() has been called. It means
// termination has been requested.
DCHECK(RequestedTermination());
- (*instance_host_)->RequestTermination();
+ (*instance_host_)
+ ->RequestTermination(base::BindOnce(
+ &ServiceWorkerContextClient::OnRequestedTermination, GetWeakPtr()));
+}
+
+void ServiceWorkerContextClient::OnRequestedTermination(
+ bool will_be_terminated) {
+ DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled());
+ 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 {
return context_->timeout_timer->did_idle_timeout();
}
+void ServiceWorkerContextClient::StopWorker() {
+ DCHECK(main_thread_task_runner_->RunsTasksInCurrentSequence());
+ if (embedded_worker_client_)
+ embedded_worker_client_->StopWorker();
+}
+
void ServiceWorkerContextClient::AddServiceWorkerObject(
int64_t version_id,
WebServiceWorkerImpl* worker) {
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 b48aa9a8847..f5770f23a2d 100644
--- a/chromium/content/renderer/service_worker/service_worker_context_client.h
+++ b/chromium/content/renderer/service_worker/service_worker_context_client.h
@@ -28,11 +28,12 @@
#include "mojo/public/cpp/bindings/binding.h"
#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
#include "third_party/blink/public/mojom/blob/blob_registry.mojom.h"
+#include "third_party/blink/public/mojom/payments/payment_app.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_event_status.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
-#include "third_party/blink/public/platform/modules/payments/payment_app.mojom.h"
+#include "third_party/blink/public/platform/modules/background_fetch/background_fetch.mojom.h"
#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_error.h"
#include "third_party/blink/public/web/modules/service_worker/web_service_worker_context_client.h"
#include "third_party/blink/public/web/modules/service_worker/web_service_worker_context_proxy.h"
@@ -55,8 +56,8 @@ class WebURLResponse;
namespace content {
struct PlatformNotificationData;
-struct PushEventPayload;
class EmbeddedWorkerInstanceClientImpl;
+class HostChildURLLoaderFactoryBundle;
class ServiceWorkerNetworkProvider;
class ServiceWorkerProviderContext;
class ServiceWorkerTimeoutTimer;
@@ -99,6 +100,8 @@ class CONTENT_EXPORT ServiceWorkerContextClient
mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
std::unique_ptr<EmbeddedWorkerInstanceClientImpl> embedded_worker_client,
mojom::EmbeddedWorkerStartTimingPtr start_timing,
+ mojom::RendererPreferenceWatcherRequest preference_watcher_request,
+ std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loaders,
scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner);
~ServiceWorkerContextClient() override;
@@ -126,6 +129,7 @@ class CONTENT_EXPORT ServiceWorkerContextClient
void ClearCachedMetadata(const blink::WebURL&) override;
void WorkerReadyForInspection() override;
void WorkerContextFailedToStart() override;
+ void FailedToLoadInstalledScript() override;
void WorkerScriptLoaded() override;
void WorkerContextStarted(
blink::WebServiceWorkerContextProxy* proxy) override;
@@ -159,7 +163,7 @@ class CONTENT_EXPORT ServiceWorkerContextClient
int request_id,
blink::mojom::ServiceWorkerEventStatus status,
double dispatch_event_time) override;
- void DidHandleBackgroundFetchedEvent(
+ void DidHandleBackgroundFetchSuccessEvent(
int request_id,
blink::mojom::ServiceWorkerEventStatus status,
double dispatch_event_time) override;
@@ -250,7 +254,7 @@ class CONTENT_EXPORT ServiceWorkerContextClient
// client, which means it is coming through the ControllerServiceWorkerImpl.
void DispatchOrQueueFetchEvent(
blink::mojom::DispatchFetchEventParamsPtr params,
- mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
+ blink::mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
DispatchFetchEventCallback callback);
private:
@@ -283,30 +287,27 @@ class CONTENT_EXPORT ServiceWorkerContextClient
DispatchInstallEventCallback callback) override;
void DispatchActivateEvent(DispatchActivateEventCallback callback) override;
void DispatchBackgroundFetchAbortEvent(
- const std::string& developer_id,
- const std::string& unique_id,
- const std::vector<BackgroundFetchSettledFetch>& fetches,
+ const BackgroundFetchRegistration& registration,
DispatchBackgroundFetchAbortEventCallback callback) override;
void DispatchBackgroundFetchClickEvent(
- const std::string& developer_id,
- mojom::BackgroundFetchState state,
+ const BackgroundFetchRegistration& registration,
DispatchBackgroundFetchClickEventCallback callback) override;
void DispatchBackgroundFetchFailEvent(
- const std::string& developer_id,
- const std::string& unique_id,
- const std::vector<BackgroundFetchSettledFetch>& fetches,
+ const BackgroundFetchRegistration& registration,
DispatchBackgroundFetchFailEventCallback callback) override;
- void DispatchBackgroundFetchedEvent(
- const std::string& developer_id,
- const std::string& unique_id,
- const std::vector<BackgroundFetchSettledFetch>& fetches,
- DispatchBackgroundFetchedEventCallback callback) override;
+ void DispatchBackgroundFetchSuccessEvent(
+ const BackgroundFetchRegistration& registration,
+ DispatchBackgroundFetchSuccessEventCallback callback) override;
void DispatchExtendableMessageEvent(
mojom::ExtendableMessageEventPtr event,
DispatchExtendableMessageEventCallback callback) override;
+ void DispatchExtendableMessageEventWithCustomTimeout(
+ mojom::ExtendableMessageEventPtr event,
+ base::TimeDelta timeout,
+ DispatchExtendableMessageEventCallback callback) override;
void DispatchFetchEvent(
blink::mojom::DispatchFetchEventParamsPtr params,
- mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
+ blink::mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
DispatchFetchEventCallback callback) override;
void DispatchNotificationClickEvent(
const std::string& notification_id,
@@ -318,7 +319,7 @@ class CONTENT_EXPORT ServiceWorkerContextClient
const std::string& notification_id,
const PlatformNotificationData& notification_data,
DispatchNotificationCloseEventCallback callback) override;
- void DispatchPushEvent(const PushEventPayload& payload,
+ void DispatchPushEvent(const base::Optional<std::string>& payload,
DispatchPushEventCallback callback) override;
void DispatchSyncEvent(const std::string& tag,
bool last_chance,
@@ -388,10 +389,15 @@ class CONTENT_EXPORT ServiceWorkerContextClient
// 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 StopWorker();
+
// Keeps the mapping from version id to ServiceWorker object.
void AddServiceWorkerObject(int64_t version_id, WebServiceWorkerImpl* worker);
void RemoveServiceWorkerObject(int64_t version_id);
@@ -412,6 +418,8 @@ class CONTENT_EXPORT ServiceWorkerContextClient
const bool is_starting_installed_worker_;
RendererPreferences renderer_preferences_;
+ // Passed on creation of ServiceWorkerFetchContext.
+ mojom::RendererPreferenceWatcherRequest preference_watcher_request_;
scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
scoped_refptr<base::TaskRunner> worker_task_runner_;
@@ -446,6 +454,15 @@ class CONTENT_EXPORT ServiceWorkerContextClient
// startup completes.
mojom::EmbeddedWorkerStartTimingPtr start_timing_;
+ // S13nServiceWorker:
+ // A URLLoaderFactory instance used for subresource loading.
+ scoped_refptr<HostChildURLLoaderFactoryBundle> loader_factories_;
+
+ // Out-of-process NetworkService:
+ // Detects disconnection from the network service.
+ network::mojom::URLLoaderFactoryPtr
+ network_service_connection_error_handler_holder_;
+
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerContextClient);
};
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
index fbd3fceab5d..273452c5a13 100644
--- a/chromium/content/renderer/service_worker/service_worker_context_client_unittest.cc
+++ b/chromium/content/renderer/service_worker/service_worker_context_client_unittest.cc
@@ -14,8 +14,12 @@
#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/service_worker/web_service_worker_impl.h"
#include "content/renderer/worker_thread_registry.h"
#include "mojo/public/cpp/bindings/associated_binding_set.h"
@@ -26,7 +30,7 @@
#include "third_party/blink/public/common/message_port/message_port_channel.h"
#include "third_party/blink/public/common/service_worker/service_worker_utils.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
-#include "third_party/blink/public/platform/modules/background_fetch/web_background_fetch_settled_fetch.h"
+#include "third_party/blink/public/platform/modules/background_fetch/background_fetch.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"
@@ -78,31 +82,22 @@ class MockWebServiceWorkerContextProxy
void DispatchActivateEvent(int event_id) override { NOTREACHED(); }
void DispatchBackgroundFetchAbortEvent(
int event_id,
- const blink::WebString& developer_id,
- const blink::WebString& unique_id,
- const blink::WebVector<blink::WebBackgroundFetchSettledFetch>& fetches)
- override {
+ const blink::WebBackgroundFetchRegistration& registration) override {
NOTREACHED();
}
- void DispatchBackgroundFetchClickEvent(int event_id,
- const blink::WebString& developer_id,
- BackgroundFetchState status) override {
+ void DispatchBackgroundFetchClickEvent(
+ int event_id,
+ const blink::WebBackgroundFetchRegistration& registration) override {
NOTREACHED();
}
void DispatchBackgroundFetchFailEvent(
int event_id,
- const blink::WebString& developer_id,
- const blink::WebString& unique_id,
- const blink::WebVector<blink::WebBackgroundFetchSettledFetch>& fetches)
- override {
+ const blink::WebBackgroundFetchRegistration& registration) override {
NOTREACHED();
}
- void DispatchBackgroundFetchedEvent(
+ void DispatchBackgroundFetchSuccessEvent(
int event_id,
- const blink::WebString& developer_id,
- const blink::WebString& unique_id,
- const blink::WebVector<blink::WebBackgroundFetchSettledFetch>& fetches)
- override {
+ const blink::WebBackgroundFetchRegistration& registration) override {
NOTREACHED();
}
void DispatchCookieChangeEvent(
@@ -281,6 +276,8 @@ class ServiceWorkerContextClientTest : public testing::Test {
embedded_worker_host_ptr.PassInterface(), CreateProviderInfo(),
nullptr /* embedded_worker_client */,
mojom::EmbeddedWorkerStartTiming::New(),
+ nullptr /* preference_watcher_request */,
+ nullptr /* subresource_loaders */,
blink::scheduler::GetSingleThreadTaskRunnerForTesting());
context_client->WorkerContextStarted(proxy);
@@ -340,11 +337,11 @@ TEST_F(ServiceWorkerContextClientTest, DispatchFetchEvent) {
EXPECT_TRUE(mock_proxy.fetch_events().empty());
const GURL expected_url("https://example.com/expected");
- mojom::ServiceWorkerFetchResponseCallbackRequest fetch_callback_request;
auto request = std::make_unique<network::ResourceRequest>();
request->url = expected_url;
- mojom::ServiceWorkerFetchResponseCallbackPtr fetch_callback_ptr;
- fetch_callback_request = mojo::MakeRequest(&fetch_callback_ptr);
+ 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 = *request;
pipes.service_worker->DispatchFetchEvent(
@@ -354,10 +351,60 @@ TEST_F(ServiceWorkerContextClientTest, DispatchFetchEvent) {
task_runner()->RunUntilIdle();
ASSERT_EQ(1u, mock_proxy.fetch_events().size());
- EXPECT_EQ(request->url,
+ 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;
+ std::unique_ptr<ServiceWorkerContextClient> context_client =
+ CreateContextClient(&pipes, &mock_proxy);
+ context_client->DidEvaluateClassicScript(true /* success */);
+ task_runner()->RunUntilIdle();
+ EXPECT_TRUE(mock_proxy.fetch_events().empty());
+
+ const GURL expected_url("https://example.com/expected");
+ auto request = std::make_unique<network::ResourceRequest>();
+ request->url = expected_url;
+ request->headers.SetHeader("x-bye-bye", "excluded");
+ request->headers.SetHeader("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 = *request;
+ pipes.service_worker->DispatchFetchEvent(
+ std::move(params), std::move(fetch_callback_ptr),
+ base::BindOnce(
+ [](blink::mojom::ServiceWorkerEventStatus, base::Time) {}));
+ task_runner()->RunUntilIdle();
+
+ ASSERT_EQ(1u, mock_proxy.fetch_events().size());
+ const blink::WebServiceWorkerRequest& received_request =
+ mock_proxy.fetch_events()[0].second;
+ ServiceWorkerHeaderMap header_map;
+ GetServiceWorkerHeaderMapFromWebRequest(received_request, &header_map);
+
+ EXPECT_EQ(expected_url, static_cast<GURL>(received_request.Url()));
+ EXPECT_TRUE(header_map.find("x-bye-bye") == header_map.end());
+ auto iter = header_map.find("x-hi-hi");
+ ASSERT_TRUE(iter != header_map.end());
+ EXPECT_EQ("present", iter->second);
+
+ SetRendererClientForTesting(old_client);
+}
+
TEST_F(ServiceWorkerContextClientTest,
DispatchOrQueueFetchEvent_NotRequestedTermination) {
EnableServicification();
@@ -377,9 +424,9 @@ TEST_F(ServiceWorkerContextClientTest,
// The dispatched fetch event should be recorded by |mock_proxy|.
const GURL expected_url("https://example.com/expected");
- mojom::ServiceWorkerFetchResponseCallbackPtr fetch_callback_ptr;
- mojom::ServiceWorkerFetchResponseCallbackRequest fetch_callback_request =
- mojo::MakeRequest(&fetch_callback_ptr);
+ blink::mojom::ServiceWorkerFetchResponseCallbackPtr fetch_callback_ptr;
+ blink::mojom::ServiceWorkerFetchResponseCallbackRequest
+ fetch_callback_request = mojo::MakeRequest(&fetch_callback_ptr);
auto request = std::make_unique<network::ResourceRequest>();
request->url = expected_url;
auto params = blink::mojom::DispatchFetchEventParams::New();
@@ -421,13 +468,13 @@ TEST_F(ServiceWorkerContextClientTest,
EXPECT_TRUE(context_client->RequestedTermination());
const GURL expected_url("https://example.com/expected");
- mojom::ServiceWorkerFetchResponseCallbackRequest fetch_callback_request;
// FetchEvent dispatched directly from the controlled clients through
// mojom::ControllerServiceWorker should be queued in the idle state.
{
- mojom::ServiceWorkerFetchResponseCallbackPtr fetch_callback_ptr;
- fetch_callback_request = mojo::MakeRequest(&fetch_callback_ptr);
+ blink::mojom::ServiceWorkerFetchResponseCallbackPtr fetch_callback_ptr;
+ blink::mojom::ServiceWorkerFetchResponseCallbackRequest
+ fetch_callback_request = mojo::MakeRequest(&fetch_callback_ptr);
auto request = std::make_unique<network::ResourceRequest>();
request->url = expected_url;
auto params = blink::mojom::DispatchFetchEventParams::New();
@@ -469,13 +516,15 @@ TEST_F(ServiceWorkerContextClientTest,
const GURL expected_url_1("https://example.com/expected_1");
const GURL expected_url_2("https://example.com/expected_2");
- mojom::ServiceWorkerFetchResponseCallbackRequest fetch_callback_request_1;
- mojom::ServiceWorkerFetchResponseCallbackRequest fetch_callback_request_2;
+ blink::mojom::ServiceWorkerFetchResponseCallbackRequest
+ fetch_callback_request_1;
+ blink::mojom::ServiceWorkerFetchResponseCallbackRequest
+ fetch_callback_request_2;
// FetchEvent dispatched directly from the controlled clients through
// mojom::ControllerServiceWorker should be queued in the idle state.
{
- mojom::ServiceWorkerFetchResponseCallbackPtr fetch_callback_ptr;
+ blink::mojom::ServiceWorkerFetchResponseCallbackPtr fetch_callback_ptr;
fetch_callback_request_1 = mojo::MakeRequest(&fetch_callback_ptr);
auto request = std::make_unique<network::ResourceRequest>();
request->url = expected_url_1;
@@ -492,7 +541,7 @@ TEST_F(ServiceWorkerContextClientTest,
// Another event dispatched to mojom::ServiceWorker wakes up
// the context client.
{
- mojom::ServiceWorkerFetchResponseCallbackPtr fetch_callback_ptr;
+ blink::mojom::ServiceWorkerFetchResponseCallbackPtr fetch_callback_ptr;
fetch_callback_request_2 = mojo::MakeRequest(&fetch_callback_ptr);
auto request = std::make_unique<network::ResourceRequest>();
request->url = expected_url_2;
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 5cdaab338f6..97cea9b8ce9 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
@@ -28,7 +28,8 @@ ServiceWorkerFetchContextImpl::ServiceWorkerFetchContextImpl(
int service_worker_provider_id,
std::unique_ptr<URLLoaderThrottleProvider> throttle_provider,
std::unique_ptr<WebSocketHandshakeThrottleProvider>
- websocket_handshake_throttle_provider)
+ websocket_handshake_throttle_provider,
+ mojom::RendererPreferenceWatcherRequest preference_watcher_request)
: renderer_preferences_(std::move(renderer_preferences)),
worker_script_url_(worker_script_url),
url_loader_factory_info_(std::move(url_loader_factory_info)),
@@ -36,7 +37,9 @@ ServiceWorkerFetchContextImpl::ServiceWorkerFetchContextImpl(
service_worker_provider_id_(service_worker_provider_id),
throttle_provider_(std::move(throttle_provider)),
websocket_handshake_throttle_provider_(
- std::move(websocket_handshake_throttle_provider)) {}
+ std::move(websocket_handshake_throttle_provider)),
+ preference_watcher_binding_(this),
+ preference_watcher_request_(std::move(preference_watcher_request)) {}
ServiceWorkerFetchContextImpl::~ServiceWorkerFetchContextImpl() {}
@@ -50,6 +53,7 @@ void ServiceWorkerFetchContextImpl::InitializeOnWorkerThread() {
resource_dispatcher_ = std::make_unique<ResourceDispatcher>();
resource_dispatcher_->set_terminate_sync_load_event(
terminate_sync_load_event_);
+ preference_watcher_binding_.Bind(std::move(preference_watcher_request_));
url_loader_factory_ = network::SharedURLLoaderFactory::Create(
std::move(url_loader_factory_info_));
@@ -128,4 +132,9 @@ ServiceWorkerFetchContextImpl::CreateWebSocketHandshakeThrottle() {
MSG_ROUTING_NONE);
}
+void ServiceWorkerFetchContextImpl::NotifyUpdate(
+ const RendererPreferences& new_prefs) {
+ renderer_preferences_ = new_prefs;
+}
+
} // namespace content
diff --git a/chromium/content/renderer/service_worker/service_worker_fetch_context_impl.h b/chromium/content/renderer/service_worker/service_worker_fetch_context_impl.h
index 082614a85c7..2548d82b650 100644
--- a/chromium/content/renderer/service_worker/service_worker_fetch_context_impl.h
+++ b/chromium/content/renderer/service_worker/service_worker_fetch_context_impl.h
@@ -5,7 +5,9 @@
#ifndef CONTENT_RENDERER_SERVICE_WORKER_SERVICE_WORKER_FETCH_CONTEXT_IMPL_H_
#define CONTENT_RENDERER_SERVICE_WORKER_SERVICE_WORKER_FETCH_CONTEXT_IMPL_H_
+#include "content/public/common/renderer_preference_watcher.mojom.h"
#include "content/public/common/renderer_preferences.h"
+#include "mojo/public/cpp/bindings/binding.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "third_party/blink/public/platform/web_worker_fetch_context.h"
#include "url/gurl.h"
@@ -15,7 +17,8 @@ class ResourceDispatcher;
class URLLoaderThrottleProvider;
class WebSocketHandshakeThrottleProvider;
-class ServiceWorkerFetchContextImpl : public blink::WebWorkerFetchContext {
+class ServiceWorkerFetchContextImpl : public blink::WebWorkerFetchContext,
+ public mojom::RendererPreferenceWatcher {
public:
// |url_loader_factory_info| is used for regular loads from the service worker
// (i.e., Fetch API). It typically goes to network, but it might internally
@@ -34,7 +37,8 @@ class ServiceWorkerFetchContextImpl : public blink::WebWorkerFetchContext {
int service_worker_provider_id,
std::unique_ptr<URLLoaderThrottleProvider> throttle_provider,
std::unique_ptr<WebSocketHandshakeThrottleProvider>
- websocket_handshake_throttle_provider);
+ websocket_handshake_throttle_provider,
+ mojom::RendererPreferenceWatcherRequest preference_watcher_request);
~ServiceWorkerFetchContextImpl() override;
// blink::WebWorkerFetchContext implementation:
@@ -53,6 +57,9 @@ class ServiceWorkerFetchContextImpl : public blink::WebWorkerFetchContext {
CreateWebSocketHandshakeThrottle() override;
private:
+ // Implements mojom::RendererPreferenceWatcher.
+ void NotifyUpdate(const RendererPreferences& new_prefs) override;
+
RendererPreferences renderer_preferences_;
const GURL worker_script_url_;
// Consumed on the worker thread to create |url_loader_factory_|.
@@ -74,6 +81,12 @@ class ServiceWorkerFetchContextImpl : public blink::WebWorkerFetchContext {
std::unique_ptr<WebSocketHandshakeThrottleProvider>
websocket_handshake_throttle_provider_;
+ mojo::Binding<mojom::RendererPreferenceWatcher> preference_watcher_binding_;
+
+ // Kept while staring up the worker thread. Valid until
+ // InitializeOnWorkerThread().
+ mojom::RendererPreferenceWatcherRequest preference_watcher_request_;
+
// This is owned by ThreadedMessagingProxyBase on the main thread.
base::WaitableEvent* terminate_sync_load_event_ = nullptr;
};
diff --git a/chromium/content/renderer/service_worker/service_worker_network_provider.cc b/chromium/content/renderer/service_worker/service_worker_network_provider.cc
index c3cec85dfed..64b0d8bcec7 100644
--- a/chromium/content/renderer/service_worker/service_worker_network_provider.cc
+++ b/chromium/content/renderer/service_worker/service_worker_network_provider.cc
@@ -7,7 +7,6 @@
#include "base/atomic_sequence_num.h"
#include "base/single_thread_task_runner.h"
#include "content/common/navigation_params.h"
-#include "content/common/service_worker/service_worker_messages.h"
#include "content/common/service_worker/service_worker_provider.mojom.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/common/browser_side_navigation_policy.h"
diff --git a/chromium/content/renderer/service_worker/service_worker_network_provider.h b/chromium/content/renderer/service_worker/service_worker_network_provider.h
index ab53df97d40..01457653fb7 100644
--- a/chromium/content/renderer/service_worker/service_worker_network_provider.h
+++ b/chromium/content/renderer/service_worker/service_worker_network_provider.h
@@ -63,6 +63,8 @@ class CONTENT_EXPORT ServiceWorkerNetworkProvider {
// renderer by the browser on a navigation commit. It is null if we have not
// yet heard from the browser (currently only during the time it takes from
// having the renderer initiate a navigation until the browser commits it).
+ // Note: in particular, provisional load failure do not provide
+ // |request_params|.
// TODO(ahemery): Update this comment when do not create placeholder document
// loaders for renderer-initiated navigations. In this case, this should never
// be null.
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 c187d3c147e..697f3e36a08 100644
--- a/chromium/content/renderer/service_worker/service_worker_provider_context.cc
+++ b/chromium/content/renderer/service_worker/service_worker_provider_context.cc
@@ -11,7 +11,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/stl_util.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/child/child_thread_impl.h"
#include "content/child/thread_safe_sender.h"
@@ -56,80 +56,6 @@ void CreateSubresourceLoaderFactoryForProviderContext(
} // namespace
-// Holds state for service worker clients.
-struct ServiceWorkerProviderContext::ProviderStateForClient {
- explicit ProviderStateForClient(
- scoped_refptr<network::SharedURLLoaderFactory> fallback_loader_factory)
- : fallback_loader_factory(std::move(fallback_loader_factory)) {}
- ~ProviderStateForClient() = default;
-
- // |controller| will be set by SetController() and taken by TakeController().
- blink::mojom::ServiceWorkerObjectInfoPtr controller;
- // Keeps version id of the current controller service worker object.
- int64_t controller_version_id = blink::mojom::kInvalidServiceWorkerVersionId;
-
- // S13nServiceWorker:
- // Used to intercept requests from the controllee and dispatch them
- // as events to the controller ServiceWorker.
- network::mojom::URLLoaderFactoryPtr subresource_loader_factory;
-
- // S13nServiceWorker:
- // Used when we create |subresource_loader_factory|.
- scoped_refptr<network::SharedURLLoaderFactory> fallback_loader_factory;
-
- // S13nServiceWorker:
- // The Client#id value of the client.
- std::string client_id;
-
- blink::mojom::ControllerServiceWorkerMode controller_mode =
- blink::mojom::ControllerServiceWorkerMode::kNoController;
-
- // Tracks feature usage for UseCounter.
- std::set<blink::mojom::WebFeature> used_features;
-
- // Corresponds to a ServiceWorkerContainer. We notify it when
- // ServiceWorkerContainer#controller should be changed.
- base::WeakPtr<WebServiceWorkerProviderImpl> web_service_worker_provider;
-
- // Keeps ServiceWorkerWorkerClient pointers of dedicated or shared workers
- // which are associated with the ServiceWorkerProviderContext.
- // - If this ServiceWorkerProviderContext is for a Document, then
- // |worker_clients| contains all its dedicated workers.
- // - If this ServiceWorkerProviderContext is for a SharedWorker (technically
- // speaking, for its shadow page), then |worker_clients| has one element:
- // the shared worker.
- std::vector<mojom::ServiceWorkerWorkerClientPtr> worker_clients;
-
- // For adding new ServiceWorkerWorkerClients.
- mojo::BindingSet<mojom::ServiceWorkerWorkerClientRegistry>
- worker_client_registry_bindings;
-
- // S13nServiceWorker
- // Used in |subresource_loader_factory| to get the connection to the
- // controller service worker.
- //
- // |controller_endpoint| is a Mojo pipe to the controller service worker,
- // and is to be passed to (i.e. taken by) a subresource loader factory when
- // GetSubresourceLoaderFactory() is called for the first time when a valid
- // controller exists.
- //
- // |controller_connector| is a Mojo pipe to the
- // ControllerServiceWorkerConnector that is attached to the newly created
- // subresource loader factory and lives on a background thread. This is
- // populated when GetSubresourceLoader() creates the subresource loader
- // factory and takes |controller_endpoint|.
- mojom::ControllerServiceWorkerPtrInfo controller_endpoint;
- mojom::ControllerServiceWorkerConnectorPtr controller_connector;
-
- // For service worker clients. Map from registration id to JavaScript
- // ServiceWorkerRegistration object.
- std::map<int64_t, WebServiceWorkerRegistrationImpl*> registrations_;
-
- // For service worker clients. Map from version id to JavaScript ServiceWorker
- // object.
- std::map<int64_t, WebServiceWorkerImpl*> workers_;
-};
-
// For service worker clients.
ServiceWorkerProviderContext::ServiceWorkerProviderContext(
int provider_id,
@@ -144,7 +70,7 @@ ServiceWorkerProviderContext::ServiceWorkerProviderContext(
binding_(this, std::move(request)),
weak_factory_(this) {
container_host_.Bind(std::move(host_ptr_info));
- state_for_client_ = std::make_unique<ProviderStateForClient>(
+ state_for_client_ = std::make_unique<ServiceWorkerProviderStateForClient>(
std::move(fallback_loader_factory));
// Set up the URL loader factory for sending subresource requests to
@@ -330,7 +256,7 @@ void ServiceWorkerProviderContext::PingContainerHost(
void ServiceWorkerProviderContext::DispatchNetworkQuiet() {
DCHECK(main_thread_task_runner_->RunsTasksInCurrentSequence());
- ProviderStateForClient* state = state_for_client_.get();
+ ServiceWorkerProviderStateForClient* state = state_for_client_.get();
DCHECK(state);
// In non-S13nSW, this hint isn't needed because the browser process
@@ -362,7 +288,7 @@ void ServiceWorkerProviderContext::SetController(
const std::vector<blink::mojom::WebFeature>& used_features,
bool should_notify_controllerchange) {
DCHECK(main_thread_task_runner_->RunsTasksInCurrentSequence());
- ProviderStateForClient* state = state_for_client_.get();
+ ServiceWorkerProviderStateForClient* state = state_for_client_.get();
DCHECK(state);
state->controller = std::move(controller_info->object_info);
@@ -440,7 +366,7 @@ void ServiceWorkerProviderContext::PostMessageToClient(
blink::TransferableMessage message) {
DCHECK(main_thread_task_runner_->RunsTasksInCurrentSequence());
- ProviderStateForClient* state = state_for_client_.get();
+ ServiceWorkerProviderStateForClient* state = state_for_client_.get();
DCHECK(state);
if (state->web_service_worker_provider) {
state->web_service_worker_provider->PostMessageToClient(std::move(source),
@@ -495,7 +421,7 @@ void ServiceWorkerProviderContext::CountFeature(
blink::mojom::WebFeature feature) {
DCHECK(main_thread_task_runner_->RunsTasksInCurrentSequence());
DCHECK(state_for_client_);
- ProviderStateForClient* state = state_for_client_.get();
+ ServiceWorkerProviderStateForClient* state = state_for_client_.get();
// ServiceWorkerProviderContext keeps track of features in order to propagate
// it to WebServiceWorkerProviderClient, which actually records the
diff --git a/chromium/content/renderer/service_worker/service_worker_provider_context.h b/chromium/content/renderer/service_worker/service_worker_provider_context.h
index 405c40c960f..e8515eb57cb 100644
--- a/chromium/content/renderer/service_worker/service_worker_provider_context.h
+++ b/chromium/content/renderer/service_worker/service_worker_provider_context.h
@@ -6,6 +6,9 @@
#define CONTENT_RENDERER_SERVICE_WORKER_SERVICE_WORKER_PROVIDER_CONTEXT_H_
#include <memory>
+#include <set>
+#include <string>
+#include <vector>
#include "base/macros.h"
#include "base/memory/ref_counted.h"
@@ -15,6 +18,7 @@
#include "content/common/service_worker/controller_service_worker.mojom.h"
#include "content/common/service_worker/service_worker_container.mojom.h"
#include "content/common/service_worker/service_worker_provider.mojom.h"
+#include "content/renderer/service_worker/service_worker_provider_state_for_client.h"
#include "content/renderer/service_worker/web_service_worker_provider_impl.h"
#include "mojo/public/cpp/bindings/associated_binding.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
@@ -205,7 +209,6 @@ class CONTENT_EXPORT ServiceWorkerProviderContext
friend class WebServiceWorkerImpl;
friend class WebServiceWorkerRegistrationImpl;
friend struct ServiceWorkerProviderContextDeleter;
- struct ProviderStateForClient;
~ServiceWorkerProviderContext() override;
void DestructOnMainThread() const;
@@ -264,7 +267,7 @@ class CONTENT_EXPORT ServiceWorkerProviderContext
mojom::ServiceWorkerContainerHostAssociatedPtr container_host_;
// State for service worker clients.
- std::unique_ptr<ProviderStateForClient> state_for_client_;
+ std::unique_ptr<ServiceWorkerProviderStateForClient> state_for_client_;
// NOTE: Add new members to |state_for_client_| if they are relevant only for
// service worker clients. Not here!
diff --git a/chromium/content/renderer/service_worker/service_worker_provider_context_unittest.cc b/chromium/content/renderer/service_worker/service_worker_provider_context_unittest.cc
index d5d256d404b..0e34a0da26b 100644
--- a/chromium/content/renderer/service_worker/service_worker_provider_context_unittest.cc
+++ b/chromium/content/renderer/service_worker/service_worker_provider_context_unittest.cc
@@ -5,6 +5,10 @@
#include "content/renderer/service_worker/service_worker_provider_context.h"
#include <memory>
+#include <set>
+#include <string>
+#include <utility>
+#include <vector>
#include "base/macros.h"
#include "base/message_loop/message_loop.h"
@@ -13,12 +17,10 @@
#include "base/test/scoped_task_environment.h"
#include "content/child/thread_safe_sender.h"
#include "content/common/service_worker/service_worker_container.mojom.h"
-#include "content/common/service_worker/service_worker_messages.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/public/common/content_features.h"
#include "content/public/common/resource_type.h"
#include "content/renderer/service_worker/controller_service_worker_connector.h"
-#include "content/renderer/service_worker/service_worker_provider_context.h"
#include "content/renderer/service_worker/web_service_worker_impl.h"
#include "content/renderer/service_worker/web_service_worker_registration_impl.h"
#include "mojo/public/cpp/bindings/associated_binding_set.h"
@@ -44,7 +46,11 @@ class MockServiceWorkerObjectHost
: public blink::mojom::ServiceWorkerObjectHost {
public:
explicit MockServiceWorkerObjectHost(int64_t version_id)
- : version_id_(version_id) {}
+ : version_id_(version_id) {
+ bindings_.set_connection_error_handler(
+ base::BindRepeating(&MockServiceWorkerObjectHost::OnConnectionError,
+ base::Unretained(this)));
+ }
~MockServiceWorkerObjectHost() override = default;
blink::mojom::ServiceWorkerObjectInfoPtr CreateObjectInfo() {
@@ -55,6 +61,16 @@ class MockServiceWorkerObjectHost
return info;
}
+ void OnConnectionError() {
+ if (error_callback_)
+ std::move(error_callback_).Run();
+ }
+
+ void RunOnConnectionError(base::OnceClosure error_callback) {
+ DCHECK(!error_callback_);
+ error_callback_ = std::move(error_callback);
+ }
+
int GetBindingCount() const { return bindings_.size(); }
private:
@@ -70,6 +86,7 @@ class MockServiceWorkerObjectHost
const int64_t version_id_;
mojo::AssociatedBindingSet<blink::mojom::ServiceWorkerObjectHost> bindings_;
blink::mojom::ServiceWorkerObjectAssociatedPtr remote_object_;
+ base::OnceClosure error_callback_;
};
class MockServiceWorkerRegistrationObjectHost
@@ -239,7 +256,7 @@ class FakeControllerServiceWorker : public mojom::ControllerServiceWorker {
// mojom::ControllerServiceWorker:
void DispatchFetchEvent(
blink::mojom::DispatchFetchEventParamsPtr params,
- mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
+ blink::mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
DispatchFetchEventCallback callback) override {
fetch_event_count_++;
fetch_event_request_ = params->request;
@@ -353,6 +370,11 @@ class ServiceWorkerProviderContextTest : public testing::Test {
return provider_context->ContainsServiceWorkerObjectForTesting(version_id);
}
+ void FlushControllerConnector(
+ ServiceWorkerProviderContext* provider_context) {
+ provider_context->state_for_client_->controller_connector.FlushForTesting();
+ }
+
protected:
base::test::ScopedTaskEnvironment task_environment;
@@ -479,13 +501,26 @@ TEST_F(ServiceWorkerProviderContextTest, SetControllerServiceWorker) {
EnableS13nServiceWorker();
const int kProviderId = 10;
+ // Make the ServiceWorkerContainerHost implementation and
+ // ServiceWorkerContainer request.
+ mojom::ServiceWorkerContainerHostAssociatedPtr host_ptr;
+ FakeServiceWorkerContainerHost host(
+ mojo::MakeRequestAssociatedWithDedicatedPipe(&host_ptr));
+ mojom::ServiceWorkerContainerAssociatedPtr container_ptr;
+ mojom::ServiceWorkerContainerAssociatedRequest container_request =
+ mojo::MakeRequestAssociatedWithDedicatedPipe(&container_ptr);
+
// (1) Test if setting the controller via the CTOR works.
+
+ // Make the object host for .controller.
auto object_host1 =
std::make_unique<MockServiceWorkerObjectHost>(200 /* version_id */);
- ASSERT_EQ(0, object_host1->GetBindingCount());
+ EXPECT_EQ(0, object_host1->GetBindingCount());
blink::mojom::ServiceWorkerObjectInfoPtr object_info1 =
object_host1->CreateObjectInfo();
EXPECT_EQ(1, object_host1->GetBindingCount());
+
+ // Make the ControllerServiceWorkerInfo.
FakeControllerServiceWorker fake_controller1;
auto controller_info1 = mojom::ControllerServiceWorkerInfo::New();
mojom::ControllerServiceWorkerPtr controller_ptr1;
@@ -495,21 +530,15 @@ TEST_F(ServiceWorkerProviderContextTest, SetControllerServiceWorker) {
controller_info1->object_info = std::move(object_info1);
controller_info1->endpoint = controller_ptr1.PassInterface();
- mojom::ServiceWorkerContainerHostAssociatedPtr host_ptr;
- FakeServiceWorkerContainerHost host(
- mojo::MakeRequestAssociatedWithDedicatedPipe(&host_ptr));
-
- mojom::ServiceWorkerContainerAssociatedPtr container_ptr;
- mojom::ServiceWorkerContainerAssociatedRequest container_request =
- mojo::MakeRequestAssociatedWithDedicatedPipe(&container_ptr);
+ // Make the ServiceWorkerProviderContext, pasing it the controller, container,
+ // and container host.
auto provider_context = base::MakeRefCounted<ServiceWorkerProviderContext>(
kProviderId, blink::mojom::ServiceWorkerProviderType::kForWindow,
std::move(container_request), host_ptr.PassInterface(),
std::move(controller_info1), loader_factory_);
- base::RunLoop().RunUntilIdle();
- // Subresource loader factory must be available.
- auto* subresource_loader_factory1 =
+ // The subresource loader factory must be available.
+ network::mojom::URLLoaderFactory* subresource_loader_factory1 =
provider_context->GetSubresourceLoaderFactory();
ASSERT_NE(nullptr, subresource_loader_factory1);
@@ -524,6 +553,8 @@ TEST_F(ServiceWorkerProviderContextTest, SetControllerServiceWorker) {
// (2) Test if resetting the controller to a new one via SetController
// works.
+
+ // Setup the new controller.
auto object_host2 =
std::make_unique<MockServiceWorkerObjectHost>(201 /* version_id */);
ASSERT_EQ(0, object_host2->GetBindingCount());
@@ -538,21 +569,29 @@ TEST_F(ServiceWorkerProviderContextTest, SetControllerServiceWorker) {
blink::mojom::ControllerServiceWorkerMode::kControlled;
controller_info2->object_info = std::move(object_info2);
controller_info2->endpoint = controller_ptr2.PassInterface();
+
+ // Resetting the controller will trigger many things happening, including the
+ // object binding being broken.
+ base::RunLoop drop_binding_loop;
+ object_host1->RunOnConnectionError(drop_binding_loop.QuitClosure());
container_ptr->SetController(std::move(controller_info2),
std::vector<blink::mojom::WebFeature>(), true);
-
- // The controller is reset. References to the old controller must be
- // released.
- base::RunLoop().RunUntilIdle();
+ container_ptr.FlushForTesting();
+ drop_binding_loop.Run();
EXPECT_EQ(0, object_host1->GetBindingCount());
// Subresource loader factory must be available, and should be the same
// one as we got before.
- auto* subresource_loader_factory2 =
+ network::mojom::URLLoaderFactory* subresource_loader_factory2 =
provider_context->GetSubresourceLoaderFactory();
ASSERT_NE(nullptr, subresource_loader_factory2);
EXPECT_EQ(subresource_loader_factory1, subresource_loader_factory2);
+ // The SetController() call results in another Mojo call to
+ // ControllerServiceWorkerConnector.UpdateController(). Flush that interface
+ // pointer to ensure the message was received.
+ FlushControllerConnector(provider_context.get());
+
// Performing a request should reach the new controller.
const GURL kURL2("https://www.example.com/foo2.png");
base::RunLoop loop2;
@@ -565,17 +604,25 @@ TEST_F(ServiceWorkerProviderContextTest, SetControllerServiceWorker) {
EXPECT_EQ(1, fake_controller1.fetch_event_count());
// (3) Test if resetting the controller to nullptr works.
+ base::RunLoop drop_binding_loop2;
+ object_host2->RunOnConnectionError(drop_binding_loop2.QuitClosure());
container_ptr->SetController(mojom::ControllerServiceWorkerInfo::New(),
std::vector<blink::mojom::WebFeature>(), true);
// The controller is reset. References to the old controller must be
// released.
- base::RunLoop().RunUntilIdle();
+ container_ptr.FlushForTesting();
+ drop_binding_loop2.Run();
EXPECT_EQ(0, object_host2->GetBindingCount());
// Subresource loader factory must not be available.
EXPECT_EQ(nullptr, provider_context->GetSubresourceLoaderFactory());
+ // The SetController() call results in another Mojo call to
+ // ControllerServiceWorkerConnector.UpdateController(). Flush that interface
+ // pointer to ensure the message was received.
+ FlushControllerConnector(provider_context.get());
+
// Performing a request using the subresource factory obtained before
// falls back to the network.
const GURL kURL3("https://www.example.com/foo3.png");
@@ -609,13 +656,18 @@ TEST_F(ServiceWorkerProviderContextTest, SetControllerServiceWorker) {
controller_info4->endpoint = controller_ptr4.PassInterface();
container_ptr->SetController(std::move(controller_info4),
std::vector<blink::mojom::WebFeature>(), true);
- base::RunLoop().RunUntilIdle();
+ container_ptr.FlushForTesting();
// Subresource loader factory must be available.
auto* subresource_loader_factory4 =
provider_context->GetSubresourceLoaderFactory();
ASSERT_NE(nullptr, subresource_loader_factory4);
+ // The SetController() call results in another Mojo call to
+ // ControllerServiceWorkerConnector.UpdateController(). Flush that interface
+ // pointer to ensure the message was received.
+ FlushControllerConnector(provider_context.get());
+
// Performing a request should reach the new controller.
const GURL kURL4("https://www.example.com/foo4.png");
base::RunLoop loop4;
diff --git a/chromium/content/renderer/service_worker/service_worker_provider_state_for_client.cc b/chromium/content/renderer/service_worker/service_worker_provider_state_for_client.cc
new file mode 100644
index 00000000000..b5c043f02c8
--- /dev/null
+++ b/chromium/content/renderer/service_worker/service_worker_provider_state_for_client.cc
@@ -0,0 +1,18 @@
+// 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/renderer/service_worker/service_worker_provider_state_for_client.h"
+
+#include <utility>
+
+namespace content {
+
+ServiceWorkerProviderStateForClient::ServiceWorkerProviderStateForClient(
+ scoped_refptr<network::SharedURLLoaderFactory> fallback_loader_factory)
+ : fallback_loader_factory(std::move(fallback_loader_factory)) {}
+
+ServiceWorkerProviderStateForClient::~ServiceWorkerProviderStateForClient() =
+ default;
+
+} // namespace content
diff --git a/chromium/content/renderer/service_worker/service_worker_provider_state_for_client.h b/chromium/content/renderer/service_worker/service_worker_provider_state_for_client.h
new file mode 100644
index 00000000000..dd93d3c3fe9
--- /dev/null
+++ b/chromium/content/renderer/service_worker/service_worker_provider_state_for_client.h
@@ -0,0 +1,106 @@
+// 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_RENDERER_SERVICE_WORKER_SERVICE_WORKER_PROVIDER_STATE_FOR_CLIENT_H_
+#define CONTENT_RENDERER_SERVICE_WORKER_SERVICE_WORKER_PROVIDER_STATE_FOR_CLIENT_H_
+
+#include <stdint.h>
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "content/common/content_export.h"
+#include "content/common/service_worker/controller_service_worker.mojom.h"
+#include "content/common/service_worker/service_worker_container.mojom.h"
+#include "content/common/service_worker/service_worker_provider.mojom.h"
+#include "content/renderer/service_worker/web_service_worker_impl.h"
+#include "content/renderer/service_worker/web_service_worker_provider_impl.h"
+#include "content/renderer/service_worker/web_service_worker_registration_impl.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "services/network/public/mojom/url_loader_factory.mojom.h"
+#include "third_party/blink/public/platform/web_feature.mojom.h"
+
+namespace content {
+
+// Holds state for ServiceWorkerProviderContext instances for service worker
+// clients.
+struct ServiceWorkerProviderStateForClient {
+ explicit ServiceWorkerProviderStateForClient(
+ scoped_refptr<network::SharedURLLoaderFactory> fallback_loader_factory);
+ ~ServiceWorkerProviderStateForClient();
+
+ // |controller| will be set by SetController() and taken by TakeController().
+ blink::mojom::ServiceWorkerObjectInfoPtr controller;
+ // Keeps version id of the current controller service worker object.
+ int64_t controller_version_id = blink::mojom::kInvalidServiceWorkerVersionId;
+
+ // S13nServiceWorker:
+ // Used to intercept requests from the controllee and dispatch them
+ // as events to the controller ServiceWorker.
+ network::mojom::URLLoaderFactoryPtr subresource_loader_factory;
+
+ // S13nServiceWorker:
+ // Used when we create |subresource_loader_factory|.
+ scoped_refptr<network::SharedURLLoaderFactory> fallback_loader_factory;
+
+ // S13nServiceWorker:
+ // The Client#id value of the client.
+ std::string client_id;
+
+ blink::mojom::ControllerServiceWorkerMode controller_mode =
+ blink::mojom::ControllerServiceWorkerMode::kNoController;
+
+ // Tracks feature usage for UseCounter.
+ std::set<blink::mojom::WebFeature> used_features;
+
+ // Corresponds to a ServiceWorkerContainer. We notify it when
+ // ServiceWorkerContainer#controller should be changed.
+ base::WeakPtr<WebServiceWorkerProviderImpl> web_service_worker_provider;
+
+ // Keeps ServiceWorkerWorkerClient pointers of dedicated or shared workers
+ // which are associated with the ServiceWorkerProviderContext.
+ // - If this ServiceWorkerProviderContext is for a Document, then
+ // |worker_clients| contains all its dedicated workers.
+ // - If this ServiceWorkerProviderContext is for a SharedWorker (technically
+ // speaking, for its shadow page), then |worker_clients| has one element:
+ // the shared worker.
+ std::vector<mojom::ServiceWorkerWorkerClientPtr> worker_clients;
+
+ // For adding new ServiceWorkerWorkerClients.
+ mojo::BindingSet<mojom::ServiceWorkerWorkerClientRegistry>
+ worker_client_registry_bindings;
+
+ // S13nServiceWorker
+ // Used in |subresource_loader_factory| to get the connection to the
+ // controller service worker.
+ //
+ // |controller_endpoint| is a Mojo pipe to the controller service worker,
+ // and is to be passed to (i.e. taken by) a subresource loader factory when
+ // GetSubresourceLoaderFactory() is called for the first time when a valid
+ // controller exists.
+ //
+ // |controller_connector| is a Mojo pipe to the
+ // ControllerServiceWorkerConnector that is attached to the newly created
+ // subresource loader factory and lives on a background thread. This is
+ // populated when GetSubresourceLoader() creates the subresource loader
+ // factory and takes |controller_endpoint|.
+ mojom::ControllerServiceWorkerPtrInfo controller_endpoint;
+ mojom::ControllerServiceWorkerConnectorPtr controller_connector;
+
+ // For service worker clients. Map from registration id to JavaScript
+ // ServiceWorkerRegistration object.
+ std::map<int64_t, WebServiceWorkerRegistrationImpl*> registrations_;
+
+ // For service worker clients. Map from version id to JavaScript ServiceWorker
+ // object.
+ std::map<int64_t, WebServiceWorkerImpl*> workers_;
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_SERVICE_WORKER_SERVICE_WORKER_PROVIDER_STATE_FOR_CLIENT_H_
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 3e5b7dbfd77..09349114c3c 100644
--- a/chromium/content/renderer/service_worker/service_worker_subresource_loader.cc
+++ b/chromium/content/renderer/service_worker/service_worker_subresource_loader.cc
@@ -209,7 +209,7 @@ void ServiceWorkerSubresourceLoader::StartRequest(
}
void ServiceWorkerSubresourceLoader::DispatchFetchEvent() {
- mojom::ServiceWorkerFetchResponseCallbackPtr response_callback_ptr;
+ blink::mojom::ServiceWorkerFetchResponseCallbackPtr response_callback_ptr;
response_callback_binding_.Bind(mojo::MakeRequest(&response_callback_ptr));
mojom::ControllerServiceWorker* controller =
controller_connector_->GetControllerServiceWorker(
@@ -339,38 +339,24 @@ void ServiceWorkerSubresourceLoader::SettleFetchEventDispatch(
}
void ServiceWorkerSubresourceLoader::OnResponse(
- const ServiceWorkerResponse& response,
+ blink::mojom::FetchAPIResponsePtr response,
base::Time dispatch_event_time) {
TRACE_EVENT_WITH_FLOW0("ServiceWorker",
"ServiceWorkerSubresourceLoader::OnResponse", this,
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
SettleFetchEventDispatch(blink::ServiceWorkerStatusCode::kOk);
- StartResponse(response, nullptr /* body_as_blob */,
- nullptr /* body_as_stream */);
-}
-
-void ServiceWorkerSubresourceLoader::OnResponseBlob(
- const ServiceWorkerResponse& response,
- blink::mojom::BlobPtr body_as_blob,
- base::Time dispatch_event_time) {
- TRACE_EVENT_WITH_FLOW0("ServiceWorker",
- "ServiceWorkerSubresourceLoader::OnResponseBlob", this,
- TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
- SettleFetchEventDispatch(blink::ServiceWorkerStatusCode::kOk);
- StartResponse(response, std::move(body_as_blob),
- nullptr /* body_as_stream */);
+ StartResponse(std::move(response), nullptr /* body_as_stream */);
}
void ServiceWorkerSubresourceLoader::OnResponseStream(
- const ServiceWorkerResponse& response,
+ blink::mojom::FetchAPIResponsePtr response,
blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
base::Time dispatch_event_time) {
TRACE_EVENT_WITH_FLOW0(
"ServiceWorker", "ServiceWorkerSubresourceLoader::OnResponseStream", this,
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
SettleFetchEventDispatch(blink::ServiceWorkerStatusCode::kOk);
- StartResponse(response, nullptr /* body_as_blob */,
- std::move(body_as_stream));
+ StartResponse(std::move(response), std::move(body_as_stream));
}
void ServiceWorkerSubresourceLoader::OnFallback(
@@ -425,19 +411,18 @@ void ServiceWorkerSubresourceLoader::OnFallback(
}
void ServiceWorkerSubresourceLoader::StartResponse(
- const ServiceWorkerResponse& response,
- blink::mojom::BlobPtr body_as_blob,
+ blink::mojom::FetchAPIResponsePtr response,
blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream) {
// A response with status code 0 is Blink telling us to respond with network
// error.
- if (response.status_code == 0) {
+ if (response->status_code == 0) {
CommitCompleted(net::ERR_FAILED);
return;
}
- ServiceWorkerLoaderHelpers::SaveResponseInfo(response, &response_head_);
+ ServiceWorkerLoaderHelpers::SaveResponseInfo(*response, &response_head_);
ServiceWorkerLoaderHelpers::SaveResponseHeaders(
- response.status_code, response.status_text, response.headers,
+ response->status_code, response->status_text, response->headers,
&response_head_);
response_head_.response_start = base::TimeTicks::Now();
response_head_.load_timing.receive_headers_end = base::TimeTicks::Now();
@@ -463,7 +448,7 @@ void ServiceWorkerSubresourceLoader::StartResponse(
// Handle a stream response body.
if (!body_as_stream.is_null() && body_as_stream->stream.is_valid()) {
- DCHECK(!body_as_blob);
+ DCHECK(!response->blob);
DCHECK(url_loader_client_.is_bound());
stream_waiter_ = std::make_unique<StreamWaiter>(
this, std::move(body_as_stream->callback_request));
@@ -473,9 +458,10 @@ void ServiceWorkerSubresourceLoader::StartResponse(
}
// Handle a blob response body.
- if (body_as_blob) {
+ if (response->blob) {
DCHECK(!body_as_stream);
- body_as_blob_ = std::move(body_as_blob);
+ DCHECK(response->blob->blob.is_valid());
+ body_as_blob_.Bind(std::move(response->blob->blob));
body_as_blob_->ReadSideData(base::BindOnce(
&ServiceWorkerSubresourceLoader::OnBlobSideDataReadingComplete,
base::Unretained(this)));
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 91b180b27af..b17ef54f371 100644
--- a/chromium/content/renderer/service_worker/service_worker_subresource_loader.h
+++ b/chromium/content/renderer/service_worker/service_worker_subresource_loader.h
@@ -37,7 +37,7 @@ class ControllerServiceWorkerConnector;
// the main thread (while the implementation itself is thread agnostic).
class CONTENT_EXPORT ServiceWorkerSubresourceLoader
: public network::mojom::URLLoader,
- public mojom::ServiceWorkerFetchResponseCallback,
+ public blink::mojom::ServiceWorkerFetchResponseCallback,
public ControllerServiceWorkerConnector::Observer {
public:
// See the comments for ServiceWorkerSubresourceLoaderFactory's ctor (below)
@@ -74,20 +74,16 @@ class CONTENT_EXPORT ServiceWorkerSubresourceLoader
void SettleFetchEventDispatch(
base::Optional<blink::ServiceWorkerStatusCode> status);
- // mojom::ServiceWorkerFetchResponseCallback overrides:
- void OnResponse(const ServiceWorkerResponse& response,
+ // blink::mojom::ServiceWorkerFetchResponseCallback overrides:
+ void OnResponse(blink::mojom::FetchAPIResponsePtr response,
base::Time dispatch_event_time) override;
- void OnResponseBlob(const ServiceWorkerResponse& response,
- blink::mojom::BlobPtr blob,
- base::Time dispatch_event_time) override;
void OnResponseStream(
- const ServiceWorkerResponse& response,
+ blink::mojom::FetchAPIResponsePtr response,
blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
base::Time dispatch_event_time) override;
void OnFallback(base::Time dispatch_event_time) override;
- void StartResponse(const ServiceWorkerResponse& response,
- blink::mojom::BlobPtr body_as_blob,
+ void StartResponse(blink::mojom::FetchAPIResponsePtr response,
blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream);
// network::mojom::URLLoader overrides:
@@ -119,7 +115,8 @@ class CONTENT_EXPORT ServiceWorkerSubresourceLoader
mojo::Binding<network::mojom::URLLoader> url_loader_binding_;
// For handling FetchEvent response.
- mojo::Binding<ServiceWorkerFetchResponseCallback> response_callback_binding_;
+ mojo::Binding<blink::mojom::ServiceWorkerFetchResponseCallback>
+ response_callback_binding_;
// The blob needs to be held while it's read to keep it alive.
blink::mojom::BlobPtr body_as_blob_;
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 73f5661eb9a..67f4b12700e 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
@@ -121,46 +121,33 @@ class FakeControllerServiceWorker : public mojom::ControllerServiceWorker {
FakeControllerServiceWorker() = default;
~FakeControllerServiceWorker() override = default;
- static ServiceWorkerResponse OkResponse() {
- return ServiceWorkerResponse(
- std::make_unique<std::vector<GURL>>(), 200, "OK",
- network::mojom::FetchResponseType::kDefault,
- std::make_unique<ServiceWorkerHeaderMap>(), "" /* blob_uuid */,
- 0 /* blob_size */, nullptr /* blob */,
- blink::mojom::ServiceWorkerResponseError::kUnknown, base::Time(),
- false /* response_is_in_cache_storage */,
- std::string() /* response_cache_storage_cache_name */,
- std::make_unique<
- ServiceWorkerHeaderList>() /* cors_exposed_header_names */);
+ static blink::mojom::FetchAPIResponsePtr OkResponse(
+ blink::mojom::SerializedBlobPtr blob_body) {
+ auto response = blink::mojom::FetchAPIResponse::New();
+ response->status_code = 200;
+ response->status_text = "OK";
+ response->response_type = network::mojom::FetchResponseType::kDefault;
+ response->blob = std::move(blob_body);
+ return response;
}
- static ServiceWorkerResponse ErrorResponse() {
- return ServiceWorkerResponse(
- std::make_unique<std::vector<GURL>>(), 0 /* status_code */,
- "" /* status_text */, network::mojom::FetchResponseType::kDefault,
- std::make_unique<ServiceWorkerHeaderMap>(), "" /* blob_uuid */,
- 0 /* blob_size */, nullptr /* blob */,
- blink::mojom::ServiceWorkerResponseError::kPromiseRejected,
- base::Time(), false /* response_is_in_cache_storage */,
- std::string() /* response_cache_storage_cache_name */,
- std::make_unique<
- ServiceWorkerHeaderList>() /* cors_exposed_header_names */);
+ static blink::mojom::FetchAPIResponsePtr ErrorResponse() {
+ auto response = blink::mojom::FetchAPIResponse::New();
+ response->status_code = 0;
+ response->response_type = network::mojom::FetchResponseType::kDefault;
+ response->error =
+ blink::mojom::ServiceWorkerResponseError::kPromiseRejected;
+ return response;
}
- static ServiceWorkerResponse RedirectResponse(
+ static blink::mojom::FetchAPIResponsePtr RedirectResponse(
const std::string& redirect_location_header) {
- auto headers = std::make_unique<ServiceWorkerHeaderMap>();
- (*headers)["Location"] = redirect_location_header;
-
- return ServiceWorkerResponse(
- std::make_unique<std::vector<GURL>>(), 302, "Found",
- network::mojom::FetchResponseType::kDefault, std::move(headers),
- "" /* blob_uuid */, 0 /* blob_size */, nullptr /* blob */,
- blink::mojom::ServiceWorkerResponseError::kUnknown, base::Time(),
- false /* response_is_in_cache_storage */,
- std::string() /* response_cache_storage_cache_name */,
- std::make_unique<
- ServiceWorkerHeaderList>() /* cors_exposed_header_names */);
+ auto response = blink::mojom::FetchAPIResponse::New();
+ response->status_code = 302;
+ response->status_text = "Found";
+ response->response_type = network::mojom::FetchResponseType::kDefault;
+ response->headers["Location"] = redirect_location_header;
+ return response;
}
void CloseAllBindings() { bindings_.CloseAllBindings(); }
@@ -197,9 +184,11 @@ class FakeControllerServiceWorker : public mojom::ControllerServiceWorker {
void RespondWithBlob(base::Optional<std::vector<uint8_t>> metadata,
std::string body) {
response_mode_ = ResponseMode::kBlob;
+ blob_body_ = blink::mojom::SerializedBlob::New();
+ blob_body_->uuid = "dummy-blob-uuid";
mojo::MakeStrongBinding(
std::make_unique<FakeBlob>(std::move(metadata), std::move(body)),
- mojo::MakeRequest(&blob_));
+ mojo::MakeRequest(&blob_body_->blob));
}
void ReadRequestBody(std::string* out_string) {
@@ -233,7 +222,7 @@ class FakeControllerServiceWorker : public mojom::ControllerServiceWorker {
// mojom::ControllerServiceWorker:
void DispatchFetchEvent(
blink::mojom::DispatchFetchEventParamsPtr params,
- mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
+ blink::mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
DispatchFetchEventCallback callback) override {
EXPECT_FALSE(ServiceWorkerUtils::IsMainResourceType(
static_cast<ResourceType>(params->request.resource_type)));
@@ -244,7 +233,8 @@ class FakeControllerServiceWorker : public mojom::ControllerServiceWorker {
switch (response_mode_) {
case ResponseMode::kDefault:
- response_callback->OnResponse(OkResponse(), base::Time::Now());
+ response_callback->OnResponse(OkResponse(nullptr /* blob_body */),
+ base::Time::Now());
std::move(callback).Run(
blink::mojom::ServiceWorkerEventStatus::COMPLETED, base::Time());
break;
@@ -253,14 +243,15 @@ class FakeControllerServiceWorker : public mojom::ControllerServiceWorker {
base::Time());
break;
case ResponseMode::kStream:
- response_callback->OnResponseStream(
- OkResponse(), std::move(stream_handle_), base::Time::Now());
+ response_callback->OnResponseStream(OkResponse(nullptr /* blob_body */),
+ std::move(stream_handle_),
+ base::Time::Now());
std::move(callback).Run(
blink::mojom::ServiceWorkerEventStatus::COMPLETED, base::Time());
break;
case ResponseMode::kBlob:
- response_callback->OnResponseBlob(OkResponse(), std::move(blob_),
- base::Time::Now());
+ response_callback->OnResponse(OkResponse(std::move(blob_body_)),
+ base::Time::Now());
std::move(callback).Run(
blink::mojom::ServiceWorkerEventStatus::COMPLETED, base::Time());
break;
@@ -326,7 +317,7 @@ class FakeControllerServiceWorker : public mojom::ControllerServiceWorker {
blink::mojom::ServiceWorkerStreamHandlePtr stream_handle_;
// For ResponseMode::kBlob.
- blink::mojom::BlobPtr blob_;
+ blink::mojom::SerializedBlobPtr blob_body_;
// For ResponseMode::kRedirectResponse
std::string redirect_location_header_;
@@ -401,8 +392,7 @@ CreateResponseInfoFromServiceWorker() {
head->was_fetched_via_service_worker = true;
head->was_fallback_required_by_service_worker = false;
head->url_list_via_service_worker = std::vector<GURL>();
- head->response_type_via_service_worker =
- network::mojom::FetchResponseType::kDefault;
+ head->response_type = network::mojom::FetchResponseType::kDefault;
head->is_in_cache_storage = false;
head->cache_storage_cache_name = std::string();
head->did_service_worker_navigation_preload = false;
@@ -472,8 +462,7 @@ class ServiceWorkerSubresourceLoaderTest : public ::testing::Test {
info.was_fallback_required_by_service_worker);
EXPECT_EQ(expected_info.url_list_via_service_worker,
info.url_list_via_service_worker);
- EXPECT_EQ(expected_info.response_type_via_service_worker,
- info.response_type_via_service_worker);
+ EXPECT_EQ(expected_info.response_type, info.response_type);
EXPECT_EQ(expected_info.is_in_cache_storage, info.is_in_cache_storage);
EXPECT_EQ(expected_info.cache_storage_cache_name,
info.cache_storage_cache_name);
@@ -1032,8 +1021,7 @@ TEST_F(ServiceWorkerSubresourceLoaderTest, RedirectResponse) {
const network::ResourceResponseHead& info = client->response_head();
EXPECT_EQ(200, info.headers->response_code());
- EXPECT_EQ(network::mojom::FetchResponseType::kDefault,
- info.response_type_via_service_worker);
+ EXPECT_EQ(network::mojom::FetchResponseType::kDefault, info.response_type);
// Write the body stream.
uint32_t written_bytes = sizeof(kResponseBody) - 1;
diff --git a/chromium/content/renderer/service_worker/service_worker_timeout_timer.cc b/chromium/content/renderer/service_worker/service_worker_timeout_timer.cc
index f61a8b98a5d..624664d316f 100644
--- a/chromium/content/renderer/service_worker/service_worker_timeout_timer.cc
+++ b/chromium/content/renderer/service_worker/service_worker_timeout_timer.cc
@@ -4,6 +4,7 @@
#include "content/renderer/service_worker/service_worker_timeout_timer.h"
+#include "base/atomic_sequence_num.h"
#include "base/stl_util.h"
#include "base/time/default_tick_clock.h"
#include "base/time/time.h"
@@ -17,9 +18,10 @@ namespace {
int NextEventId() {
// Event id should not start from zero since HashMap in Blink requires
// non-zero keys.
- static int s_next_event_id = 1;
- CHECK_LT(s_next_event_id, std::numeric_limits<int>::max());
- return s_next_event_id++;
+ 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
@@ -60,12 +62,16 @@ int ServiceWorkerTimeoutTimer::StartEventWithCustomTimeout(
base::OnceCallback<void(int /* event_id */)> 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();
@@ -85,7 +91,7 @@ void ServiceWorkerTimeoutTimer::EndEvent(int event_id) {
DCHECK(iter != id_event_map_.end());
inflight_events_.erase(iter->second);
id_event_map_.erase(iter);
- if (inflight_events_.empty()) {
+ if (!HasInflightEvent()) {
idle_time_ = tick_clock_->NowTicks() + kIdleDelay;
MaybeTriggerIdleTimer();
}
@@ -101,7 +107,7 @@ void ServiceWorkerTimeoutTimer::PushPendingTask(
void ServiceWorkerTimeoutTimer::SetIdleTimerDelayToZero() {
DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled());
zero_idle_timer_delay_ = true;
- if (inflight_events_.empty())
+ if (!HasInflightEvent())
MaybeTriggerIdleTimer();
}
@@ -124,8 +130,9 @@ void ServiceWorkerTimeoutTimer::UpdateStatus() {
zero_idle_timer_delay_ = true;
}
- // If |inflight_events_| is empty, the worker is now idle.
- if (inflight_events_.empty() && idle_time_.is_null()) {
+ // If the worker is now idle, set the |idle_time_| and possibly trigger the
+ // idle callback.
+ if (!HasInflightEvent() && idle_time_.is_null()) {
idle_time_ = tick_clock_->NowTicks() + kIdleDelay;
if (MaybeTriggerIdleTimer())
return;
@@ -138,7 +145,7 @@ void ServiceWorkerTimeoutTimer::UpdateStatus() {
}
bool ServiceWorkerTimeoutTimer::MaybeTriggerIdleTimer() {
- DCHECK(inflight_events_.empty());
+ DCHECK(!HasInflightEvent());
if (!zero_idle_timer_delay_)
return false;
@@ -147,6 +154,10 @@ bool ServiceWorkerTimeoutTimer::MaybeTriggerIdleTimer() {
return true;
}
+bool ServiceWorkerTimeoutTimer::HasInflightEvent() const {
+ return !inflight_events_.empty() || running_pending_tasks_;
+}
+
ServiceWorkerTimeoutTimer::EventInfo::EventInfo(
int id,
base::TimeTicks expiration_time,
diff --git a/chromium/content/renderer/service_worker/service_worker_timeout_timer.h b/chromium/content/renderer/service_worker/service_worker_timeout_timer.h
index 484f7e156f5..c068ac32ddf 100644
--- a/chromium/content/renderer/service_worker/service_worker_timeout_timer.h
+++ b/chromium/content/renderer/service_worker/service_worker_timeout_timer.h
@@ -51,8 +51,9 @@ class CONTENT_EXPORT ServiceWorkerTimeoutTimer {
~ServiceWorkerTimeoutTimer();
// StartEvent() should be called at the beginning of an event. It returns an
- // event id. The event id should be passed to EndEvent() when the event has
- // finished. If there are pending tasks queued by PushPendingTask(), they will
+ // 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(base::OnceCallback<void(int /* event_id */)> abort_callback);
@@ -99,6 +100,9 @@ class CONTENT_EXPORT ServiceWorkerTimeoutTimer {
// the idle callback is called.
bool MaybeTriggerIdleTimer();
+ // Returns true if there are running events.
+ bool HasInflightEvent() const;
+
struct EventInfo {
EventInfo(int id,
base::TimeTicks expiration_time,
@@ -135,10 +139,17 @@ class CONTENT_EXPORT ServiceWorkerTimeoutTimer {
// StartEvent() is called.
bool did_idle_timeout_ = false;
- // Tasks waiting for the timer getting the next request to start an event
- // by StartEvent().
+ // 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;
+
// |timer_| invokes UpdateEventStatus() periodically.
base::RepeatingTimer timer_;
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
index 27396c1bea6..c03a3c47b85 100644
--- a/chromium/content/renderer/service_worker/service_worker_timeout_timer_unittest.cc
+++ b/chromium/content/renderer/service_worker/service_worker_timeout_timer_unittest.cc
@@ -47,6 +47,28 @@ base::RepeatingClosure CreateReceiverWithCalledFlag(bool* out_is_called) {
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.has_aborted());
+
+ out_tags->emplace_back(std::move(tag));
+
+ timer->EndEvent(event_id);
+ EXPECT_FALSE(event.has_aborted());
+ },
+ timer, std::move(tag), out_tags);
+}
+
} // namespace
class ServiceWorkerTimeoutTimerTest : public testing::Test {
@@ -224,6 +246,31 @@ TEST_F(ServiceWorkerTimeoutTimerTest, PushPendingTask) {
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) {
+ EnableServicification();
+ ServiceWorkerTimeoutTimer timer(base::DoNothing(),
+ task_runner()->GetMockTickClock());
+ 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) {
EnableServicification();
{
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 ca15fab9670..1e0b86ac99a 100644
--- a/chromium/content/renderer/service_worker/service_worker_type_converters.cc
+++ b/chromium/content/renderer/service_worker/service_worker_type_converters.cc
@@ -126,23 +126,4 @@ TypeConverter<blink::WebPaymentDetailsModifier,
return output;
}
-blink::WebServiceWorkerContextProxy::BackgroundFetchState
-TypeConverter<blink::WebServiceWorkerContextProxy::BackgroundFetchState,
- content::mojom::BackgroundFetchState>::
- Convert(content::mojom::BackgroundFetchState input) {
- switch (input) {
- case content::mojom::BackgroundFetchState::PENDING:
- return blink::WebServiceWorkerContextProxy::BackgroundFetchState::
- kPending;
- case content::mojom::BackgroundFetchState::SUCCEEDED:
- return blink::WebServiceWorkerContextProxy::BackgroundFetchState::
- kSucceeded;
- case content::mojom::BackgroundFetchState::FAILED:
- return blink::WebServiceWorkerContextProxy::BackgroundFetchState::kFailed;
- }
-
- NOTREACHED();
- return blink::WebServiceWorkerContextProxy::BackgroundFetchState::kPending;
-}
-
} // namespace mojo
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 796c7467632..1e7f290e928 100644
--- a/chromium/content/renderer/service_worker/service_worker_type_converters.h
+++ b/chromium/content/renderer/service_worker/service_worker_type_converters.h
@@ -7,8 +7,8 @@
#include "content/common/service_worker/service_worker.mojom.h"
#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/platform/modules/payments/payment_app.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/web/modules/service_worker/web_service_worker_context_proxy.h"
@@ -56,13 +56,6 @@ struct TypeConverter<blink::WebPaymentDetailsModifier,
const payments::mojom::PaymentDetailsModifierPtr& input);
};
-template <>
-struct TypeConverter<blink::WebServiceWorkerContextProxy::BackgroundFetchState,
- content::mojom::BackgroundFetchState> {
- static blink::WebServiceWorkerContextProxy::BackgroundFetchState Convert(
- content::mojom::BackgroundFetchState input);
-};
-
} // namespace
#endif // CONTENT_RENDERER_SERVICE_WORKER_SERVICE_WORKER_TYPE_CONVERTERS_H_
diff --git a/chromium/content/renderer/service_worker/service_worker_type_util.cc b/chromium/content/renderer/service_worker/service_worker_type_util.cc
index 020f30164d2..5eac4daa9e6 100644
--- a/chromium/content/renderer/service_worker/service_worker_type_util.cc
+++ b/chromium/content/renderer/service_worker/service_worker_type_util.cc
@@ -19,9 +19,10 @@ namespace content {
namespace {
+template <typename T>
class HeaderVisitor : public blink::WebHTTPHeaderVisitor {
public:
- explicit HeaderVisitor(ServiceWorkerHeaderMap* headers) : headers_(headers) {}
+ explicit HeaderVisitor(T* headers) : headers_(headers) {}
~HeaderVisitor() override {}
void VisitHeader(const blink::WebString& name,
@@ -31,41 +32,30 @@ class HeaderVisitor : public blink::WebHTTPHeaderVisitor {
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(ServiceWorkerHeaderMap::value_type(
- header_name, header_value));
+ headers_->insert(typename T::value_type(header_name, header_value));
}
private:
- ServiceWorkerHeaderMap* const headers_;
+ T* const headers_;
};
-std::unique_ptr<HeaderVisitor> MakeHeaderVisitor(
- ServiceWorkerHeaderMap* headers) {
- return std::unique_ptr<HeaderVisitor>(new HeaderVisitor(headers));
-}
-
-std::unique_ptr<ServiceWorkerHeaderMap> GetHeaderMap(
- const blink::WebServiceWorkerResponse& web_response) {
- std::unique_ptr<ServiceWorkerHeaderMap> result =
- std::make_unique<ServiceWorkerHeaderMap>();
- web_response.VisitHTTPHeaderFields(MakeHeaderVisitor(result.get()).get());
- return result;
+template <typename T>
+std::unique_ptr<HeaderVisitor<T>> MakeHeaderVisitor(T* headers) {
+ return std::make_unique<HeaderVisitor<T>>(headers);
}
-std::unique_ptr<ServiceWorkerHeaderList> GetHeaderList(
+std::vector<std::string> GetHeaderList(
const blink::WebVector<blink::WebString>& web_headers) {
- std::unique_ptr<ServiceWorkerHeaderList> result =
- std::make_unique<ServiceWorkerHeaderList>(web_headers.size());
- std::transform(web_headers.begin(), web_headers.end(), result->begin(),
+ 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::unique_ptr<std::vector<GURL>> GetURLList(
+std::vector<GURL> GetURLList(
const blink::WebVector<blink::WebURL>& web_url_list) {
- std::unique_ptr<std::vector<GURL>> result =
- std::make_unique<std::vector<GURL>>(web_url_list.size());
- std::transform(web_url_list.begin(), web_url_list.end(), result->begin(),
+ 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;
}
@@ -80,39 +70,41 @@ void GetServiceWorkerHeaderMapFromWebRequest(
web_request.VisitHTTPHeaderFields(MakeHeaderVisitor(headers).get());
}
-ServiceWorkerResponse GetServiceWorkerResponseFromWebResponse(
+blink::mojom::FetchAPIResponsePtr GetFetchAPIResponseFromWebResponse(
const blink::WebServiceWorkerResponse& web_response) {
- scoped_refptr<storage::BlobHandle> blob;
- auto blob_pipe = web_response.CloneBlobPtr();
- if (blob_pipe.is_valid()) {
- blink::mojom::BlobPtr blob_ptr;
- blob_ptr.Bind(blink::mojom::BlobPtrInfo(std::move(blob_pipe),
- blink::mojom::Blob::Version_));
- blob = base::MakeRefCounted<storage::BlobHandle>(std::move(blob_ptr));
+ 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_);
}
- ServiceWorkerResponse response = ServiceWorkerResponse(
+ 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(),
- GetHeaderMap(web_response), web_response.BlobUUID().Utf8(),
- web_response.BlobSize(), std::move(blob), web_response.GetError(),
- web_response.ResponseTime(),
- !web_response.CacheStorageCacheName().IsNull(),
+ web_response.StatusText().Utf8(), web_response.ResponseType(), headers,
+ std::move(blob), web_response.GetError(), web_response.ResponseTime(),
web_response.CacheStorageCacheName().Utf8(),
- GetHeaderList(web_response.CorsExposedHeaderNames()));
- if (!web_response.SideDataBlobSize())
- return response;
- response.side_data_blob_uuid = web_response.SideDataBlobUUID().Utf8();
- response.side_data_blob_size = web_response.SideDataBlobSize();
- auto side_data_blob_pipe = web_response.CloneSideDataBlobPtr();
- if (side_data_blob_pipe.is_valid()) {
- blink::mojom::BlobPtr side_data_blob_ptr;
- side_data_blob_ptr.Bind(blink::mojom::BlobPtrInfo(
- std::move(side_data_blob_pipe), blink::mojom::Blob::Version_));
- response.side_data_blob = base::MakeRefCounted<storage::BlobHandle>(
- std::move(side_data_blob_ptr));
- }
- return response;
+ GetHeaderList(web_response.CorsExposedHeaderNames()),
+ !web_response.CacheStorageCacheName().IsNull(),
+ 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
index f78839d4e2d..006aef8854c 100644
--- a/chromium/content/renderer/service_worker/service_worker_type_util.h
+++ b/chromium/content/renderer/service_worker/service_worker_type_util.h
@@ -6,6 +6,7 @@
#define CONTENT_RENDERER_SERVICE_WORKER_SERVICE_WORKER_TYPE_UTIL_H_
#include "content/common/service_worker/service_worker_types.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_response.mojom.h"
namespace blink {
class WebServiceWorkerRequest;
@@ -14,11 +15,11 @@ class WebServiceWorkerResponse;
namespace content {
-void GetServiceWorkerHeaderMapFromWebRequest(
+void CONTENT_EXPORT GetServiceWorkerHeaderMapFromWebRequest(
const blink::WebServiceWorkerRequest& web_request,
ServiceWorkerHeaderMap* headers);
-ServiceWorkerResponse GetServiceWorkerResponseFromWebResponse(
+blink::mojom::FetchAPIResponsePtr GetFetchAPIResponseFromWebResponse(
const blink::WebServiceWorkerResponse& web_response);
} // namespace content
diff --git a/chromium/content/renderer/service_worker/web_service_worker_impl.cc b/chromium/content/renderer/service_worker/web_service_worker_impl.cc
index dba3fc329f7..75f91c13248 100644
--- a/chromium/content/renderer/service_worker/web_service_worker_impl.cc
+++ b/chromium/content/renderer/service_worker/web_service_worker_impl.cc
@@ -7,7 +7,6 @@
#include <utility>
#include "base/macros.h"
-#include "content/common/service_worker/service_worker_messages.h"
#include "content/renderer/service_worker/service_worker_context_client.h"
#include "content/renderer/service_worker/service_worker_provider_context.h"
#include "content/renderer/service_worker/web_service_worker_provider_impl.h"
diff --git a/chromium/content/renderer/shared_worker/embedded_shared_worker_stub.cc b/chromium/content/renderer/shared_worker/embedded_shared_worker_stub.cc
index a2be7d7cdef..34ff87e85b0 100644
--- a/chromium/content/renderer/shared_worker/embedded_shared_worker_stub.cc
+++ b/chromium/content/renderer/shared_worker/embedded_shared_worker_stub.cc
@@ -54,11 +54,12 @@ class SharedWorkerWebApplicationCacheHostImpl
: public WebApplicationCacheHostImpl {
public:
SharedWorkerWebApplicationCacheHostImpl(
- blink::WebApplicationCacheHostClient* client)
+ blink::WebApplicationCacheHostClient* client,
+ int appcache_host_id)
: WebApplicationCacheHostImpl(
client,
RenderThreadImpl::current()->appcache_dispatcher()->backend_proxy(),
- kAppCacheNoHostId) {}
+ appcache_host_id) {}
// Main resource loading is different for workers. The main resource is
// loaded by the worker using WorkerClassicScriptLoader.
@@ -197,9 +198,11 @@ EmbeddedSharedWorkerStub::EmbeddedSharedWorkerStub(
bool pause_on_start,
const base::UnguessableToken& devtools_worker_token,
const RendererPreferences& renderer_preferences,
+ mojom::RendererPreferenceWatcherRequest preference_watcher_request,
blink::mojom::WorkerContentSettingsProxyPtr content_settings,
mojom::ServiceWorkerProviderInfoForSharedWorkerPtr
service_worker_provider_info,
+ int appcache_host_id,
network::mojom::URLLoaderFactoryAssociatedPtrInfo
script_loader_factory_info,
std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loaders,
@@ -210,7 +213,14 @@ EmbeddedSharedWorkerStub::EmbeddedSharedWorkerStub(
host_(std::move(host)),
name_(info->name),
url_(info->url),
- renderer_preferences_(renderer_preferences) {
+ renderer_preferences_(renderer_preferences),
+ preference_watcher_request_(std::move(preference_watcher_request)),
+ appcache_host_id_(appcache_host_id) {
+ // 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 == kAppCacheNoHostId);
+
impl_ = blink::WebSharedWorker::Create(this);
if (pause_on_start) {
// Pause worker context when it starts and wait until either DevTools client
@@ -318,7 +328,8 @@ std::unique_ptr<blink::WebApplicationCacheHost>
EmbeddedSharedWorkerStub::CreateApplicationCacheHost(
blink::WebApplicationCacheHostClient* client) {
std::unique_ptr<WebApplicationCacheHostImpl> host =
- std::make_unique<SharedWorkerWebApplicationCacheHostImpl>(client);
+ std::make_unique<SharedWorkerWebApplicationCacheHostImpl>(
+ client, appcache_host_id_);
app_cache_host_ = host.get();
return std::move(host);
}
@@ -383,7 +394,8 @@ EmbeddedSharedWorkerStub::CreateWorkerFetchContext(
loader_factories_->Clone();
auto worker_fetch_context = std::make_unique<WebWorkerFetchContextImpl>(
- std::move(renderer_preferences_), std::move(worker_client_request),
+ std::move(renderer_preferences_), std::move(preference_watcher_request_),
+ std::move(worker_client_request),
std::move(worker_client_registry_ptr_info),
std::move(container_host_ptr_info), loader_factories_->Clone(),
std::move(fallback_factory),
diff --git a/chromium/content/renderer/shared_worker/embedded_shared_worker_stub.h b/chromium/content/renderer/shared_worker/embedded_shared_worker_stub.h
index 6014d199411..85dc8d5d78a 100644
--- a/chromium/content/renderer/shared_worker/embedded_shared_worker_stub.h
+++ b/chromium/content/renderer/shared_worker/embedded_shared_worker_stub.h
@@ -15,6 +15,7 @@
#include "content/common/shared_worker/shared_worker.mojom.h"
#include "content/common/shared_worker/shared_worker_host.mojom.h"
#include "content/common/shared_worker/shared_worker_info.mojom.h"
+#include "content/public/common/renderer_preference_watcher.mojom.h"
#include "content/public/common/renderer_preferences.h"
#include "ipc/ipc_listener.h"
#include "mojo/public/cpp/bindings/binding.h"
@@ -61,9 +62,11 @@ class EmbeddedSharedWorkerStub : public blink::WebSharedWorkerClient,
bool pause_on_start,
const base::UnguessableToken& devtools_worker_token,
const RendererPreferences& renderer_preferences,
+ mojom::RendererPreferenceWatcherRequest preference_watcher_request,
blink::mojom::WorkerContentSettingsProxyPtr content_settings,
mojom::ServiceWorkerProviderInfoForSharedWorkerPtr
service_worker_provider_info,
+ int appcache_host_id,
network::mojom::URLLoaderFactoryAssociatedPtrInfo
script_loader_factory_info,
std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loaders,
@@ -109,6 +112,9 @@ class EmbeddedSharedWorkerStub : public blink::WebSharedWorkerClient,
bool running_ = false;
GURL url_;
RendererPreferences renderer_preferences_;
+ // Set on ctor and passed to the fetch context created when
+ // CreateWorkerFetchContext() is called.
+ mojom::RendererPreferenceWatcherRequest preference_watcher_request_;
std::unique_ptr<blink::WebSharedWorker> impl_;
using PendingChannel =
@@ -116,6 +122,7 @@ class EmbeddedSharedWorkerStub : public blink::WebSharedWorkerClient,
std::vector<PendingChannel> pending_channels_;
ScopedChildProcessReference process_ref_;
+ const int appcache_host_id_;
WebApplicationCacheHostImpl* app_cache_host_ = nullptr; // Not owned.
// S13nServiceWorker: The info needed to connect to the
diff --git a/chromium/content/renderer/shared_worker/shared_worker_factory_impl.cc b/chromium/content/renderer/shared_worker/shared_worker_factory_impl.cc
index 48a5091476b..a8c429de2bb 100644
--- a/chromium/content/renderer/shared_worker/shared_worker_factory_impl.cc
+++ b/chromium/content/renderer/shared_worker/shared_worker_factory_impl.cc
@@ -25,9 +25,11 @@ void SharedWorkerFactoryImpl::CreateSharedWorker(
bool pause_on_start,
const base::UnguessableToken& devtools_worker_token,
const RendererPreferences& renderer_preferences,
+ mojom::RendererPreferenceWatcherRequest preference_watcher_request,
blink::mojom::WorkerContentSettingsProxyPtr content_settings,
mojom::ServiceWorkerProviderInfoForSharedWorkerPtr
service_worker_provider_info,
+ int appcache_host_id,
network::mojom::URLLoaderFactoryAssociatedPtrInfo
script_loader_factory_ptr_info,
std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loaders,
@@ -37,10 +39,11 @@ void SharedWorkerFactoryImpl::CreateSharedWorker(
// Bound to the lifetime of the underlying blink::WebSharedWorker instance.
new EmbeddedSharedWorkerStub(
std::move(info), pause_on_start, devtools_worker_token,
- renderer_preferences, std::move(content_settings),
- std::move(service_worker_provider_info),
- std::move(script_loader_factory_ptr_info), std::move(subresource_loaders),
- std::move(host), std::move(request), std::move(interface_provider));
+ renderer_preferences, std::move(preference_watcher_request),
+ std::move(content_settings), std::move(service_worker_provider_info),
+ appcache_host_id, std::move(script_loader_factory_ptr_info),
+ std::move(subresource_loaders), std::move(host), std::move(request),
+ std::move(interface_provider));
}
} // namespace content
diff --git a/chromium/content/renderer/shared_worker/shared_worker_factory_impl.h b/chromium/content/renderer/shared_worker/shared_worker_factory_impl.h
index 78aef0102e6..42433c91128 100644
--- a/chromium/content/renderer/shared_worker/shared_worker_factory_impl.h
+++ b/chromium/content/renderer/shared_worker/shared_worker_factory_impl.h
@@ -26,9 +26,11 @@ class SharedWorkerFactoryImpl : public mojom::SharedWorkerFactory {
bool pause_on_start,
const base::UnguessableToken& devtools_worker_token,
const RendererPreferences& renderer_preferences,
+ mojom::RendererPreferenceWatcherRequest preference_watcher_request,
blink::mojom::WorkerContentSettingsProxyPtr content_settings,
mojom::ServiceWorkerProviderInfoForSharedWorkerPtr
service_worker_provider_info,
+ int appcache_host_id,
network::mojom::URLLoaderFactoryAssociatedPtrInfo
script_loader_factory_ptr_info,
std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loaders,
diff --git a/chromium/content/renderer/visual_state_browsertest.cc b/chromium/content/renderer/visual_state_browsertest.cc
index e01ae0c286e..c32ee513c73 100644
--- a/chromium/content/renderer/visual_state_browsertest.cc
+++ b/chromium/content/renderer/visual_state_browsertest.cc
@@ -116,8 +116,9 @@ IN_PROC_BROWSER_TEST_F(VisualStateTest, DISABLED_CallbackDoesNotDeadlock) {
base::Bind(&VisualStateTest::AssertIsIdle, base::Unretained(this)));
// Insert a visual state callback.
- shell()->web_contents()->GetMainFrame()->InsertVisualStateCallback(base::Bind(
- &VisualStateTest::InvokeVisualStateCallback, base::Unretained(this)));
+ shell()->web_contents()->GetMainFrame()->InsertVisualStateCallback(
+ base::BindOnce(&VisualStateTest::InvokeVisualStateCallback,
+ base::Unretained(this)));
// Verify that the callback is invoked and a new commit completed.
PostTaskToInProcessRendererAndWait(base::Bind(
diff --git a/chromium/content/renderer/webclipboard_impl_browsertest.cc b/chromium/content/renderer/webclipboard_impl_browsertest.cc
index 181dfe0a8e1..d86dddb7ade 100644
--- a/chromium/content/renderer/webclipboard_impl_browsertest.cc
+++ b/chromium/content/renderer/webclipboard_impl_browsertest.cc
@@ -28,9 +28,9 @@ IN_PROC_BROWSER_TEST_F(WebClipboardImplTest, PasteRTF) {
const std::string rtf_content = "{\\rtf1\\ansi Hello, {\\b world.}}";
clipboard.SetRtf(rtf_content);
+ FrameFocusedObserver focus_observer(shell()->web_contents()->GetMainFrame());
// paste_listener.html takes RTF from the clipboard and sets the title.
NavigateToURL(shell(), GetTestUrl(".", "paste_listener.html"));
- FrameFocusedObserver focus_observer(shell()->web_contents()->GetMainFrame());
focus_observer.Wait();
const base::string16 expected_title = base::UTF8ToUTF16(rtf_content);
@@ -46,9 +46,9 @@ IN_PROC_BROWSER_TEST_F(WebClipboardImplTest, ImageCopy) {
base::string16 expected_types;
expected_types = base::ASCIIToUTF16("file;image/png string;text/html");
- NavigateToURL(shell(), GetTestUrl(".", "image_copy_types.html"));
WebContents* web_contents = shell()->web_contents();
FrameFocusedObserver focus_observer(web_contents->GetMainFrame());
+ NavigateToURL(shell(), GetTestUrl(".", "image_copy_types.html"));
focus_observer.Wait();
// Populate an iframe with an image, and wait for load to complete.
diff --git a/chromium/content/renderer/webgraphicscontext3d_provider_impl.cc b/chromium/content/renderer/webgraphicscontext3d_provider_impl.cc
index f44ed327657..0e2a4a96bd2 100644
--- a/chromium/content/renderer/webgraphicscontext3d_provider_impl.cc
+++ b/chromium/content/renderer/webgraphicscontext3d_provider_impl.cc
@@ -4,15 +4,16 @@
#include "content/renderer/webgraphicscontext3d_provider_impl.h"
+#include "cc/paint/paint_image.h"
#include "cc/tiles/gpu_image_decode_cache.h"
#include "components/viz/common/gl_helper.h"
#include "gpu/command_buffer/client/context_support.h"
-#include "services/ui/public/cpp/gpu/context_provider_command_buffer.h"
+#include "services/ws/public/cpp/gpu/context_provider_command_buffer.h"
namespace content {
WebGraphicsContext3DProviderImpl::WebGraphicsContext3DProviderImpl(
- scoped_refptr<ui::ContextProviderCommandBuffer> provider)
+ scoped_refptr<ws::ContextProviderCommandBuffer> provider)
: provider_(std::move(provider)) {}
WebGraphicsContext3DProviderImpl::~WebGraphicsContext3DProviderImpl() {
@@ -32,6 +33,11 @@ gpu::gles2::GLES2Interface* WebGraphicsContext3DProviderImpl::ContextGL() {
return provider_->ContextGL();
}
+gpu::webgpu::WebGPUInterface*
+WebGraphicsContext3DProviderImpl::WebGPUInterface() {
+ return provider_->WebGPUInterface();
+}
+
GrContext* WebGraphicsContext3DProviderImpl::GetGrContext() {
return provider_->GrContext();
}
@@ -83,7 +89,8 @@ cc::ImageDecodeCache* WebGraphicsContext3DProviderImpl::ImageDecodeCache() {
image_decode_cache_ = std::make_unique<cc::GpuImageDecodeCache>(
provider_.get(), use_transfer_cache, kN32_SkColorType,
- kMaxWorkingSetBytes, provider_->ContextCapabilities().max_texture_size);
+ kMaxWorkingSetBytes, provider_->ContextCapabilities().max_texture_size,
+ cc::PaintImage::kDefaultGeneratorClientId);
return image_decode_cache_.get();
}
diff --git a/chromium/content/renderer/webgraphicscontext3d_provider_impl.h b/chromium/content/renderer/webgraphicscontext3d_provider_impl.h
index 28947063460..2199c641c17 100644
--- a/chromium/content/renderer/webgraphicscontext3d_provider_impl.h
+++ b/chromium/content/renderer/webgraphicscontext3d_provider_impl.h
@@ -21,14 +21,14 @@ class GLES2Interface;
} // namespace gles2
} // namespace gpu
-namespace ui {
-class ContextProviderCommandBuffer;
-} // namespace ui
-
namespace viz {
class GLHelper;
} // namespace viz
+namespace ws {
+class ContextProviderCommandBuffer;
+} // namespace ws
+
namespace content {
class CONTENT_EXPORT WebGraphicsContext3DProviderImpl
@@ -36,12 +36,13 @@ class CONTENT_EXPORT WebGraphicsContext3DProviderImpl
public viz::ContextLostObserver {
public:
WebGraphicsContext3DProviderImpl(
- scoped_refptr<ui::ContextProviderCommandBuffer> provider);
+ scoped_refptr<ws::ContextProviderCommandBuffer> provider);
~WebGraphicsContext3DProviderImpl() override;
// WebGraphicsContext3DProvider implementation.
bool BindToCurrentThread() override;
gpu::gles2::GLES2Interface* ContextGL() override;
+ gpu::webgpu::WebGPUInterface* WebGPUInterface() override;
GrContext* GetGrContext() override;
const gpu::Capabilities& GetCapabilities() const override;
const gpu::GpuFeatureInfo& GetGpuFeatureInfo() const override;
@@ -51,7 +52,7 @@ class CONTENT_EXPORT WebGraphicsContext3DProviderImpl
base::RepeatingCallback<void(const char*, int32_t)>) override;
cc::ImageDecodeCache* ImageDecodeCache() override;
- ui::ContextProviderCommandBuffer* context_provider() const {
+ ws::ContextProviderCommandBuffer* context_provider() const {
return provider_.get();
}
@@ -59,7 +60,7 @@ class CONTENT_EXPORT WebGraphicsContext3DProviderImpl
// viz::ContextLostObserver implementation.
void OnContextLost() override;
- scoped_refptr<ui::ContextProviderCommandBuffer> provider_;
+ scoped_refptr<ws::ContextProviderCommandBuffer> provider_;
std::unique_ptr<viz::GLHelper> gl_helper_;
base::RepeatingClosure context_lost_callback_;
std::unique_ptr<cc::ImageDecodeCache> image_decode_cache_;
diff --git a/chromium/content/renderer/worker_thread_registry.cc b/chromium/content/renderer/worker_thread_registry.cc
index 47546f0e52b..e5204cd74e2 100644
--- a/chromium/content/renderer/worker_thread_registry.cc
+++ b/chromium/content/renderer/worker_thread_registry.cc
@@ -21,7 +21,8 @@ namespace content {
namespace {
-using WorkerThreadObservers = base::ObserverList<WorkerThread::Observer>;
+using WorkerThreadObservers =
+ base::ObserverList<WorkerThread::Observer>::Unchecked;
using ThreadLocalWorkerThreadObservers =
base::ThreadLocalPointer<WorkerThreadObservers>;
diff --git a/chromium/content/shell/BUILD.gn b/chromium/content/shell/BUILD.gn
index 698aaa4c79d..9df50e24a3c 100644
--- a/chromium/content/shell/BUILD.gn
+++ b/chromium/content/shell/BUILD.gn
@@ -54,6 +54,19 @@ source_set("layout_test_switches") {
]
}
+source_set("layout_test_utils") {
+ testonly = true
+ sources = [
+ "common/layout_test/layout_test_utils.cc",
+ "common/layout_test/layout_test_utils.h",
+ ]
+ deps = [
+ "//cc/paint:paint",
+ "//skia",
+ "//third_party/blink/public:blink_headers",
+ ]
+}
+
static_library("content_shell_lib") {
testonly = true
sources = [
@@ -238,6 +251,7 @@ static_library("content_shell_lib") {
deps = [
":content_shell_packaged_services_manifest_overlay",
":layout_test_switches",
+ ":layout_test_utils",
":mojo_bindings",
":resources",
"//base",
@@ -375,6 +389,10 @@ static_library("content_shell_lib") {
]
}
+ if (toolkit_views) {
+ deps += [ "//ui/views" ]
+ }
+
if (use_aura) {
deps += [
"//ui/aura",
@@ -391,7 +409,6 @@ static_library("content_shell_lib") {
]
deps += [
"//ui/resources",
- "//ui/views",
"//ui/views:test_support",
"//ui/views/controls/webview",
"//ui/wm:test_support",
@@ -899,7 +916,7 @@ group("content_shell_crash_test") {
testonly = true
data_deps = [
":content_shell",
- "//third_party/mesa:osmesa",
+ "//third_party/mesa_headers",
]
data = [
"//content/shell/tools/breakpad_integration_test.py",
diff --git a/chromium/content/shell/android/BUILD.gn b/chromium/content/shell/android/BUILD.gn
index 20e35f2f218..20334067e43 100644
--- a/chromium/content/shell/android/BUILD.gn
+++ b/chromium/content/shell/android/BUILD.gn
@@ -79,6 +79,7 @@ android_library("content_shell_java") {
"//base:base_java",
"//components/embedder_support/android:content_view_java",
"//components/embedder_support/android:view_java",
+ "//components/viz/service:service_java",
"//content/public/android:content_java",
"//media/base/android:media_java",
"//media/capture/video/android:capture_java",
@@ -172,18 +173,20 @@ android_apk("content_shell_apk") {
":content_shell_assets",
":content_shell_java",
"//base:base_java",
+ "//base:base_java_test_support",
+ "//components/crash/android:java",
"//content/public/android:content_java",
"//content/public/test/android:layouttest_java_support",
"//media/capture/video/android:capture_java",
"//net/android:net_java",
- "//third_party/mesa:osmesa",
+ "//services/shape_detection:shape_detection_java",
+ "//third_party/mesa_headers",
"//ui/android:ui_java",
]
apk_name = "ContentShell"
android_manifest = content_shell_manifest
android_manifest_dep = ":content_shell_manifest"
shared_libraries = [ ":libcontent_shell_content_view" ]
- loadable_modules = [ "$root_out_dir/libosmesa.so" ]
command_line_flags_file = "content-shell-command-line"
}
diff --git a/chromium/content/shell/common/layout_test.mojom b/chromium/content/shell/common/layout_test.mojom
index 5b4599b13cf..ae4e13d4527 100644
--- a/chromium/content/shell/common/layout_test.mojom
+++ b/chromium/content/shell/common/layout_test.mojom
@@ -22,7 +22,7 @@ struct ShellTestConfiguration {
// True if pixel tests are enabled.
bool enable_pixel_dumping = true;
- // True if tests can open external URLs
+ // True if tests can open external URLs.
bool allow_external_pages;
// The expected MD5 hash of the pixel results.
@@ -43,6 +43,9 @@ struct LayoutTestDump {
// Image dump.
skia.mojom.Bitmap? pixels;
string actual_pixel_hash;
+
+ // Selection rect dump.
+ gfx.mojom.Rect selection_rect;
};
interface LayoutTestControl {
diff --git a/chromium/content/shell/common/layout_test/layout_test_utils.cc b/chromium/content/shell/common/layout_test/layout_test_utils.cc
new file mode 100644
index 00000000000..12886f5b3de
--- /dev/null
+++ b/chromium/content/shell/common/layout_test/layout_test_utils.cc
@@ -0,0 +1,28 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/shell/common/layout_test/layout_test_utils.h"
+
+#include "cc/paint/skia_paint_canvas.h"
+#include "third_party/blink/public/platform/web_rect.h"
+
+namespace content {
+namespace layout_test_utils {
+
+// Utility function to draw a selection rect into a bitmap.
+void DrawSelectionRect(const SkBitmap& bitmap, const blink::WebRect& wr) {
+ // Render a red rectangle bounding selection rect
+ cc::SkiaPaintCanvas canvas(bitmap);
+ cc::PaintFlags flags;
+ flags.setColor(0xFFFF0000); // Fully opaque red
+ flags.setStyle(cc::PaintFlags::kStroke_Style);
+ flags.setAntiAlias(true);
+ flags.setStrokeWidth(1.0f);
+ SkIRect rect; // Bounding rect
+ rect.set(wr.x, wr.y, wr.x + wr.width, wr.y + wr.height);
+ canvas.drawIRect(rect, flags);
+}
+
+} // namespace layout_test_utils
+} // namespace content
diff --git a/chromium/content/shell/common/layout_test/layout_test_utils.h b/chromium/content/shell/common/layout_test/layout_test_utils.h
new file mode 100644
index 00000000000..c58c004a9d9
--- /dev/null
+++ b/chromium/content/shell/common/layout_test/layout_test_utils.h
@@ -0,0 +1,24 @@
+// 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.
+
+// Helpful layout_test utility functions, built in both content_shell and
+// test_runner.
+
+#ifndef CONTENT_SHELL_COMMON_LAYOUT_TEST_LAYOUT_TEST_UTILS_H_
+#define CONTENT_SHELL_COMMON_LAYOUT_TEST_LAYOUT_TEST_UTILS_H_
+
+class SkBitmap;
+namespace blink {
+struct WebRect;
+}
+
+namespace content {
+namespace layout_test_utils {
+
+void DrawSelectionRect(const SkBitmap& bitmap, const blink::WebRect& wr);
+
+} // namespace layout_test_utils
+} // namespace content
+
+#endif // CONTENT_SHELL_COMMON_LAYOUT_TEST_LAYOUT_TEST_UTILS_H_
diff --git a/chromium/content/shell/common/shell_content_client.cc b/chromium/content/shell/common/shell_content_client.cc
index 5042ed84fa8..806cd512134 100644
--- a/chromium/content/shell/common/shell_content_client.cc
+++ b/chromium/content/shell/common/shell_content_client.cc
@@ -7,6 +7,7 @@
#include "base/command_line.h"
#include "base/strings/string_piece.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/values.h"
#include "build/build_config.h"
#include "content/app/resources/grit/content_resources.h"
#include "content/app/strings/grit/content_strings.h"
@@ -87,6 +88,17 @@ gfx::Image& ShellContentClient::GetNativeImageNamed(int resource_id) const {
resource_id);
}
+base::DictionaryValue ShellContentClient::GetNetLogConstants() const {
+ base::DictionaryValue client_constants;
+ client_constants.SetString("name", "content_shell");
+ client_constants.SetString(
+ "command_line",
+ base::CommandLine::ForCurrentProcess()->GetCommandLineString());
+ base::DictionaryValue constants;
+ constants.SetKey("clientInfo", std::move(client_constants));
+ return constants;
+}
+
blink::OriginTrialPolicy* ShellContentClient::GetOriginTrialPolicy() {
return &origin_trial_policy_;
}
diff --git a/chromium/content/shell/common/shell_content_client.h b/chromium/content/shell/common/shell_content_client.h
index 635f4931283..bbf00112e99 100644
--- a/chromium/content/shell/common/shell_content_client.h
+++ b/chromium/content/shell/common/shell_content_client.h
@@ -29,6 +29,7 @@ class ShellContentClient : public ContentClient {
base::RefCountedMemory* GetDataResourceBytes(
int resource_id) const override;
gfx::Image& GetNativeImageNamed(int resource_id) const override;
+ base::DictionaryValue GetNetLogConstants() const override;
blink::OriginTrialPolicy* GetOriginTrialPolicy() override;
private:
diff --git a/chromium/content/shell/test_runner/BUILD.gn b/chromium/content/shell/test_runner/BUILD.gn
index 1b5c11abca9..c94c5eb9631 100644
--- a/chromium/content/shell/test_runner/BUILD.gn
+++ b/chromium/content/shell/test_runner/BUILD.gn
@@ -11,6 +11,12 @@ if (is_android) {
component("test_runner") {
testonly = true
+ # See comment at the top of //content/BUILD.gn for why this is disabled in
+ # component builds.
+ if (is_component_build) {
+ check_includes = false
+ }
+
defines = [ "TEST_RUNNER_IMPLEMENTATION" ]
sources = [
@@ -98,7 +104,9 @@ component("test_runner") {
"//content/public/common",
"//content/public/common:service_names",
"//content/public/renderer",
+ "//content/renderer:for_content_tests",
"//content/shell:layout_test_switches",
+ "//content/shell:layout_test_utils",
"//content/test:test_runner_support",
"//device/base/synchronization",
"//device/gamepad/public/cpp:shared_with_blink",
@@ -108,7 +116,6 @@ component("test_runner") {
"//gpu/command_buffer/client:gles2_interface",
"//media/midi:mojo",
"//net",
- "//services/device/public/cpp/generic_sensor:shared_with_blink",
"//services/device/public/mojom",
"//skia",
"//third_party/blink/public:blink",
diff --git a/chromium/content/test/BUILD.gn b/chromium/content/test/BUILD.gn
index 15a64a49d5c..862228af120 100644
--- a/chromium/content/test/BUILD.gn
+++ b/chromium/content/test/BUILD.gn
@@ -9,6 +9,7 @@ import("//build/config/crypto.gni")
import("//build/config/features.gni")
import("//build/config/jumbo.gni")
import("//build/config/ui.gni")
+import("//build/nocompile.gni")
import("//media/media_options.gni")
import("//net/features.gni")
import("//mojo/public/tools/bindings/mojom.gni")
@@ -71,6 +72,8 @@ jumbo_static_library("test_support") {
"../public/test/browsing_data_remover_test_util.h",
"../public/test/cache_test_util.cc",
"../public/test/cache_test_util.h",
+ "../public/test/content_mock_cert_verifier.cc",
+ "../public/test/content_mock_cert_verifier.h",
"../public/test/content_test_suite_base.cc",
"../public/test/content_test_suite_base.h",
"../public/test/download_test_observer.cc",
@@ -95,8 +98,6 @@ jumbo_static_library("test_support") {
"../public/test/mock_browsing_data_remover_delegate.h",
"../public/test/mock_download_manager.cc",
"../public/test/mock_download_manager.h",
- "../public/test/mock_network_connection_tracker.cc",
- "../public/test/mock_network_connection_tracker.h",
"../public/test/mock_notification_observer.cc",
"../public/test/mock_notification_observer.h",
"../public/test/mock_permission_manager.cc",
@@ -198,6 +199,8 @@ jumbo_static_library("test_support") {
"accessibility_browser_test_utils.h",
"appcache_test_helper.cc",
"appcache_test_helper.h",
+ "barrier_builder.cc",
+ "barrier_builder.h",
"content_browser_sanity_checker.cc",
"content_browser_sanity_checker.h",
"content_test_suite.cc",
@@ -308,6 +311,7 @@ jumbo_static_library("test_support") {
"//ipc",
"//media/mojo/clients",
"//media/mojo/interfaces",
+ "//services/media_session/public/mojom",
"//third_party/blink/public:blink",
"//third_party/blink/public:test_support",
]
@@ -342,7 +346,7 @@ jumbo_static_library("test_support") {
"//net:test_support",
"//services/audio/public/mojom",
"//services/device/public/mojom",
- "//services/ui/public/cpp/gpu",
+ "//services/ws/public/cpp/gpu",
# TODO(jam): remove this by adding a public header for the NetworkContext
# public testing method.
@@ -507,6 +511,8 @@ jumbo_static_library("browsertest_support") {
"../public/test/content_browser_test_utils.cc",
"../public/test/content_browser_test_utils.h",
"../public/test/content_browser_test_utils_mac.mm",
+ "../public/test/content_cert_verifier_browser_test.cc",
+ "../public/test/content_cert_verifier_browser_test.h",
"content_browser_test_utils_internal.cc",
"content_browser_test_utils_internal.h",
"content_test_launcher.cc",
@@ -526,6 +532,7 @@ jumbo_static_library("browsertest_support") {
"//gin",
"//media",
"//net",
+ "//services/catalog:lib",
"//skia",
"//testing/gtest",
"//ui/accessibility:ax_enums_mojo",
@@ -539,6 +546,10 @@ jumbo_static_library("browsertest_support") {
deps += [ "//content/public/browser" ]
}
+ if (is_chromeos) {
+ deps += [ ":content_browsertests_catalog_source" ]
+ }
+
if (use_aura && toolkit_views) {
deps += [ "//ui/views" ]
}
@@ -613,7 +624,7 @@ static_library("layouttest_support") {
"//device/gamepad/public/cpp:shared_with_blink",
"//gpu/ipc/service",
"//services/device/public/cpp/generic_sensor",
- "//services/ui/public/cpp/gpu",
+ "//services/ws/public/cpp/gpu",
"//skia",
"//ui/accessibility:ax_enums_mojo",
"//ui/events/blink",
@@ -715,8 +726,9 @@ test("content_browsertests") {
"../browser/blob_storage/blob_url_browsertest.cc",
"../browser/bookmarklet_browsertest.cc",
"../browser/browser_side_navigation_browsertest.cc",
+ "../browser/browser_thread_browsertest.cc",
"../browser/browsing_data/browsing_data_remover_impl_browsertest.cc",
- "../browser/browsing_data/clear_site_data_throttle_browsertest.cc",
+ "../browser/browsing_data/clear_site_data_handler_browsertest.cc",
"../browser/browsing_data/conditional_cache_deletion_helper_browsertest.cc",
"../browser/child_process_launcher_browsertest.cc",
"../browser/child_process_security_policy_browsertest.cc",
@@ -726,6 +738,8 @@ test("content_browsertests") {
"../browser/device_sensors/device_sensor_browsertest.cc",
"../browser/devtools/devtools_video_consumer_browsertest.cc",
"../browser/devtools/protocol/devtools_protocol_browsertest.cc",
+ "../browser/devtools/protocol/devtools_protocol_test_support.cc",
+ "../browser/devtools/protocol/devtools_protocol_test_support.h",
"../browser/devtools/render_frame_devtools_agent_host_browsertest.cc",
"../browser/devtools/site_per_process_devtools_browsertest.cc",
"../browser/display_cutout/display_cutout_browsertest.cc",
@@ -742,6 +756,7 @@ test("content_browsertests") {
"../browser/fileapi/fileapi_browsertest.cc",
"../browser/find_request_manager_browsertest.cc",
+ "../browser/font_unique_name_lookup/font_unique_name_browsertest.cc",
"../browser/frame_host/blocked_scheme_navigation_browsertest.cc",
"../browser/frame_host/form_submission_throttle_browsertest.cc",
"../browser/frame_host/frame_tree_browsertest.cc",
@@ -787,6 +802,7 @@ test("content_browsertests") {
"../browser/media/session/media_session_service_impl_browsertest.cc",
"../browser/media/session/mock_media_session_player_observer.cc",
"../browser/media/session/mock_media_session_player_observer.h",
+ "../browser/media/webaudio/audio_context_manager_browsertest.cc",
"../browser/memory/memory_coordinator_impl_browsertest.cc",
"../browser/message_port_provider_browsertest.cc",
"../browser/mojo_sandbox_browsertest.cc",
@@ -800,8 +816,10 @@ test("content_browsertests") {
"../browser/pointer_lock_browsertest.cc",
"../browser/pointer_lock_browsertest.h",
"../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",
"../browser/renderer_host/input/fling_browsertest.cc",
@@ -813,6 +831,7 @@ test("content_browsertests") {
"../browser/renderer_host/input/touch_input_browsertest.cc",
"../browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc",
"../browser/renderer_host/input/touchpad_pinch_browsertest.cc",
+ "../browser/renderer_host/input/wheel_event_listener_browsertest.cc",
"../browser/renderer_host/input/wheel_scroll_latching_browsertest.cc",
"../browser/renderer_host/media/video_capture_browsertest.cc",
"../browser/renderer_host/render_process_host_browsertest.cc",
@@ -822,6 +841,8 @@ test("content_browsertests") {
"../browser/renderer_host/render_widget_host_view_child_frame_browsertest.cc",
"../browser/renderer_host/render_widget_host_view_mac_browsertest.mm",
"../browser/resource_loading_browsertest.cc",
+ "../browser/scheduler/responsiveness/native_event_observer_browsertest.mm",
+ "../browser/scheduler/responsiveness/native_event_observer_browsertest_win.cc",
"../browser/screen_orientation/screen_orientation_browsertest.cc",
"../browser/security_exploit_browsertest.cc",
"../browser/service_manager/service_manager_context_browsertest.cc",
@@ -942,6 +963,7 @@ test("content_browsertests") {
"//ipc",
"//ipc:test_support",
"//media:test_support",
+ "//media/webrtc",
"//mojo/core/embedder",
"//mojo/public/cpp/bindings",
"//net:test_support",
@@ -959,10 +981,10 @@ test("content_browsertests") {
"//services/network:test_support",
"//services/service_manager/public/cpp",
"//services/test/echo/public/mojom",
- "//services/ui/public/cpp/gpu",
"//services/video_capture/public/cpp",
"//services/video_capture/public/mojom:constants",
"//services/viz/privileged/interfaces",
+ "//services/ws/public/cpp/gpu",
"//storage/browser",
"//storage/browser:test_support",
"//testing/gmock",
@@ -970,7 +992,7 @@ test("content_browsertests") {
"//third_party/blink/public:blink",
"//third_party/leveldatabase",
"//third_party/libaom:av1_buildflags",
- "//third_party/mesa:osmesa",
+ "//third_party/mesa_headers",
"//third_party/zlib",
"//ui/accessibility",
"//ui/accessibility:ax_enums_mojo",
@@ -996,7 +1018,7 @@ test("content_browsertests") {
":web_ui_test_mojo_bindings_js_data_deps",
"//content/shell:pak",
"//testing/buildbot/filters:content_browsertests_filters",
- "//third_party/mesa:osmesa",
+ "//third_party/mesa_headers",
]
if (enable_plugins) {
@@ -1028,6 +1050,7 @@ test("content_browsertests") {
"../browser/media/capture/fake_video_capture_stack.h",
"../browser/media/capture/frame_test_util.cc",
"../browser/media/capture/frame_test_util.h",
+ "../browser/media/capture/mouse_cursor_overlay_controller_browsertest.cc",
"../browser/media/capture/web_contents_video_capture_device_browsertest.cc",
]
@@ -1043,7 +1066,7 @@ test("content_browsertests") {
"//ppapi/tests/test_page.css",
"//ppapi/tests/test_url_loader_data/",
"//third_party/pyftpdlib/",
- "//third_party/pywebsocket/",
+ "//third_party/pywebsocket/src/mod_pywebsocket/",
"//third_party/tlslite/",
]
}
@@ -1136,6 +1159,7 @@ test("content_browsertests") {
if (is_chromeos) {
deps += [ "//chromeos" ]
+ data_deps += [ "//services/ws/test_ws" ]
}
if (use_aura && !is_win) {
@@ -1219,6 +1243,34 @@ test("content_browsertests") {
}
}
+if (is_chromeos) {
+ catalog("content_browsertests_catalog") {
+ testonly = true
+
+ standalone_services = [ "//services/ws/test_ws:manifest" ]
+ }
+
+ catalog_cpp_source("content_browsertests_catalog_source") {
+ testonly = true
+
+ catalog = ":content_browsertests_catalog"
+ generated_function_name = "content::CreateContentBrowserTestsCatalog"
+ }
+}
+
+static_library("run_all_unittests") {
+ testonly = true
+ sources = [
+ "run_all_unittests.cc",
+ ]
+ deps = [
+ ":content_unittests_catalog_source",
+ ":test_support",
+ "//base/test:test_support",
+ "//services/catalog:lib",
+ ]
+}
+
test("content_unittests") {
# See comment at the top of //content/BUILD.gn for why this is disabled in
# component builds.
@@ -1266,6 +1318,7 @@ test("content_unittests") {
"../browser/background_fetch/background_fetch_registration_notifier_unittest.cc",
"../browser/background_fetch/background_fetch_scheduler_unittest.cc",
"../browser/background_fetch/background_fetch_service_unittest.cc",
+ "../browser/background_fetch/storage/image_helpers_unittest.cc",
"../browser/background_sync/background_sync_manager_unittest.cc",
"../browser/background_sync/background_sync_network_observer_unittest.cc",
"../browser/background_sync/background_sync_service_impl_unittest.cc",
@@ -1280,6 +1333,7 @@ test("content_unittests") {
"../browser/browser_url_handler_impl_unittest.cc",
"../browser/browsing_data/browsing_data_filter_builder_impl_unittest.cc",
"../browser/browsing_data/browsing_data_remover_impl_unittest.cc",
+ "../browser/browsing_data/clear_site_data_handler_unittest.cc",
"../browser/browsing_data/clear_site_data_throttle_unittest.cc",
"../browser/byte_stream_unittest.cc",
"../browser/cache_storage/cache_storage_blob_to_disk_cache_unittest.cc",
@@ -1322,7 +1376,6 @@ test("content_unittests") {
"../browser/download/save_package_unittest.cc",
"../browser/fileapi/browser_file_system_helper_unittest.cc",
"../browser/fileapi/file_system_operation_runner_unittest.cc",
- "../browser/fileapi/fileapi_message_filter_unittest.cc",
"../browser/frame_host/ancestor_throttle_unittest.cc",
"../browser/frame_host/frame_service_base_unittest.cc",
"../browser/frame_host/frame_tree_node_blame_context_unittest.cc",
@@ -1376,6 +1429,8 @@ test("content_unittests") {
"../browser/indexed_db/mock_mojo_indexed_db_callbacks.h",
"../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/scopes_lock_manager_unittest.cc",
"../browser/loader/cross_site_document_resource_handler_unittest.cc",
"../browser/loader/data_pipe_to_source_stream_unittest.cc",
"../browser/loader/detachable_resource_handler_unittest.cc",
@@ -1431,11 +1486,13 @@ test("content_unittests") {
"../browser/notifications/notification_database_unittest.cc",
"../browser/notifications/notification_event_dispatcher_impl_unittest.cc",
"../browser/notifications/notification_id_generator_unittest.cc",
+ "../browser/notifications/notification_storage_unittest.cc",
"../browser/notifications/platform_notification_context_unittest.cc",
"../browser/payments/payment_app_content_unittest_base.cc",
"../browser/payments/payment_app_content_unittest_base.h",
"../browser/payments/payment_app_provider_impl_unittest.cc",
"../browser/payments/payment_manager_unittest.cc",
+ "../browser/portal/portal_unit_test.cc",
"../browser/presentation/presentation_service_impl_unittest.cc",
"../browser/renderer_host/clipboard_host_impl_unittest.cc",
"../browser/renderer_host/cursor_manager_unittest.cc",
@@ -1493,11 +1550,6 @@ test("content_unittests") {
"../browser/renderer_host/media/video_capture_manager_unittest.cc",
"../browser/renderer_host/media/video_capture_unittest.cc",
"../browser/renderer_host/overscroll_controller_unittest.cc",
- "../browser/renderer_host/p2p/socket_host_tcp_server_unittest.cc",
- "../browser/renderer_host/p2p/socket_host_tcp_unittest.cc",
- "../browser/renderer_host/p2p/socket_host_test_utils.cc",
- "../browser/renderer_host/p2p/socket_host_test_utils.h",
- "../browser/renderer_host/p2p/socket_host_udp_unittest.cc",
"../browser/renderer_host/render_process_host_unittest.cc",
"../browser/renderer_host/render_view_host_unittest.cc",
"../browser/renderer_host/render_widget_host_input_event_router_unittest.cc",
@@ -1508,7 +1560,10 @@ test("content_unittests") {
"../browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm",
"../browser/renderer_host/render_widget_host_view_mac_unittest.mm",
"../browser/renderer_host/text_input_client_mac_unittest.mm",
+ "../browser/renderer_host/web_database_host_impl_unittest.cc",
"../browser/resolve_proxy_msg_helper_unittest.cc",
+ "../browser/scheduler/responsiveness/calculator_unittest.cc",
+ "../browser/scheduler/responsiveness/watcher_unittest.cc",
"../browser/screen_orientation/screen_orientation_provider_unittest.cc",
"../browser/service_worker/embedded_worker_instance_unittest.cc",
"../browser/service_worker/service_worker_cache_writer_unittest.cc",
@@ -1532,6 +1587,7 @@ test("content_unittests") {
"../browser/service_worker/service_worker_read_from_cache_job_unittest.cc",
"../browser/service_worker/service_worker_registration_unittest.cc",
"../browser/service_worker/service_worker_request_handler_unittest.cc",
+ "../browser/service_worker/service_worker_script_loader_factory_unittest.cc",
"../browser/service_worker/service_worker_storage_unittest.cc",
"../browser/service_worker/service_worker_url_request_job_unittest.cc",
"../browser/service_worker/service_worker_version_unittest.cc",
@@ -1548,6 +1604,7 @@ test("content_unittests") {
"../browser/storage_partition_impl_unittest.cc",
"../browser/streams/stream_unittest.cc",
"../browser/streams/stream_url_request_job_unittest.cc",
+ "../browser/tracing/background_startup_tracing_observer_unittest.cc",
"../browser/tracing/background_tracing_config_unittest.cc",
"../browser/tracing/tracing_ui_unittest.cc",
"../browser/web_contents/aura/gesture_nav_simple_unittest.cc",
@@ -1590,14 +1647,15 @@ test("content_unittests") {
"../common/content_switches_internal_unittest.cc",
"../common/cursors/webcursor_unittest.cc",
"../common/dom_storage/dom_storage_map_unittest.cc",
- "../common/indexed_db/indexed_db_key_unittest.cc",
"../common/input/event_with_latency_info_unittest.cc",
"../common/input/gesture_event_stream_validator_unittest.cc",
+ "../common/input/synthetic_web_input_event_builders_unittest.cc",
"../common/input/touch_event_stream_validator_unittest.cc",
"../common/inter_process_time_ticks_converter_unittest.cc",
"../common/mac/attributed_string_coder_unittest.mm",
"../common/manifest_util_unittest.cc",
"../common/media/media_devices_unittest.cc",
+ "../common/mime_sniffing_throttle_unittest.cc",
"../common/notifications/notification_struct_traits_unittest.cc",
"../common/origin_util_unittest.cc",
"../common/page_state_serialization_unittest.cc",
@@ -1614,7 +1672,6 @@ test("content_unittests") {
"../common/throttling_url_loader_unittest.cc",
"../common/unique_name_helper_unittest.cc",
"../common/webplugininfo_unittest.cc",
- "../public/browser/network_connection_tracker_unittest.cc",
"../public/browser/site_isolation_policy_unittest.cc",
# TODO(jam): move these network/ tests to services/network.
@@ -1622,7 +1679,6 @@ test("content_unittests") {
"../public/common/url_utils_unittest.cc",
"../public/test/referrer_unittest.cc",
"../public/test/test_browser_thread_bundle_unittest.cc",
- "../renderer/android/disambiguation_popup_helper_unittest.cc",
"../renderer/bmp_image_decoder_unittest.cc",
"../renderer/categorized_worker_pool_unittest.cc",
"../renderer/child_frame_compositing_helper_unittest.cc",
@@ -1698,6 +1754,7 @@ test("content_unittests") {
"../renderer/media/webrtc/rtc_rtp_sender_unittest.cc",
"../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",
@@ -1737,7 +1794,6 @@ test("content_unittests") {
"image_decoder_test.h",
"navigation_simulator_unittest.cc",
"proxy_service_mojo_unittest.cc",
- "run_all_unittests.cc",
"url_request_context_builder_mojo_unittest.cc",
]
@@ -1752,6 +1808,13 @@ test("content_unittests") {
sources += [ "../renderer/sandbox_mac_v2_unittest.mm" ]
}
+ if (use_atk) {
+ sources += [
+ "../browser/accessibility/browser_accessibility_auralinux_unittest.cc",
+ ]
+ configs += [ "//build/config/linux/atk" ]
+ }
+
if (is_android || is_linux || is_mac || is_win || is_fuchsia) {
data = [
"$root_out_dir/content_shell.pak",
@@ -1764,7 +1827,7 @@ test("content_unittests") {
deps = [
":content_test_mojo_bindings",
- ":content_unittests_catalog_source",
+ ":run_all_unittests",
":test_interfaces",
":test_support",
"//base/allocator:buildflags",
@@ -1789,6 +1852,7 @@ test("content_unittests") {
"//content:resources",
"//content/app:both_for_content_tests",
"//content/browser:for_content_tests",
+ "//content/browser/background_fetch:background_fetch_proto",
"//content/browser/cache_storage:cache_storage_proto",
"//content/browser/dom_storage:local_storage_proto",
"//content/browser/notifications:notification_proto",
@@ -1830,7 +1894,6 @@ test("content_unittests") {
"//printing",
"//services/audio/public/cpp:test_support",
"//services/audio/public/mojom",
- "//services/catalog:lib",
"//services/device/public/cpp/generic_sensor",
"//services/device/public/cpp/test:test_support",
"//services/device/public/mojom",
@@ -1861,6 +1924,7 @@ test("content_unittests") {
"//third_party/metrics_proto",
"//third_party/opus",
"//third_party/re2",
+ "//third_party/sqlite",
"//third_party/webrtc/api:libjingle_peerconnection_api",
"//third_party/webrtc/api:rtc_stats_api",
"//third_party/webrtc/api/video:video_frame",
@@ -1898,7 +1962,7 @@ test("content_unittests") {
data_deps = [
"//components/services/filesystem:filesystem",
"//testing/buildbot/filters:content_unittests_filters",
- "//third_party/mesa:osmesa",
+ "//third_party/mesa_headers",
]
if (is_posix) {
@@ -1913,6 +1977,7 @@ test("content_unittests") {
"../browser/renderer_host/pepper/pepper_file_system_browser_host_unittest.cc",
"../browser/renderer_host/pepper/pepper_gamepad_host_unittest.cc",
"../browser/renderer_host/pepper/pepper_printing_host_unittest.cc",
+ "../browser/renderer_host/pepper/pepper_proxy_lookup_helper_unittest.cc",
"../browser/renderer_host/pepper/quota_reservation_unittest.cc",
"../renderer/media/pepper/pepper_to_video_track_adapter_unittest.cc",
"../renderer/media/pepper/video_track_to_pepper_adapter_unittest.cc",
@@ -1948,6 +2013,7 @@ test("content_unittests") {
# Screen capture unit tests.
if (is_linux || is_mac || is_win) {
deps += [
+ "//media/capture:test_support",
"//third_party/libyuv",
"//third_party/webrtc/modules/desktop_capture",
]
@@ -1955,11 +2021,10 @@ test("content_unittests") {
"../browser/media/capture/desktop_capture_device_unittest.cc",
"../browser/media/capture/frame_sink_video_capture_device_unittest.cc",
]
- if (use_aura) {
- sources += [ "../browser/media/capture/cursor_renderer_aura_unittest.cc" ]
- }
- if (is_mac) {
- sources += [ "../browser/media/capture/cursor_renderer_mac_unittest.mm" ]
+ if (is_chromeos) {
+ sources += [
+ "../browser/media/capture/lame_capture_overlay_chromeos_unittest.cc",
+ ]
}
}
@@ -1992,6 +2057,7 @@ test("content_unittests") {
"../browser/android/overscroll_controller_android_unittest.cc",
"../browser/android/scoped_surface_request_manager_unittest.cc",
"../browser/android/url_request_content_job_unittest.cc",
+ "../browser/font_unique_name_lookup/font_unique_name_lookup_unittest.cc",
"../browser/media/capture/screen_capture_device_android_unittest.cc",
"../renderer/java/gin_java_bridge_value_converter_unittest.cc",
"../renderer/media/android/stream_texture_wrapper_impl_unittest.cc",
@@ -2004,9 +2070,12 @@ test("content_unittests") {
deps += [
"//base:base_java_unittest_support",
+ "//build/config/freetype",
"//content/public/android:content_java",
"//media/capture/content/android",
"//media/capture/content/android:screen_capture_java",
+ "//third_party/blink/public/common",
+ "//third_party/blink/public/common:font_unique_name_table_proto",
"//ui/android:android",
]
@@ -2035,6 +2104,8 @@ test("content_unittests") {
sources += [ "../browser/webauth/authenticator_impl_unittest.cc" ]
deps += [
"//device/base",
+ "//device/fido",
+ "//device/fido:mocks",
"//device/fido:test_support",
]
}
@@ -2056,10 +2127,6 @@ test("content_unittests") {
]
}
- # Avoid windows due to non-availability of cursor resources in test.
- if (is_win) {
- sources -= [ "../browser/media/capture/cursor_renderer_aura_unittest.cc" ]
- }
if (use_aura || toolkit_views) {
deps += [ "//ui/events:test_support" ]
}
@@ -2087,6 +2154,21 @@ test("content_unittests") {
}
}
+if (enable_nocompile_tests) {
+ nocompile_test("content_nocompile_tests") {
+ sources = [
+ "../public/browser/browser_task_traits_unittest.nc",
+ ]
+
+ deps = [
+ ":run_all_unittests",
+ "//base",
+ "//content/public/browser",
+ "//testing/gtest",
+ ]
+ }
+}
+
service_manifest("content_unittests_manifest") {
name = "content_unittests"
source = "unittests_manifest.json"
diff --git a/chromium/content/utility/BUILD.gn b/chromium/content/utility/BUILD.gn
index 610106e74b7..d8da671ee09 100644
--- a/chromium/content/utility/BUILD.gn
+++ b/chromium/content/utility/BUILD.gn
@@ -3,6 +3,7 @@
# found in the LICENSE file.
import("//build/config/jumbo.gni")
+import("//chromeos/assistant/assistant.gni")
import("//media/media_options.gni")
jumbo_source_set("utility") {
@@ -17,8 +18,6 @@ jumbo_source_set("utility") {
sources = [
"in_process_utility_thread.cc",
"in_process_utility_thread.h",
- "utility_blink_platform_impl.cc",
- "utility_blink_platform_impl.h",
"utility_blink_platform_with_sandbox_support_impl.cc",
"utility_blink_platform_with_sandbox_support_impl.h",
"utility_main.cc",
@@ -68,6 +67,17 @@ jumbo_source_set("utility") {
"//media/mojo/services",
]
}
+
+ if (is_chromeos) {
+ deps += [ "//chromeos/assistant:buildflags" ]
+ }
+
+ if (enable_cros_libassistant) {
+ deps += [
+ "//chromeos/services/assistant/audio_decoder:lib",
+ "//chromeos/services/assistant/public/mojom",
+ ]
+ }
}
# See comment at the top of //content/BUILD.gn for how this works.
diff --git a/chromium/content/utility/DEPS b/chromium/content/utility/DEPS
index 51f92f362e2..98f68268225 100644
--- a/chromium/content/utility/DEPS
+++ b/chromium/content/utility/DEPS
@@ -1,6 +1,8 @@
include_rules = [
"+content/child",
"+content/public/utility",
+ "+chromeos/assistant/buildflags.h",
+ "+chromeos/services/assistant",
"+services/audio",
"+services/data_decoder",
"+services/network",
diff --git a/chromium/content/utility/utility_blink_platform_impl.cc b/chromium/content/utility/utility_blink_platform_impl.cc
deleted file mode 100644
index f2074986725..00000000000
--- a/chromium/content/utility/utility_blink_platform_impl.cc
+++ /dev/null
@@ -1,24 +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/utility/utility_blink_platform_impl.h"
-
-#include "third_party/blink/public/platform/scheduler/child/webthread_base.h"
-
-namespace content {
-
-UtilityBlinkPlatformImpl::UtilityBlinkPlatformImpl()
- : main_thread_(blink::scheduler::WebThreadBase::InitializeUtilityThread()) {
-}
-
-UtilityBlinkPlatformImpl::~UtilityBlinkPlatformImpl() {
-}
-
-blink::WebThread* UtilityBlinkPlatformImpl::CurrentThread() {
- if (main_thread_->IsCurrentThread())
- return main_thread_.get();
- return BlinkPlatformImpl::CurrentThread();
-}
-
-} // namespace content
diff --git a/chromium/content/utility/utility_blink_platform_impl.h b/chromium/content/utility/utility_blink_platform_impl.h
deleted file mode 100644
index 3c5e7015492..00000000000
--- a/chromium/content/utility/utility_blink_platform_impl.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_UTILITY_UTILITY_BLINK_PLATFORM_IMPL_H_
-#define CONTENT_UTILITY_UTILITY_BLINK_PLATFORM_IMPL_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "content/child/blink_platform_impl.h"
-
-namespace blink {
-namespace scheduler {
-class WebThreadBase;
-}
-}
-
-namespace content {
-
-class UtilityBlinkPlatformImpl : public BlinkPlatformImpl {
- public:
- UtilityBlinkPlatformImpl();
- ~UtilityBlinkPlatformImpl() override;
-
- // BlinkPlatformImpl implementation.
- blink::WebThread* CurrentThread() override;
-
- private:
- std::unique_ptr<blink::scheduler::WebThreadBase> main_thread_;
-
- DISALLOW_COPY_AND_ASSIGN(UtilityBlinkPlatformImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_UTILITY_UTILITY_BLINK_PLATFORM_IMPL_H_
diff --git a/chromium/content/utility/utility_blink_platform_with_sandbox_support_impl.h b/chromium/content/utility/utility_blink_platform_with_sandbox_support_impl.h
index 3461acddb50..b2eb141ce83 100644
--- a/chromium/content/utility/utility_blink_platform_with_sandbox_support_impl.h
+++ b/chromium/content/utility/utility_blink_platform_with_sandbox_support_impl.h
@@ -9,7 +9,7 @@
#include "base/macros.h"
#include "build/build_config.h"
-#include "content/utility/utility_blink_platform_impl.h"
+#include "third_party/blink/public/platform/platform.h"
#if defined(OS_POSIX) && !defined(OS_ANDROID)
#include "components/services/font/public/cpp/font_loader.h" // nogncheck
@@ -28,8 +28,7 @@ namespace content {
// This class extends from UtilityBlinkPlatformImpl with added blink web
// sandbox support.
-class UtilityBlinkPlatformWithSandboxSupportImpl
- : public UtilityBlinkPlatformImpl {
+class UtilityBlinkPlatformWithSandboxSupportImpl : public blink::Platform {
public:
UtilityBlinkPlatformWithSandboxSupportImpl() = delete;
explicit UtilityBlinkPlatformWithSandboxSupportImpl(
diff --git a/chromium/content/utility/utility_main.cc b/chromium/content/utility/utility_main.cc
index b8eca5578f5..a1f19198fbb 100644
--- a/chromium/content/utility/utility_main.cc
+++ b/chromium/content/utility/utility_main.cc
@@ -20,6 +20,7 @@
#include "services/service_manager/sandbox/sandbox.h"
#if defined(OS_LINUX)
+#include "services/audio/audio_sandbox_hook_linux.h"
#include "services/network/network_sandbox_hook_linux.h"
#include "services/service_manager/sandbox/linux/sandbox_linux.h"
#endif
@@ -71,10 +72,14 @@ int UtilityMain(const MainFunctionParams& parameters) {
auto sandbox_type =
service_manager::SandboxTypeFromCommandLine(parameters.command_line);
if (parameters.zygote_child ||
- sandbox_type == service_manager::SANDBOX_TYPE_NETWORK) {
+ sandbox_type == service_manager::SANDBOX_TYPE_NETWORK ||
+ sandbox_type == service_manager::SANDBOX_TYPE_AUDIO) {
service_manager::SandboxLinux::PreSandboxHook pre_sandbox_hook;
if (sandbox_type == service_manager::SANDBOX_TYPE_NETWORK)
pre_sandbox_hook = base::BindOnce(&network::NetworkPreSandboxHook);
+ else if (sandbox_type == service_manager::SANDBOX_TYPE_AUDIO)
+ pre_sandbox_hook = base::BindOnce(&audio::AudioPreSandboxHook);
+
service_manager::Sandbox::Initialize(
sandbox_type, std::move(pre_sandbox_hook),
service_manager::SandboxLinux::Options());
diff --git a/chromium/content/utility/utility_service_factory.cc b/chromium/content/utility/utility_service_factory.cc
index 4d2eb9525b2..aa667ddec9d 100644
--- a/chromium/content/utility/utility_service_factory.cc
+++ b/chromium/content/utility/utility_service_factory.cc
@@ -27,8 +27,6 @@
#include "services/network/network_service.h"
#include "services/network/public/cpp/features.h"
#include "services/service_manager/public/mojom/service.mojom.h"
-#include "services/shape_detection/public/mojom/constants.mojom.h"
-#include "services/shape_detection/shape_detection_service.h"
#include "services/video_capture/public/mojom/constants.mojom.h"
#include "services/video_capture/service_impl.h"
#include "services/viz/public/interfaces/constants.mojom.h"
@@ -45,12 +43,25 @@
#endif // BUILDFLAG(ENABLE_CDM_HOST_VERIFICATION)
#endif
+#if defined(OS_MACOSX)
+#include "sandbox/mac/system_services.h"
+#include "services/service_manager/sandbox/features.h"
+#endif
+
#if defined(OS_WIN)
#include "sandbox/win/src/sandbox.h"
extern sandbox::TargetServices* g_utility_target_services;
#endif
+#if defined(OS_CHROMEOS)
+#include "chromeos/assistant/buildflags.h" // nogncheck
+#if BUILDFLAG(ENABLE_CROS_LIBASSISTANT)
+#include "chromeos/services/assistant/audio_decoder/assistant_audio_decoder_service.h" // nogncheck
+#include "chromeos/services/assistant/public/mojom/constants.mojom.h" // nogncheck
+#endif // BUILDFLAG(ENABLE_CROS_LIBASSISTANT)
+#endif
+
namespace content {
namespace {
@@ -145,11 +156,17 @@ void UtilityServiceFactory::RegisterServices(ServiceMap* services) {
services->emplace(media::mojom::kCdmServiceName, info);
#endif
- service_manager::EmbeddedServiceInfo shape_detection_info;
- shape_detection_info.factory =
- base::Bind(&shape_detection::ShapeDetectionService::Create);
- services->insert(std::make_pair(shape_detection::mojom::kServiceName,
- shape_detection_info));
+#if defined(OS_CHROMEOS)
+#if BUILDFLAG(ENABLE_CROS_LIBASSISTANT)
+ {
+ service_manager::EmbeddedServiceInfo assistant_audio_decoder_info;
+ assistant_audio_decoder_info.factory = base::BindRepeating(
+ &chromeos::assistant::AssistantAudioDecoderService::CreateService);
+ services->emplace(chromeos::assistant::mojom::kAudioDecoderServiceName,
+ assistant_audio_decoder_info);
+ }
+#endif // BUILDFLAG(ENABLE_CROS_LIBASSISTANT)
+#endif
service_manager::EmbeddedServiceInfo data_decoder_info;
data_decoder_info.factory = base::Bind(&CreateDataDecoderService);
@@ -191,6 +208,15 @@ UtilityServiceFactory::CreateNetworkService() {
std::unique_ptr<service_manager::Service>
UtilityServiceFactory::CreateAudioService() {
+#if defined(OS_MACOSX)
+ // Don't connect to launch services when running sandboxed
+ // (https://crbug.com/874785).
+ if (base::FeatureList::IsEnabled(
+ service_manager::features::kAudioServiceSandbox)) {
+ sandbox::DisableLaunchServices();
+ }
+#endif
+
return audio::CreateStandaloneService(std::move(audio_registry_));
}
diff --git a/chromium/content/utility/utility_thread_impl.cc b/chromium/content/utility/utility_thread_impl.cc
index 607cea7465d..57c3bfc105e 100644
--- a/chromium/content/utility/utility_thread_impl.cc
+++ b/chromium/content/utility/utility_thread_impl.cc
@@ -8,12 +8,10 @@
#include "base/command_line.h"
#include "build/build_config.h"
-#include "content/child/blink_platform_impl.h"
#include "content/child/child_process.h"
#include "content/public/common/service_manager_connection.h"
#include "content/public/common/simple_connection_filter.h"
#include "content/public/utility/content_utility_client.h"
-#include "content/utility/utility_blink_platform_impl.h"
#include "content/utility/utility_blink_platform_with_sandbox_support_impl.h"
#include "content/utility/utility_service_factory.h"
#include "ipc/ipc_sync_channel.h"
@@ -120,8 +118,8 @@ void UtilityThreadImpl::EnsureBlinkInitializedInternal(bool sandbox_support) {
sandbox_support
? std::make_unique<UtilityBlinkPlatformWithSandboxSupportImpl>(
GetConnector())
- : std::make_unique<UtilityBlinkPlatformImpl>();
- blink::Platform::Initialize(blink_platform_impl_.get());
+ : std::make_unique<blink::Platform>();
+ blink::Platform::CreateMainThreadAndInitialize(blink_platform_impl_.get());
}
void UtilityThreadImpl::Init() {
@@ -150,8 +148,10 @@ void UtilityThreadImpl::Init() {
service_factory_.reset(new UtilityServiceFactory);
- if (connection)
+ if (connection) {
connection->Start();
+ GetContentClient()->OnServiceManagerConnected(connection);
+ }
}
bool UtilityThreadImpl::OnControlMessageReceived(const IPC::Message& msg) {
diff --git a/chromium/content/utility/utility_thread_impl.h b/chromium/content/utility/utility_thread_impl.h
index a1b8d47b379..5aad58e72c1 100644
--- a/chromium/content/utility/utility_thread_impl.h
+++ b/chromium/content/utility/utility_thread_impl.h
@@ -14,9 +14,9 @@
#include "content/public/utility/utility_thread.h"
#include "mojo/public/cpp/bindings/binding_set.h"
#include "services/service_manager/public/mojom/service_factory.mojom.h"
+#include "third_party/blink/public/platform/platform.h"
namespace content {
-class UtilityBlinkPlatformImpl;
class UtilityServiceFactory;
namespace mojom {
@@ -64,7 +64,7 @@ class UtilityThreadImpl : public UtilityThread,
service_manager::mojom::ServiceFactoryRequest request);
// blink::Platform implementation if needed.
- std::unique_ptr<UtilityBlinkPlatformImpl> blink_platform_impl_;
+ std::unique_ptr<blink::Platform> blink_platform_impl_;
// service_manager::mojom::ServiceFactory for service_manager::Service
// hosting.